patches/gcc/4.2.2/300-avr32-atmel-v1.1.3.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Jan 12 19:24:03 2010 +0100 (2010-01-12)
changeset 1761 88020b2c3246
permissions -rw-r--r--
scripts/functions: change handling of nochdir

- 'nochdir' must be the first option
- have systematic pushd/popd, even if nochdir
mgl@1371
     1
--- a/configure.in
mgl@1371
     2
+++ b/configure.in
mgl@1371
     3
@@ -503,6 +503,9 @@ case "${target}" in
mgl@1371
     4
   arm-*-riscix*)
mgl@1371
     5
     noconfigdirs="$noconfigdirs ld target-libgloss ${libgcj}"
mgl@1371
     6
     ;;
mgl@1371
     7
+  avr32-*-*)
mgl@1371
     8
+    noconfigdirs="$noconfigdirs target-libiberty target-libmudflap target-libffi ${libgcj}"
mgl@1371
     9
+    ;;
mgl@1371
    10
   avr-*-*)
mgl@1371
    11
     noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
mgl@1371
    12
     ;;
mgl@1371
    13
--- a/gcc/builtins.c
mgl@1371
    14
+++ b/gcc/builtins.c
mgl@1371
    15
@@ -9223,7 +9223,7 @@ validate_arglist (tree arglist, ...)
mgl@1371
    16
 
mgl@1371
    17
   do
mgl@1371
    18
     {
mgl@1371
    19
-      code = va_arg (ap, enum tree_code);
mgl@1371
    20
+      code = va_arg (ap, int);
mgl@1371
    21
       switch (code)
mgl@1371
    22
 	{
mgl@1371
    23
 	case 0:
mgl@1371
    24
--- a/gcc/calls.c
mgl@1371
    25
+++ b/gcc/calls.c
mgl@1371
    26
@@ -3447,7 +3447,7 @@ emit_library_call_value_1 (int retval, r
mgl@1371
    27
   for (; count < nargs; count++)
mgl@1371
    28
     {
mgl@1371
    29
       rtx val = va_arg (p, rtx);
mgl@1371
    30
-      enum machine_mode mode = va_arg (p, enum machine_mode);
mgl@1371
    31
+      enum machine_mode mode = va_arg (p, int);
mgl@1371
    32
 
mgl@1371
    33
       /* We cannot convert the arg value to the mode the library wants here;
mgl@1371
    34
 	 must do it earlier where we know the signedness of the arg.  */
mgl@1371
    35
--- a/gcc/c-incpath.c
mgl@1371
    36
+++ b/gcc/c-incpath.c
mgl@1371
    37
@@ -347,6 +347,18 @@ add_path (char *path, int chain, int cxx
mgl@1371
    38
   char* c;
mgl@1371
    39
   for (c = path; *c; c++)
mgl@1371
    40
     if (*c == '\\') *c = '/';
mgl@1371
    41
+  /* Remove unnecessary trailing slashes.  On some versions of MS
mgl@1371
    42
+     Windows, trailing  _forward_ slashes cause no problems for stat().
mgl@1371
    43
+     On newer versions, stat() does not recognise a directory that ends
mgl@1371
    44
+     in a '\\' or '/', unless it is a drive root dir, such as "c:/",
mgl@1371
    45
+     where it is obligatory.  */
mgl@1371
    46
+  int pathlen = strlen (path);
mgl@1371
    47
+  char* end = path + pathlen - 1;
mgl@1371
    48
+  /* Preserve the lead '/' or lead "c:/".  */
mgl@1371
    49
+  char* start = path + (pathlen > 2 && path[1] == ':' ? 3 : 1);
mgl@1371
    50
+
mgl@1371
    51
+  for (; end > start && IS_DIR_SEPARATOR (*end); end--)
mgl@1371
    52
+    *end = 0;
mgl@1371
    53
 #endif
mgl@1371
    54
 
mgl@1371
    55
   p = XNEW (cpp_dir);
mgl@1371
    56
--- /dev/null
mgl@1371
    57
+++ b/gcc/config/avr32/avr32.c
mgl@1371
    58
@@ -0,0 +1,7915 @@
mgl@1371
    59
+/*
mgl@1371
    60
+   Target hooks and helper functions for AVR32.
mgl@1371
    61
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
    62
+
mgl@1371
    63
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
    64
+   Initial porting by Anders �dland.
mgl@1371
    65
+
mgl@1371
    66
+   This file is part of GCC.
mgl@1371
    67
+
mgl@1371
    68
+   This program is free software; you can redistribute it and/or modify
mgl@1371
    69
+   it under the terms of the GNU General Public License as published by
mgl@1371
    70
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
    71
+   (at your option) any later version.
mgl@1371
    72
+
mgl@1371
    73
+   This program is distributed in the hope that it will be useful,
mgl@1371
    74
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
    75
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
    76
+   GNU General Public License for more details.
mgl@1371
    77
+
mgl@1371
    78
+   You should have received a copy of the GNU General Public License
mgl@1371
    79
+   along with this program; if not, write to the Free Software
mgl@1371
    80
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
    81
+
mgl@1371
    82
+#include "config.h"
mgl@1371
    83
+#include "system.h"
mgl@1371
    84
+#include "coretypes.h"
mgl@1371
    85
+#include "tm.h"
mgl@1371
    86
+#include "rtl.h"
mgl@1371
    87
+#include "tree.h"
mgl@1371
    88
+#include "obstack.h"
mgl@1371
    89
+#include "regs.h"
mgl@1371
    90
+#include "hard-reg-set.h"
mgl@1371
    91
+#include "real.h"
mgl@1371
    92
+#include "insn-config.h"
mgl@1371
    93
+#include "conditions.h"
mgl@1371
    94
+#include "output.h"
mgl@1371
    95
+#include "insn-attr.h"
mgl@1371
    96
+#include "flags.h"
mgl@1371
    97
+#include "reload.h"
mgl@1371
    98
+#include "function.h"
mgl@1371
    99
+#include "expr.h"
mgl@1371
   100
+#include "optabs.h"
mgl@1371
   101
+#include "toplev.h"
mgl@1371
   102
+#include "recog.h"
mgl@1371
   103
+#include "ggc.h"
mgl@1371
   104
+#include "except.h"
mgl@1371
   105
+#include "c-pragma.h"
mgl@1371
   106
+#include "integrate.h"
mgl@1371
   107
+#include "tm_p.h"
mgl@1371
   108
+#include "langhooks.h"
mgl@1371
   109
+
mgl@1371
   110
+#include "target.h"
mgl@1371
   111
+#include "target-def.h"
mgl@1371
   112
+
mgl@1371
   113
+#include <ctype.h>
mgl@1371
   114
+
mgl@1371
   115
+/* Forward definitions of types.  */
mgl@1371
   116
+typedef struct minipool_node Mnode;
mgl@1371
   117
+typedef struct minipool_fixup Mfix;
mgl@1371
   118
+
mgl@1371
   119
+/* Obstack for minipool constant handling.  */
mgl@1371
   120
+static struct obstack minipool_obstack;
mgl@1371
   121
+static char *minipool_startobj;
mgl@1371
   122
+static rtx minipool_vector_label;
mgl@1371
   123
+
mgl@1371
   124
+/* True if we are currently building a constant table.  */
mgl@1371
   125
+int making_const_table;
mgl@1371
   126
+
mgl@1371
   127
+/* Some forward function declarations */
mgl@1371
   128
+static unsigned long avr32_isr_value (tree);
mgl@1371
   129
+static unsigned long avr32_compute_func_type (void);
mgl@1371
   130
+static tree avr32_handle_isr_attribute (tree *, tree, tree, int, bool *);
mgl@1371
   131
+static tree avr32_handle_acall_attribute (tree *, tree, tree, int, bool *);
mgl@1371
   132
+static tree avr32_handle_fndecl_attribute (tree * node, tree name, tree args,
mgl@1371
   133
+					   int flags, bool * no_add_attrs);
mgl@1371
   134
+static void avr32_reorg (void);
mgl@1371
   135
+bool avr32_return_in_msb (tree type);
mgl@1371
   136
+bool avr32_vector_mode_supported (enum machine_mode mode);
mgl@1371
   137
+static void avr32_init_libfuncs (void);
mgl@1371
   138
+
mgl@1371
   139
+
mgl@1371
   140
+static void
mgl@1371
   141
+avr32_add_gc_roots (void)
mgl@1371
   142
+{
mgl@1371
   143
+  gcc_obstack_init (&minipool_obstack);
mgl@1371
   144
+  minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
mgl@1371
   145
+}
mgl@1371
   146
+
mgl@1371
   147
+
mgl@1371
   148
+/* List of all known AVR32 parts  */
mgl@1371
   149
+static const struct part_type_s avr32_part_types[] = {
mgl@1371
   150
+  /* name, part_type, architecture type, macro */
mgl@1371
   151
+  {"none", PART_TYPE_AVR32_NONE, ARCH_TYPE_AVR32_AP, "__AVR32__"},
mgl@1371
   152
+  {"ap7000", PART_TYPE_AVR32_AP7000, ARCH_TYPE_AVR32_AP, "__AVR32_AP7000__"},
mgl@1371
   153
+  {"ap7001", PART_TYPE_AVR32_AP7001, ARCH_TYPE_AVR32_AP, "__AVR32_AP7001__"},
mgl@1371
   154
+  {"ap7002", PART_TYPE_AVR32_AP7002, ARCH_TYPE_AVR32_AP, "__AVR32_AP7002__"},
mgl@1371
   155
+  {"ap7200", PART_TYPE_AVR32_AP7200, ARCH_TYPE_AVR32_AP, "__AVR32_AP7200__"},
mgl@1371
   156
+  {"uc3a0128", PART_TYPE_AVR32_UC3A0128, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   157
+   "__AVR32_UC3A0128__"},
mgl@1371
   158
+  {"uc3a0256", PART_TYPE_AVR32_UC3A0256, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   159
+   "__AVR32_UC3A0256__"},
mgl@1371
   160
+  {"uc3a0512", PART_TYPE_AVR32_UC3A0512, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   161
+   "__AVR32_UC3A0512__"},
mgl@1371
   162
+  {"uc3a0512es", PART_TYPE_AVR32_UC3A0512ES, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   163
+    "__AVR32_UC3A0512ES__"},
mgl@1371
   164
+  {"uc3a1128", PART_TYPE_AVR32_UC3A1128, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   165
+   "__AVR32_UC3A1128__"},
mgl@1371
   166
+  {"uc3a1256", PART_TYPE_AVR32_UC3A1256, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   167
+   "__AVR32_UC3A1256__"},
mgl@1371
   168
+  {"uc3a1512", PART_TYPE_AVR32_UC3A1512, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   169
+   "__AVR32_UC3A1512__"},
mgl@1371
   170
+  {"uc3a1512es", PART_TYPE_AVR32_UC3A1512ES, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   171
+   "__AVR32_UC3A1512ES__"},
mgl@1371
   172
+   {"uc3a3revd", PART_TYPE_AVR32_UC3A3REVD, ARCH_TYPE_AVR32_UCR2NOMUL,
mgl@1371
   173
+    "__AVR32_UC3A3256S__"},
mgl@1371
   174
+  {"uc3a364", PART_TYPE_AVR32_UC3A364, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   175
+   "__AVR32_UC3A364__"},
mgl@1371
   176
+  {"uc3a364s", PART_TYPE_AVR32_UC3A364S, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   177
+   "__AVR32_UC3A364S__"},
mgl@1371
   178
+  {"uc3a3128", PART_TYPE_AVR32_UC3A3128, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   179
+   "__AVR32_UC3A3128__"},
mgl@1371
   180
+  {"uc3a3128s", PART_TYPE_AVR32_UC3A3128S, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   181
+   "__AVR32_UC3A3128S__"},
mgl@1371
   182
+  {"uc3a3256", PART_TYPE_AVR32_UC3A3256, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   183
+   "__AVR32_UC3A3256__"},
mgl@1371
   184
+  {"uc3a3256s", PART_TYPE_AVR32_UC3A3256S, ARCH_TYPE_AVR32_UCR2,
mgl@1371
   185
+   "__AVR32_UC3A3256S__"},
mgl@1371
   186
+  {"uc3b064", PART_TYPE_AVR32_UC3B064, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   187
+   "__AVR32_UC3B064__"},
mgl@1371
   188
+  {"uc3b0128", PART_TYPE_AVR32_UC3B0128, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   189
+   "__AVR32_UC3B0128__"},
mgl@1371
   190
+  {"uc3b0256", PART_TYPE_AVR32_UC3B0256, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   191
+   "__AVR32_UC3B0256__"},
mgl@1371
   192
+  {"uc3b0256es", PART_TYPE_AVR32_UC3B0256ES, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   193
+   "__AVR32_UC3B0256ES__"},
mgl@1371
   194
+  {"uc3b164", PART_TYPE_AVR32_UC3B164, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   195
+   "__AVR32_UC3B164__"},
mgl@1371
   196
+  {"uc3b1128", PART_TYPE_AVR32_UC3B1128, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   197
+   "__AVR32_UC3B1128__"},
mgl@1371
   198
+  {"uc3b1256", PART_TYPE_AVR32_UC3B1256, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   199
+   "__AVR32_UC3B1256__"},
mgl@1371
   200
+  {"uc3b1256es", PART_TYPE_AVR32_UC3B1256ES, ARCH_TYPE_AVR32_UCR1,
mgl@1371
   201
+   "__AVR32_UC3B1256ES__"},
mgl@1371
   202
+  {NULL, 0, 0, NULL}
mgl@1371
   203
+};
mgl@1371
   204
+
mgl@1371
   205
+/* List of all known AVR32 architectures  */
mgl@1371
   206
+static const struct arch_type_s avr32_arch_types[] = {
mgl@1371
   207
+  /* name, architecture type, microarchitecture type, feature flags, macro */
mgl@1371
   208
+  {"ap", ARCH_TYPE_AVR32_AP, UARCH_TYPE_AVR32B,
mgl@1371
   209
+   (FLAG_AVR32_HAS_DSP
mgl@1371
   210
+    | FLAG_AVR32_HAS_SIMD
mgl@1371
   211
+    | FLAG_AVR32_HAS_UNALIGNED_WORD
mgl@1371
   212
+    | FLAG_AVR32_HAS_BRANCH_PRED | FLAG_AVR32_HAS_RETURN_STACK
mgl@1371
   213
+    | FLAG_AVR32_HAS_CACHES),
mgl@1371
   214
+   "__AVR32_AP__"},
mgl@1371
   215
+  {"ucr1", ARCH_TYPE_AVR32_UCR1, UARCH_TYPE_AVR32A,
mgl@1371
   216
+   (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW),
mgl@1371
   217
+   "__AVR32_UC__=1"},
mgl@1371
   218
+  {"ucr2", ARCH_TYPE_AVR32_UCR2, UARCH_TYPE_AVR32A,
mgl@1371
   219
+   (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
mgl@1371
   220
+    | FLAG_AVR32_HAS_V2_INSNS),
mgl@1371
   221
+   "__AVR32_UC__=2"},
mgl@1371
   222
+  {"ucr2nomul", ARCH_TYPE_AVR32_UCR2NOMUL, UARCH_TYPE_AVR32A,
mgl@1371
   223
+   (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
mgl@1371
   224
+    | FLAG_AVR32_HAS_V2_INSNS | FLAG_AVR32_HAS_NO_MUL_INSNS),
mgl@1371
   225
+   "__AVR32_UC__=3"},
mgl@1371
   226
+  {NULL, 0, 0, 0, NULL}
mgl@1371
   227
+};
mgl@1371
   228
+
mgl@1371
   229
+/* Default arch name */
mgl@1371
   230
+const char *avr32_arch_name = "none";
mgl@1371
   231
+const char *avr32_part_name = "none";
mgl@1371
   232
+
mgl@1371
   233
+const struct part_type_s *avr32_part;
mgl@1371
   234
+const struct arch_type_s *avr32_arch;
mgl@1371
   235
+
mgl@1371
   236
+
mgl@1371
   237
+/* Set default target_flags. */
mgl@1371
   238
+#undef TARGET_DEFAULT_TARGET_FLAGS
mgl@1371
   239
+#define TARGET_DEFAULT_TARGET_FLAGS \
mgl@1371
   240
+  (MASK_HAS_ASM_ADDR_PSEUDOS | MASK_MD_REORG_OPTIMIZATION | MASK_COND_EXEC_BEFORE_RELOAD)
mgl@1371
   241
+
mgl@1371
   242
+void
mgl@1371
   243
+avr32_optimization_options (int level,
mgl@1371
   244
+                            int size){
mgl@1371
   245
+  if (AVR32_ALWAYS_PIC)
mgl@1371
   246
+    flag_pic = 1;
mgl@1371
   247
+
mgl@1371
   248
+  /* Enable section anchors if optimization is enabled. */
mgl@1371
   249
+  if (level > 0 || size)
mgl@1371
   250
+    flag_section_anchors = 1;
mgl@1371
   251
+}
mgl@1371
   252
+
mgl@1371
   253
+/* Override command line options */
mgl@1371
   254
+void
mgl@1371
   255
+avr32_override_options (void)
mgl@1371
   256
+{
mgl@1371
   257
+  const struct part_type_s *part;
mgl@1371
   258
+  const struct arch_type_s *arch;
mgl@1371
   259
+
mgl@1371
   260
+  /*Add backward compability*/
mgl@1371
   261
+  if (strcmp ("uc", avr32_arch_name)== 0)
mgl@1371
   262
+    {
mgl@1371
   263
+      fprintf (stderr, "Warning: Deprecated arch `%s' specified. "
mgl@1371
   264
+                       "Please use '-march=ucr1' instead. "
mgl@1371
   265
+                       "Converting to arch 'ucr1'\n",
mgl@1371
   266
+               avr32_arch_name);
mgl@1371
   267
+      avr32_arch_name="ucr1";
mgl@1371
   268
+    }
mgl@1371
   269
+
mgl@1371
   270
+  /* Check if arch type is set. */
mgl@1371
   271
+  for (arch = avr32_arch_types; arch->name; arch++)
mgl@1371
   272
+    {
mgl@1371
   273
+      if (strcmp (arch->name, avr32_arch_name) == 0)
mgl@1371
   274
+        break;
mgl@1371
   275
+    }
mgl@1371
   276
+  avr32_arch = arch;
mgl@1371
   277
+
mgl@1371
   278
+  if (!arch->name && strcmp("none", avr32_arch_name) != 0)
mgl@1371
   279
+    {
mgl@1371
   280
+      fprintf (stderr, "Unknown arch `%s' specified\n"
mgl@1371
   281
+                       "Known arch names:\n"
mgl@1371
   282
+                       "\tuc (deprecated)\n",
mgl@1371
   283
+               avr32_arch_name);
mgl@1371
   284
+      for (arch = avr32_arch_types; arch->name; arch++)
mgl@1371
   285
+        fprintf (stderr, "\t%s\n", arch->name);
mgl@1371
   286
+      avr32_arch = &avr32_arch_types[ARCH_TYPE_AVR32_AP];
mgl@1371
   287
+    }
mgl@1371
   288
+
mgl@1371
   289
+  /* Check if part type is set. */
mgl@1371
   290
+  for (part = avr32_part_types; part->name; part++)
mgl@1371
   291
+    if (strcmp (part->name, avr32_part_name) == 0)
mgl@1371
   292
+      break;
mgl@1371
   293
+
mgl@1371
   294
+  avr32_part = part;
mgl@1371
   295
+  if (!part->name)
mgl@1371
   296
+    {
mgl@1371
   297
+      fprintf (stderr, "Unknown part `%s' specified\nKnown part names:\n",
mgl@1371
   298
+               avr32_part_name);
mgl@1371
   299
+      for (part = avr32_part_types; part->name; part++)
mgl@1371
   300
+        {
mgl@1371
   301
+          if (strcmp("none", part->name) != 0)
mgl@1371
   302
+            fprintf (stderr, "\t%s\n", part->name);
mgl@1371
   303
+        }
mgl@1371
   304
+      /* Set default to NONE*/
mgl@1371
   305
+      avr32_part = &avr32_part_types[PART_TYPE_AVR32_NONE];
mgl@1371
   306
+    }
mgl@1371
   307
+
mgl@1371
   308
+  /* NB! option -march= overrides option -mpart
mgl@1371
   309
+   * if both are used at the same time */
mgl@1371
   310
+  if (!arch->name)
mgl@1371
   311
+    avr32_arch = &avr32_arch_types[avr32_part->arch_type];
mgl@1371
   312
+
mgl@1371
   313
+  /* If optimization level is two or greater, then align start of loops to a
mgl@1371
   314
+     word boundary since this will allow folding the first insn of the loop.
mgl@1371
   315
+     Do this only for targets supporting branch prediction. */
mgl@1371
   316
+  if (optimize >= 2 && TARGET_BRANCH_PRED)
mgl@1371
   317
+    align_loops = 2;
mgl@1371
   318
+
mgl@1371
   319
+
mgl@1371
   320
+  /* Enable fast-float library if unsafe math optimizations
mgl@1371
   321
+     are used. */
mgl@1371
   322
+  if (flag_unsafe_math_optimizations)
mgl@1371
   323
+    target_flags |= MASK_FAST_FLOAT;
mgl@1371
   324
+
mgl@1371
   325
+  /* Check if we should set avr32_imm_in_const_pool
mgl@1371
   326
+     based on if caches are present or not. */
mgl@1371
   327
+  if ( avr32_imm_in_const_pool == -1 )
mgl@1371
   328
+    {
mgl@1371
   329
+      if ( TARGET_CACHES )
mgl@1371
   330
+        avr32_imm_in_const_pool = 1;
mgl@1371
   331
+      else
mgl@1371
   332
+        avr32_imm_in_const_pool = 0;
mgl@1371
   333
+    }
mgl@1371
   334
+
mgl@1371
   335
+  if (TARGET_NO_PIC)
mgl@1371
   336
+    flag_pic = 0;
mgl@1371
   337
+
mgl@1371
   338
+  avr32_add_gc_roots ();
mgl@1371
   339
+}
mgl@1371
   340
+
mgl@1371
   341
+
mgl@1371
   342
+/*
mgl@1371
   343
+If defined, a function that outputs the assembler code for entry to a
mgl@1371
   344
+function.  The prologue is responsible for setting up the stack frame,
mgl@1371
   345
+initializing the frame pointer register, saving registers that must be
mgl@1371
   346
+saved, and allocating size additional bytes of storage for the
mgl@1371
   347
+local variables.  size is an integer.  file is a stdio
mgl@1371
   348
+stream to which the assembler code should be output.
mgl@1371
   349
+
mgl@1371
   350
+The label for the beginning of the function need not be output by this
mgl@1371
   351
+macro.  That has already been done when the macro is run.
mgl@1371
   352
+
mgl@1371
   353
+To determine which registers to save, the macro can refer to the array
mgl@1371
   354
+regs_ever_live: element r is nonzero if hard register
mgl@1371
   355
+r is used anywhere within the function.  This implies the function
mgl@1371
   356
+prologue should save register r, provided it is not one of the
mgl@1371
   357
+call-used registers.  (TARGET_ASM_FUNCTION_EPILOGUE must likewise use
mgl@1371
   358
+regs_ever_live.)
mgl@1371
   359
+
mgl@1371
   360
+On machines that have ``register windows'', the function entry code does
mgl@1371
   361
+not save on the stack the registers that are in the windows, even if
mgl@1371
   362
+they are supposed to be preserved by function calls; instead it takes
mgl@1371
   363
+appropriate steps to ``push'' the register stack, if any non-call-used
mgl@1371
   364
+registers are used in the function.
mgl@1371
   365
+
mgl@1371
   366
+On machines where functions may or may not have frame-pointers, the
mgl@1371
   367
+function entry code must vary accordingly; it must set up the frame
mgl@1371
   368
+pointer if one is wanted, and not otherwise.  To determine whether a
mgl@1371
   369
+frame pointer is in wanted, the macro can refer to the variable
mgl@1371
   370
+frame_pointer_needed.  The variable's value will be 1 at run
mgl@1371
   371
+time in a function that needs a frame pointer.  (see Elimination).
mgl@1371
   372
+
mgl@1371
   373
+The function entry code is responsible for allocating any stack space
mgl@1371
   374
+required for the function.  This stack space consists of the regions
mgl@1371
   375
+listed below.  In most cases, these regions are allocated in the
mgl@1371
   376
+order listed, with the last listed region closest to the top of the
mgl@1371
   377
+stack (the lowest address if STACK_GROWS_DOWNWARD is defined, and
mgl@1371
   378
+the highest address if it is not defined).  You can use a different order
mgl@1371
   379
+for a machine if doing so is more convenient or required for
mgl@1371
   380
+compatibility reasons.  Except in cases where required by standard
mgl@1371
   381
+or by a debugger, there is no reason why the stack layout used by GCC
mgl@1371
   382
+need agree with that used by other compilers for a machine.
mgl@1371
   383
+*/
mgl@1371
   384
+
mgl@1371
   385
+#undef TARGET_ASM_FUNCTION_PROLOGUE
mgl@1371
   386
+#define TARGET_ASM_FUNCTION_PROLOGUE avr32_target_asm_function_prologue
mgl@1371
   387
+
mgl@1371
   388
+
mgl@1371
   389
+#undef TARGET_DEFAULT_SHORT_ENUMS
mgl@1371
   390
+#define TARGET_DEFAULT_SHORT_ENUMS hook_bool_void_false
mgl@1371
   391
+
mgl@1371
   392
+#undef TARGET_PROMOTE_FUNCTION_ARGS
mgl@1371
   393
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
mgl@1371
   394
+
mgl@1371
   395
+#undef TARGET_PROMOTE_FUNCTION_RETURN
mgl@1371
   396
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
mgl@1371
   397
+
mgl@1371
   398
+#undef TARGET_PROMOTE_PROTOTYPES
mgl@1371
   399
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
mgl@1371
   400
+
mgl@1371
   401
+#undef TARGET_MUST_PASS_IN_STACK
mgl@1371
   402
+#define TARGET_MUST_PASS_IN_STACK avr32_must_pass_in_stack
mgl@1371
   403
+
mgl@1371
   404
+#undef TARGET_PASS_BY_REFERENCE
mgl@1371
   405
+#define TARGET_PASS_BY_REFERENCE avr32_pass_by_reference
mgl@1371
   406
+
mgl@1371
   407
+#undef TARGET_STRICT_ARGUMENT_NAMING
mgl@1371
   408
+#define TARGET_STRICT_ARGUMENT_NAMING avr32_strict_argument_naming
mgl@1371
   409
+
mgl@1371
   410
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
mgl@1371
   411
+#define TARGET_VECTOR_MODE_SUPPORTED_P avr32_vector_mode_supported
mgl@1371
   412
+
mgl@1371
   413
+#undef TARGET_RETURN_IN_MEMORY
mgl@1371
   414
+#define TARGET_RETURN_IN_MEMORY avr32_return_in_memory
mgl@1371
   415
+
mgl@1371
   416
+#undef TARGET_RETURN_IN_MSB
mgl@1371
   417
+#define TARGET_RETURN_IN_MSB avr32_return_in_msb
mgl@1371
   418
+
mgl@1371
   419
+#undef TARGET_ENCODE_SECTION_INFO
mgl@1371
   420
+#define TARGET_ENCODE_SECTION_INFO avr32_encode_section_info
mgl@1371
   421
+
mgl@1371
   422
+#undef TARGET_ARG_PARTIAL_BYTES
mgl@1371
   423
+#define TARGET_ARG_PARTIAL_BYTES avr32_arg_partial_bytes
mgl@1371
   424
+
mgl@1371
   425
+#undef TARGET_STRIP_NAME_ENCODING
mgl@1371
   426
+#define TARGET_STRIP_NAME_ENCODING avr32_strip_name_encoding
mgl@1371
   427
+
mgl@1371
   428
+#define streq(string1, string2) (strcmp (string1, string2) == 0)
mgl@1371
   429
+
mgl@1371
   430
+#undef  TARGET_NARROW_VOLATILE_BITFIELD
mgl@1371
   431
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
mgl@1371
   432
+
mgl@1371
   433
+#undef  TARGET_ATTRIBUTE_TABLE
mgl@1371
   434
+#define TARGET_ATTRIBUTE_TABLE avr32_attribute_table
mgl@1371
   435
+
mgl@1371
   436
+#undef  TARGET_COMP_TYPE_ATTRIBUTES
mgl@1371
   437
+#define TARGET_COMP_TYPE_ATTRIBUTES avr32_comp_type_attributes
mgl@1371
   438
+
mgl@1371
   439
+
mgl@1371
   440
+#undef  TARGET_RTX_COSTS
mgl@1371
   441
+#define TARGET_RTX_COSTS avr32_rtx_costs
mgl@1371
   442
+
mgl@1371
   443
+#undef  TARGET_CANNOT_FORCE_CONST_MEM
mgl@1371
   444
+#define  TARGET_CANNOT_FORCE_CONST_MEM avr32_cannot_force_const_mem
mgl@1371
   445
+
mgl@1371
   446
+#undef  TARGET_ASM_INTEGER
mgl@1371
   447
+#define TARGET_ASM_INTEGER avr32_assemble_integer
mgl@1371
   448
+
mgl@1371
   449
+#undef  TARGET_FUNCTION_VALUE
mgl@1371
   450
+#define TARGET_FUNCTION_VALUE avr32_function_value
mgl@1371
   451
+
mgl@1371
   452
+#undef  TARGET_MIN_ANCHOR_OFFSET
mgl@1371
   453
+#define TARGET_MIN_ANCHOR_OFFSET (0)
mgl@1371
   454
+
mgl@1371
   455
+#undef  TARGET_MAX_ANCHOR_OFFSET
mgl@1371
   456
+#define TARGET_MAX_ANCHOR_OFFSET ((1 << 15) - 1)
mgl@1371
   457
+
mgl@1371
   458
+#undef TARGET_SECONDARY_RELOAD
mgl@1371
   459
+#define TARGET_SECONDARY_RELOAD avr32_secondary_reload
mgl@1371
   460
+
mgl@1371
   461
+enum reg_class
mgl@1371
   462
+avr32_secondary_reload (bool in_p, rtx x, enum reg_class class ATTRIBUTE_UNUSED,
mgl@1371
   463
+                        enum machine_mode mode, secondary_reload_info *sri)
mgl@1371
   464
+{
mgl@1371
   465
+
mgl@1371
   466
+  if ( avr32_rmw_memory_operand (x, mode) )
mgl@1371
   467
+    {
mgl@1371
   468
+      if (!in_p)
mgl@1371
   469
+        sri->icode = CODE_FOR_reload_out_rmw_memory_operand;
mgl@1371
   470
+      else
mgl@1371
   471
+        sri->icode = CODE_FOR_reload_in_rmw_memory_operand;
mgl@1371
   472
+    }
mgl@1371
   473
+  return NO_REGS;
mgl@1371
   474
+
mgl@1371
   475
+}
mgl@1371
   476
+
mgl@1371
   477
+/*
mgl@1371
   478
+ * Switches to the appropriate section for output of constant pool
mgl@1371
   479
+ * entry x in mode. You can assume that x is some kind of constant in
mgl@1371
   480
+ * RTL. The argument mode is redundant except in the case of a
mgl@1371
   481
+ * const_int rtx. Select the section by calling readonly_data_ section
mgl@1371
   482
+ * or one of the alternatives for other sections. align is the
mgl@1371
   483
+ * constant alignment in bits.
mgl@1371
   484
+ *
mgl@1371
   485
+ * The default version of this function takes care of putting symbolic
mgl@1371
   486
+ * constants in flag_ pic mode in data_section and everything else in
mgl@1371
   487
+ * readonly_data_section.
mgl@1371
   488
+ */
mgl@1371
   489
+//#undef TARGET_ASM_SELECT_RTX_SECTION
mgl@1371
   490
+//#define TARGET_ASM_SELECT_RTX_SECTION avr32_select_rtx_section
mgl@1371
   491
+
mgl@1371
   492
+
mgl@1371
   493
+/*
mgl@1371
   494
+ * If non-null, this hook performs a target-specific pass over the
mgl@1371
   495
+ * instruction stream. The compiler will run it at all optimization
mgl@1371
   496
+ * levels, just before the point at which it normally does
mgl@1371
   497
+ * delayed-branch scheduling.
mgl@1371
   498
+ *
mgl@1371
   499
+ * The exact purpose of the hook varies from target to target. Some
mgl@1371
   500
+ * use it to do transformations that are necessary for correctness,
mgl@1371
   501
+ * such as laying out in-function constant pools or avoiding hardware
mgl@1371
   502
+ * hazards. Others use it as an opportunity to do some
mgl@1371
   503
+ * machine-dependent optimizations.
mgl@1371
   504
+ *
mgl@1371
   505
+ * You need not implement the hook if it has nothing to do. The
mgl@1371
   506
+ * default definition is null.
mgl@1371
   507
+ */
mgl@1371
   508
+#undef TARGET_MACHINE_DEPENDENT_REORG
mgl@1371
   509
+#define TARGET_MACHINE_DEPENDENT_REORG avr32_reorg
mgl@1371
   510
+
mgl@1371
   511
+/* Target hook for assembling integer objects.
mgl@1371
   512
+   Need to handle integer vectors */
mgl@1371
   513
+static bool
mgl@1371
   514
+avr32_assemble_integer (rtx x, unsigned int size, int aligned_p)
mgl@1371
   515
+{
mgl@1371
   516
+  if (avr32_vector_mode_supported (GET_MODE (x)))
mgl@1371
   517
+    {
mgl@1371
   518
+      int i, units;
mgl@1371
   519
+
mgl@1371
   520
+      if (GET_CODE (x) != CONST_VECTOR)
mgl@1371
   521
+	abort ();
mgl@1371
   522
+
mgl@1371
   523
+      units = CONST_VECTOR_NUNITS (x);
mgl@1371
   524
+
mgl@1371
   525
+      switch (GET_MODE (x))
mgl@1371
   526
+	{
mgl@1371
   527
+	case V2HImode:
mgl@1371
   528
+	  size = 2;
mgl@1371
   529
+	  break;
mgl@1371
   530
+	case V4QImode:
mgl@1371
   531
+	  size = 1;
mgl@1371
   532
+	  break;
mgl@1371
   533
+	default:
mgl@1371
   534
+	  abort ();
mgl@1371
   535
+	}
mgl@1371
   536
+
mgl@1371
   537
+      for (i = 0; i < units; i++)
mgl@1371
   538
+	{
mgl@1371
   539
+	  rtx elt;
mgl@1371
   540
+
mgl@1371
   541
+	  elt = CONST_VECTOR_ELT (x, i);
mgl@1371
   542
+	  assemble_integer (elt, size, i == 0 ? 32 : size * BITS_PER_UNIT, 1);
mgl@1371
   543
+	}
mgl@1371
   544
+
mgl@1371
   545
+      return true;
mgl@1371
   546
+    }
mgl@1371
   547
+
mgl@1371
   548
+  return default_assemble_integer (x, size, aligned_p);
mgl@1371
   549
+}
mgl@1371
   550
+
mgl@1371
   551
+/*
mgl@1371
   552
+ * This target hook describes the relative costs of RTL expressions.
mgl@1371
   553
+ *
mgl@1371
   554
+ * The cost may depend on the precise form of the expression, which is
mgl@1371
   555
+ * available for examination in x, and the rtx code of the expression
mgl@1371
   556
+ * in which it is contained, found in outer_code. code is the
mgl@1371
   557
+ * expression code--redundant, since it can be obtained with GET_CODE
mgl@1371
   558
+ * (x).
mgl@1371
   559
+ *
mgl@1371
   560
+ * In implementing this hook, you can use the construct COSTS_N_INSNS
mgl@1371
   561
+ * (n) to specify a cost equal to n fast instructions.
mgl@1371
   562
+ *
mgl@1371
   563
+ * On entry to the hook, *total contains a default estimate for the
mgl@1371
   564
+ * cost of the expression. The hook should modify this value as
mgl@1371
   565
+ * necessary. Traditionally, the default costs are COSTS_N_INSNS (5)
mgl@1371
   566
+ * for multiplications, COSTS_N_INSNS (7) for division and modulus
mgl@1371
   567
+ * operations, and COSTS_N_INSNS (1) for all other operations.
mgl@1371
   568
+ *
mgl@1371
   569
+ * When optimizing for code size, i.e. when optimize_size is non-zero,
mgl@1371
   570
+ * this target hook should be used to estimate the relative size cost
mgl@1371
   571
+ * of an expression, again relative to COSTS_N_INSNS.
mgl@1371
   572
+ *
mgl@1371
   573
+ * The hook returns true when all subexpressions of x have been
mgl@1371
   574
+ * processed, and false when rtx_cost should recurse.
mgl@1371
   575
+ */
mgl@1371
   576
+
mgl@1371
   577
+/* Worker routine for avr32_rtx_costs.  */
mgl@1371
   578
+static inline int
mgl@1371
   579
+avr32_rtx_costs_1 (rtx x, enum rtx_code code ATTRIBUTE_UNUSED,
mgl@1371
   580
+		   enum rtx_code outer ATTRIBUTE_UNUSED)
mgl@1371
   581
+{
mgl@1371
   582
+  enum machine_mode mode = GET_MODE (x);
mgl@1371
   583
+
mgl@1371
   584
+  switch (GET_CODE (x))
mgl@1371
   585
+    {
mgl@1371
   586
+    case MEM:
mgl@1371
   587
+      /* Using pre decrement / post increment memory operations on the
mgl@1371
   588
+         avr32_uc architecture means that two writebacks must be performed
mgl@1371
   589
+         and hence two cycles are needed. */
mgl@1371
   590
+      if (!optimize_size
mgl@1371
   591
+	  && GET_MODE_SIZE (mode) <= 2 * UNITS_PER_WORD
mgl@1371
   592
+	  && TARGET_ARCH_UC
mgl@1371
   593
+	  && (GET_CODE (XEXP (x, 0)) == PRE_DEC
mgl@1371
   594
+	      || GET_CODE (XEXP (x, 0)) == POST_INC))
mgl@1371
   595
+	return COSTS_N_INSNS (5);
mgl@1371
   596
+
mgl@1371
   597
+      /* Memory costs quite a lot for the first word, but subsequent words
mgl@1371
   598
+         load at the equivalent of a single insn each.  */
mgl@1371
   599
+      if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
mgl@1371
   600
+	return COSTS_N_INSNS (3 + (GET_MODE_SIZE (mode) / UNITS_PER_WORD));
mgl@1371
   601
+
mgl@1371
   602
+      return COSTS_N_INSNS (4);
mgl@1371
   603
+    case SYMBOL_REF:
mgl@1371
   604
+    case CONST:
mgl@1371
   605
+      /* These are valid for the pseudo insns: lda.w and call which operates
mgl@1371
   606
+         on direct addresses. We assume that the cost of a lda.w is the same
mgl@1371
   607
+         as the cost of a ld.w insn. */
mgl@1371
   608
+      return (outer == SET) ? COSTS_N_INSNS (4) : COSTS_N_INSNS (1);
mgl@1371
   609
+    case DIV:
mgl@1371
   610
+    case MOD:
mgl@1371
   611
+    case UDIV:
mgl@1371
   612
+    case UMOD:
mgl@1371
   613
+      return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
mgl@1371
   614
+
mgl@1371
   615
+    case ROTATE:
mgl@1371
   616
+    case ROTATERT:
mgl@1371
   617
+      if (mode == TImode)
mgl@1371
   618
+	return COSTS_N_INSNS (100);
mgl@1371
   619
+
mgl@1371
   620
+      if (mode == DImode)
mgl@1371
   621
+	return COSTS_N_INSNS (10);
mgl@1371
   622
+      return COSTS_N_INSNS (4);
mgl@1371
   623
+    case ASHIFT:
mgl@1371
   624
+    case LSHIFTRT:
mgl@1371
   625
+    case ASHIFTRT:
mgl@1371
   626
+    case NOT:
mgl@1371
   627
+      if (mode == TImode)
mgl@1371
   628
+	return COSTS_N_INSNS (10);
mgl@1371
   629
+
mgl@1371
   630
+      if (mode == DImode)
mgl@1371
   631
+	return COSTS_N_INSNS (4);
mgl@1371
   632
+      return COSTS_N_INSNS (1);
mgl@1371
   633
+    case PLUS:
mgl@1371
   634
+    case MINUS:
mgl@1371
   635
+    case NEG:
mgl@1371
   636
+    case COMPARE:
mgl@1371
   637
+    case ABS:
mgl@1371
   638
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
mgl@1371
   639
+	return COSTS_N_INSNS (100);
mgl@1371
   640
+
mgl@1371
   641
+      if (mode == TImode)
mgl@1371
   642
+	return COSTS_N_INSNS (50);
mgl@1371
   643
+
mgl@1371
   644
+      if (mode == DImode)
mgl@1371
   645
+	return COSTS_N_INSNS (2);
mgl@1371
   646
+      return COSTS_N_INSNS (1);
mgl@1371
   647
+
mgl@1371
   648
+    case MULT:
mgl@1371
   649
+      {
mgl@1371
   650
+	if (GET_MODE_CLASS (mode) == MODE_FLOAT)
mgl@1371
   651
+	  return COSTS_N_INSNS (300);
mgl@1371
   652
+
mgl@1371
   653
+	if (mode == TImode)
mgl@1371
   654
+	  return COSTS_N_INSNS (16);
mgl@1371
   655
+
mgl@1371
   656
+	if (mode == DImode)
mgl@1371
   657
+	  return COSTS_N_INSNS (4);
mgl@1371
   658
+
mgl@1371
   659
+	if (mode == HImode)
mgl@1371
   660
+	  return COSTS_N_INSNS (2);
mgl@1371
   661
+
mgl@1371
   662
+	return COSTS_N_INSNS (3);
mgl@1371
   663
+      }
mgl@1371
   664
+    case IF_THEN_ELSE:
mgl@1371
   665
+      if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
mgl@1371
   666
+	return COSTS_N_INSNS (4);
mgl@1371
   667
+      return COSTS_N_INSNS (1);
mgl@1371
   668
+    case SIGN_EXTEND:
mgl@1371
   669
+    case ZERO_EXTEND:
mgl@1371
   670
+      /* Sign/Zero extensions of registers cost quite much since these
mgl@1371
   671
+         instrcutions only take one register operand which means that gcc
mgl@1371
   672
+         often must insert some move instrcutions */
mgl@1371
   673
+      if (mode == QImode || mode == HImode)
mgl@1371
   674
+	return (COSTS_N_INSNS (GET_CODE (XEXP (x, 0)) == MEM ? 0 : 1));
mgl@1371
   675
+      return COSTS_N_INSNS (4);
mgl@1371
   676
+    case UNSPEC:
mgl@1371
   677
+      /* divmod operations */
mgl@1371
   678
+      if (XINT (x, 1) == UNSPEC_UDIVMODSI4_INTERNAL
mgl@1371
   679
+	  || XINT (x, 1) == UNSPEC_DIVMODSI4_INTERNAL)
mgl@1371
   680
+	{
mgl@1371
   681
+	  return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
mgl@1371
   682
+	}
mgl@1371
   683
+      /* Fallthrough */
mgl@1371
   684
+    default:
mgl@1371
   685
+      return COSTS_N_INSNS (1);
mgl@1371
   686
+    }
mgl@1371
   687
+}
mgl@1371
   688
+
mgl@1371
   689
+static bool
mgl@1371
   690
+avr32_rtx_costs (rtx x, int code, int outer_code, int *total)
mgl@1371
   691
+{
mgl@1371
   692
+  *total = avr32_rtx_costs_1 (x, code, outer_code);
mgl@1371
   693
+  return true;
mgl@1371
   694
+}
mgl@1371
   695
+
mgl@1371
   696
+
mgl@1371
   697
+bool
mgl@1371
   698
+avr32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
mgl@1371
   699
+{
mgl@1371
   700
+  /* Do not want symbols in the constant pool when compiling pic or if using
mgl@1371
   701
+     address pseudo instructions. */
mgl@1371
   702
+  return ((flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS)
mgl@1371
   703
+	  && avr32_find_symbol (x) != NULL_RTX);
mgl@1371
   704
+}
mgl@1371
   705
+
mgl@1371
   706
+
mgl@1371
   707
+/* Table of machine attributes.  */
mgl@1371
   708
+const struct attribute_spec avr32_attribute_table[] = {
mgl@1371
   709
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
mgl@1371
   710
+  /* Interrupt Service Routines have special prologue and epilogue
mgl@1371
   711
+     requirements.  */
mgl@1371
   712
+  {"isr", 0, 1, false, false, false, avr32_handle_isr_attribute},
mgl@1371
   713
+  {"interrupt", 0, 1, false, false, false, avr32_handle_isr_attribute},
mgl@1371
   714
+  {"acall", 0, 1, false, true, true, avr32_handle_acall_attribute},
mgl@1371
   715
+  {"naked", 0, 0, true, false, false, avr32_handle_fndecl_attribute},
mgl@1371
   716
+  {"rmw_addressable", 0, 0, true, false, false, NULL},
mgl@1371
   717
+  {NULL, 0, 0, false, false, false, NULL}
mgl@1371
   718
+};
mgl@1371
   719
+
mgl@1371
   720
+
mgl@1371
   721
+typedef struct
mgl@1371
   722
+{
mgl@1371
   723
+  const char *const arg;
mgl@1371
   724
+  const unsigned long return_value;
mgl@1371
   725
+}
mgl@1371
   726
+isr_attribute_arg;
mgl@1371
   727
+
mgl@1371
   728
+static const isr_attribute_arg isr_attribute_args[] = {
mgl@1371
   729
+  {"FULL", AVR32_FT_ISR_FULL},
mgl@1371
   730
+  {"full", AVR32_FT_ISR_FULL},
mgl@1371
   731
+  {"HALF", AVR32_FT_ISR_HALF},
mgl@1371
   732
+  {"half", AVR32_FT_ISR_HALF},
mgl@1371
   733
+  {"NONE", AVR32_FT_ISR_NONE},
mgl@1371
   734
+  {"none", AVR32_FT_ISR_NONE},
mgl@1371
   735
+  {"UNDEF", AVR32_FT_ISR_NONE},
mgl@1371
   736
+  {"undef", AVR32_FT_ISR_NONE},
mgl@1371
   737
+  {"SWI", AVR32_FT_ISR_NONE},
mgl@1371
   738
+  {"swi", AVR32_FT_ISR_NONE},
mgl@1371
   739
+  {NULL, AVR32_FT_ISR_NONE}
mgl@1371
   740
+};
mgl@1371
   741
+
mgl@1371
   742
+/* Returns the (interrupt) function type of the current
mgl@1371
   743
+   function, or AVR32_FT_UNKNOWN if the type cannot be determined.  */
mgl@1371
   744
+
mgl@1371
   745
+static unsigned long
mgl@1371
   746
+avr32_isr_value (tree argument)
mgl@1371
   747
+{
mgl@1371
   748
+  const isr_attribute_arg *ptr;
mgl@1371
   749
+  const char *arg;
mgl@1371
   750
+
mgl@1371
   751
+  /* No argument - default to ISR_NONE.  */
mgl@1371
   752
+  if (argument == NULL_TREE)
mgl@1371
   753
+    return AVR32_FT_ISR_NONE;
mgl@1371
   754
+
mgl@1371
   755
+  /* Get the value of the argument.  */
mgl@1371
   756
+  if (TREE_VALUE (argument) == NULL_TREE
mgl@1371
   757
+      || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
mgl@1371
   758
+    return AVR32_FT_UNKNOWN;
mgl@1371
   759
+
mgl@1371
   760
+  arg = TREE_STRING_POINTER (TREE_VALUE (argument));
mgl@1371
   761
+
mgl@1371
   762
+  /* Check it against the list of known arguments.  */
mgl@1371
   763
+  for (ptr = isr_attribute_args; ptr->arg != NULL; ptr++)
mgl@1371
   764
+    if (streq (arg, ptr->arg))
mgl@1371
   765
+      return ptr->return_value;
mgl@1371
   766
+
mgl@1371
   767
+  /* An unrecognized interrupt type.  */
mgl@1371
   768
+  return AVR32_FT_UNKNOWN;
mgl@1371
   769
+}
mgl@1371
   770
+
mgl@1371
   771
+
mgl@1371
   772
+
mgl@1371
   773
+/*
mgl@1371
   774
+These hooks specify assembly directives for creating certain kinds
mgl@1371
   775
+of integer object.  The TARGET_ASM_BYTE_OP directive creates a
mgl@1371
   776
+byte-sized object, the TARGET_ASM_ALIGNED_HI_OP one creates an
mgl@1371
   777
+aligned two-byte object, and so on.  Any of the hooks may be
mgl@1371
   778
+NULL, indicating that no suitable directive is available.
mgl@1371
   779
+
mgl@1371
   780
+The compiler will print these strings at the start of a new line,
mgl@1371
   781
+followed immediately by the object's initial value.  In most cases,
mgl@1371
   782
+the string should contain a tab, a pseudo-op, and then another tab.
mgl@1371
   783
+*/
mgl@1371
   784
+#undef  TARGET_ASM_BYTE_OP
mgl@1371
   785
+#define TARGET_ASM_BYTE_OP "\t.byte\t"
mgl@1371
   786
+#undef  TARGET_ASM_ALIGNED_HI_OP
mgl@1371
   787
+#define TARGET_ASM_ALIGNED_HI_OP "\t.align 1\n\t.short\t"
mgl@1371
   788
+#undef  TARGET_ASM_ALIGNED_SI_OP
mgl@1371
   789
+#define TARGET_ASM_ALIGNED_SI_OP "\t.align 2\n\t.int\t"
mgl@1371
   790
+#undef  TARGET_ASM_ALIGNED_DI_OP
mgl@1371
   791
+#define TARGET_ASM_ALIGNED_DI_OP NULL
mgl@1371
   792
+#undef  TARGET_ASM_ALIGNED_TI_OP
mgl@1371
   793
+#define TARGET_ASM_ALIGNED_TI_OP NULL
mgl@1371
   794
+#undef  TARGET_ASM_UNALIGNED_HI_OP
mgl@1371
   795
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
mgl@1371
   796
+#undef  TARGET_ASM_UNALIGNED_SI_OP
mgl@1371
   797
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.int\t"
mgl@1371
   798
+#undef  TARGET_ASM_UNALIGNED_DI_OP
mgl@1371
   799
+#define TARGET_ASM_UNALIGNED_DI_OP NULL
mgl@1371
   800
+#undef  TARGET_ASM_UNALIGNED_TI_OP
mgl@1371
   801
+#define TARGET_ASM_UNALIGNED_TI_OP NULL
mgl@1371
   802
+
mgl@1371
   803
+#undef TARGET_ASM_OUTPUT_MI_THUNK
mgl@1371
   804
+#define TARGET_ASM_OUTPUT_MI_THUNK avr32_output_mi_thunk
mgl@1371
   805
+
mgl@1371
   806
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
mgl@1371
   807
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
mgl@1371
   808
+
mgl@1371
   809
+static void
mgl@1371
   810
+avr32_output_mi_thunk (FILE * file,
mgl@1371
   811
+    tree thunk ATTRIBUTE_UNUSED,
mgl@1371
   812
+    HOST_WIDE_INT delta,
mgl@1371
   813
+    HOST_WIDE_INT vcall_offset, tree function)
mgl@1371
   814
+  {
mgl@1371
   815
+    int mi_delta = delta;
mgl@1371
   816
+    int this_regno =
mgl@1371
   817
+      (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ?
mgl@1371
   818
+       INTERNAL_REGNUM (11) : INTERNAL_REGNUM (12));
mgl@1371
   819
+
mgl@1371
   820
+
mgl@1371
   821
+    if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21")
mgl@1371
   822
+        || vcall_offset)
mgl@1371
   823
+      {
mgl@1371
   824
+        fputs ("\tpushm\tlr\n", file);
mgl@1371
   825
+      }
mgl@1371
   826
+
mgl@1371
   827
+
mgl@1371
   828
+    if (mi_delta != 0)
mgl@1371
   829
+      {
mgl@1371
   830
+        if (avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21"))
mgl@1371
   831
+          {
mgl@1371
   832
+            fprintf (file, "\tsub\t%s, %d\n", reg_names[this_regno], -mi_delta);
mgl@1371
   833
+          }
mgl@1371
   834
+        else
mgl@1371
   835
+          {
mgl@1371
   836
+            /* Immediate is larger than k21 we must make us a temp register by
mgl@1371
   837
+	     pushing a register to the stack. */
mgl@1371
   838
+            fprintf (file, "\tmov\tlr, lo(%d)\n", mi_delta);
mgl@1371
   839
+            fprintf (file, "\torh\tlr, hi(%d)\n", mi_delta);
mgl@1371
   840
+            fprintf (file, "\tadd\t%s, lr\n", reg_names[this_regno]);
mgl@1371
   841
+          }
mgl@1371
   842
+      }
mgl@1371
   843
+
mgl@1371
   844
+
mgl@1371
   845
+    if (vcall_offset != 0)
mgl@1371
   846
+      {
mgl@1371
   847
+        fprintf (file, "\tld.w\tlr, %s[0]\n", reg_names[this_regno]);
mgl@1371
   848
+        fprintf (file, "\tld.w\tlr, lr[%i]\n", (int) vcall_offset);
mgl@1371
   849
+        fprintf (file, "\tadd\t%s, lr\n", reg_names[this_regno]);
mgl@1371
   850
+      }
mgl@1371
   851
+
mgl@1371
   852
+
mgl@1371
   853
+    if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21")
mgl@1371
   854
+        || vcall_offset)
mgl@1371
   855
+      {
mgl@1371
   856
+        fputs ("\tpopm\tlr\n", file);
mgl@1371
   857
+      }
mgl@1371
   858
+
mgl@1371
   859
+    /* Jump to the function. We assume that we can use an rjmp since the
mgl@1371
   860
+       function to jump to is local and probably not too far away from
mgl@1371
   861
+       the thunk. If this assumption proves to be wrong we could implement
mgl@1371
   862
+       this jump by calculating the offset between the jump source and destination
mgl@1371
   863
+       and put this in the constant pool and then perform an add to pc.
mgl@1371
   864
+       This would also be legitimate PIC code. But for now we hope that an rjmp
mgl@1371
   865
+       will be sufficient...
mgl@1371
   866
+    */
mgl@1371
   867
+    fputs ("\trjmp\t", file);
mgl@1371
   868
+    assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
mgl@1371
   869
+    fputc ('\n', file);
mgl@1371
   870
+  }
mgl@1371
   871
+
mgl@1371
   872
+
mgl@1371
   873
+/* Implements target hook vector_mode_supported.  */
mgl@1371
   874
+bool
mgl@1371
   875
+avr32_vector_mode_supported (enum machine_mode mode)
mgl@1371
   876
+{
mgl@1371
   877
+  if ((mode == V2HImode) || (mode == V4QImode))
mgl@1371
   878
+    return true;
mgl@1371
   879
+
mgl@1371
   880
+  return false;
mgl@1371
   881
+}
mgl@1371
   882
+
mgl@1371
   883
+
mgl@1371
   884
+#undef TARGET_INIT_LIBFUNCS
mgl@1371
   885
+#define TARGET_INIT_LIBFUNCS avr32_init_libfuncs
mgl@1371
   886
+
mgl@1371
   887
+#undef  TARGET_INIT_BUILTINS
mgl@1371
   888
+#define TARGET_INIT_BUILTINS avr32_init_builtins
mgl@1371
   889
+
mgl@1371
   890
+#undef  TARGET_EXPAND_BUILTIN
mgl@1371
   891
+#define TARGET_EXPAND_BUILTIN avr32_expand_builtin
mgl@1371
   892
+
mgl@1371
   893
+tree int_ftype_int, int_ftype_void, short_ftype_short, void_ftype_int_int,
mgl@1371
   894
+  void_ftype_ptr_int;
mgl@1371
   895
+tree void_ftype_int, void_ftype_void, int_ftype_ptr_int;
mgl@1371
   896
+tree short_ftype_short, int_ftype_int_short, int_ftype_short_short,
mgl@1371
   897
+  short_ftype_short_short;
mgl@1371
   898
+tree int_ftype_int_int, longlong_ftype_int_short, longlong_ftype_short_short;
mgl@1371
   899
+tree void_ftype_int_int_int_int_int, void_ftype_int_int_int;
mgl@1371
   900
+tree longlong_ftype_int_int, void_ftype_int_int_longlong;
mgl@1371
   901
+tree int_ftype_int_int_int, longlong_ftype_longlong_int_short;
mgl@1371
   902
+tree longlong_ftype_longlong_short_short, int_ftype_int_short_short;
mgl@1371
   903
+
mgl@1371
   904
+#define def_builtin(NAME, TYPE, CODE)					\
mgl@1371
   905
+  lang_hooks.builtin_function ((NAME), (TYPE), (CODE),			\
mgl@1371
   906
+		  	       BUILT_IN_MD, NULL, NULL_TREE)
mgl@1371
   907
+
mgl@1371
   908
+#define def_mbuiltin(MASK, NAME, TYPE, CODE)				\
mgl@1371
   909
+  do									\
mgl@1371
   910
+    {									\
mgl@1371
   911
+      if ((MASK))							\
mgl@1371
   912
+	lang_hooks.builtin_function ((NAME), (TYPE), (CODE),		\
mgl@1371
   913
+				     BUILT_IN_MD, NULL, NULL_TREE);	\
mgl@1371
   914
+    }									\
mgl@1371
   915
+  while (0)
mgl@1371
   916
+
mgl@1371
   917
+struct builtin_description
mgl@1371
   918
+{
mgl@1371
   919
+  const unsigned int mask;
mgl@1371
   920
+  const enum insn_code icode;
mgl@1371
   921
+  const char *const name;
mgl@1371
   922
+  const int code;
mgl@1371
   923
+  const enum rtx_code comparison;
mgl@1371
   924
+  const unsigned int flag;
mgl@1371
   925
+  const tree *ftype;
mgl@1371
   926
+};
mgl@1371
   927
+
mgl@1371
   928
+static const struct builtin_description bdesc_2arg[] = {
mgl@1371
   929
+#define DSP_BUILTIN(code, builtin, ftype) \
mgl@1371
   930
+  { 1, CODE_FOR_##code, "__builtin_" #code , \
mgl@1371
   931
+    AVR32_BUILTIN_##builtin, 0, 0, ftype }
mgl@1371
   932
+
mgl@1371
   933
+  DSP_BUILTIN (mulsathh_h, MULSATHH_H, &short_ftype_short_short),
mgl@1371
   934
+  DSP_BUILTIN (mulsathh_w, MULSATHH_W, &int_ftype_short_short),
mgl@1371
   935
+  DSP_BUILTIN (mulsatrndhh_h, MULSATRNDHH_H, &short_ftype_short_short),
mgl@1371
   936
+  DSP_BUILTIN (mulsatrndwh_w, MULSATRNDWH_W, &int_ftype_int_short),
mgl@1371
   937
+  DSP_BUILTIN (mulsatwh_w, MULSATWH_W, &int_ftype_int_short),
mgl@1371
   938
+  DSP_BUILTIN (satadd_h, SATADD_H, &short_ftype_short_short),
mgl@1371
   939
+  DSP_BUILTIN (satsub_h, SATSUB_H, &short_ftype_short_short),
mgl@1371
   940
+  DSP_BUILTIN (satadd_w, SATADD_W, &int_ftype_int_int),
mgl@1371
   941
+  DSP_BUILTIN (satsub_w, SATSUB_W, &int_ftype_int_int),
mgl@1371
   942
+  DSP_BUILTIN (mulwh_d, MULWH_D, &longlong_ftype_int_short),
mgl@1371
   943
+  DSP_BUILTIN (mulnwh_d, MULNWH_D, &longlong_ftype_int_short)
mgl@1371
   944
+};
mgl@1371
   945
+
mgl@1371
   946
+
mgl@1371
   947
+void
mgl@1371
   948
+avr32_init_builtins (void)
mgl@1371
   949
+{
mgl@1371
   950
+  unsigned int i;
mgl@1371
   951
+  const struct builtin_description *d;
mgl@1371
   952
+  tree endlink = void_list_node;
mgl@1371
   953
+  tree int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
mgl@1371
   954
+  tree longlong_endlink =
mgl@1371
   955
+    tree_cons (NULL_TREE, long_long_integer_type_node, endlink);
mgl@1371
   956
+  tree short_endlink =
mgl@1371
   957
+    tree_cons (NULL_TREE, short_integer_type_node, endlink);
mgl@1371
   958
+  tree void_endlink = tree_cons (NULL_TREE, void_type_node, endlink);
mgl@1371
   959
+
mgl@1371
   960
+  /* int func (int) */
mgl@1371
   961
+  int_ftype_int = build_function_type (integer_type_node, int_endlink);
mgl@1371
   962
+
mgl@1371
   963
+  /* short func (short) */
mgl@1371
   964
+  short_ftype_short
mgl@1371
   965
+    = build_function_type (short_integer_type_node, short_endlink);
mgl@1371
   966
+
mgl@1371
   967
+  /* short func (short, short) */
mgl@1371
   968
+  short_ftype_short_short
mgl@1371
   969
+    = build_function_type (short_integer_type_node,
mgl@1371
   970
+			   tree_cons (NULL_TREE, short_integer_type_node,
mgl@1371
   971
+				      short_endlink));
mgl@1371
   972
+
mgl@1371
   973
+  /* long long func (long long, short, short) */
mgl@1371
   974
+  longlong_ftype_longlong_short_short
mgl@1371
   975
+    = build_function_type (long_long_integer_type_node,
mgl@1371
   976
+			   tree_cons (NULL_TREE, long_long_integer_type_node,
mgl@1371
   977
+				      tree_cons (NULL_TREE,
mgl@1371
   978
+						 short_integer_type_node,
mgl@1371
   979
+						 short_endlink)));
mgl@1371
   980
+
mgl@1371
   981
+  /* long long func (short, short) */
mgl@1371
   982
+  longlong_ftype_short_short
mgl@1371
   983
+    = build_function_type (long_long_integer_type_node,
mgl@1371
   984
+			   tree_cons (NULL_TREE, short_integer_type_node,
mgl@1371
   985
+				      short_endlink));
mgl@1371
   986
+
mgl@1371
   987
+  /* int func (int, int) */
mgl@1371
   988
+  int_ftype_int_int
mgl@1371
   989
+    = build_function_type (integer_type_node,
mgl@1371
   990
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
   991
+				      int_endlink));
mgl@1371
   992
+
mgl@1371
   993
+  /* long long func (int, int) */
mgl@1371
   994
+  longlong_ftype_int_int
mgl@1371
   995
+    = build_function_type (long_long_integer_type_node,
mgl@1371
   996
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
   997
+				      int_endlink));
mgl@1371
   998
+
mgl@1371
   999
+  /* long long int func (long long, int, short) */
mgl@1371
  1000
+  longlong_ftype_longlong_int_short
mgl@1371
  1001
+    = build_function_type (long_long_integer_type_node,
mgl@1371
  1002
+			   tree_cons (NULL_TREE, long_long_integer_type_node,
mgl@1371
  1003
+				      tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1004
+						 short_endlink)));
mgl@1371
  1005
+
mgl@1371
  1006
+  /* long long int func (int, short) */
mgl@1371
  1007
+  longlong_ftype_int_short
mgl@1371
  1008
+    = build_function_type (long_long_integer_type_node,
mgl@1371
  1009
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1010
+				      short_endlink));
mgl@1371
  1011
+
mgl@1371
  1012
+  /* int func (int, short, short) */
mgl@1371
  1013
+  int_ftype_int_short_short
mgl@1371
  1014
+    = build_function_type (integer_type_node,
mgl@1371
  1015
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1016
+				      tree_cons (NULL_TREE,
mgl@1371
  1017
+						 short_integer_type_node,
mgl@1371
  1018
+						 short_endlink)));
mgl@1371
  1019
+
mgl@1371
  1020
+  /* int func (short, short) */
mgl@1371
  1021
+  int_ftype_short_short
mgl@1371
  1022
+    = build_function_type (integer_type_node,
mgl@1371
  1023
+			   tree_cons (NULL_TREE, short_integer_type_node,
mgl@1371
  1024
+				      short_endlink));
mgl@1371
  1025
+
mgl@1371
  1026
+  /* int func (int, short) */
mgl@1371
  1027
+  int_ftype_int_short
mgl@1371
  1028
+    = build_function_type (integer_type_node,
mgl@1371
  1029
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1030
+				      short_endlink));
mgl@1371
  1031
+
mgl@1371
  1032
+  /* void func (int, int) */
mgl@1371
  1033
+  void_ftype_int_int
mgl@1371
  1034
+    = build_function_type (void_type_node,
mgl@1371
  1035
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1036
+				      int_endlink));
mgl@1371
  1037
+
mgl@1371
  1038
+  /* void func (int, int, int) */
mgl@1371
  1039
+  void_ftype_int_int_int
mgl@1371
  1040
+    = build_function_type (void_type_node,
mgl@1371
  1041
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1042
+				      tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1043
+						 int_endlink)));
mgl@1371
  1044
+
mgl@1371
  1045
+  /* void func (int, int, long long) */
mgl@1371
  1046
+  void_ftype_int_int_longlong
mgl@1371
  1047
+    = build_function_type (void_type_node,
mgl@1371
  1048
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1049
+				      tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1050
+						 longlong_endlink)));
mgl@1371
  1051
+
mgl@1371
  1052
+  /* void func (int, int, int, int, int) */
mgl@1371
  1053
+  void_ftype_int_int_int_int_int
mgl@1371
  1054
+    = build_function_type (void_type_node,
mgl@1371
  1055
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1056
+				      tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1057
+						 tree_cons (NULL_TREE,
mgl@1371
  1058
+							    integer_type_node,
mgl@1371
  1059
+							    tree_cons
mgl@1371
  1060
+							    (NULL_TREE,
mgl@1371
  1061
+							     integer_type_node,
mgl@1371
  1062
+							     int_endlink)))));
mgl@1371
  1063
+
mgl@1371
  1064
+  /* void func (void *, int) */
mgl@1371
  1065
+  void_ftype_ptr_int
mgl@1371
  1066
+    = build_function_type (void_type_node,
mgl@1371
  1067
+			   tree_cons (NULL_TREE, ptr_type_node, int_endlink));
mgl@1371
  1068
+
mgl@1371
  1069
+  /* void func (int) */
mgl@1371
  1070
+  void_ftype_int = build_function_type (void_type_node, int_endlink);
mgl@1371
  1071
+
mgl@1371
  1072
+  /* void func (void) */
mgl@1371
  1073
+  void_ftype_void = build_function_type (void_type_node, void_endlink);
mgl@1371
  1074
+
mgl@1371
  1075
+  /* int func (void) */
mgl@1371
  1076
+  int_ftype_void = build_function_type (integer_type_node, void_endlink);
mgl@1371
  1077
+
mgl@1371
  1078
+  /* int func (void *, int) */
mgl@1371
  1079
+  int_ftype_ptr_int
mgl@1371
  1080
+    = build_function_type (integer_type_node,
mgl@1371
  1081
+			   tree_cons (NULL_TREE, ptr_type_node, int_endlink));
mgl@1371
  1082
+
mgl@1371
  1083
+  /* int func (int, int, int) */
mgl@1371
  1084
+  int_ftype_int_int_int
mgl@1371
  1085
+    = build_function_type (integer_type_node,
mgl@1371
  1086
+			   tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1087
+				      tree_cons (NULL_TREE, integer_type_node,
mgl@1371
  1088
+						 int_endlink)));
mgl@1371
  1089
+
mgl@1371
  1090
+  /* Initialize avr32 builtins.  */
mgl@1371
  1091
+  def_builtin ("__builtin_mfsr", int_ftype_int, AVR32_BUILTIN_MFSR);
mgl@1371
  1092
+  def_builtin ("__builtin_mtsr", void_ftype_int_int, AVR32_BUILTIN_MTSR);
mgl@1371
  1093
+  def_builtin ("__builtin_mfdr", int_ftype_int, AVR32_BUILTIN_MFDR);
mgl@1371
  1094
+  def_builtin ("__builtin_mtdr", void_ftype_int_int, AVR32_BUILTIN_MTDR);
mgl@1371
  1095
+  def_builtin ("__builtin_cache", void_ftype_ptr_int, AVR32_BUILTIN_CACHE);
mgl@1371
  1096
+  def_builtin ("__builtin_sync", void_ftype_int, AVR32_BUILTIN_SYNC);
mgl@1371
  1097
+  def_builtin ("__builtin_ssrf", void_ftype_int, AVR32_BUILTIN_SSRF);
mgl@1371
  1098
+  def_builtin ("__builtin_csrf", void_ftype_int, AVR32_BUILTIN_CSRF);
mgl@1371
  1099
+  def_builtin ("__builtin_tlbr", void_ftype_void, AVR32_BUILTIN_TLBR);
mgl@1371
  1100
+  def_builtin ("__builtin_tlbs", void_ftype_void, AVR32_BUILTIN_TLBS);
mgl@1371
  1101
+  def_builtin ("__builtin_tlbw", void_ftype_void, AVR32_BUILTIN_TLBW);
mgl@1371
  1102
+  def_builtin ("__builtin_breakpoint", void_ftype_void,
mgl@1371
  1103
+	       AVR32_BUILTIN_BREAKPOINT);
mgl@1371
  1104
+  def_builtin ("__builtin_xchg", int_ftype_ptr_int, AVR32_BUILTIN_XCHG);
mgl@1371
  1105
+  def_builtin ("__builtin_ldxi", int_ftype_ptr_int, AVR32_BUILTIN_LDXI);
mgl@1371
  1106
+  def_builtin ("__builtin_bswap_16", short_ftype_short,
mgl@1371
  1107
+	       AVR32_BUILTIN_BSWAP16);
mgl@1371
  1108
+  def_builtin ("__builtin_bswap_32", int_ftype_int, AVR32_BUILTIN_BSWAP32);
mgl@1371
  1109
+  def_builtin ("__builtin_cop", void_ftype_int_int_int_int_int,
mgl@1371
  1110
+	       AVR32_BUILTIN_COP);
mgl@1371
  1111
+  def_builtin ("__builtin_mvcr_w", int_ftype_int_int, AVR32_BUILTIN_MVCR_W);
mgl@1371
  1112
+  def_builtin ("__builtin_mvrc_w", void_ftype_int_int_int,
mgl@1371
  1113
+	       AVR32_BUILTIN_MVRC_W);
mgl@1371
  1114
+  def_builtin ("__builtin_mvcr_d", longlong_ftype_int_int,
mgl@1371
  1115
+	       AVR32_BUILTIN_MVCR_D);
mgl@1371
  1116
+  def_builtin ("__builtin_mvrc_d", void_ftype_int_int_longlong,
mgl@1371
  1117
+	       AVR32_BUILTIN_MVRC_D);
mgl@1371
  1118
+  def_builtin ("__builtin_sats", int_ftype_int_int_int, AVR32_BUILTIN_SATS);
mgl@1371
  1119
+  def_builtin ("__builtin_satu", int_ftype_int_int_int, AVR32_BUILTIN_SATU);
mgl@1371
  1120
+  def_builtin ("__builtin_satrnds", int_ftype_int_int_int,
mgl@1371
  1121
+	       AVR32_BUILTIN_SATRNDS);
mgl@1371
  1122
+  def_builtin ("__builtin_satrndu", int_ftype_int_int_int,
mgl@1371
  1123
+	       AVR32_BUILTIN_SATRNDU);
mgl@1371
  1124
+  def_builtin ("__builtin_musfr", void_ftype_int, AVR32_BUILTIN_MUSFR);
mgl@1371
  1125
+  def_builtin ("__builtin_mustr", int_ftype_void, AVR32_BUILTIN_MUSTR);
mgl@1371
  1126
+  def_builtin ("__builtin_macsathh_w", int_ftype_int_short_short,
mgl@1371
  1127
+	       AVR32_BUILTIN_MACSATHH_W);
mgl@1371
  1128
+  def_builtin ("__builtin_macwh_d", longlong_ftype_longlong_int_short,
mgl@1371
  1129
+	       AVR32_BUILTIN_MACWH_D);
mgl@1371
  1130
+  def_builtin ("__builtin_machh_d", longlong_ftype_longlong_short_short,
mgl@1371
  1131
+	       AVR32_BUILTIN_MACHH_D);
mgl@1371
  1132
+  def_builtin ("__builtin_mems", void_ftype_ptr_int, AVR32_BUILTIN_MEMS);
mgl@1371
  1133
+  def_builtin ("__builtin_memt", void_ftype_ptr_int, AVR32_BUILTIN_MEMT);
mgl@1371
  1134
+  def_builtin ("__builtin_memc", void_ftype_ptr_int, AVR32_BUILTIN_MEMC);
mgl@1371
  1135
+
mgl@1371
  1136
+  /* Add all builtins that are more or less simple operations on two
mgl@1371
  1137
+     operands.  */
mgl@1371
  1138
+  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
mgl@1371
  1139
+    {
mgl@1371
  1140
+      /* Use one of the operands; the target can have a different mode for
mgl@1371
  1141
+         mask-generating compares.  */
mgl@1371
  1142
+
mgl@1371
  1143
+      if (d->name == 0)
mgl@1371
  1144
+	continue;
mgl@1371
  1145
+
mgl@1371
  1146
+      def_mbuiltin (d->mask, d->name, *(d->ftype), d->code);
mgl@1371
  1147
+    }
mgl@1371
  1148
+}
mgl@1371
  1149
+
mgl@1371
  1150
+
mgl@1371
  1151
+/* Subroutine of avr32_expand_builtin to take care of binop insns.  */
mgl@1371
  1152
+
mgl@1371
  1153
+static rtx
mgl@1371
  1154
+avr32_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
mgl@1371
  1155
+{
mgl@1371
  1156
+  rtx pat;
mgl@1371
  1157
+  tree arg0 = TREE_VALUE (arglist);
mgl@1371
  1158
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1159
+  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1160
+  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1161
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1162
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1163
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
mgl@1371
  1164
+
mgl@1371
  1165
+  if (!target
mgl@1371
  1166
+      || GET_MODE (target) != tmode
mgl@1371
  1167
+      || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1168
+    target = gen_reg_rtx (tmode);
mgl@1371
  1169
+
mgl@1371
  1170
+  /* In case the insn wants input operands in modes different from the
mgl@1371
  1171
+     result, abort.  */
mgl@1371
  1172
+  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1173
+    {
mgl@1371
  1174
+      /* If op0 is already a reg we must cast it to the correct mode. */
mgl@1371
  1175
+      if (REG_P (op0))
mgl@1371
  1176
+	op0 = convert_to_mode (mode0, op0, 1);
mgl@1371
  1177
+      else
mgl@1371
  1178
+	op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1179
+    }
mgl@1371
  1180
+  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
mgl@1371
  1181
+    {
mgl@1371
  1182
+      /* If op1 is already a reg we must cast it to the correct mode. */
mgl@1371
  1183
+      if (REG_P (op1))
mgl@1371
  1184
+	op1 = convert_to_mode (mode1, op1, 1);
mgl@1371
  1185
+      else
mgl@1371
  1186
+	op1 = copy_to_mode_reg (mode1, op1);
mgl@1371
  1187
+    }
mgl@1371
  1188
+  pat = GEN_FCN (icode) (target, op0, op1);
mgl@1371
  1189
+  if (!pat)
mgl@1371
  1190
+    return 0;
mgl@1371
  1191
+  emit_insn (pat);
mgl@1371
  1192
+  return target;
mgl@1371
  1193
+}
mgl@1371
  1194
+
mgl@1371
  1195
+/* Expand an expression EXP that calls a built-in function,
mgl@1371
  1196
+   with result going to TARGET if that's convenient
mgl@1371
  1197
+   (and in mode MODE if that's convenient).
mgl@1371
  1198
+   SUBTARGET may be used as the target for computing one of EXP's operands.
mgl@1371
  1199
+   IGNORE is nonzero if the value is to be ignored.  */
mgl@1371
  1200
+
mgl@1371
  1201
+rtx
mgl@1371
  1202
+avr32_expand_builtin (tree exp,
mgl@1371
  1203
+		      rtx target,
mgl@1371
  1204
+		      rtx subtarget ATTRIBUTE_UNUSED,
mgl@1371
  1205
+		      enum machine_mode mode ATTRIBUTE_UNUSED,
mgl@1371
  1206
+		      int ignore ATTRIBUTE_UNUSED)
mgl@1371
  1207
+{
mgl@1371
  1208
+  const struct builtin_description *d;
mgl@1371
  1209
+  unsigned int i;
mgl@1371
  1210
+  enum insn_code icode = 0;
mgl@1371
  1211
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
mgl@1371
  1212
+  tree arglist = TREE_OPERAND (exp, 1);
mgl@1371
  1213
+  tree arg0, arg1, arg2;
mgl@1371
  1214
+  rtx op0, op1, op2, pat;
mgl@1371
  1215
+  enum machine_mode tmode, mode0, mode1;
mgl@1371
  1216
+  enum machine_mode arg0_mode;
mgl@1371
  1217
+  int fcode = DECL_FUNCTION_CODE (fndecl);
mgl@1371
  1218
+
mgl@1371
  1219
+  switch (fcode)
mgl@1371
  1220
+    {
mgl@1371
  1221
+    default:
mgl@1371
  1222
+      break;
mgl@1371
  1223
+
mgl@1371
  1224
+    case AVR32_BUILTIN_SATS:
mgl@1371
  1225
+    case AVR32_BUILTIN_SATU:
mgl@1371
  1226
+    case AVR32_BUILTIN_SATRNDS:
mgl@1371
  1227
+    case AVR32_BUILTIN_SATRNDU:
mgl@1371
  1228
+      {
mgl@1371
  1229
+	const char *fname;
mgl@1371
  1230
+	switch (fcode)
mgl@1371
  1231
+	  {
mgl@1371
  1232
+	  default:
mgl@1371
  1233
+	  case AVR32_BUILTIN_SATS:
mgl@1371
  1234
+	    icode = CODE_FOR_sats;
mgl@1371
  1235
+	    fname = "sats";
mgl@1371
  1236
+	    break;
mgl@1371
  1237
+	  case AVR32_BUILTIN_SATU:
mgl@1371
  1238
+	    icode = CODE_FOR_satu;
mgl@1371
  1239
+	    fname = "satu";
mgl@1371
  1240
+	    break;
mgl@1371
  1241
+	  case AVR32_BUILTIN_SATRNDS:
mgl@1371
  1242
+	    icode = CODE_FOR_satrnds;
mgl@1371
  1243
+	    fname = "satrnds";
mgl@1371
  1244
+	    break;
mgl@1371
  1245
+	  case AVR32_BUILTIN_SATRNDU:
mgl@1371
  1246
+	    icode = CODE_FOR_satrndu;
mgl@1371
  1247
+	    fname = "satrndu";
mgl@1371
  1248
+	    break;
mgl@1371
  1249
+	  }
mgl@1371
  1250
+
mgl@1371
  1251
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1252
+	arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1253
+	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
mgl@1371
  1254
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1255
+	op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1256
+	op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
mgl@1371
  1257
+
mgl@1371
  1258
+	tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1259
+
mgl@1371
  1260
+
mgl@1371
  1261
+	if (target == 0
mgl@1371
  1262
+	    || GET_MODE (target) != tmode
mgl@1371
  1263
+	    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1264
+	  target = gen_reg_rtx (tmode);
mgl@1371
  1265
+
mgl@1371
  1266
+
mgl@1371
  1267
+	if (!(*insn_data[icode].operand[0].predicate) (op0, GET_MODE (op0)))
mgl@1371
  1268
+	  {
mgl@1371
  1269
+	    op0 = copy_to_mode_reg (insn_data[icode].operand[0].mode, op0);
mgl@1371
  1270
+	  }
mgl@1371
  1271
+
mgl@1371
  1272
+	if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
mgl@1371
  1273
+	  {
mgl@1371
  1274
+	    error ("Parameter 2 to __builtin_%s should be a constant number.",
mgl@1371
  1275
+		   fname);
mgl@1371
  1276
+	    return NULL_RTX;
mgl@1371
  1277
+	  }
mgl@1371
  1278
+
mgl@1371
  1279
+	if (!(*insn_data[icode].operand[1].predicate) (op2, SImode))
mgl@1371
  1280
+	  {
mgl@1371
  1281
+	    error ("Parameter 3 to __builtin_%s should be a constant number.",
mgl@1371
  1282
+		   fname);
mgl@1371
  1283
+	    return NULL_RTX;
mgl@1371
  1284
+	  }
mgl@1371
  1285
+
mgl@1371
  1286
+	emit_move_insn (target, op0);
mgl@1371
  1287
+	pat = GEN_FCN (icode) (target, op1, op2);
mgl@1371
  1288
+	if (!pat)
mgl@1371
  1289
+	  return 0;
mgl@1371
  1290
+	emit_insn (pat);
mgl@1371
  1291
+
mgl@1371
  1292
+	return target;
mgl@1371
  1293
+      }
mgl@1371
  1294
+    case AVR32_BUILTIN_MUSTR:
mgl@1371
  1295
+      icode = CODE_FOR_mustr;
mgl@1371
  1296
+      tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1297
+
mgl@1371
  1298
+      if (target == 0
mgl@1371
  1299
+	  || GET_MODE (target) != tmode
mgl@1371
  1300
+	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1301
+	target = gen_reg_rtx (tmode);
mgl@1371
  1302
+      pat = GEN_FCN (icode) (target);
mgl@1371
  1303
+      if (!pat)
mgl@1371
  1304
+	return 0;
mgl@1371
  1305
+      emit_insn (pat);
mgl@1371
  1306
+      return target;
mgl@1371
  1307
+
mgl@1371
  1308
+    case AVR32_BUILTIN_MFSR:
mgl@1371
  1309
+      icode = CODE_FOR_mfsr;
mgl@1371
  1310
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1311
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1312
+      tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1313
+      mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1314
+
mgl@1371
  1315
+      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1316
+	{
mgl@1371
  1317
+	  error ("Parameter 1 to __builtin_mfsr must be a constant number");
mgl@1371
  1318
+	}
mgl@1371
  1319
+
mgl@1371
  1320
+      if (target == 0
mgl@1371
  1321
+	  || GET_MODE (target) != tmode
mgl@1371
  1322
+	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1323
+	target = gen_reg_rtx (tmode);
mgl@1371
  1324
+      pat = GEN_FCN (icode) (target, op0);
mgl@1371
  1325
+      if (!pat)
mgl@1371
  1326
+	return 0;
mgl@1371
  1327
+      emit_insn (pat);
mgl@1371
  1328
+      return target;
mgl@1371
  1329
+    case AVR32_BUILTIN_MTSR:
mgl@1371
  1330
+      icode = CODE_FOR_mtsr;
mgl@1371
  1331
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1332
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1333
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1334
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1335
+      mode0 = insn_data[icode].operand[0].mode;
mgl@1371
  1336
+      mode1 = insn_data[icode].operand[1].mode;
mgl@1371
  1337
+
mgl@1371
  1338
+      if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
mgl@1371
  1339
+	{
mgl@1371
  1340
+	  error ("Parameter 1 to __builtin_mtsr must be a constant number");
mgl@1371
  1341
+	  return gen_reg_rtx (mode0);
mgl@1371
  1342
+	}
mgl@1371
  1343
+      if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
mgl@1371
  1344
+	op1 = copy_to_mode_reg (mode1, op1);
mgl@1371
  1345
+      pat = GEN_FCN (icode) (op0, op1);
mgl@1371
  1346
+      if (!pat)
mgl@1371
  1347
+	return 0;
mgl@1371
  1348
+      emit_insn (pat);
mgl@1371
  1349
+      return NULL_RTX;
mgl@1371
  1350
+    case AVR32_BUILTIN_MFDR:
mgl@1371
  1351
+      icode = CODE_FOR_mfdr;
mgl@1371
  1352
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1353
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1354
+      tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1355
+      mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1356
+
mgl@1371
  1357
+      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1358
+	{
mgl@1371
  1359
+	  error ("Parameter 1 to __builtin_mfdr must be a constant number");
mgl@1371
  1360
+	}
mgl@1371
  1361
+
mgl@1371
  1362
+      if (target == 0
mgl@1371
  1363
+	  || GET_MODE (target) != tmode
mgl@1371
  1364
+	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1365
+	target = gen_reg_rtx (tmode);
mgl@1371
  1366
+      pat = GEN_FCN (icode) (target, op0);
mgl@1371
  1367
+      if (!pat)
mgl@1371
  1368
+	return 0;
mgl@1371
  1369
+      emit_insn (pat);
mgl@1371
  1370
+      return target;
mgl@1371
  1371
+    case AVR32_BUILTIN_MTDR:
mgl@1371
  1372
+      icode = CODE_FOR_mtdr;
mgl@1371
  1373
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1374
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1375
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1376
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1377
+      mode0 = insn_data[icode].operand[0].mode;
mgl@1371
  1378
+      mode1 = insn_data[icode].operand[1].mode;
mgl@1371
  1379
+
mgl@1371
  1380
+      if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
mgl@1371
  1381
+	{
mgl@1371
  1382
+	  error ("Parameter 1 to __builtin_mtdr must be a constant number");
mgl@1371
  1383
+	  return gen_reg_rtx (mode0);
mgl@1371
  1384
+	}
mgl@1371
  1385
+      if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
mgl@1371
  1386
+	op1 = copy_to_mode_reg (mode1, op1);
mgl@1371
  1387
+      pat = GEN_FCN (icode) (op0, op1);
mgl@1371
  1388
+      if (!pat)
mgl@1371
  1389
+	return 0;
mgl@1371
  1390
+      emit_insn (pat);
mgl@1371
  1391
+      return NULL_RTX;
mgl@1371
  1392
+    case AVR32_BUILTIN_CACHE:
mgl@1371
  1393
+      icode = CODE_FOR_cache;
mgl@1371
  1394
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1395
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1396
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1397
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1398
+      mode0 = insn_data[icode].operand[0].mode;
mgl@1371
  1399
+      mode1 = insn_data[icode].operand[1].mode;
mgl@1371
  1400
+
mgl@1371
  1401
+      if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
mgl@1371
  1402
+	{
mgl@1371
  1403
+	  error ("Parameter 2 to __builtin_cache must be a constant number");
mgl@1371
  1404
+	  return gen_reg_rtx (mode1);
mgl@1371
  1405
+	}
mgl@1371
  1406
+
mgl@1371
  1407
+      if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
mgl@1371
  1408
+	op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1409
+
mgl@1371
  1410
+      pat = GEN_FCN (icode) (op0, op1);
mgl@1371
  1411
+      if (!pat)
mgl@1371
  1412
+	return 0;
mgl@1371
  1413
+      emit_insn (pat);
mgl@1371
  1414
+      return NULL_RTX;
mgl@1371
  1415
+    case AVR32_BUILTIN_SYNC:
mgl@1371
  1416
+    case AVR32_BUILTIN_MUSFR:
mgl@1371
  1417
+    case AVR32_BUILTIN_SSRF:
mgl@1371
  1418
+    case AVR32_BUILTIN_CSRF:
mgl@1371
  1419
+      {
mgl@1371
  1420
+	const char *fname;
mgl@1371
  1421
+	switch (fcode)
mgl@1371
  1422
+	  {
mgl@1371
  1423
+	  default:
mgl@1371
  1424
+	  case AVR32_BUILTIN_SYNC:
mgl@1371
  1425
+	    icode = CODE_FOR_sync;
mgl@1371
  1426
+	    fname = "sync";
mgl@1371
  1427
+	    break;
mgl@1371
  1428
+	  case AVR32_BUILTIN_MUSFR:
mgl@1371
  1429
+	    icode = CODE_FOR_musfr;
mgl@1371
  1430
+	    fname = "musfr";
mgl@1371
  1431
+	    break;
mgl@1371
  1432
+	  case AVR32_BUILTIN_SSRF:
mgl@1371
  1433
+	    icode = CODE_FOR_ssrf;
mgl@1371
  1434
+	    fname = "ssrf";
mgl@1371
  1435
+	    break;
mgl@1371
  1436
+	  case AVR32_BUILTIN_CSRF:
mgl@1371
  1437
+	    icode = CODE_FOR_csrf;
mgl@1371
  1438
+	    fname = "csrf";
mgl@1371
  1439
+	    break;
mgl@1371
  1440
+	  }
mgl@1371
  1441
+
mgl@1371
  1442
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1443
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1444
+	mode0 = insn_data[icode].operand[0].mode;
mgl@1371
  1445
+
mgl@1371
  1446
+	if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
mgl@1371
  1447
+	  {
mgl@1371
  1448
+	    if (icode == CODE_FOR_musfr)
mgl@1371
  1449
+	      op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1450
+	    else
mgl@1371
  1451
+	      {
mgl@1371
  1452
+		error ("Parameter to __builtin_%s is illegal.", fname);
mgl@1371
  1453
+		return gen_reg_rtx (mode0);
mgl@1371
  1454
+	      }
mgl@1371
  1455
+	  }
mgl@1371
  1456
+	pat = GEN_FCN (icode) (op0);
mgl@1371
  1457
+	if (!pat)
mgl@1371
  1458
+	  return 0;
mgl@1371
  1459
+	emit_insn (pat);
mgl@1371
  1460
+	return NULL_RTX;
mgl@1371
  1461
+      }
mgl@1371
  1462
+    case AVR32_BUILTIN_TLBR:
mgl@1371
  1463
+      icode = CODE_FOR_tlbr;
mgl@1371
  1464
+      pat = GEN_FCN (icode) (NULL_RTX);
mgl@1371
  1465
+      if (!pat)
mgl@1371
  1466
+	return 0;
mgl@1371
  1467
+      emit_insn (pat);
mgl@1371
  1468
+      return NULL_RTX;
mgl@1371
  1469
+    case AVR32_BUILTIN_TLBS:
mgl@1371
  1470
+      icode = CODE_FOR_tlbs;
mgl@1371
  1471
+      pat = GEN_FCN (icode) (NULL_RTX);
mgl@1371
  1472
+      if (!pat)
mgl@1371
  1473
+	return 0;
mgl@1371
  1474
+      emit_insn (pat);
mgl@1371
  1475
+      return NULL_RTX;
mgl@1371
  1476
+    case AVR32_BUILTIN_TLBW:
mgl@1371
  1477
+      icode = CODE_FOR_tlbw;
mgl@1371
  1478
+      pat = GEN_FCN (icode) (NULL_RTX);
mgl@1371
  1479
+      if (!pat)
mgl@1371
  1480
+	return 0;
mgl@1371
  1481
+      emit_insn (pat);
mgl@1371
  1482
+      return NULL_RTX;
mgl@1371
  1483
+    case AVR32_BUILTIN_BREAKPOINT:
mgl@1371
  1484
+      icode = CODE_FOR_breakpoint;
mgl@1371
  1485
+      pat = GEN_FCN (icode) (NULL_RTX);
mgl@1371
  1486
+      if (!pat)
mgl@1371
  1487
+	return 0;
mgl@1371
  1488
+      emit_insn (pat);
mgl@1371
  1489
+      return NULL_RTX;
mgl@1371
  1490
+    case AVR32_BUILTIN_XCHG:
mgl@1371
  1491
+      icode = CODE_FOR_sync_lock_test_and_setsi;
mgl@1371
  1492
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1493
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1494
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1495
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1496
+      tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1497
+      mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1498
+      mode1 = insn_data[icode].operand[2].mode;
mgl@1371
  1499
+
mgl@1371
  1500
+      if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
mgl@1371
  1501
+	{
mgl@1371
  1502
+	  op1 = copy_to_mode_reg (mode1, op1);
mgl@1371
  1503
+	}
mgl@1371
  1504
+
mgl@1371
  1505
+      op0 = force_reg (GET_MODE (op0), op0);
mgl@1371
  1506
+      op0 = gen_rtx_MEM (GET_MODE (op0), op0);
mgl@1371
  1507
+      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1508
+	{
mgl@1371
  1509
+	  error
mgl@1371
  1510
+	    ("Parameter 1 to __builtin_xchg must be a pointer to an integer.");
mgl@1371
  1511
+	}
mgl@1371
  1512
+
mgl@1371
  1513
+      if (target == 0
mgl@1371
  1514
+	  || GET_MODE (target) != tmode
mgl@1371
  1515
+	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1516
+	target = gen_reg_rtx (tmode);
mgl@1371
  1517
+      pat = GEN_FCN (icode) (target, op0, op1);
mgl@1371
  1518
+      if (!pat)
mgl@1371
  1519
+	return 0;
mgl@1371
  1520
+      emit_insn (pat);
mgl@1371
  1521
+      return target;
mgl@1371
  1522
+    case AVR32_BUILTIN_LDXI:
mgl@1371
  1523
+      icode = CODE_FOR_ldxi;
mgl@1371
  1524
+      arg0 = TREE_VALUE (arglist);
mgl@1371
  1525
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1526
+      arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
mgl@1371
  1527
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1528
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1529
+      op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
mgl@1371
  1530
+      tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1531
+      mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1532
+      mode1 = insn_data[icode].operand[2].mode;
mgl@1371
  1533
+
mgl@1371
  1534
+      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1535
+	{
mgl@1371
  1536
+	  op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1537
+	}
mgl@1371
  1538
+
mgl@1371
  1539
+      if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
mgl@1371
  1540
+	{
mgl@1371
  1541
+	  op1 = copy_to_mode_reg (mode1, op1);
mgl@1371
  1542
+	}
mgl@1371
  1543
+
mgl@1371
  1544
+      if (!(*insn_data[icode].operand[3].predicate) (op2, SImode))
mgl@1371
  1545
+	{
mgl@1371
  1546
+	  error
mgl@1371
  1547
+	    ("Parameter 3 to __builtin_ldxi must be a valid extract shift operand: (0|8|16|24)");
mgl@1371
  1548
+	  return gen_reg_rtx (mode0);
mgl@1371
  1549
+	}
mgl@1371
  1550
+
mgl@1371
  1551
+      if (target == 0
mgl@1371
  1552
+	  || GET_MODE (target) != tmode
mgl@1371
  1553
+	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1554
+	target = gen_reg_rtx (tmode);
mgl@1371
  1555
+      pat = GEN_FCN (icode) (target, op0, op1, op2);
mgl@1371
  1556
+      if (!pat)
mgl@1371
  1557
+	return 0;
mgl@1371
  1558
+      emit_insn (pat);
mgl@1371
  1559
+      return target;
mgl@1371
  1560
+    case AVR32_BUILTIN_BSWAP16:
mgl@1371
  1561
+      {
mgl@1371
  1562
+	icode = CODE_FOR_bswap_16;
mgl@1371
  1563
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1564
+	arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
mgl@1371
  1565
+	mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1566
+	if (arg0_mode != mode0)
mgl@1371
  1567
+	  arg0 = build1 (NOP_EXPR,
mgl@1371
  1568
+			 (*lang_hooks.types.type_for_mode) (mode0, 0), arg0);
mgl@1371
  1569
+
mgl@1371
  1570
+	op0 = expand_expr (arg0, NULL_RTX, HImode, 0);
mgl@1371
  1571
+	tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1572
+
mgl@1371
  1573
+
mgl@1371
  1574
+	if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1575
+	  {
mgl@1371
  1576
+            if ( CONST_INT_P (op0) )
mgl@1371
  1577
+              {
mgl@1371
  1578
+                HOST_WIDE_INT val = ( ((INTVAL (op0)&0x00ff) << 8) |
mgl@1371
  1579
+                                      ((INTVAL (op0)&0xff00) >> 8) );
mgl@1371
  1580
+                /* Sign extend 16-bit value to host wide int */
mgl@1371
  1581
+                val <<= (HOST_BITS_PER_WIDE_INT - 16);
mgl@1371
  1582
+                val >>= (HOST_BITS_PER_WIDE_INT - 16);
mgl@1371
  1583
+                op0 = GEN_INT(val);
mgl@1371
  1584
+                if (target == 0
mgl@1371
  1585
+                    || GET_MODE (target) != tmode
mgl@1371
  1586
+                    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1587
+                  target = gen_reg_rtx (tmode);
mgl@1371
  1588
+                emit_move_insn(target, op0);
mgl@1371
  1589
+                return target;
mgl@1371
  1590
+              }
mgl@1371
  1591
+            else
mgl@1371
  1592
+              op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1593
+	  }
mgl@1371
  1594
+
mgl@1371
  1595
+	if (target == 0
mgl@1371
  1596
+	    || GET_MODE (target) != tmode
mgl@1371
  1597
+	    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1598
+	  {
mgl@1371
  1599
+	    target = gen_reg_rtx (tmode);
mgl@1371
  1600
+	  }
mgl@1371
  1601
+
mgl@1371
  1602
+
mgl@1371
  1603
+	pat = GEN_FCN (icode) (target, op0);
mgl@1371
  1604
+	if (!pat)
mgl@1371
  1605
+	  return 0;
mgl@1371
  1606
+	emit_insn (pat);
mgl@1371
  1607
+
mgl@1371
  1608
+	return target;
mgl@1371
  1609
+      }
mgl@1371
  1610
+    case AVR32_BUILTIN_BSWAP32:
mgl@1371
  1611
+      {
mgl@1371
  1612
+	icode = CODE_FOR_bswap_32;
mgl@1371
  1613
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1614
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1615
+	tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1616
+	mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1617
+
mgl@1371
  1618
+	if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1619
+	  {
mgl@1371
  1620
+            if ( CONST_INT_P (op0) )
mgl@1371
  1621
+              {
mgl@1371
  1622
+                HOST_WIDE_INT val = ( ((INTVAL (op0)&0x000000ff) << 24) |
mgl@1371
  1623
+                                      ((INTVAL (op0)&0x0000ff00) << 8) |
mgl@1371
  1624
+                                      ((INTVAL (op0)&0x00ff0000) >> 8) |
mgl@1371
  1625
+                                      ((INTVAL (op0)&0xff000000) >> 24) );
mgl@1371
  1626
+                /* Sign extend 32-bit value to host wide int */
mgl@1371
  1627
+                val <<= (HOST_BITS_PER_WIDE_INT - 32);
mgl@1371
  1628
+                val >>= (HOST_BITS_PER_WIDE_INT - 32);
mgl@1371
  1629
+                op0 = GEN_INT(val);
mgl@1371
  1630
+                if (target == 0
mgl@1371
  1631
+                    || GET_MODE (target) != tmode
mgl@1371
  1632
+                    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1633
+                  target = gen_reg_rtx (tmode);
mgl@1371
  1634
+                emit_move_insn(target, op0);
mgl@1371
  1635
+                return target;
mgl@1371
  1636
+              }
mgl@1371
  1637
+            else
mgl@1371
  1638
+              op0 = copy_to_mode_reg (mode0, op0);
mgl@1371
  1639
+	  }
mgl@1371
  1640
+
mgl@1371
  1641
+	if (target == 0
mgl@1371
  1642
+	    || GET_MODE (target) != tmode
mgl@1371
  1643
+	    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1644
+	  target = gen_reg_rtx (tmode);
mgl@1371
  1645
+
mgl@1371
  1646
+
mgl@1371
  1647
+	pat = GEN_FCN (icode) (target, op0);
mgl@1371
  1648
+	if (!pat)
mgl@1371
  1649
+	  return 0;
mgl@1371
  1650
+	emit_insn (pat);
mgl@1371
  1651
+
mgl@1371
  1652
+	return target;
mgl@1371
  1653
+      }
mgl@1371
  1654
+    case AVR32_BUILTIN_MVCR_W:
mgl@1371
  1655
+    case AVR32_BUILTIN_MVCR_D:
mgl@1371
  1656
+      {
mgl@1371
  1657
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1658
+	arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1659
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1660
+	op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1661
+
mgl@1371
  1662
+	if (fcode == AVR32_BUILTIN_MVCR_W)
mgl@1371
  1663
+	  icode = CODE_FOR_mvcrsi;
mgl@1371
  1664
+	else
mgl@1371
  1665
+	  icode = CODE_FOR_mvcrdi;
mgl@1371
  1666
+
mgl@1371
  1667
+	tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1668
+
mgl@1371
  1669
+	if (target == 0
mgl@1371
  1670
+	    || GET_MODE (target) != tmode
mgl@1371
  1671
+	    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1672
+	  target = gen_reg_rtx (tmode);
mgl@1371
  1673
+
mgl@1371
  1674
+	if (!(*insn_data[icode].operand[1].predicate) (op0, SImode))
mgl@1371
  1675
+	  {
mgl@1371
  1676
+	    error
mgl@1371
  1677
+	      ("Parameter 1 to __builtin_cop is not a valid coprocessor number.");
mgl@1371
  1678
+	    error ("Number should be between 0 and 7.");
mgl@1371
  1679
+	    return NULL_RTX;
mgl@1371
  1680
+	  }
mgl@1371
  1681
+
mgl@1371
  1682
+	if (!(*insn_data[icode].operand[2].predicate) (op1, SImode))
mgl@1371
  1683
+	  {
mgl@1371
  1684
+	    error
mgl@1371
  1685
+	      ("Parameter 2 to __builtin_cop is not a valid coprocessor register number.");
mgl@1371
  1686
+	    error ("Number should be between 0 and 15.");
mgl@1371
  1687
+	    return NULL_RTX;
mgl@1371
  1688
+	  }
mgl@1371
  1689
+
mgl@1371
  1690
+	pat = GEN_FCN (icode) (target, op0, op1);
mgl@1371
  1691
+	if (!pat)
mgl@1371
  1692
+	  return 0;
mgl@1371
  1693
+	emit_insn (pat);
mgl@1371
  1694
+
mgl@1371
  1695
+	return target;
mgl@1371
  1696
+      }
mgl@1371
  1697
+    case AVR32_BUILTIN_MACSATHH_W:
mgl@1371
  1698
+    case AVR32_BUILTIN_MACWH_D:
mgl@1371
  1699
+    case AVR32_BUILTIN_MACHH_D:
mgl@1371
  1700
+      {
mgl@1371
  1701
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1702
+	arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1703
+	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
mgl@1371
  1704
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1705
+	op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1706
+	op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
mgl@1371
  1707
+
mgl@1371
  1708
+	icode = ((fcode == AVR32_BUILTIN_MACSATHH_W) ? CODE_FOR_macsathh_w :
mgl@1371
  1709
+		 (fcode == AVR32_BUILTIN_MACWH_D) ? CODE_FOR_macwh_d :
mgl@1371
  1710
+		 CODE_FOR_machh_d);
mgl@1371
  1711
+
mgl@1371
  1712
+	tmode = insn_data[icode].operand[0].mode;
mgl@1371
  1713
+	mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1714
+	mode1 = insn_data[icode].operand[2].mode;
mgl@1371
  1715
+
mgl@1371
  1716
+
mgl@1371
  1717
+	if (!target
mgl@1371
  1718
+	    || GET_MODE (target) != tmode
mgl@1371
  1719
+	    || !(*insn_data[icode].operand[0].predicate) (target, tmode))
mgl@1371
  1720
+	  target = gen_reg_rtx (tmode);
mgl@1371
  1721
+
mgl@1371
  1722
+	if (!(*insn_data[icode].operand[0].predicate) (op0, tmode))
mgl@1371
  1723
+	  {
mgl@1371
  1724
+	    /* If op0 is already a reg we must cast it to the correct mode. */
mgl@1371
  1725
+	    if (REG_P (op0))
mgl@1371
  1726
+	      op0 = convert_to_mode (tmode, op0, 1);
mgl@1371
  1727
+	    else
mgl@1371
  1728
+	      op0 = copy_to_mode_reg (tmode, op0);
mgl@1371
  1729
+	  }
mgl@1371
  1730
+
mgl@1371
  1731
+	if (!(*insn_data[icode].operand[1].predicate) (op1, mode0))
mgl@1371
  1732
+	  {
mgl@1371
  1733
+	    /* If op1 is already a reg we must cast it to the correct mode. */
mgl@1371
  1734
+	    if (REG_P (op1))
mgl@1371
  1735
+	      op1 = convert_to_mode (mode0, op1, 1);
mgl@1371
  1736
+	    else
mgl@1371
  1737
+	      op1 = copy_to_mode_reg (mode0, op1);
mgl@1371
  1738
+	  }
mgl@1371
  1739
+
mgl@1371
  1740
+	if (!(*insn_data[icode].operand[2].predicate) (op2, mode1))
mgl@1371
  1741
+	  {
mgl@1371
  1742
+	    /* If op1 is already a reg we must cast it to the correct mode. */
mgl@1371
  1743
+	    if (REG_P (op2))
mgl@1371
  1744
+	      op2 = convert_to_mode (mode1, op2, 1);
mgl@1371
  1745
+	    else
mgl@1371
  1746
+	      op2 = copy_to_mode_reg (mode1, op2);
mgl@1371
  1747
+	  }
mgl@1371
  1748
+
mgl@1371
  1749
+	emit_move_insn (target, op0);
mgl@1371
  1750
+
mgl@1371
  1751
+	pat = GEN_FCN (icode) (target, op1, op2);
mgl@1371
  1752
+	if (!pat)
mgl@1371
  1753
+	  return 0;
mgl@1371
  1754
+	emit_insn (pat);
mgl@1371
  1755
+	return target;
mgl@1371
  1756
+      }
mgl@1371
  1757
+    case AVR32_BUILTIN_MVRC_W:
mgl@1371
  1758
+    case AVR32_BUILTIN_MVRC_D:
mgl@1371
  1759
+      {
mgl@1371
  1760
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1761
+	arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1762
+	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
mgl@1371
  1763
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1764
+	op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1765
+	op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
mgl@1371
  1766
+
mgl@1371
  1767
+	if (fcode == AVR32_BUILTIN_MVRC_W)
mgl@1371
  1768
+	  icode = CODE_FOR_mvrcsi;
mgl@1371
  1769
+	else
mgl@1371
  1770
+	  icode = CODE_FOR_mvrcdi;
mgl@1371
  1771
+
mgl@1371
  1772
+	if (!(*insn_data[icode].operand[0].predicate) (op0, SImode))
mgl@1371
  1773
+	  {
mgl@1371
  1774
+	    error ("Parameter 1 is not a valid coprocessor number.");
mgl@1371
  1775
+	    error ("Number should be between 0 and 7.");
mgl@1371
  1776
+	    return NULL_RTX;
mgl@1371
  1777
+	  }
mgl@1371
  1778
+
mgl@1371
  1779
+	if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
mgl@1371
  1780
+	  {
mgl@1371
  1781
+	    error ("Parameter 2 is not a valid coprocessor register number.");
mgl@1371
  1782
+	    error ("Number should be between 0 and 15.");
mgl@1371
  1783
+	    return NULL_RTX;
mgl@1371
  1784
+	  }
mgl@1371
  1785
+
mgl@1371
  1786
+	if (GET_CODE (op2) == CONST_INT
mgl@1371
  1787
+	    || GET_CODE (op2) == CONST
mgl@1371
  1788
+	    || GET_CODE (op2) == SYMBOL_REF || GET_CODE (op2) == LABEL_REF)
mgl@1371
  1789
+	  {
mgl@1371
  1790
+	    op2 = force_const_mem (insn_data[icode].operand[2].mode, op2);
mgl@1371
  1791
+	  }
mgl@1371
  1792
+
mgl@1371
  1793
+	if (!(*insn_data[icode].operand[2].predicate) (op2, GET_MODE (op2)))
mgl@1371
  1794
+	  op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
mgl@1371
  1795
+
mgl@1371
  1796
+
mgl@1371
  1797
+	pat = GEN_FCN (icode) (op0, op1, op2);
mgl@1371
  1798
+	if (!pat)
mgl@1371
  1799
+	  return 0;
mgl@1371
  1800
+	emit_insn (pat);
mgl@1371
  1801
+
mgl@1371
  1802
+	return NULL_RTX;
mgl@1371
  1803
+      }
mgl@1371
  1804
+    case AVR32_BUILTIN_COP:
mgl@1371
  1805
+      {
mgl@1371
  1806
+	rtx op3, op4;
mgl@1371
  1807
+	tree arg3, arg4;
mgl@1371
  1808
+	icode = CODE_FOR_cop;
mgl@1371
  1809
+	arg0 = TREE_VALUE (arglist);
mgl@1371
  1810
+	arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1811
+	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
mgl@1371
  1812
+	arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
mgl@1371
  1813
+	arg4 =
mgl@1371
  1814
+	  TREE_VALUE (TREE_CHAIN
mgl@1371
  1815
+		      (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))));
mgl@1371
  1816
+	op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1817
+	op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1818
+	op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
mgl@1371
  1819
+	op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
mgl@1371
  1820
+	op4 = expand_expr (arg4, NULL_RTX, VOIDmode, 0);
mgl@1371
  1821
+
mgl@1371
  1822
+	if (!(*insn_data[icode].operand[0].predicate) (op0, SImode))
mgl@1371
  1823
+	  {
mgl@1371
  1824
+	    error
mgl@1371
  1825
+	      ("Parameter 1 to __builtin_cop is not a valid coprocessor number.");
mgl@1371
  1826
+	    error ("Number should be between 0 and 7.");
mgl@1371
  1827
+	    return NULL_RTX;
mgl@1371
  1828
+	  }
mgl@1371
  1829
+
mgl@1371
  1830
+	if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
mgl@1371
  1831
+	  {
mgl@1371
  1832
+	    error
mgl@1371
  1833
+	      ("Parameter 2 to __builtin_cop is not a valid coprocessor register number.");
mgl@1371
  1834
+	    error ("Number should be between 0 and 15.");
mgl@1371
  1835
+	    return NULL_RTX;
mgl@1371
  1836
+	  }
mgl@1371
  1837
+
mgl@1371
  1838
+	if (!(*insn_data[icode].operand[2].predicate) (op2, SImode))
mgl@1371
  1839
+	  {
mgl@1371
  1840
+	    error
mgl@1371
  1841
+	      ("Parameter 3 to __builtin_cop is not a valid coprocessor register number.");
mgl@1371
  1842
+	    error ("Number should be between 0 and 15.");
mgl@1371
  1843
+	    return NULL_RTX;
mgl@1371
  1844
+	  }
mgl@1371
  1845
+
mgl@1371
  1846
+	if (!(*insn_data[icode].operand[3].predicate) (op3, SImode))
mgl@1371
  1847
+	  {
mgl@1371
  1848
+	    error
mgl@1371
  1849
+	      ("Parameter 4 to __builtin_cop is not a valid coprocessor register number.");
mgl@1371
  1850
+	    error ("Number should be between 0 and 15.");
mgl@1371
  1851
+	    return NULL_RTX;
mgl@1371
  1852
+	  }
mgl@1371
  1853
+
mgl@1371
  1854
+	if (!(*insn_data[icode].operand[4].predicate) (op4, SImode))
mgl@1371
  1855
+	  {
mgl@1371
  1856
+	    error
mgl@1371
  1857
+	      ("Parameter 5 to __builtin_cop is not a valid coprocessor operation.");
mgl@1371
  1858
+	    error ("Number should be between 0 and 127.");
mgl@1371
  1859
+	    return NULL_RTX;
mgl@1371
  1860
+	  }
mgl@1371
  1861
+
mgl@1371
  1862
+	pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
mgl@1371
  1863
+	if (!pat)
mgl@1371
  1864
+	  return 0;
mgl@1371
  1865
+	emit_insn (pat);
mgl@1371
  1866
+
mgl@1371
  1867
+	return target;
mgl@1371
  1868
+      }
mgl@1371
  1869
+    case AVR32_BUILTIN_MEMS:
mgl@1371
  1870
+    case AVR32_BUILTIN_MEMC:
mgl@1371
  1871
+    case AVR32_BUILTIN_MEMT:
mgl@1371
  1872
+      {
mgl@1371
  1873
+        if (!TARGET_RMW)
mgl@1371
  1874
+          error ("Trying to use __builtin_mem(s/c/t) when target does not support RMW insns.");
mgl@1371
  1875
+
mgl@1371
  1876
+        switch (fcode) {
mgl@1371
  1877
+        case AVR32_BUILTIN_MEMS:
mgl@1371
  1878
+          icode = CODE_FOR_iorsi3;
mgl@1371
  1879
+          break;
mgl@1371
  1880
+        case AVR32_BUILTIN_MEMC:
mgl@1371
  1881
+          icode = CODE_FOR_andsi3;
mgl@1371
  1882
+          break;
mgl@1371
  1883
+        case AVR32_BUILTIN_MEMT:
mgl@1371
  1884
+          icode = CODE_FOR_xorsi3;
mgl@1371
  1885
+          break;
mgl@1371
  1886
+        }
mgl@1371
  1887
+
mgl@1371
  1888
+        arg0 = TREE_VALUE (arglist);
mgl@1371
  1889
+        arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mgl@1371
  1890
+        op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
mgl@1371
  1891
+        if ( GET_CODE (op0) == SYMBOL_REF )
mgl@1371
  1892
+          // This symbol must be RMW addressable
mgl@1371
  1893
+          SYMBOL_REF_FLAGS (op0) |= (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT);
mgl@1371
  1894
+        op0 = gen_rtx_MEM(SImode, op0);
mgl@1371
  1895
+        op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
mgl@1371
  1896
+        mode0 = insn_data[icode].operand[1].mode;
mgl@1371
  1897
+
mgl@1371
  1898
+
mgl@1371
  1899
+        if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
mgl@1371
  1900
+          {
mgl@1371
  1901
+            error ("Parameter 1 to __builtin_mem(s/c/t) must be a Ks15<<2 address or a rmw addressable symbol.");
mgl@1371
  1902
+          }
mgl@1371
  1903
+
mgl@1371
  1904
+        if ( !CONST_INT_P (op1)
mgl@1371
  1905
+             || INTVAL (op1) > 31
mgl@1371
  1906
+             || INTVAL (op1) < 0 )
mgl@1371
  1907
+          error ("Parameter 2 to __builtin_mem(s/c/t) must be a constant between 0 and 31.");
mgl@1371
  1908
+
mgl@1371
  1909
+        if ( fcode == AVR32_BUILTIN_MEMC )
mgl@1371
  1910
+          op1 = GEN_INT((~(1 << INTVAL(op1)))&0xffffffff);
mgl@1371
  1911
+        else
mgl@1371
  1912
+          op1 = GEN_INT((1 << INTVAL(op1))&0xffffffff);
mgl@1371
  1913
+        pat = GEN_FCN (icode) (op0, op0, op1);
mgl@1371
  1914
+        if (!pat)
mgl@1371
  1915
+          return 0;
mgl@1371
  1916
+        emit_insn (pat);
mgl@1371
  1917
+        return op0;
mgl@1371
  1918
+      }
mgl@1371
  1919
+
mgl@1371
  1920
+    }
mgl@1371
  1921
+
mgl@1371
  1922
+  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
mgl@1371
  1923
+    if (d->code == fcode)
mgl@1371
  1924
+      return avr32_expand_binop_builtin (d->icode, arglist, target);
mgl@1371
  1925
+
mgl@1371
  1926
+
mgl@1371
  1927
+  /* @@@ Should really do something sensible here.  */
mgl@1371
  1928
+  return NULL_RTX;
mgl@1371
  1929
+}
mgl@1371
  1930
+
mgl@1371
  1931
+
mgl@1371
  1932
+/* Handle an "interrupt" or "isr" attribute;
mgl@1371
  1933
+   arguments as in struct attribute_spec.handler.  */
mgl@1371
  1934
+
mgl@1371
  1935
+static tree
mgl@1371
  1936
+avr32_handle_isr_attribute (tree * node, tree name, tree args,
mgl@1371
  1937
+			    int flags, bool * no_add_attrs)
mgl@1371
  1938
+{
mgl@1371
  1939
+  if (DECL_P (*node))
mgl@1371
  1940
+    {
mgl@1371
  1941
+      if (TREE_CODE (*node) != FUNCTION_DECL)
mgl@1371
  1942
+	{
mgl@1371
  1943
+	  warning (OPT_Wattributes,"`%s' attribute only applies to functions",
mgl@1371
  1944
+		   IDENTIFIER_POINTER (name));
mgl@1371
  1945
+	  *no_add_attrs = true;
mgl@1371
  1946
+	}
mgl@1371
  1947
+      /* FIXME: the argument if any is checked for type attributes; should it
mgl@1371
  1948
+         be checked for decl ones? */
mgl@1371
  1949
+    }
mgl@1371
  1950
+  else
mgl@1371
  1951
+    {
mgl@1371
  1952
+      if (TREE_CODE (*node) == FUNCTION_TYPE
mgl@1371
  1953
+	  || TREE_CODE (*node) == METHOD_TYPE)
mgl@1371
  1954
+	{
mgl@1371
  1955
+	  if (avr32_isr_value (args) == AVR32_FT_UNKNOWN)
mgl@1371
  1956
+	    {
mgl@1371
  1957
+	      warning (OPT_Wattributes,"`%s' attribute ignored", IDENTIFIER_POINTER (name));
mgl@1371
  1958
+	      *no_add_attrs = true;
mgl@1371
  1959
+	    }
mgl@1371
  1960
+	}
mgl@1371
  1961
+      else if (TREE_CODE (*node) == POINTER_TYPE
mgl@1371
  1962
+	       && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
mgl@1371
  1963
+		   || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
mgl@1371
  1964
+	       && avr32_isr_value (args) != AVR32_FT_UNKNOWN)
mgl@1371
  1965
+	{
mgl@1371
  1966
+	  *node = build_variant_type_copy (*node);
mgl@1371
  1967
+	  TREE_TYPE (*node) = build_type_attribute_variant
mgl@1371
  1968
+	    (TREE_TYPE (*node),
mgl@1371
  1969
+	     tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
mgl@1371
  1970
+	  *no_add_attrs = true;
mgl@1371
  1971
+	}
mgl@1371
  1972
+      else
mgl@1371
  1973
+	{
mgl@1371
  1974
+	  /* Possibly pass this attribute on from the type to a decl.  */
mgl@1371
  1975
+	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
mgl@1371
  1976
+		       | (int) ATTR_FLAG_FUNCTION_NEXT
mgl@1371
  1977
+		       | (int) ATTR_FLAG_ARRAY_NEXT))
mgl@1371
  1978
+	    {
mgl@1371
  1979
+	      *no_add_attrs = true;
mgl@1371
  1980
+	      return tree_cons (name, args, NULL_TREE);
mgl@1371
  1981
+	    }
mgl@1371
  1982
+	  else
mgl@1371
  1983
+	    {
mgl@1371
  1984
+	      warning (OPT_Wattributes,"`%s' attribute ignored", IDENTIFIER_POINTER (name));
mgl@1371
  1985
+	    }
mgl@1371
  1986
+	}
mgl@1371
  1987
+    }
mgl@1371
  1988
+
mgl@1371
  1989
+  return NULL_TREE;
mgl@1371
  1990
+}
mgl@1371
  1991
+
mgl@1371
  1992
+/* Handle an attribute requiring a FUNCTION_DECL;
mgl@1371
  1993
+   arguments as in struct attribute_spec.handler.  */
mgl@1371
  1994
+static tree
mgl@1371
  1995
+avr32_handle_fndecl_attribute (tree * node, tree name,
mgl@1371
  1996
+			       tree args ATTRIBUTE_UNUSED,
mgl@1371
  1997
+			       int flags ATTRIBUTE_UNUSED,
mgl@1371
  1998
+			       bool * no_add_attrs)
mgl@1371
  1999
+{
mgl@1371
  2000
+  if (TREE_CODE (*node) != FUNCTION_DECL)
mgl@1371
  2001
+    {
mgl@1371
  2002
+      warning (OPT_Wattributes,"%qs attribute only applies to functions",
mgl@1371
  2003
+	       IDENTIFIER_POINTER (name));
mgl@1371
  2004
+      *no_add_attrs = true;
mgl@1371
  2005
+    }
mgl@1371
  2006
+
mgl@1371
  2007
+  return NULL_TREE;
mgl@1371
  2008
+}
mgl@1371
  2009
+
mgl@1371
  2010
+
mgl@1371
  2011
+/* Handle an acall attribute;
mgl@1371
  2012
+   arguments as in struct attribute_spec.handler.  */
mgl@1371
  2013
+
mgl@1371
  2014
+static tree
mgl@1371
  2015
+avr32_handle_acall_attribute (tree * node, tree name,
mgl@1371
  2016
+			      tree args ATTRIBUTE_UNUSED,
mgl@1371
  2017
+			      int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
mgl@1371
  2018
+{
mgl@1371
  2019
+  if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)
mgl@1371
  2020
+    {
mgl@1371
  2021
+      warning (OPT_Wattributes,"`%s' attribute not yet supported...",
mgl@1371
  2022
+	       IDENTIFIER_POINTER (name));
mgl@1371
  2023
+      *no_add_attrs = true;
mgl@1371
  2024
+      return NULL_TREE;
mgl@1371
  2025
+    }
mgl@1371
  2026
+
mgl@1371
  2027
+  warning (OPT_Wattributes,"`%s' attribute only applies to functions",
mgl@1371
  2028
+	   IDENTIFIER_POINTER (name));
mgl@1371
  2029
+  *no_add_attrs = true;
mgl@1371
  2030
+  return NULL_TREE;
mgl@1371
  2031
+}
mgl@1371
  2032
+
mgl@1371
  2033
+
mgl@1371
  2034
+/* Return 0 if the attributes for two types are incompatible, 1 if they
mgl@1371
  2035
+   are compatible, and 2 if they are nearly compatible (which causes a
mgl@1371
  2036
+   warning to be generated).  */
mgl@1371
  2037
+
mgl@1371
  2038
+static int
mgl@1371
  2039
+avr32_comp_type_attributes (tree type1, tree type2)
mgl@1371
  2040
+{
mgl@1371
  2041
+  int acall1, acall2, isr1, isr2, naked1, naked2;
mgl@1371
  2042
+
mgl@1371
  2043
+  /* Check for mismatch of non-default calling convention.  */
mgl@1371
  2044
+  if (TREE_CODE (type1) != FUNCTION_TYPE)
mgl@1371
  2045
+    return 1;
mgl@1371
  2046
+
mgl@1371
  2047
+  /* Check for mismatched call attributes.  */
mgl@1371
  2048
+  acall1 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type1)) != NULL;
mgl@1371
  2049
+  acall2 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type2)) != NULL;
mgl@1371
  2050
+  naked1 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type1)) != NULL;
mgl@1371
  2051
+  naked2 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type2)) != NULL;
mgl@1371
  2052
+  isr1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
mgl@1371
  2053
+  if (!isr1)
mgl@1371
  2054
+    isr1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
mgl@1371
  2055
+
mgl@1371
  2056
+  isr2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
mgl@1371
  2057
+  if (!isr2)
mgl@1371
  2058
+    isr2 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
mgl@1371
  2059
+
mgl@1371
  2060
+  if ((acall1 && isr2)
mgl@1371
  2061
+      || (acall2 && isr1) || (naked1 && isr2) || (naked2 && isr1))
mgl@1371
  2062
+    return 0;
mgl@1371
  2063
+
mgl@1371
  2064
+  return 1;
mgl@1371
  2065
+}
mgl@1371
  2066
+
mgl@1371
  2067
+
mgl@1371
  2068
+/* Computes the type of the current function.  */
mgl@1371
  2069
+
mgl@1371
  2070
+static unsigned long
mgl@1371
  2071
+avr32_compute_func_type (void)
mgl@1371
  2072
+{
mgl@1371
  2073
+  unsigned long type = AVR32_FT_UNKNOWN;
mgl@1371
  2074
+  tree a;
mgl@1371
  2075
+  tree attr;
mgl@1371
  2076
+
mgl@1371
  2077
+  if (TREE_CODE (current_function_decl) != FUNCTION_DECL)
mgl@1371
  2078
+    abort ();
mgl@1371
  2079
+
mgl@1371
  2080
+  /* Decide if the current function is volatile.  Such functions never
mgl@1371
  2081
+     return, and many memory cycles can be saved by not storing register
mgl@1371
  2082
+     values that will never be needed again.  This optimization was added to
mgl@1371
  2083
+     speed up context switching in a kernel application.  */
mgl@1371
  2084
+  if (optimize > 0
mgl@1371
  2085
+      && TREE_NOTHROW (current_function_decl)
mgl@1371
  2086
+      && TREE_THIS_VOLATILE (current_function_decl))
mgl@1371
  2087
+    type |= AVR32_FT_VOLATILE;
mgl@1371
  2088
+
mgl@1371
  2089
+  if (cfun->static_chain_decl != NULL)
mgl@1371
  2090
+    type |= AVR32_FT_NESTED;
mgl@1371
  2091
+
mgl@1371
  2092
+  attr = DECL_ATTRIBUTES (current_function_decl);
mgl@1371
  2093
+
mgl@1371
  2094
+  a = lookup_attribute ("isr", attr);
mgl@1371
  2095
+  if (a == NULL_TREE)
mgl@1371
  2096
+    a = lookup_attribute ("interrupt", attr);
mgl@1371
  2097
+
mgl@1371
  2098
+  if (a == NULL_TREE)
mgl@1371
  2099
+    type |= AVR32_FT_NORMAL;
mgl@1371
  2100
+  else
mgl@1371
  2101
+    type |= avr32_isr_value (TREE_VALUE (a));
mgl@1371
  2102
+
mgl@1371
  2103
+
mgl@1371
  2104
+  a = lookup_attribute ("acall", attr);
mgl@1371
  2105
+  if (a != NULL_TREE)
mgl@1371
  2106
+    type |= AVR32_FT_ACALL;
mgl@1371
  2107
+
mgl@1371
  2108
+  a = lookup_attribute ("naked", attr);
mgl@1371
  2109
+  if (a != NULL_TREE)
mgl@1371
  2110
+    type |= AVR32_FT_NAKED;
mgl@1371
  2111
+
mgl@1371
  2112
+  return type;
mgl@1371
  2113
+}
mgl@1371
  2114
+
mgl@1371
  2115
+/* Returns the type of the current function.  */
mgl@1371
  2116
+
mgl@1371
  2117
+static unsigned long
mgl@1371
  2118
+avr32_current_func_type (void)
mgl@1371
  2119
+{
mgl@1371
  2120
+  if (AVR32_FUNC_TYPE (cfun->machine->func_type) == AVR32_FT_UNKNOWN)
mgl@1371
  2121
+    cfun->machine->func_type = avr32_compute_func_type ();
mgl@1371
  2122
+
mgl@1371
  2123
+  return cfun->machine->func_type;
mgl@1371
  2124
+}
mgl@1371
  2125
+
mgl@1371
  2126
+/*
mgl@1371
  2127
+   This target hook should return true if we should not pass type solely
mgl@1371
  2128
+   in registers. The file expr.h defines a definition that is usually appropriate,
mgl@1371
  2129
+   refer to expr.h for additional documentation.
mgl@1371
  2130
+*/
mgl@1371
  2131
+bool
mgl@1371
  2132
+avr32_must_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)
mgl@1371
  2133
+{
mgl@1371
  2134
+  if (type && AGGREGATE_TYPE_P (type)
mgl@1371
  2135
+      /* If the alignment is less than the size then pass in the struct on
mgl@1371
  2136
+         the stack. */
mgl@1371
  2137
+      && ((unsigned int) TYPE_ALIGN_UNIT (type) <
mgl@1371
  2138
+	  (unsigned int) int_size_in_bytes (type))
mgl@1371
  2139
+      /* If we support unaligned word accesses then structs of size 4 and 8
mgl@1371
  2140
+         can have any alignment and still be passed in registers. */
mgl@1371
  2141
+      && !(TARGET_UNALIGNED_WORD
mgl@1371
  2142
+	   && (int_size_in_bytes (type) == 4
mgl@1371
  2143
+	       || int_size_in_bytes (type) == 8))
mgl@1371
  2144
+      /* Double word structs need only a word alignment. */
mgl@1371
  2145
+      && !(int_size_in_bytes (type) == 8 && TYPE_ALIGN_UNIT (type) >= 4))
mgl@1371
  2146
+    return true;
mgl@1371
  2147
+
mgl@1371
  2148
+  if (type && AGGREGATE_TYPE_P (type)
mgl@1371
  2149
+      /* Structs of size 3,5,6,7 are always passed in registers. */
mgl@1371
  2150
+      && (int_size_in_bytes (type) == 3
mgl@1371
  2151
+	  || int_size_in_bytes (type) == 5
mgl@1371
  2152
+	  || int_size_in_bytes (type) == 6 || int_size_in_bytes (type) == 7))
mgl@1371
  2153
+    return true;
mgl@1371
  2154
+
mgl@1371
  2155
+
mgl@1371
  2156
+  return (type && TREE_ADDRESSABLE (type));
mgl@1371
  2157
+}
mgl@1371
  2158
+
mgl@1371
  2159
+
mgl@1371
  2160
+bool
mgl@1371
  2161
+avr32_strict_argument_naming (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED)
mgl@1371
  2162
+{
mgl@1371
  2163
+  return true;
mgl@1371
  2164
+}
mgl@1371
  2165
+
mgl@1371
  2166
+/*
mgl@1371
  2167
+   This target hook should return true if an argument at the position indicated
mgl@1371
  2168
+   by cum should be passed by reference. This predicate is queried after target
mgl@1371
  2169
+   independent reasons for being passed by reference, such as TREE_ADDRESSABLE (type).
mgl@1371
  2170
+
mgl@1371
  2171
+   If the hook returns true, a copy of that argument is made in memory and a
mgl@1371
  2172
+   pointer to the argument is passed instead of the argument itself. The pointer
mgl@1371
  2173
+   is passed in whatever way is appropriate for passing a pointer to that type.
mgl@1371
  2174
+*/
mgl@1371
  2175
+bool
mgl@1371
  2176
+avr32_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
mgl@1371
  2177
+			 enum machine_mode mode ATTRIBUTE_UNUSED,
mgl@1371
  2178
+			 tree type, bool named ATTRIBUTE_UNUSED)
mgl@1371
  2179
+{
mgl@1371
  2180
+  return (type && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST));
mgl@1371
  2181
+}
mgl@1371
  2182
+
mgl@1371
  2183
+static int
mgl@1371
  2184
+avr32_arg_partial_bytes (CUMULATIVE_ARGS * pcum ATTRIBUTE_UNUSED,
mgl@1371
  2185
+			 enum machine_mode mode ATTRIBUTE_UNUSED,
mgl@1371
  2186
+			 tree type ATTRIBUTE_UNUSED,
mgl@1371
  2187
+			 bool named ATTRIBUTE_UNUSED)
mgl@1371
  2188
+{
mgl@1371
  2189
+  return 0;
mgl@1371
  2190
+}
mgl@1371
  2191
+
mgl@1371
  2192
+
mgl@1371
  2193
+struct gcc_target targetm = TARGET_INITIALIZER;
mgl@1371
  2194
+
mgl@1371
  2195
+/*
mgl@1371
  2196
+  Table used to convert from register number in the assembler instructions and
mgl@1371
  2197
+  the register numbers used in gcc.
mgl@1371
  2198
+*/
mgl@1371
  2199
+const int avr32_function_arg_reglist[] = {
mgl@1371
  2200
+  INTERNAL_REGNUM (12),
mgl@1371
  2201
+  INTERNAL_REGNUM (11),
mgl@1371
  2202
+  INTERNAL_REGNUM (10),
mgl@1371
  2203
+  INTERNAL_REGNUM (9),
mgl@1371
  2204
+  INTERNAL_REGNUM (8)
mgl@1371
  2205
+};
mgl@1371
  2206
+
mgl@1371
  2207
+rtx avr32_compare_op0 = NULL_RTX;
mgl@1371
  2208
+rtx avr32_compare_op1 = NULL_RTX;
mgl@1371
  2209
+rtx avr32_compare_operator = NULL_RTX;
mgl@1371
  2210
+rtx avr32_acc_cache = NULL_RTX;
mgl@1371
  2211
+
mgl@1371
  2212
+/*
mgl@1371
  2213
+  Returns nonzero if it is allowed to store a value of mode mode in hard
mgl@1371
  2214
+  register number regno.
mgl@1371
  2215
+*/
mgl@1371
  2216
+int
mgl@1371
  2217
+avr32_hard_regno_mode_ok (int regnr, enum machine_mode mode)
mgl@1371
  2218
+{
mgl@1371
  2219
+  /* We allow only float modes in the fp-registers */
mgl@1371
  2220
+  if (regnr >= FIRST_FP_REGNUM
mgl@1371
  2221
+      && regnr <= LAST_FP_REGNUM && GET_MODE_CLASS (mode) != MODE_FLOAT)
mgl@1371
  2222
+    {
mgl@1371
  2223
+      return 0;
mgl@1371
  2224
+    }
mgl@1371
  2225
+
mgl@1371
  2226
+  switch (mode)
mgl@1371
  2227
+    {
mgl@1371
  2228
+    case DImode:		/* long long */
mgl@1371
  2229
+    case DFmode:		/* double */
mgl@1371
  2230
+    case SCmode:		/* __complex__ float */
mgl@1371
  2231
+    case CSImode:		/* __complex__ int */
mgl@1371
  2232
+      if (regnr < 4)
mgl@1371
  2233
+	{			/* long long int not supported in r12, sp, lr
mgl@1371
  2234
+				   or pc. */
mgl@1371
  2235
+	  return 0;
mgl@1371
  2236
+	}
mgl@1371
  2237
+      else
mgl@1371
  2238
+	{
mgl@1371
  2239
+	  if (regnr % 2)	/* long long int has to be refered in even
mgl@1371
  2240
+				   registers. */
mgl@1371
  2241
+	    return 0;
mgl@1371
  2242
+	  else
mgl@1371
  2243
+	    return 1;
mgl@1371
  2244
+	}
mgl@1371
  2245
+    case CDImode:		/* __complex__ long long */
mgl@1371
  2246
+    case DCmode:		/* __complex__ double */
mgl@1371
  2247
+    case TImode:		/* 16 bytes */
mgl@1371
  2248
+      if (regnr < 7)
mgl@1371
  2249
+	return 0;
mgl@1371
  2250
+      else if (regnr % 2)
mgl@1371
  2251
+	return 0;
mgl@1371
  2252
+      else
mgl@1371
  2253
+	return 1;
mgl@1371
  2254
+    default:
mgl@1371
  2255
+      return 1;
mgl@1371
  2256
+    }
mgl@1371
  2257
+}
mgl@1371
  2258
+
mgl@1371
  2259
+
mgl@1371
  2260
+int
mgl@1371
  2261
+avr32_rnd_operands (rtx add, rtx shift)
mgl@1371
  2262
+{
mgl@1371
  2263
+  if (GET_CODE (shift) == CONST_INT &&
mgl@1371
  2264
+      GET_CODE (add) == CONST_INT && INTVAL (shift) > 0)
mgl@1371
  2265
+    {
mgl@1371
  2266
+      if ((1 << (INTVAL (shift) - 1)) == INTVAL (add))
mgl@1371
  2267
+	return TRUE;
mgl@1371
  2268
+    }
mgl@1371
  2269
+
mgl@1371
  2270
+  return FALSE;
mgl@1371
  2271
+}
mgl@1371
  2272
+
mgl@1371
  2273
+
mgl@1371
  2274
+
mgl@1371
  2275
+int
mgl@1371
  2276
+avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c, const char *str)
mgl@1371
  2277
+{
mgl@1371
  2278
+  switch (c)
mgl@1371
  2279
+    {
mgl@1371
  2280
+    case 'K':
mgl@1371
  2281
+    case 'I':
mgl@1371
  2282
+      {
mgl@1371
  2283
+	HOST_WIDE_INT min_value = 0, max_value = 0;
mgl@1371
  2284
+	char size_str[3];
mgl@1371
  2285
+	int const_size;
mgl@1371
  2286
+
mgl@1371
  2287
+	size_str[0] = str[2];
mgl@1371
  2288
+	size_str[1] = str[3];
mgl@1371
  2289
+	size_str[2] = '\0';
mgl@1371
  2290
+	const_size = atoi (size_str);
mgl@1371
  2291
+
mgl@1371
  2292
+	if (toupper (str[1]) == 'U')
mgl@1371
  2293
+	  {
mgl@1371
  2294
+	    min_value = 0;
mgl@1371
  2295
+	    max_value = (1 << const_size) - 1;
mgl@1371
  2296
+	  }
mgl@1371
  2297
+	else if (toupper (str[1]) == 'S')
mgl@1371
  2298
+	  {
mgl@1371
  2299
+	    min_value = -(1 << (const_size - 1));
mgl@1371
  2300
+	    max_value = (1 << (const_size - 1)) - 1;
mgl@1371
  2301
+	  }
mgl@1371
  2302
+
mgl@1371
  2303
+	if (c == 'I')
mgl@1371
  2304
+	  {
mgl@1371
  2305
+	    value = -value;
mgl@1371
  2306
+	  }
mgl@1371
  2307
+
mgl@1371
  2308
+	if (value >= min_value && value <= max_value)
mgl@1371
  2309
+	  {
mgl@1371
  2310
+	    return 1;
mgl@1371
  2311
+	  }
mgl@1371
  2312
+	break;
mgl@1371
  2313
+      }
mgl@1371
  2314
+    case 'M':
mgl@1371
  2315
+      return avr32_mask_upper_bits_operand (GEN_INT (value), VOIDmode);
mgl@1371
  2316
+    case 'J':
mgl@1371
  2317
+      return avr32_hi16_immediate_operand (GEN_INT (value), VOIDmode);
mgl@1371
  2318
+    case 'O':
mgl@1371
  2319
+      return one_bit_set_operand (GEN_INT (value), VOIDmode);
mgl@1371
  2320
+    case 'N':
mgl@1371
  2321
+      return one_bit_cleared_operand (GEN_INT (value), VOIDmode);
mgl@1371
  2322
+    case 'L':
mgl@1371
  2323
+      /* The lower 16-bits are set. */
mgl@1371
  2324
+      return ((value & 0xffff) == 0xffff) ;
mgl@1371
  2325
+    }
mgl@1371
  2326
+
mgl@1371
  2327
+  return 0;
mgl@1371
  2328
+}
mgl@1371
  2329
+
mgl@1371
  2330
+
mgl@1371
  2331
+/*Compute mask of which floating-point registers needs saving upon
mgl@1371
  2332
+  entry to this function*/
mgl@1371
  2333
+static unsigned long
mgl@1371
  2334
+avr32_compute_save_fp_reg_mask (void)
mgl@1371
  2335
+{
mgl@1371
  2336
+  unsigned long func_type = avr32_current_func_type ();
mgl@1371
  2337
+  unsigned int save_reg_mask = 0;
mgl@1371
  2338
+  unsigned int reg;
mgl@1371
  2339
+  unsigned int max_reg = 7;
mgl@1371
  2340
+  int save_all_call_used_regs = FALSE;
mgl@1371
  2341
+
mgl@1371
  2342
+  /* This only applies for hardware floating-point implementation. */
mgl@1371
  2343
+  if (!TARGET_HARD_FLOAT)
mgl@1371
  2344
+    return 0;
mgl@1371
  2345
+
mgl@1371
  2346
+  if (IS_INTERRUPT (func_type))
mgl@1371
  2347
+    {
mgl@1371
  2348
+
mgl@1371
  2349
+      /* Interrupt functions must not corrupt any registers, even call
mgl@1371
  2350
+         clobbered ones.  If this is a leaf function we can just examine the
mgl@1371
  2351
+         registers used by the RTL, but otherwise we have to assume that
mgl@1371
  2352
+         whatever function is called might clobber anything, and so we have
mgl@1371
  2353
+         to save all the call-clobbered registers as well.  */
mgl@1371
  2354
+      max_reg = 13;
mgl@1371
  2355
+      save_all_call_used_regs = !current_function_is_leaf;
mgl@1371
  2356
+    }
mgl@1371
  2357
+
mgl@1371
  2358
+  /* All used registers used must be saved */
mgl@1371
  2359
+  for (reg = 0; reg <= max_reg; reg++)
mgl@1371
  2360
+    if (regs_ever_live[INTERNAL_FP_REGNUM (reg)]
mgl@1371
  2361
+	|| (save_all_call_used_regs
mgl@1371
  2362
+	    && call_used_regs[INTERNAL_FP_REGNUM (reg)]))
mgl@1371
  2363
+      save_reg_mask |= (1 << reg);
mgl@1371
  2364
+
mgl@1371
  2365
+  return save_reg_mask;
mgl@1371
  2366
+}
mgl@1371
  2367
+
mgl@1371
  2368
+/*Compute mask of registers which needs saving upon function entry */
mgl@1371
  2369
+static unsigned long
mgl@1371
  2370
+avr32_compute_save_reg_mask (int push)
mgl@1371
  2371
+{
mgl@1371
  2372
+  unsigned long func_type;
mgl@1371
  2373
+  unsigned int save_reg_mask = 0;
mgl@1371
  2374
+  unsigned int reg;
mgl@1371
  2375
+
mgl@1371
  2376
+  func_type = avr32_current_func_type ();
mgl@1371
  2377
+
mgl@1371
  2378
+  if (IS_INTERRUPT (func_type))
mgl@1371
  2379
+    {
mgl@1371
  2380
+      unsigned int max_reg = 12;
mgl@1371
  2381
+
mgl@1371
  2382
+
mgl@1371
  2383
+      /* Get the banking scheme for the interrupt */
mgl@1371
  2384
+      switch (func_type)
mgl@1371
  2385
+	{
mgl@1371
  2386
+	case AVR32_FT_ISR_FULL:
mgl@1371
  2387
+	  max_reg = 0;
mgl@1371
  2388
+	  break;
mgl@1371
  2389
+	case AVR32_FT_ISR_HALF:
mgl@1371
  2390
+	  max_reg = 7;
mgl@1371
  2391
+	  break;
mgl@1371
  2392
+	case AVR32_FT_ISR_NONE:
mgl@1371
  2393
+	  max_reg = 12;
mgl@1371
  2394
+	  break;
mgl@1371
  2395
+	}
mgl@1371
  2396
+
mgl@1371
  2397
+      /* Interrupt functions must not corrupt any registers, even call
mgl@1371
  2398
+         clobbered ones.  If this is a leaf function we can just examine the
mgl@1371
  2399
+         registers used by the RTL, but otherwise we have to assume that
mgl@1371
  2400
+         whatever function is called might clobber anything, and so we have
mgl@1371
  2401
+         to save all the call-clobbered registers as well.  */
mgl@1371
  2402
+
mgl@1371
  2403
+      /* Need not push the registers r8-r12 for AVR32A architectures, as this
mgl@1371
  2404
+         is automatially done in hardware. We also do not have any shadow
mgl@1371
  2405
+         registers. */
mgl@1371
  2406
+      if (TARGET_UARCH_AVR32A)
mgl@1371
  2407
+	{
mgl@1371
  2408
+	  max_reg = 7;
mgl@1371
  2409
+	  func_type = AVR32_FT_ISR_NONE;
mgl@1371
  2410
+	}
mgl@1371
  2411
+
mgl@1371
  2412
+      /* All registers which are used and is not shadowed must be saved */
mgl@1371
  2413
+      for (reg = 0; reg <= max_reg; reg++)
mgl@1371
  2414
+	if (regs_ever_live[INTERNAL_REGNUM (reg)]
mgl@1371
  2415
+	    || (!current_function_is_leaf
mgl@1371
  2416
+		&& call_used_regs[INTERNAL_REGNUM (reg)]))
mgl@1371
  2417
+	  save_reg_mask |= (1 << reg);
mgl@1371
  2418
+
mgl@1371
  2419
+      /* Check LR */
mgl@1371
  2420
+      if ((regs_ever_live[LR_REGNUM]
mgl@1371
  2421
+	   || !current_function_is_leaf || frame_pointer_needed)
mgl@1371
  2422
+	  /* Only non-shadowed register models */
mgl@1371
  2423
+	  && (func_type == AVR32_FT_ISR_NONE))
mgl@1371
  2424
+	save_reg_mask |= (1 << ASM_REGNUM (LR_REGNUM));
mgl@1371
  2425
+
mgl@1371
  2426
+      /* Make sure that the GOT register is pushed. */
mgl@1371
  2427
+      if (max_reg >= ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM)
mgl@1371
  2428
+	  && current_function_uses_pic_offset_table)
mgl@1371
  2429
+	save_reg_mask |= (1 << ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM));
mgl@1371
  2430
+
mgl@1371
  2431
+    }
mgl@1371
  2432
+  else
mgl@1371
  2433
+    {
mgl@1371
  2434
+      int use_pushm = optimize_size;
mgl@1371
  2435
+
mgl@1371
  2436
+      /* In the normal case we only need to save those registers which are
mgl@1371
  2437
+         call saved and which are used by this function.  */
mgl@1371
  2438
+      for (reg = 0; reg <= 7; reg++)
mgl@1371
  2439
+	if (regs_ever_live[INTERNAL_REGNUM (reg)]
mgl@1371
  2440
+	    && !call_used_regs[INTERNAL_REGNUM (reg)])
mgl@1371
  2441
+	  save_reg_mask |= (1 << reg);
mgl@1371
  2442
+
mgl@1371
  2443
+      /* Make sure that the GOT register is pushed. */
mgl@1371
  2444
+      if (current_function_uses_pic_offset_table)
mgl@1371
  2445
+	save_reg_mask |= (1 << ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM));
mgl@1371
  2446
+
mgl@1371
  2447
+
mgl@1371
  2448
+      /* If we optimize for size and do not have anonymous arguments: use
mgl@1371
  2449
+         popm/pushm always */
mgl@1371
  2450
+      if (use_pushm)
mgl@1371
  2451
+	{
mgl@1371
  2452
+	  if ((save_reg_mask & (1 << 0))
mgl@1371
  2453
+	      || (save_reg_mask & (1 << 1))
mgl@1371
  2454
+	      || (save_reg_mask & (1 << 2)) || (save_reg_mask & (1 << 3)))
mgl@1371
  2455
+	    save_reg_mask |= 0xf;
mgl@1371
  2456
+
mgl@1371
  2457
+	  if ((save_reg_mask & (1 << 4))
mgl@1371
  2458
+	      || (save_reg_mask & (1 << 5))
mgl@1371
  2459
+	      || (save_reg_mask & (1 << 6)) || (save_reg_mask & (1 << 7)))
mgl@1371
  2460
+	    save_reg_mask |= 0xf0;
mgl@1371
  2461
+
mgl@1371
  2462
+	  if ((save_reg_mask & (1 << 8)) || (save_reg_mask & (1 << 9)))
mgl@1371
  2463
+	    save_reg_mask |= 0x300;
mgl@1371
  2464
+	}
mgl@1371
  2465
+
mgl@1371
  2466
+
mgl@1371
  2467
+      /* Check LR */
mgl@1371
  2468
+      if ((regs_ever_live[LR_REGNUM]
mgl@1371
  2469
+	   || !current_function_is_leaf
mgl@1371
  2470
+	   || (optimize_size
mgl@1371
  2471
+	       && save_reg_mask
mgl@1371
  2472
+	       && !current_function_calls_eh_return) || frame_pointer_needed))
mgl@1371
  2473
+	{
mgl@1371
  2474
+	  if (push
mgl@1371
  2475
+	      /* Never pop LR into PC for functions which
mgl@1371
  2476
+	         calls __builtin_eh_return, since we need to
mgl@1371
  2477
+	         fix the SP after the restoring of the registers
mgl@1371
  2478
+	         and before returning. */
mgl@1371
  2479
+	      || current_function_calls_eh_return)
mgl@1371
  2480
+	    {
mgl@1371
  2481
+	      /* Push/Pop LR */
mgl@1371
  2482
+	      save_reg_mask |= (1 << ASM_REGNUM (LR_REGNUM));
mgl@1371
  2483
+	    }
mgl@1371
  2484
+	  else
mgl@1371
  2485
+	    {
mgl@1371
  2486
+	      /* Pop PC */
mgl@1371
  2487
+	      save_reg_mask |= (1 << ASM_REGNUM (PC_REGNUM));
mgl@1371
  2488
+	    }
mgl@1371
  2489
+	}
mgl@1371
  2490
+    }
mgl@1371
  2491
+
mgl@1371
  2492
+
mgl@1371
  2493
+  /* Save registers so the exception handler can modify them.  */
mgl@1371
  2494
+  if (current_function_calls_eh_return)
mgl@1371
  2495
+    {
mgl@1371
  2496
+      unsigned int i;
mgl@1371
  2497
+
mgl@1371
  2498
+      for (i = 0;; i++)
mgl@1371
  2499
+	{
mgl@1371
  2500
+	  reg = EH_RETURN_DATA_REGNO (i);
mgl@1371
  2501
+	  if (reg == INVALID_REGNUM)
mgl@1371
  2502
+	    break;
mgl@1371
  2503
+	  save_reg_mask |= 1 << ASM_REGNUM (reg);
mgl@1371
  2504
+	}
mgl@1371
  2505
+    }
mgl@1371
  2506
+
mgl@1371
  2507
+  return save_reg_mask;
mgl@1371
  2508
+}
mgl@1371
  2509
+
mgl@1371
  2510
+/*Compute total size in bytes of all saved registers  */
mgl@1371
  2511
+static int
mgl@1371
  2512
+avr32_get_reg_mask_size (int reg_mask)
mgl@1371
  2513
+{
mgl@1371
  2514
+  int reg, size;
mgl@1371
  2515
+  size = 0;
mgl@1371
  2516
+
mgl@1371
  2517
+  for (reg = 0; reg <= 15; reg++)
mgl@1371
  2518
+    if (reg_mask & (1 << reg))
mgl@1371
  2519
+      size += 4;
mgl@1371
  2520
+
mgl@1371
  2521
+  return size;
mgl@1371
  2522
+}
mgl@1371
  2523
+
mgl@1371
  2524
+/*Get a register from one of the registers which are saved onto the stack
mgl@1371
  2525
+  upon function entry */
mgl@1371
  2526
+
mgl@1371
  2527
+static int
mgl@1371
  2528
+avr32_get_saved_reg (int save_reg_mask)
mgl@1371
  2529
+{
mgl@1371
  2530
+  unsigned int reg;
mgl@1371
  2531
+
mgl@1371
  2532
+  /* Find the first register which is saved in the saved_reg_mask */
mgl@1371
  2533
+  for (reg = 0; reg <= 15; reg++)
mgl@1371
  2534
+    if (save_reg_mask & (1 << reg))
mgl@1371
  2535
+      return reg;
mgl@1371
  2536
+
mgl@1371
  2537
+  return -1;
mgl@1371
  2538
+}
mgl@1371
  2539
+
mgl@1371
  2540
+/* Return 1 if it is possible to return using a single instruction.  */
mgl@1371
  2541
+int
mgl@1371
  2542
+avr32_use_return_insn (int iscond)
mgl@1371
  2543
+{
mgl@1371
  2544
+  unsigned int func_type = avr32_current_func_type ();
mgl@1371
  2545
+  unsigned long saved_int_regs;
mgl@1371
  2546
+  unsigned long saved_fp_regs;
mgl@1371
  2547
+
mgl@1371
  2548
+  /* Never use a return instruction before reload has run.  */
mgl@1371
  2549
+  if (!reload_completed)
mgl@1371
  2550
+    return 0;
mgl@1371
  2551
+
mgl@1371
  2552
+  /* Must adjust the stack for vararg functions. */
mgl@1371
  2553
+  if (current_function_args_info.uses_anonymous_args)
mgl@1371
  2554
+    return 0;
mgl@1371
  2555
+
mgl@1371
  2556
+  /* If there a stack adjstment.  */
mgl@1371
  2557
+  if (get_frame_size ())
mgl@1371
  2558
+    return 0;
mgl@1371
  2559
+
mgl@1371
  2560
+  saved_int_regs = avr32_compute_save_reg_mask (TRUE);
mgl@1371
  2561
+  saved_fp_regs = avr32_compute_save_fp_reg_mask ();
mgl@1371
  2562
+
mgl@1371
  2563
+  /* Functions which have saved fp-regs on the stack can not be performed in
mgl@1371
  2564
+     one instruction */
mgl@1371
  2565
+  if (saved_fp_regs)
mgl@1371
  2566
+    return 0;
mgl@1371
  2567
+
mgl@1371
  2568
+  /* Conditional returns can not be performed in one instruction if we need
mgl@1371
  2569
+     to restore registers from the stack */
mgl@1371
  2570
+  if (iscond && saved_int_regs)
mgl@1371
  2571
+    return 0;
mgl@1371
  2572
+
mgl@1371
  2573
+  /* Conditional return can not be used for interrupt handlers. */
mgl@1371
  2574
+  if (iscond && IS_INTERRUPT (func_type))
mgl@1371
  2575
+    return 0;
mgl@1371
  2576
+
mgl@1371
  2577
+  /* For interrupt handlers which needs to pop registers */
mgl@1371
  2578
+  if (saved_int_regs && IS_INTERRUPT (func_type))
mgl@1371
  2579
+    return 0;
mgl@1371
  2580
+
mgl@1371
  2581
+
mgl@1371
  2582
+  /* If there are saved registers but the LR isn't saved, then we need two
mgl@1371
  2583
+     instructions for the return.  */
mgl@1371
  2584
+  if (saved_int_regs && !(saved_int_regs & (1 << ASM_REGNUM (LR_REGNUM))))
mgl@1371
  2585
+    return 0;
mgl@1371
  2586
+
mgl@1371
  2587
+
mgl@1371
  2588
+  return 1;
mgl@1371
  2589
+}
mgl@1371
  2590
+
mgl@1371
  2591
+
mgl@1371
  2592
+/*Generate some function prologue info in the assembly file*/
mgl@1371
  2593
+
mgl@1371
  2594
+void
mgl@1371
  2595
+avr32_target_asm_function_prologue (FILE * f, HOST_WIDE_INT frame_size)
mgl@1371
  2596
+{
mgl@1371
  2597
+  if (IS_NAKED (avr32_current_func_type ()))
mgl@1371
  2598
+    fprintf (f,
mgl@1371
  2599
+	     "\t# Function is naked: Prologue and epilogue provided by programmer\n");
mgl@1371
  2600
+
mgl@1371
  2601
+  if (IS_INTERRUPT (avr32_current_func_type ()))
mgl@1371
  2602
+    {
mgl@1371
  2603
+      switch (avr32_current_func_type ())
mgl@1371
  2604
+	{
mgl@1371
  2605
+	case AVR32_FT_ISR_FULL:
mgl@1371
  2606
+	  fprintf (f,
mgl@1371
  2607
+		   "\t# Interrupt Function: Fully shadowed register file\n");
mgl@1371
  2608
+	  break;
mgl@1371
  2609
+	case AVR32_FT_ISR_HALF:
mgl@1371
  2610
+	  fprintf (f,
mgl@1371
  2611
+		   "\t# Interrupt Function: Half shadowed register file\n");
mgl@1371
  2612
+	  break;
mgl@1371
  2613
+	default:
mgl@1371
  2614
+	case AVR32_FT_ISR_NONE:
mgl@1371
  2615
+	  fprintf (f, "\t# Interrupt Function: No shadowed register file\n");
mgl@1371
  2616
+	  break;
mgl@1371
  2617
+	}
mgl@1371
  2618
+    }
mgl@1371
  2619
+
mgl@1371
  2620
+
mgl@1371
  2621
+  fprintf (f, "\t# args = %i, frame = %li, pretend = %i\n",
mgl@1371
  2622
+	   current_function_args_size, frame_size,
mgl@1371
  2623
+	   current_function_pretend_args_size);
mgl@1371
  2624
+
mgl@1371
  2625
+  fprintf (f, "\t# frame_needed = %i, leaf_function = %i\n",
mgl@1371
  2626
+	   frame_pointer_needed, current_function_is_leaf);
mgl@1371
  2627
+
mgl@1371
  2628
+  fprintf (f, "\t# uses_anonymous_args = %i\n",
mgl@1371
  2629
+	   current_function_args_info.uses_anonymous_args);
mgl@1371
  2630
+  if (current_function_calls_eh_return)
mgl@1371
  2631
+    fprintf (f, "\t# Calls __builtin_eh_return.\n");
mgl@1371
  2632
+
mgl@1371
  2633
+}
mgl@1371
  2634
+
mgl@1371
  2635
+
mgl@1371
  2636
+/* Generate and emit an insn that we will recognize as a pushm or stm.
mgl@1371
  2637
+   Unfortunately, since this insn does not reflect very well the actual
mgl@1371
  2638
+   semantics of the operation, we need to annotate the insn for the benefit
mgl@1371
  2639
+   of DWARF2 frame unwind information.  */
mgl@1371
  2640
+
mgl@1371
  2641
+int avr32_convert_to_reglist16 (int reglist8_vect);
mgl@1371
  2642
+
mgl@1371
  2643
+static rtx
mgl@1371
  2644
+emit_multi_reg_push (int reglist, int usePUSHM)
mgl@1371
  2645
+{
mgl@1371
  2646
+  rtx insn;
mgl@1371
  2647
+  rtx dwarf;
mgl@1371
  2648
+  rtx tmp;
mgl@1371
  2649
+  rtx reg;
mgl@1371
  2650
+  int i;
mgl@1371
  2651
+  int nr_regs;
mgl@1371
  2652
+  int index = 0;
mgl@1371
  2653
+
mgl@1371
  2654
+  if (usePUSHM)
mgl@1371
  2655
+    {
mgl@1371
  2656
+      insn = emit_insn (gen_pushm (gen_rtx_CONST_INT (SImode, reglist)));
mgl@1371
  2657
+      reglist = avr32_convert_to_reglist16 (reglist);
mgl@1371
  2658
+    }
mgl@1371
  2659
+  else
mgl@1371
  2660
+    {
mgl@1371
  2661
+      insn = emit_insn (gen_stm (stack_pointer_rtx,
mgl@1371
  2662
+				 gen_rtx_CONST_INT (SImode, reglist),
mgl@1371
  2663
+				 gen_rtx_CONST_INT (SImode, 1)));
mgl@1371
  2664
+    }
mgl@1371
  2665
+
mgl@1371
  2666
+  nr_regs = avr32_get_reg_mask_size (reglist) / 4;
mgl@1371
  2667
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (nr_regs + 1));
mgl@1371
  2668
+
mgl@1371
  2669
+  for (i = 15; i >= 0; i--)
mgl@1371
  2670
+    {
mgl@1371
  2671
+      if (reglist & (1 << i))
mgl@1371
  2672
+	{
mgl@1371
  2673
+	  reg = gen_rtx_REG (SImode, INTERNAL_REGNUM (i));
mgl@1371
  2674
+	  tmp = gen_rtx_SET (VOIDmode,
mgl@1371
  2675
+			     gen_rtx_MEM (SImode,
mgl@1371
  2676
+					  plus_constant (stack_pointer_rtx,
mgl@1371
  2677
+							 4 * index)), reg);
mgl@1371
  2678
+	  RTX_FRAME_RELATED_P (tmp) = 1;
mgl@1371
  2679
+	  XVECEXP (dwarf, 0, 1 + index++) = tmp;
mgl@1371
  2680
+	}
mgl@1371
  2681
+    }
mgl@1371
  2682
+
mgl@1371
  2683
+  tmp = gen_rtx_SET (SImode,
mgl@1371
  2684
+		     stack_pointer_rtx,
mgl@1371
  2685
+		     gen_rtx_PLUS (SImode,
mgl@1371
  2686
+				   stack_pointer_rtx,
mgl@1371
  2687
+				   GEN_INT (-4 * nr_regs)));
mgl@1371
  2688
+  RTX_FRAME_RELATED_P (tmp) = 1;
mgl@1371
  2689
+  XVECEXP (dwarf, 0, 0) = tmp;
mgl@1371
  2690
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
mgl@1371
  2691
+					REG_NOTES (insn));
mgl@1371
  2692
+  return insn;
mgl@1371
  2693
+}
mgl@1371
  2694
+
mgl@1371
  2695
+
mgl@1371
  2696
+static rtx
mgl@1371
  2697
+emit_multi_fp_reg_push (int reglist)
mgl@1371
  2698
+{
mgl@1371
  2699
+  rtx insn;
mgl@1371
  2700
+  rtx dwarf;
mgl@1371
  2701
+  rtx tmp;
mgl@1371
  2702
+  rtx reg;
mgl@1371
  2703
+  int i;
mgl@1371
  2704
+  int nr_regs;
mgl@1371
  2705
+  int index = 0;
mgl@1371
  2706
+
mgl@1371
  2707
+  insn = emit_insn (gen_stm_fp (stack_pointer_rtx,
mgl@1371
  2708
+				gen_rtx_CONST_INT (SImode, reglist),
mgl@1371
  2709
+				gen_rtx_CONST_INT (SImode, 1)));
mgl@1371
  2710
+
mgl@1371
  2711
+  nr_regs = avr32_get_reg_mask_size (reglist) / 4;
mgl@1371
  2712
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (nr_regs + 1));
mgl@1371
  2713
+
mgl@1371
  2714
+  for (i = 15; i >= 0; i--)
mgl@1371
  2715
+    {
mgl@1371
  2716
+      if (reglist & (1 << i))
mgl@1371
  2717
+	{
mgl@1371
  2718
+	  reg = gen_rtx_REG (SImode, INTERNAL_FP_REGNUM (i));
mgl@1371
  2719
+	  tmp = gen_rtx_SET (VOIDmode,
mgl@1371
  2720
+			     gen_rtx_MEM (SImode,
mgl@1371
  2721
+					  plus_constant (stack_pointer_rtx,
mgl@1371
  2722
+							 4 * index)), reg);
mgl@1371
  2723
+	  RTX_FRAME_RELATED_P (tmp) = 1;
mgl@1371
  2724
+	  XVECEXP (dwarf, 0, 1 + index++) = tmp;
mgl@1371
  2725
+	}
mgl@1371
  2726
+    }
mgl@1371
  2727
+
mgl@1371
  2728
+  tmp = gen_rtx_SET (SImode,
mgl@1371
  2729
+		     stack_pointer_rtx,
mgl@1371
  2730
+		     gen_rtx_PLUS (SImode,
mgl@1371
  2731
+				   stack_pointer_rtx,
mgl@1371
  2732
+				   GEN_INT (-4 * nr_regs)));
mgl@1371
  2733
+  RTX_FRAME_RELATED_P (tmp) = 1;
mgl@1371
  2734
+  XVECEXP (dwarf, 0, 0) = tmp;
mgl@1371
  2735
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
mgl@1371
  2736
+					REG_NOTES (insn));
mgl@1371
  2737
+  return insn;
mgl@1371
  2738
+}
mgl@1371
  2739
+
mgl@1371
  2740
+rtx
mgl@1371
  2741
+avr32_gen_load_multiple (rtx * regs, int count, rtx from,
mgl@1371
  2742
+			 int write_back, int in_struct_p, int scalar_p)
mgl@1371
  2743
+{
mgl@1371
  2744
+
mgl@1371
  2745
+  rtx result;
mgl@1371
  2746
+  int i = 0, j;
mgl@1371
  2747
+
mgl@1371
  2748
+  result =
mgl@1371
  2749
+    gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + (write_back ? 1 : 0)));
mgl@1371
  2750
+
mgl@1371
  2751
+  if (write_back)
mgl@1371
  2752
+    {
mgl@1371
  2753
+      XVECEXP (result, 0, 0)
mgl@1371
  2754
+	= gen_rtx_SET (GET_MODE (from), from,
mgl@1371
  2755
+		       plus_constant (from, count * 4));
mgl@1371
  2756
+      i = 1;
mgl@1371
  2757
+      count++;
mgl@1371
  2758
+    }
mgl@1371
  2759
+
mgl@1371
  2760
+
mgl@1371
  2761
+  for (j = 0; i < count; i++, j++)
mgl@1371
  2762
+    {
mgl@1371
  2763
+      rtx unspec;
mgl@1371
  2764
+      rtx mem = gen_rtx_MEM (SImode, plus_constant (from, j * 4));
mgl@1371
  2765
+      MEM_IN_STRUCT_P (mem) = in_struct_p;
mgl@1371
  2766
+      MEM_SCALAR_P (mem) = scalar_p;
mgl@1371
  2767
+      unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, mem), UNSPEC_LDM);
mgl@1371
  2768
+      XVECEXP (result, 0, i) = gen_rtx_SET (VOIDmode, regs[j], unspec);
mgl@1371
  2769
+    }
mgl@1371
  2770
+
mgl@1371
  2771
+  return result;
mgl@1371
  2772
+}
mgl@1371
  2773
+
mgl@1371
  2774
+
mgl@1371
  2775
+rtx
mgl@1371
  2776
+avr32_gen_store_multiple (rtx * regs, int count, rtx to,
mgl@1371
  2777
+			  int in_struct_p, int scalar_p)
mgl@1371
  2778
+{
mgl@1371
  2779
+  rtx result;
mgl@1371
  2780
+  int i = 0, j;
mgl@1371
  2781
+
mgl@1371
  2782
+  result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
mgl@1371
  2783
+
mgl@1371
  2784
+  for (j = 0; i < count; i++, j++)
mgl@1371
  2785
+    {
mgl@1371
  2786
+      rtx mem = gen_rtx_MEM (SImode, plus_constant (to, j * 4));
mgl@1371
  2787
+      MEM_IN_STRUCT_P (mem) = in_struct_p;
mgl@1371
  2788
+      MEM_SCALAR_P (mem) = scalar_p;
mgl@1371
  2789
+      XVECEXP (result, 0, i)
mgl@1371
  2790
+	= gen_rtx_SET (VOIDmode, mem,
mgl@1371
  2791
+		       gen_rtx_UNSPEC (VOIDmode,
mgl@1371
  2792
+				       gen_rtvec (1, regs[j]),
mgl@1371
  2793
+				       UNSPEC_STORE_MULTIPLE));
mgl@1371
  2794
+    }
mgl@1371
  2795
+
mgl@1371
  2796
+  return result;
mgl@1371
  2797
+}
mgl@1371
  2798
+
mgl@1371
  2799
+
mgl@1371
  2800
+/* Move a block of memory if it is word aligned or we support unaligned
mgl@1371
  2801
+   word memory accesses. The size must be maximum 64 bytes. */
mgl@1371
  2802
+
mgl@1371
  2803
+int
mgl@1371
  2804
+avr32_gen_movmemsi (rtx * operands)
mgl@1371
  2805
+{
mgl@1371
  2806
+  HOST_WIDE_INT bytes_to_go;
mgl@1371
  2807
+  rtx src, dst;
mgl@1371
  2808
+  rtx st_src, st_dst;
mgl@1371
  2809
+  int src_offset = 0, dst_offset = 0;
mgl@1371
  2810
+  int block_size;
mgl@1371
  2811
+  int dst_in_struct_p, src_in_struct_p;
mgl@1371
  2812
+  int dst_scalar_p, src_scalar_p;
mgl@1371
  2813
+  int unaligned;
mgl@1371
  2814
+
mgl@1371
  2815
+  if (GET_CODE (operands[2]) != CONST_INT
mgl@1371
  2816
+      || GET_CODE (operands[3]) != CONST_INT
mgl@1371
  2817
+      || INTVAL (operands[2]) > 64
mgl@1371
  2818
+      || ((INTVAL (operands[3]) & 3) && !TARGET_UNALIGNED_WORD))
mgl@1371
  2819
+    return 0;
mgl@1371
  2820
+
mgl@1371
  2821
+  unaligned = (INTVAL (operands[3]) & 3) != 0;
mgl@1371
  2822
+
mgl@1371
  2823
+  block_size = 4;
mgl@1371
  2824
+
mgl@1371
  2825
+  st_dst = XEXP (operands[0], 0);
mgl@1371
  2826
+  st_src = XEXP (operands[1], 0);
mgl@1371
  2827
+
mgl@1371
  2828
+  dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
mgl@1371
  2829
+  dst_scalar_p = MEM_SCALAR_P (operands[0]);
mgl@1371
  2830
+  src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
mgl@1371
  2831
+  src_scalar_p = MEM_SCALAR_P (operands[1]);
mgl@1371
  2832
+
mgl@1371
  2833
+  dst = copy_to_mode_reg (SImode, st_dst);
mgl@1371
  2834
+  src = copy_to_mode_reg (SImode, st_src);
mgl@1371
  2835
+
mgl@1371
  2836
+  bytes_to_go = INTVAL (operands[2]);
mgl@1371
  2837
+
mgl@1371
  2838
+  while (bytes_to_go)
mgl@1371
  2839
+    {
mgl@1371
  2840
+      enum machine_mode move_mode;
mgl@1371
  2841
+      /* (Seems to be a problem with reloads for the movti pattern so this is
mgl@1371
  2842
+         disabled until that problem is resolved)
mgl@1371
  2843
+         UPDATE: Problem seems to be solved now.... */
mgl@1371
  2844
+      if (bytes_to_go >= GET_MODE_SIZE (TImode) && !unaligned
mgl@1371
  2845
+	  /* Do not emit ldm/stm for UC3 as ld.d/st.d is more optimal. */
mgl@1371
  2846
+	  && !TARGET_ARCH_UC)
mgl@1371
  2847
+	move_mode = TImode;
mgl@1371
  2848
+      else if ((bytes_to_go >= GET_MODE_SIZE (DImode)) && !unaligned)
mgl@1371
  2849
+	move_mode = DImode;
mgl@1371
  2850
+      else if (bytes_to_go >= GET_MODE_SIZE (SImode))
mgl@1371
  2851
+	move_mode = SImode;
mgl@1371
  2852
+      else
mgl@1371
  2853
+	move_mode = QImode;
mgl@1371
  2854
+
mgl@1371
  2855
+      {
mgl@1371
  2856
+        rtx src_mem;
mgl@1371
  2857
+	rtx dst_mem = gen_rtx_MEM (move_mode,
mgl@1371
  2858
+				   gen_rtx_PLUS (SImode, dst,
mgl@1371
  2859
+						 GEN_INT (dst_offset)));
mgl@1371
  2860
+        dst_offset += GET_MODE_SIZE (move_mode);
mgl@1371
  2861
+        if ( 0 /* This causes an error in GCC. Think there is
mgl@1371
  2862
+                  something wrong in the gcse pass which causes REQ_EQUIV notes
mgl@1371
  2863
+                  to be wrong so disabling it for now. */
mgl@1371
  2864
+             && move_mode == TImode
mgl@1371
  2865
+             && INTVAL (operands[2]) > GET_MODE_SIZE (TImode) )
mgl@1371
  2866
+          {
mgl@1371
  2867
+            src_mem = gen_rtx_MEM (move_mode,
mgl@1371
  2868
+				   gen_rtx_POST_INC (SImode, src));
mgl@1371
  2869
+          }
mgl@1371
  2870
+        else
mgl@1371
  2871
+          {
mgl@1371
  2872
+            src_mem = gen_rtx_MEM (move_mode,
mgl@1371
  2873
+				   gen_rtx_PLUS (SImode, src,
mgl@1371
  2874
+						 GEN_INT (src_offset)));
mgl@1371
  2875
+            src_offset += GET_MODE_SIZE (move_mode);
mgl@1371
  2876
+          }
mgl@1371
  2877
+
mgl@1371
  2878
+	bytes_to_go -= GET_MODE_SIZE (move_mode);
mgl@1371
  2879
+
mgl@1371
  2880
+	MEM_IN_STRUCT_P (dst_mem) = dst_in_struct_p;
mgl@1371
  2881
+	MEM_SCALAR_P (dst_mem) = dst_scalar_p;
mgl@1371
  2882
+
mgl@1371
  2883
+	MEM_IN_STRUCT_P (src_mem) = src_in_struct_p;
mgl@1371
  2884
+	MEM_SCALAR_P (src_mem) = src_scalar_p;
mgl@1371
  2885
+	emit_move_insn (dst_mem, src_mem);
mgl@1371
  2886
+
mgl@1371
  2887
+      }
mgl@1371
  2888
+    }
mgl@1371
  2889
+
mgl@1371
  2890
+  return 1;
mgl@1371
  2891
+}
mgl@1371
  2892
+
mgl@1371
  2893
+
mgl@1371
  2894
+
mgl@1371
  2895
+/*Expand the prologue instruction*/
mgl@1371
  2896
+void
mgl@1371
  2897
+avr32_expand_prologue (void)
mgl@1371
  2898
+{
mgl@1371
  2899
+  rtx insn, dwarf;
mgl@1371
  2900
+  unsigned long saved_reg_mask, saved_fp_reg_mask;
mgl@1371
  2901
+  int reglist8 = 0;
mgl@1371
  2902
+
mgl@1371
  2903
+  /* Naked functions does not have a prologue */
mgl@1371
  2904
+  if (IS_NAKED (avr32_current_func_type ()))
mgl@1371
  2905
+    return;
mgl@1371
  2906
+
mgl@1371
  2907
+  saved_reg_mask = avr32_compute_save_reg_mask (TRUE);
mgl@1371
  2908
+
mgl@1371
  2909
+  if (saved_reg_mask)
mgl@1371
  2910
+    {
mgl@1371
  2911
+      /* Must push used registers */
mgl@1371
  2912
+
mgl@1371
  2913
+      /* Should we use POPM or LDM? */
mgl@1371
  2914
+      int usePUSHM = TRUE;
mgl@1371
  2915
+      reglist8 = 0;
mgl@1371
  2916
+      if (((saved_reg_mask & (1 << 0)) ||
mgl@1371
  2917
+	   (saved_reg_mask & (1 << 1)) ||
mgl@1371
  2918
+	   (saved_reg_mask & (1 << 2)) || (saved_reg_mask & (1 << 3))))
mgl@1371
  2919
+	{
mgl@1371
  2920
+	  /* One of R0-R3 should at least be pushed */
mgl@1371
  2921
+	  if (((saved_reg_mask & (1 << 0)) &&
mgl@1371
  2922
+	       (saved_reg_mask & (1 << 1)) &&
mgl@1371
  2923
+	       (saved_reg_mask & (1 << 2)) && (saved_reg_mask & (1 << 3))))
mgl@1371
  2924
+	    {
mgl@1371
  2925
+	      /* All should be pushed */
mgl@1371
  2926
+	      reglist8 |= 0x01;
mgl@1371
  2927
+	    }
mgl@1371
  2928
+	  else
mgl@1371
  2929
+	    {
mgl@1371
  2930
+	      usePUSHM = FALSE;
mgl@1371
  2931
+	    }
mgl@1371
  2932
+	}
mgl@1371
  2933
+
mgl@1371
  2934
+      if (((saved_reg_mask & (1 << 4)) ||
mgl@1371
  2935
+	   (saved_reg_mask & (1 << 5)) ||
mgl@1371
  2936
+	   (saved_reg_mask & (1 << 6)) || (saved_reg_mask & (1 << 7))))
mgl@1371
  2937
+	{
mgl@1371
  2938
+	  /* One of R4-R7 should at least be pushed */
mgl@1371
  2939
+	  if (((saved_reg_mask & (1 << 4)) &&
mgl@1371
  2940
+	       (saved_reg_mask & (1 << 5)) &&
mgl@1371
  2941
+	       (saved_reg_mask & (1 << 6)) && (saved_reg_mask & (1 << 7))))
mgl@1371
  2942
+	    {
mgl@1371
  2943
+	      if (usePUSHM)
mgl@1371
  2944
+		/* All should be pushed */
mgl@1371
  2945
+		reglist8 |= 0x02;
mgl@1371
  2946
+	    }
mgl@1371
  2947
+	  else
mgl@1371
  2948
+	    {
mgl@1371
  2949
+	      usePUSHM = FALSE;
mgl@1371
  2950
+	    }
mgl@1371
  2951
+	}
mgl@1371
  2952
+
mgl@1371
  2953
+      if (((saved_reg_mask & (1 << 8)) || (saved_reg_mask & (1 << 9))))
mgl@1371
  2954
+	{
mgl@1371
  2955
+	  /* One of R8-R9 should at least be pushed */
mgl@1371
  2956
+	  if (((saved_reg_mask & (1 << 8)) && (saved_reg_mask & (1 << 9))))
mgl@1371
  2957
+	    {
mgl@1371
  2958
+	      if (usePUSHM)
mgl@1371
  2959
+		/* All should be pushed */
mgl@1371
  2960
+		reglist8 |= 0x04;
mgl@1371
  2961
+	    }
mgl@1371
  2962
+	  else
mgl@1371
  2963
+	    {
mgl@1371
  2964
+	      usePUSHM = FALSE;
mgl@1371
  2965
+	    }
mgl@1371
  2966
+	}
mgl@1371
  2967
+
mgl@1371
  2968
+      if (saved_reg_mask & (1 << 10))
mgl@1371
  2969
+	reglist8 |= 0x08;
mgl@1371
  2970
+
mgl@1371
  2971
+      if (saved_reg_mask & (1 << 11))
mgl@1371
  2972
+	reglist8 |= 0x10;
mgl@1371
  2973
+
mgl@1371
  2974
+      if (saved_reg_mask & (1 << 12))
mgl@1371
  2975
+	reglist8 |= 0x20;
mgl@1371
  2976
+
mgl@1371
  2977
+      if (saved_reg_mask & (1 << ASM_REGNUM (LR_REGNUM)))
mgl@1371
  2978
+	{
mgl@1371
  2979
+	  /* Push LR */
mgl@1371
  2980
+	  reglist8 |= 0x40;
mgl@1371
  2981
+	}
mgl@1371
  2982
+
mgl@1371
  2983
+      if (usePUSHM)
mgl@1371
  2984
+	{
mgl@1371
  2985
+	  insn = emit_multi_reg_push (reglist8, TRUE);
mgl@1371
  2986
+	}
mgl@1371
  2987
+      else
mgl@1371
  2988
+	{
mgl@1371
  2989
+	  insn = emit_multi_reg_push (saved_reg_mask, FALSE);
mgl@1371
  2990
+	}
mgl@1371
  2991
+      RTX_FRAME_RELATED_P (insn) = 1;
mgl@1371
  2992
+
mgl@1371
  2993
+      /* Prevent this instruction from being scheduled after any other
mgl@1371
  2994
+         instructions.  */
mgl@1371
  2995
+      emit_insn (gen_blockage ());
mgl@1371
  2996
+    }
mgl@1371
  2997
+
mgl@1371
  2998
+  saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
mgl@1371
  2999
+  if (saved_fp_reg_mask)
mgl@1371
  3000
+    {
mgl@1371
  3001
+      insn = emit_multi_fp_reg_push (saved_fp_reg_mask);
mgl@1371
  3002
+      RTX_FRAME_RELATED_P (insn) = 1;
mgl@1371
  3003
+
mgl@1371
  3004
+      /* Prevent this instruction from being scheduled after any other
mgl@1371
  3005
+         instructions.  */
mgl@1371
  3006
+      emit_insn (gen_blockage ());
mgl@1371
  3007
+    }
mgl@1371
  3008
+
mgl@1371
  3009
+  /* Set frame pointer */
mgl@1371
  3010
+  if (frame_pointer_needed)
mgl@1371
  3011
+    {
mgl@1371
  3012
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
mgl@1371
  3013
+      RTX_FRAME_RELATED_P (insn) = 1;
mgl@1371
  3014
+    }
mgl@1371
  3015
+
mgl@1371
  3016
+  if (get_frame_size () > 0)
mgl@1371
  3017
+    {
mgl@1371
  3018
+      if (avr32_const_ok_for_constraint_p (get_frame_size (), 'K', "Ks21"))
mgl@1371
  3019
+	{
mgl@1371
  3020
+	  insn = emit_insn (gen_rtx_SET (SImode,
mgl@1371
  3021
+					 stack_pointer_rtx,
mgl@1371
  3022
+					 gen_rtx_PLUS (SImode,
mgl@1371
  3023
+						       stack_pointer_rtx,
mgl@1371
  3024
+						       gen_rtx_CONST_INT
mgl@1371
  3025
+						       (SImode,
mgl@1371
  3026
+							-get_frame_size
mgl@1371
  3027
+							()))));
mgl@1371
  3028
+	  RTX_FRAME_RELATED_P (insn) = 1;
mgl@1371
  3029
+	}
mgl@1371
  3030
+      else
mgl@1371
  3031
+	{
mgl@1371
  3032
+	  /* Immediate is larger than k21 We must either check if we can use
mgl@1371
  3033
+	     one of the pushed reegisters as temporary storage or we must
mgl@1371
  3034
+	     make us a temp register by pushing a register to the stack. */
mgl@1371
  3035
+	  rtx temp_reg, const_pool_entry, insn;
mgl@1371
  3036
+	  if (saved_reg_mask)
mgl@1371
  3037
+	    {
mgl@1371
  3038
+	      temp_reg =
mgl@1371
  3039
+		gen_rtx_REG (SImode,
mgl@1371
  3040
+			     INTERNAL_REGNUM (avr32_get_saved_reg
mgl@1371
  3041
+					      (saved_reg_mask)));
mgl@1371
  3042
+	    }
mgl@1371
  3043
+	  else
mgl@1371
  3044
+	    {
mgl@1371
  3045
+	      temp_reg = gen_rtx_REG (SImode, INTERNAL_REGNUM (7));
mgl@1371
  3046
+	      emit_move_insn (gen_rtx_MEM
mgl@1371
  3047
+			      (SImode,
mgl@1371
  3048
+			       gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)),
mgl@1371
  3049
+			      temp_reg);
mgl@1371
  3050
+	    }
mgl@1371
  3051
+
mgl@1371
  3052
+	  const_pool_entry =
mgl@1371
  3053
+	    force_const_mem (SImode,
mgl@1371
  3054
+			     gen_rtx_CONST_INT (SImode, get_frame_size ()));
mgl@1371
  3055
+	  emit_move_insn (temp_reg, const_pool_entry);
mgl@1371
  3056
+
mgl@1371
  3057
+	  insn = emit_insn (gen_rtx_SET (SImode,
mgl@1371
  3058
+					 stack_pointer_rtx,
mgl@1371
  3059
+					 gen_rtx_MINUS (SImode,
mgl@1371
  3060
+							stack_pointer_rtx,
mgl@1371
  3061
+							temp_reg)));
mgl@1371
  3062
+
mgl@1371
  3063
+	  dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
mgl@1371
  3064
+			       gen_rtx_PLUS (SImode, stack_pointer_rtx,
mgl@1371
  3065
+					     GEN_INT (-get_frame_size ())));
mgl@1371
  3066
+	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
mgl@1371
  3067
+						dwarf, REG_NOTES (insn));
mgl@1371
  3068
+	  RTX_FRAME_RELATED_P (insn) = 1;
mgl@1371
  3069
+
mgl@1371
  3070
+	  if (!saved_reg_mask)
mgl@1371
  3071
+	    {
mgl@1371
  3072
+	      insn =
mgl@1371
  3073
+		emit_move_insn (temp_reg,
mgl@1371
  3074
+				gen_rtx_MEM (SImode,
mgl@1371
  3075
+					     gen_rtx_POST_INC (SImode,
mgl@1371
  3076
+							       gen_rtx_REG
mgl@1371
  3077
+							       (SImode,
mgl@1371
  3078
+								13))));
mgl@1371
  3079
+	    }
mgl@1371
  3080
+
mgl@1371
  3081
+	  /* Mark the temp register as dead */
mgl@1371
  3082
+	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, temp_reg,
mgl@1371
  3083
+						REG_NOTES (insn));
mgl@1371
  3084
+
mgl@1371
  3085
+
mgl@1371
  3086
+	}
mgl@1371
  3087
+
mgl@1371
  3088
+      /* Prevent the the stack adjustment to be scheduled after any
mgl@1371
  3089
+         instructions using the frame pointer.  */
mgl@1371
  3090
+      emit_insn (gen_blockage ());
mgl@1371
  3091
+    }
mgl@1371
  3092
+
mgl@1371
  3093
+  /* Load GOT */
mgl@1371
  3094
+  if (flag_pic)
mgl@1371
  3095
+    {
mgl@1371
  3096
+      avr32_load_pic_register ();
mgl@1371
  3097
+
mgl@1371
  3098
+      /* gcc does not know that load or call instructions might use the pic
mgl@1371
  3099
+         register so it might schedule these instructions before the loading
mgl@1371
  3100
+         of the pic register. To avoid this emit a barrier for now. TODO!
mgl@1371
  3101
+         Find out a better way to let gcc know which instructions might use
mgl@1371
  3102
+         the pic register. */
mgl@1371
  3103
+      emit_insn (gen_blockage ());
mgl@1371
  3104
+    }
mgl@1371
  3105
+  return;
mgl@1371
  3106
+}
mgl@1371
  3107
+
mgl@1371
  3108
+void
mgl@1371
  3109
+avr32_set_return_address (rtx source, rtx scratch)
mgl@1371
  3110
+{
mgl@1371
  3111
+  rtx addr;
mgl@1371
  3112
+  unsigned long saved_regs;
mgl@1371
  3113
+
mgl@1371
  3114
+  saved_regs = avr32_compute_save_reg_mask (TRUE);
mgl@1371
  3115
+
mgl@1371
  3116
+  if (!(saved_regs & (1 << ASM_REGNUM (LR_REGNUM))))
mgl@1371
  3117
+    emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
mgl@1371
  3118
+  else
mgl@1371
  3119
+    {
mgl@1371
  3120
+      if (frame_pointer_needed)
mgl@1371
  3121
+	addr = gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM);
mgl@1371
  3122
+      else
mgl@1371
  3123
+	if (avr32_const_ok_for_constraint_p (get_frame_size (), 'K', "Ks16"))
mgl@1371
  3124
+	{
mgl@1371
  3125
+	  addr = plus_constant (stack_pointer_rtx, get_frame_size ());
mgl@1371
  3126
+	}
mgl@1371
  3127
+      else
mgl@1371
  3128
+	{
mgl@1371
  3129
+	  emit_insn (gen_movsi (scratch, GEN_INT (get_frame_size ())));
mgl@1371
  3130
+	  addr = scratch;
mgl@1371
  3131
+	}
mgl@1371
  3132
+      emit_move_insn (gen_rtx_MEM (Pmode, addr), source);
mgl@1371
  3133
+    }
mgl@1371
  3134
+}
mgl@1371
  3135
+
mgl@1371
  3136
+
mgl@1371
  3137
+
mgl@1371
  3138
+/* Return the length of INSN.  LENGTH is the initial length computed by
mgl@1371
  3139
+   attributes in the machine-description file.  */
mgl@1371
  3140
+
mgl@1371
  3141
+int
mgl@1371
  3142
+avr32_adjust_insn_length (rtx insn ATTRIBUTE_UNUSED,
mgl@1371
  3143
+			  int length ATTRIBUTE_UNUSED)
mgl@1371
  3144
+{
mgl@1371
  3145
+  return length;
mgl@1371
  3146
+}
mgl@1371
  3147
+
mgl@1371
  3148
+void
mgl@1371
  3149
+avr32_output_return_instruction (int single_ret_inst ATTRIBUTE_UNUSED,
mgl@1371
  3150
+				 int iscond ATTRIBUTE_UNUSED,
mgl@1371
  3151
+				 rtx cond ATTRIBUTE_UNUSED, rtx r12_imm)
mgl@1371
  3152
+{
mgl@1371
  3153
+
mgl@1371
  3154
+  unsigned long saved_reg_mask, saved_fp_reg_mask;
mgl@1371
  3155
+  int insert_ret = TRUE;
mgl@1371
  3156
+  int reglist8 = 0;
mgl@1371
  3157
+  int stack_adjustment = get_frame_size ();
mgl@1371
  3158
+  unsigned int func_type = avr32_current_func_type ();
mgl@1371
  3159
+  FILE *f = asm_out_file;
mgl@1371
  3160
+
mgl@1371
  3161
+  /* Naked functions does not have an epilogue */
mgl@1371
  3162
+  if (IS_NAKED (func_type))
mgl@1371
  3163
+    return;
mgl@1371
  3164
+
mgl@1371
  3165
+  saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
mgl@1371
  3166
+
mgl@1371
  3167
+  saved_reg_mask = avr32_compute_save_reg_mask (FALSE);
mgl@1371
  3168
+
mgl@1371
  3169
+  /* Reset frame pointer */
mgl@1371
  3170
+  if (stack_adjustment > 0)
mgl@1371
  3171
+    {
mgl@1371
  3172
+      if (avr32_const_ok_for_constraint_p (stack_adjustment, 'I', "Is21"))
mgl@1371
  3173
+	{
mgl@1371
  3174
+	  fprintf (f, "\tsub\tsp, %i # Reset Frame Pointer\n",
mgl@1371
  3175
+		   -stack_adjustment);
mgl@1371
  3176
+	}
mgl@1371
  3177
+      else
mgl@1371
  3178
+	{
mgl@1371
  3179
+	  /* TODO! Is it safe to use r8 as scratch?? */
mgl@1371
  3180
+	  fprintf (f, "\tmov\tr8, lo(%i) # Reset Frame Pointer\n",
mgl@1371
  3181
+		   -stack_adjustment);
mgl@1371
  3182
+	  fprintf (f, "\torh\tr8, hi(%i) # Reset Frame Pointer\n",
mgl@1371
  3183
+		   -stack_adjustment);
mgl@1371
  3184
+	  fprintf (f, "\tadd\tsp, r8  # Reset Frame Pointer\n");
mgl@1371
  3185
+	}
mgl@1371
  3186
+    }
mgl@1371
  3187
+
mgl@1371
  3188
+  if (saved_fp_reg_mask)
mgl@1371
  3189
+    {
mgl@1371
  3190
+      char reglist[64];		/* 64 bytes should be enough... */
mgl@1371
  3191
+      avr32_make_fp_reglist_w (saved_fp_reg_mask, (char *) reglist);
mgl@1371
  3192
+      fprintf (f, "\tldcm.w\tcp0, sp++, %s\n", reglist);
mgl@1371
  3193
+      if (saved_fp_reg_mask & ~0xff)
mgl@1371
  3194
+	{
mgl@1371
  3195
+	  saved_fp_reg_mask &= ~0xff;
mgl@1371
  3196
+	  avr32_make_fp_reglist_d (saved_fp_reg_mask, (char *) reglist);
mgl@1371
  3197
+	  fprintf (f, "\tldcm.d\tcp0, sp++, %s\n", reglist);
mgl@1371
  3198
+	}
mgl@1371
  3199
+    }
mgl@1371
  3200
+
mgl@1371
  3201
+  if (saved_reg_mask)
mgl@1371
  3202
+    {
mgl@1371
  3203
+      /* Must pop used registers */
mgl@1371
  3204
+
mgl@1371
  3205
+      /* Should we use POPM or LDM? */
mgl@1371
  3206
+      int usePOPM = TRUE;
mgl@1371
  3207
+      if (((saved_reg_mask & (1 << 0)) ||
mgl@1371
  3208
+	   (saved_reg_mask & (1 << 1)) ||
mgl@1371
  3209
+	   (saved_reg_mask & (1 << 2)) || (saved_reg_mask & (1 << 3))))
mgl@1371
  3210
+	{
mgl@1371
  3211
+	  /* One of R0-R3 should at least be popped */
mgl@1371
  3212
+	  if (((saved_reg_mask & (1 << 0)) &&
mgl@1371
  3213
+	       (saved_reg_mask & (1 << 1)) &&
mgl@1371
  3214
+	       (saved_reg_mask & (1 << 2)) && (saved_reg_mask & (1 << 3))))
mgl@1371
  3215
+	    {
mgl@1371
  3216
+	      /* All should be popped */
mgl@1371
  3217
+	      reglist8 |= 0x01;
mgl@1371
  3218
+	    }
mgl@1371
  3219
+	  else
mgl@1371
  3220
+	    {
mgl@1371
  3221
+	      usePOPM = FALSE;
mgl@1371
  3222
+	    }
mgl@1371
  3223
+	}
mgl@1371
  3224
+
mgl@1371
  3225
+      if (((saved_reg_mask & (1 << 4)) ||
mgl@1371
  3226
+	   (saved_reg_mask & (1 << 5)) ||
mgl@1371
  3227
+	   (saved_reg_mask & (1 << 6)) || (saved_reg_mask & (1 << 7))))
mgl@1371
  3228
+	{
mgl@1371
  3229
+	  /* One of R0-R3 should at least be popped */
mgl@1371
  3230
+	  if (((saved_reg_mask & (1 << 4)) &&
mgl@1371
  3231
+	       (saved_reg_mask & (1 << 5)) &&
mgl@1371
  3232
+	       (saved_reg_mask & (1 << 6)) && (saved_reg_mask & (1 << 7))))
mgl@1371
  3233
+	    {
mgl@1371
  3234
+	      if (usePOPM)
mgl@1371
  3235
+		/* All should be popped */
mgl@1371
  3236
+		reglist8 |= 0x02;
mgl@1371
  3237
+	    }
mgl@1371
  3238
+	  else
mgl@1371
  3239
+	    {
mgl@1371
  3240
+	      usePOPM = FALSE;
mgl@1371
  3241
+	    }
mgl@1371
  3242
+	}
mgl@1371
  3243
+
mgl@1371
  3244
+      if (((saved_reg_mask & (1 << 8)) || (saved_reg_mask & (1 << 9))))
mgl@1371
  3245
+	{
mgl@1371
  3246
+	  /* One of R8-R9 should at least be pushed */
mgl@1371
  3247
+	  if (((saved_reg_mask & (1 << 8)) && (saved_reg_mask & (1 << 9))))
mgl@1371
  3248
+	    {
mgl@1371
  3249
+	      if (usePOPM)
mgl@1371
  3250
+		/* All should be pushed */
mgl@1371
  3251
+		reglist8 |= 0x04;
mgl@1371
  3252
+	    }
mgl@1371
  3253
+	  else
mgl@1371
  3254
+	    {
mgl@1371
  3255
+	      usePOPM = FALSE;
mgl@1371
  3256
+	    }
mgl@1371
  3257
+	}
mgl@1371
  3258
+
mgl@1371
  3259
+      if (saved_reg_mask & (1 << 10))
mgl@1371
  3260
+	reglist8 |= 0x08;
mgl@1371
  3261
+
mgl@1371
  3262
+      if (saved_reg_mask & (1 << 11))
mgl@1371
  3263
+	reglist8 |= 0x10;
mgl@1371
  3264
+
mgl@1371
  3265
+      if (saved_reg_mask & (1 << 12))
mgl@1371
  3266
+	reglist8 |= 0x20;
mgl@1371
  3267
+
mgl@1371
  3268
+      if (saved_reg_mask & (1 << ASM_REGNUM (LR_REGNUM)))
mgl@1371
  3269
+	/* Pop LR */
mgl@1371
  3270
+	reglist8 |= 0x40;
mgl@1371
  3271
+
mgl@1371
  3272
+      if (saved_reg_mask & (1 << ASM_REGNUM (PC_REGNUM)))
mgl@1371
  3273
+	/* Pop LR into PC. */
mgl@1371
  3274
+	reglist8 |= 0x80;
mgl@1371
  3275
+
mgl@1371
  3276
+      if (usePOPM)
mgl@1371
  3277
+	{
mgl@1371
  3278
+	  char reglist[64];	/* 64 bytes should be enough... */
mgl@1371
  3279
+	  avr32_make_reglist8 (reglist8, (char *) reglist);
mgl@1371
  3280
+
mgl@1371
  3281
+	  if (reglist8 & 0x80)
mgl@1371
  3282
+	    /* This instruction is also a return */
mgl@1371
  3283
+	    insert_ret = FALSE;
mgl@1371
  3284
+
mgl@1371
  3285
+	  if (r12_imm && !insert_ret)
mgl@1371
  3286
+	    fprintf (f, "\tpopm\t%s, r12=%li\n", reglist, INTVAL (r12_imm));
mgl@1371
  3287
+	  else
mgl@1371
  3288
+	    fprintf (f, "\tpopm\t%s\n", reglist);
mgl@1371
  3289
+
mgl@1371
  3290
+	}
mgl@1371
  3291
+      else
mgl@1371
  3292
+	{
mgl@1371
  3293
+	  char reglist[64];	/* 64 bytes should be enough... */
mgl@1371
  3294
+	  avr32_make_reglist16 (saved_reg_mask, (char *) reglist);
mgl@1371
  3295
+	  if (saved_reg_mask & (1 << ASM_REGNUM (PC_REGNUM)))
mgl@1371
  3296
+	    /* This instruction is also a return */
mgl@1371
  3297
+	    insert_ret = FALSE;
mgl@1371
  3298
+
mgl@1371
  3299
+	  if (r12_imm && !insert_ret)
mgl@1371
  3300
+	    fprintf (f, "\tldm\tsp++, %s, r12=%li\n", reglist,
mgl@1371
  3301
+		     INTVAL (r12_imm));
mgl@1371
  3302
+	  else
mgl@1371
  3303
+	    fprintf (f, "\tldm\tsp++, %s\n", reglist);
mgl@1371
  3304
+
mgl@1371
  3305
+	}
mgl@1371
  3306
+
mgl@1371
  3307
+    }
mgl@1371
  3308
+
mgl@1371
  3309
+  /* Stack adjustment for exception handler.  */
mgl@1371
  3310
+  if (current_function_calls_eh_return)
mgl@1371
  3311
+    fprintf (f, "\tadd\tsp, r%d\n", ASM_REGNUM (EH_RETURN_STACKADJ_REGNO));
mgl@1371
  3312
+
mgl@1371
  3313
+
mgl@1371
  3314
+  if (IS_INTERRUPT (func_type))
mgl@1371
  3315
+    {
mgl@1371
  3316
+      fprintf (f, "\trete\n");
mgl@1371
  3317
+    }
mgl@1371
  3318
+  else if (insert_ret)
mgl@1371
  3319
+    {
mgl@1371
  3320
+      if (r12_imm)
mgl@1371
  3321
+	fprintf (f, "\tretal\t%li\n", INTVAL (r12_imm));
mgl@1371
  3322
+      else
mgl@1371
  3323
+	fprintf (f, "\tretal\tr12\n");
mgl@1371
  3324
+    }
mgl@1371
  3325
+}
mgl@1371
  3326
+
mgl@1371
  3327
+/* Function for converting a fp-register mask to a
mgl@1371
  3328
+   reglistCPD8 register list string. */
mgl@1371
  3329
+void
mgl@1371
  3330
+avr32_make_fp_reglist_d (int reglist_mask, char *reglist_string)
mgl@1371
  3331
+{
mgl@1371
  3332
+  int i;
mgl@1371
  3333
+
mgl@1371
  3334
+  /* Make sure reglist_string is empty */
mgl@1371
  3335
+  reglist_string[0] = '\0';
mgl@1371
  3336
+
mgl@1371
  3337
+  for (i = 0; i < NUM_FP_REGS; i += 2)
mgl@1371
  3338
+    {
mgl@1371
  3339
+      if (reglist_mask & (1 << i))
mgl@1371
  3340
+	{
mgl@1371
  3341
+	  strlen (reglist_string) ?
mgl@1371
  3342
+	    sprintf (reglist_string, "%s, %s-%s", reglist_string,
mgl@1371
  3343
+		     reg_names[INTERNAL_FP_REGNUM (i)],
mgl@1371
  3344
+		     reg_names[INTERNAL_FP_REGNUM (i + 1)]) :
mgl@1371
  3345
+	    sprintf (reglist_string, "%s-%s",
mgl@1371
  3346
+		     reg_names[INTERNAL_FP_REGNUM (i)],
mgl@1371
  3347
+		     reg_names[INTERNAL_FP_REGNUM (i + 1)]);
mgl@1371
  3348
+	}
mgl@1371
  3349
+    }
mgl@1371
  3350
+}
mgl@1371
  3351
+
mgl@1371
  3352
+/* Function for converting a fp-register mask to a
mgl@1371
  3353
+   reglistCP8 register list string. */
mgl@1371
  3354
+void
mgl@1371
  3355
+avr32_make_fp_reglist_w (int reglist_mask, char *reglist_string)
mgl@1371
  3356
+{
mgl@1371
  3357
+  int i;
mgl@1371
  3358
+
mgl@1371
  3359
+  /* Make sure reglist_string is empty */
mgl@1371
  3360
+  reglist_string[0] = '\0';
mgl@1371
  3361
+
mgl@1371
  3362
+  for (i = 0; i < NUM_FP_REGS; ++i)
mgl@1371
  3363
+    {
mgl@1371
  3364
+      if (reglist_mask & (1 << i))
mgl@1371
  3365
+	{
mgl@1371
  3366
+	  strlen (reglist_string) ?
mgl@1371
  3367
+	    sprintf (reglist_string, "%s, %s", reglist_string,
mgl@1371
  3368
+		     reg_names[INTERNAL_FP_REGNUM (i)]) :
mgl@1371
  3369
+	    sprintf (reglist_string, "%s", reg_names[INTERNAL_FP_REGNUM (i)]);
mgl@1371
  3370
+	}
mgl@1371
  3371
+    }
mgl@1371
  3372
+}
mgl@1371
  3373
+
mgl@1371
  3374
+void
mgl@1371
  3375
+avr32_make_reglist16 (int reglist16_vect, char *reglist16_string)
mgl@1371
  3376
+{
mgl@1371
  3377
+  int i;
mgl@1371
  3378
+
mgl@1371
  3379
+  /* Make sure reglist16_string is empty */
mgl@1371
  3380
+  reglist16_string[0] = '\0';
mgl@1371
  3381
+
mgl@1371
  3382
+  for (i = 0; i < 16; ++i)
mgl@1371
  3383
+    {
mgl@1371
  3384
+      if (reglist16_vect & (1 << i))
mgl@1371
  3385
+	{
mgl@1371
  3386
+	  strlen (reglist16_string) ?
mgl@1371
  3387
+	    sprintf (reglist16_string, "%s, %s", reglist16_string,
mgl@1371
  3388
+		     reg_names[INTERNAL_REGNUM (i)]) :
mgl@1371
  3389
+	    sprintf (reglist16_string, "%s", reg_names[INTERNAL_REGNUM (i)]);
mgl@1371
  3390
+	}
mgl@1371
  3391
+    }
mgl@1371
  3392
+}
mgl@1371
  3393
+
mgl@1371
  3394
+int
mgl@1371
  3395
+avr32_convert_to_reglist16 (int reglist8_vect)
mgl@1371
  3396
+{
mgl@1371
  3397
+  int reglist16_vect = 0;
mgl@1371
  3398
+  if (reglist8_vect & 0x1)
mgl@1371
  3399
+    reglist16_vect |= 0xF;
mgl@1371
  3400
+  if (reglist8_vect & 0x2)
mgl@1371
  3401
+    reglist16_vect |= 0xF0;
mgl@1371
  3402
+  if (reglist8_vect & 0x4)
mgl@1371
  3403
+    reglist16_vect |= 0x300;
mgl@1371
  3404
+  if (reglist8_vect & 0x8)
mgl@1371
  3405
+    reglist16_vect |= 0x400;
mgl@1371
  3406
+  if (reglist8_vect & 0x10)
mgl@1371
  3407
+    reglist16_vect |= 0x800;
mgl@1371
  3408
+  if (reglist8_vect & 0x20)
mgl@1371
  3409
+    reglist16_vect |= 0x1000;
mgl@1371
  3410
+  if (reglist8_vect & 0x40)
mgl@1371
  3411
+    reglist16_vect |= 0x4000;
mgl@1371
  3412
+  if (reglist8_vect & 0x80)
mgl@1371
  3413
+    reglist16_vect |= 0x8000;
mgl@1371
  3414
+
mgl@1371
  3415
+  return reglist16_vect;
mgl@1371
  3416
+}
mgl@1371
  3417
+
mgl@1371
  3418
+void
mgl@1371
  3419
+avr32_make_reglist8 (int reglist8_vect, char *reglist8_string)
mgl@1371
  3420
+{
mgl@1371
  3421
+  /* Make sure reglist8_string is empty */
mgl@1371
  3422
+  reglist8_string[0] = '\0';
mgl@1371
  3423
+
mgl@1371
  3424
+  if (reglist8_vect & 0x1)
mgl@1371
  3425
+    sprintf (reglist8_string, "r0-r3");
mgl@1371
  3426
+  if (reglist8_vect & 0x2)
mgl@1371
  3427
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r4-r7",
mgl@1371
  3428
+					reglist8_string) :
mgl@1371
  3429
+      sprintf (reglist8_string, "r4-r7");
mgl@1371
  3430
+  if (reglist8_vect & 0x4)
mgl@1371
  3431
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r8-r9",
mgl@1371
  3432
+					reglist8_string) :
mgl@1371
  3433
+      sprintf (reglist8_string, "r8-r9");
mgl@1371
  3434
+  if (reglist8_vect & 0x8)
mgl@1371
  3435
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r10",
mgl@1371
  3436
+					reglist8_string) :
mgl@1371
  3437
+      sprintf (reglist8_string, "r10");
mgl@1371
  3438
+  if (reglist8_vect & 0x10)
mgl@1371
  3439
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r11",
mgl@1371
  3440
+					reglist8_string) :
mgl@1371
  3441
+      sprintf (reglist8_string, "r11");
mgl@1371
  3442
+  if (reglist8_vect & 0x20)
mgl@1371
  3443
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r12",
mgl@1371
  3444
+					reglist8_string) :
mgl@1371
  3445
+      sprintf (reglist8_string, "r12");
mgl@1371
  3446
+  if (reglist8_vect & 0x40)
mgl@1371
  3447
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, lr",
mgl@1371
  3448
+					reglist8_string) :
mgl@1371
  3449
+      sprintf (reglist8_string, "lr");
mgl@1371
  3450
+  if (reglist8_vect & 0x80)
mgl@1371
  3451
+    strlen (reglist8_string) ? sprintf (reglist8_string, "%s, pc",
mgl@1371
  3452
+					reglist8_string) :
mgl@1371
  3453
+      sprintf (reglist8_string, "pc");
mgl@1371
  3454
+}
mgl@1371
  3455
+
mgl@1371
  3456
+int
mgl@1371
  3457
+avr32_eh_return_data_regno (int n)
mgl@1371
  3458
+{
mgl@1371
  3459
+  if (n >= 0 && n <= 3)
mgl@1371
  3460
+    return 8 + n;
mgl@1371
  3461
+  else
mgl@1371
  3462
+    return INVALID_REGNUM;
mgl@1371
  3463
+}
mgl@1371
  3464
+
mgl@1371
  3465
+/* Compute the distance from register FROM to register TO.
mgl@1371
  3466
+   These can be the arg pointer, the frame pointer or
mgl@1371
  3467
+   the stack pointer.
mgl@1371
  3468
+   Typical stack layout looks like this:
mgl@1371
  3469
+
mgl@1371
  3470
+       old stack pointer -> |    |
mgl@1371
  3471
+			     ----
mgl@1371
  3472
+			    |    | \
mgl@1371
  3473
+			    |    |   saved arguments for
mgl@1371
  3474
+			    |    |   vararg functions
mgl@1371
  3475
+ arg_pointer	->	    |    | /
mgl@1371
  3476
+			      --
mgl@1371
  3477
+			    |    | \
mgl@1371
  3478
+			    |    |   call saved
mgl@1371
  3479
+			    |    |   registers
mgl@1371
  3480
+			    |    | /
mgl@1371
  3481
+  frame ptr	 ->	--
mgl@1371
  3482
+			    |    | \
mgl@1371
  3483
+			    |    |   local
mgl@1371
  3484
+			    |    |   variables
mgl@1371
  3485
+  stack ptr -->	     |    | /
mgl@1371
  3486
+			      --
mgl@1371
  3487
+			    |    | \
mgl@1371
  3488
+			    |    |   outgoing
mgl@1371
  3489
+			    |    |   arguments
mgl@1371
  3490
+			    |    | /
mgl@1371
  3491
+			      --
mgl@1371
  3492
+
mgl@1371
  3493
+  For a given funciton some or all of these stack compomnents
mgl@1371
  3494
+  may not be needed, giving rise to the possibility of
mgl@1371
  3495
+  eliminating some of the registers.
mgl@1371
  3496
+
mgl@1371
  3497
+  The values returned by this function must reflect the behaviour
mgl@1371
  3498
+  of avr32_expand_prologue() and avr32_compute_save_reg_mask().
mgl@1371
  3499
+
mgl@1371
  3500
+  The sign of the number returned reflects the direction of stack
mgl@1371
  3501
+  growth, so the values are positive for all eliminations except
mgl@1371
  3502
+  from the soft frame pointer to the hard frame pointer.  */
mgl@1371
  3503
+
mgl@1371
  3504
+
mgl@1371
  3505
+int
mgl@1371
  3506
+avr32_initial_elimination_offset (int from, int to)
mgl@1371
  3507
+{
mgl@1371
  3508
+  int i;
mgl@1371
  3509
+  int call_saved_regs = 0;
mgl@1371
  3510
+  unsigned long saved_reg_mask, saved_fp_reg_mask;
mgl@1371
  3511
+  unsigned int local_vars = get_frame_size ();
mgl@1371
  3512
+
mgl@1371
  3513
+  saved_reg_mask = avr32_compute_save_reg_mask (TRUE);
mgl@1371
  3514
+  saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
mgl@1371
  3515
+
mgl@1371
  3516
+  for (i = 0; i < 16; ++i)
mgl@1371
  3517
+    {
mgl@1371
  3518
+      if (saved_reg_mask & (1 << i))
mgl@1371
  3519
+	call_saved_regs += 4;
mgl@1371
  3520
+    }
mgl@1371
  3521
+
mgl@1371
  3522
+  for (i = 0; i < NUM_FP_REGS; ++i)
mgl@1371
  3523
+    {
mgl@1371
  3524
+      if (saved_fp_reg_mask & (1 << i))
mgl@1371
  3525
+	call_saved_regs += 4;
mgl@1371
  3526
+    }
mgl@1371
  3527
+
mgl@1371
  3528
+  switch (from)
mgl@1371
  3529
+    {
mgl@1371
  3530
+    case ARG_POINTER_REGNUM:
mgl@1371
  3531
+      switch (to)
mgl@1371
  3532
+	{
mgl@1371
  3533
+	case STACK_POINTER_REGNUM:
mgl@1371
  3534
+	  return call_saved_regs + local_vars;
mgl@1371
  3535
+	case FRAME_POINTER_REGNUM:
mgl@1371
  3536
+	  return call_saved_regs;
mgl@1371
  3537
+	default:
mgl@1371
  3538
+	  abort ();
mgl@1371
  3539
+	}
mgl@1371
  3540
+    case FRAME_POINTER_REGNUM:
mgl@1371
  3541
+      switch (to)
mgl@1371
  3542
+	{
mgl@1371
  3543
+	case STACK_POINTER_REGNUM:
mgl@1371
  3544
+	  return local_vars;
mgl@1371
  3545
+	default:
mgl@1371
  3546
+	  abort ();
mgl@1371
  3547
+	}
mgl@1371
  3548
+    default:
mgl@1371
  3549
+      abort ();
mgl@1371
  3550
+    }
mgl@1371
  3551
+}
mgl@1371
  3552
+
mgl@1371
  3553
+
mgl@1371
  3554
+/*
mgl@1371
  3555
+  Returns a rtx used when passing the next argument to a function.
mgl@1371
  3556
+  avr32_init_cumulative_args() and avr32_function_arg_advance() sets witch
mgl@1371
  3557
+  register to use.
mgl@1371
  3558
+*/
mgl@1371
  3559
+rtx
mgl@1371
  3560
+avr32_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
mgl@1371
  3561
+		    tree type, int named)
mgl@1371
  3562
+{
mgl@1371
  3563
+  int index = -1;
mgl@1371
  3564
+
mgl@1371
  3565
+  HOST_WIDE_INT arg_size, arg_rsize;
mgl@1371
  3566
+  if (type)
mgl@1371
  3567
+    {
mgl@1371
  3568
+      arg_size = int_size_in_bytes (type);
mgl@1371
  3569
+    }
mgl@1371
  3570
+  else
mgl@1371
  3571
+    {
mgl@1371
  3572
+      arg_size = GET_MODE_SIZE (mode);
mgl@1371
  3573
+    }
mgl@1371
  3574
+  arg_rsize = PUSH_ROUNDING (arg_size);
mgl@1371
  3575
+
mgl@1371
  3576
+  /*
mgl@1371
  3577
+     The last time this macro is called, it is called with mode == VOIDmode,
mgl@1371
  3578
+     and its result is passed to the call or call_value pattern as operands 2
mgl@1371
  3579
+     and 3 respectively. */
mgl@1371
  3580
+  if (mode == VOIDmode)
mgl@1371
  3581
+    {
mgl@1371
  3582
+      return gen_rtx_CONST_INT (SImode, 22);	/* ToDo: fixme. */
mgl@1371
  3583
+    }
mgl@1371
  3584
+
mgl@1371
  3585
+  if ((*targetm.calls.must_pass_in_stack) (mode, type) || !named)
mgl@1371
  3586
+    {
mgl@1371
  3587
+      return NULL_RTX;
mgl@1371
  3588
+    }
mgl@1371
  3589
+
mgl@1371
  3590
+  if (arg_rsize == 8)
mgl@1371
  3591
+    {
mgl@1371
  3592
+      /* use r11:r10 or r9:r8. */
mgl@1371
  3593
+      if (!(GET_USED_INDEX (cum, 1) || GET_USED_INDEX (cum, 2)))
mgl@1371
  3594
+	index = 1;
mgl@1371
  3595
+      else if (!(GET_USED_INDEX (cum, 3) || GET_USED_INDEX (cum, 4)))
mgl@1371
  3596
+	index = 3;
mgl@1371
  3597
+      else
mgl@1371
  3598
+	index = -1;
mgl@1371
  3599
+    }
mgl@1371
  3600
+  else if (arg_rsize == 4)
mgl@1371
  3601
+    {				/* Use first available register */
mgl@1371
  3602
+      index = 0;
mgl@1371
  3603
+      while (index <= LAST_CUM_REG_INDEX && GET_USED_INDEX (cum, index))
mgl@1371
  3604
+	index++;
mgl@1371
  3605
+      if (index > LAST_CUM_REG_INDEX)
mgl@1371
  3606
+	index = -1;
mgl@1371
  3607
+    }
mgl@1371
  3608
+
mgl@1371
  3609
+  SET_REG_INDEX (cum, index);
mgl@1371
  3610
+
mgl@1371
  3611
+  if (GET_REG_INDEX (cum) >= 0)
mgl@1371
  3612
+    return gen_rtx_REG (mode,
mgl@1371
  3613
+			avr32_function_arg_reglist[GET_REG_INDEX (cum)]);
mgl@1371
  3614
+
mgl@1371
  3615
+  return NULL_RTX;
mgl@1371
  3616
+}
mgl@1371
  3617
+
mgl@1371
  3618
+/*
mgl@1371
  3619
+  Set the register used for passing the first argument to a function.
mgl@1371
  3620
+*/
mgl@1371
  3621
+void
mgl@1371
  3622
+avr32_init_cumulative_args (CUMULATIVE_ARGS * cum, 
mgl@1371
  3623
+                            tree fntype ATTRIBUTE_UNUSED,
mgl@1371
  3624
+                            rtx libname ATTRIBUTE_UNUSED,
mgl@1371
  3625
+                            tree fndecl ATTRIBUTE_UNUSED)
mgl@1371
  3626
+  {
mgl@1371
  3627
+    /* Set all registers as unused. */
mgl@1371
  3628
+    SET_INDEXES_UNUSED (cum);
mgl@1371
  3629
+
mgl@1371
  3630
+    /* Reset uses_anonymous_args */
mgl@1371
  3631
+    cum->uses_anonymous_args = 0;
mgl@1371
  3632
+
mgl@1371
  3633
+    /* Reset size of stack pushed arguments */
mgl@1371
  3634
+    cum->stack_pushed_args_size = 0;
mgl@1371
  3635
+  }
mgl@1371
  3636
+
mgl@1371
  3637
+/*
mgl@1371
  3638
+  Set register used for passing the next argument to a function. Only the
mgl@1371
  3639
+  Scratch Registers are used.
mgl@1371
  3640
+
mgl@1371
  3641
+		number  name
mgl@1371
  3642
+		   15   r15  PC
mgl@1371
  3643
+		   14   r14  LR
mgl@1371
  3644
+		   13   r13 _SP_________
mgl@1371
  3645
+     FIRST_CUM_REG 12   r12 _||_
mgl@1371
  3646
+		   10   r11  ||
mgl@1371
  3647
+		   11   r10 _||_  Scratch Registers
mgl@1371
  3648
+		    8   r9   ||
mgl@1371
  3649
+  LAST_SCRATCH_REG  9   r8  _\/_________
mgl@1371
  3650
+		    6   r7   /\
mgl@1371
  3651
+		    7   r6   ||
mgl@1371
  3652
+		    4   r5   ||
mgl@1371
  3653
+		    5   r4   ||
mgl@1371
  3654
+		    2   r3   ||
mgl@1371
  3655
+		    3   r2   ||
mgl@1371
  3656
+		    0   r1   ||
mgl@1371
  3657
+		    1   r0  _||_________
mgl@1371
  3658
+
mgl@1371
  3659
+*/
mgl@1371
  3660
+void
mgl@1371
  3661
+avr32_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
mgl@1371
  3662
+			    tree type, int named ATTRIBUTE_UNUSED)
mgl@1371
  3663
+{
mgl@1371
  3664
+  HOST_WIDE_INT arg_size, arg_rsize;
mgl@1371
  3665
+
mgl@1371
  3666
+  if (type)
mgl@1371
  3667
+    {
mgl@1371
  3668
+      arg_size = int_size_in_bytes (type);
mgl@1371
  3669
+    }
mgl@1371
  3670
+  else
mgl@1371
  3671
+    {
mgl@1371
  3672
+      arg_size = GET_MODE_SIZE (mode);
mgl@1371
  3673
+    }
mgl@1371
  3674
+  arg_rsize = PUSH_ROUNDING (arg_size);
mgl@1371
  3675
+
mgl@1371
  3676
+  /* It the argument had to be passed in stack, no register is used. */
mgl@1371
  3677
+  if ((*targetm.calls.must_pass_in_stack) (mode, type))
mgl@1371
  3678
+    {
mgl@1371
  3679
+      cum->stack_pushed_args_size += PUSH_ROUNDING (int_size_in_bytes (type));
mgl@1371
  3680
+      return;
mgl@1371
  3681
+    }
mgl@1371
  3682
+
mgl@1371
  3683
+  /* Mark the used registers as "used". */
mgl@1371
  3684
+  if (GET_REG_INDEX (cum) >= 0)
mgl@1371
  3685
+    {
mgl@1371
  3686
+      SET_USED_INDEX (cum, GET_REG_INDEX (cum));
mgl@1371
  3687
+      if (arg_rsize == 8)
mgl@1371
  3688
+	{
mgl@1371
  3689
+	  SET_USED_INDEX (cum, (GET_REG_INDEX (cum) + 1));
mgl@1371
  3690
+	}
mgl@1371
  3691
+    }
mgl@1371
  3692
+  else
mgl@1371
  3693
+    {
mgl@1371
  3694
+      /* Had to use stack */
mgl@1371
  3695
+      cum->stack_pushed_args_size += arg_rsize;
mgl@1371
  3696
+    }
mgl@1371
  3697
+}
mgl@1371
  3698
+
mgl@1371
  3699
+/*
mgl@1371
  3700
+  Defines witch direction to go to find the next register to use if the
mgl@1371
  3701
+  argument is larger then one register or for arguments shorter than an
mgl@1371
  3702
+  int which is not promoted, such as the last part of structures with
mgl@1371
  3703
+  size not a multiple of 4. */
mgl@1371
  3704
+enum direction
mgl@1371
  3705
+avr32_function_arg_padding (enum machine_mode mode ATTRIBUTE_UNUSED,
mgl@1371
  3706
+			    tree type)
mgl@1371
  3707
+{
mgl@1371
  3708
+  /* Pad upward for all aggregates except byte and halfword sized aggregates
mgl@1371
  3709
+     which can be passed in registers. */
mgl@1371
  3710
+  if (type
mgl@1371
  3711
+      && AGGREGATE_TYPE_P (type)
mgl@1371
  3712
+      && (int_size_in_bytes (type) != 1)
mgl@1371
  3713
+      && !((int_size_in_bytes (type) == 2)
mgl@1371
  3714
+	   && TYPE_ALIGN_UNIT (type) >= 2)
mgl@1371
  3715
+      && (int_size_in_bytes (type) & 0x3))
mgl@1371
  3716
+    {
mgl@1371
  3717
+      return upward;
mgl@1371
  3718
+    }
mgl@1371
  3719
+
mgl@1371
  3720
+  return downward;
mgl@1371
  3721
+}
mgl@1371
  3722
+
mgl@1371
  3723
+/*
mgl@1371
  3724
+  Return a rtx used for the return value from a function call.
mgl@1371
  3725
+*/
mgl@1371
  3726
+rtx
mgl@1371
  3727
+avr32_function_value (tree type, tree func, bool outgoing ATTRIBUTE_UNUSED)
mgl@1371
  3728
+{
mgl@1371
  3729
+  if (avr32_return_in_memory (type, func))
mgl@1371
  3730
+    return NULL_RTX;
mgl@1371
  3731
+
mgl@1371
  3732
+  if (int_size_in_bytes (type) <= 4)
mgl@1371
  3733
+    if (avr32_return_in_msb (type))
mgl@1371
  3734
+      /* Aggregates of size less than a word which does align the data in the
mgl@1371
  3735
+         MSB must use SImode for r12. */
mgl@1371
  3736
+      return gen_rtx_REG (SImode, RET_REGISTER);
mgl@1371
  3737
+    else
mgl@1371
  3738
+      return gen_rtx_REG (TYPE_MODE (type), RET_REGISTER);
mgl@1371
  3739
+  else if (int_size_in_bytes (type) <= 8)
mgl@1371
  3740
+    return gen_rtx_REG (TYPE_MODE (type), INTERNAL_REGNUM (11));
mgl@1371
  3741
+
mgl@1371
  3742
+  return NULL_RTX;
mgl@1371
  3743
+}
mgl@1371
  3744
+
mgl@1371
  3745
+/*
mgl@1371
  3746
+  Return a rtx used for the return value from a library function call.
mgl@1371
  3747
+*/
mgl@1371
  3748
+rtx
mgl@1371
  3749
+avr32_libcall_value (enum machine_mode mode)
mgl@1371
  3750
+{
mgl@1371
  3751
+
mgl@1371
  3752
+  if (GET_MODE_SIZE (mode) <= 4)
mgl@1371
  3753
+    return gen_rtx_REG (mode, RET_REGISTER);
mgl@1371
  3754
+  else if (GET_MODE_SIZE (mode) <= 8)
mgl@1371
  3755
+    return gen_rtx_REG (mode, INTERNAL_REGNUM (11));
mgl@1371
  3756
+  else
mgl@1371
  3757
+    return NULL_RTX;
mgl@1371
  3758
+}
mgl@1371
  3759
+
mgl@1371
  3760
+/* Return TRUE if X references a SYMBOL_REF.  */
mgl@1371
  3761
+int
mgl@1371
  3762
+symbol_mentioned_p (rtx x)
mgl@1371
  3763
+{
mgl@1371
  3764
+  const char *fmt;
mgl@1371
  3765
+  int i;
mgl@1371
  3766
+
mgl@1371
  3767
+  if (GET_CODE (x) == SYMBOL_REF)
mgl@1371
  3768
+    return 1;
mgl@1371
  3769
+
mgl@1371
  3770
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
mgl@1371
  3771
+
mgl@1371
  3772
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
mgl@1371
  3773
+    {
mgl@1371
  3774
+      if (fmt[i] == 'E')
mgl@1371
  3775
+	{
mgl@1371
  3776
+	  int j;
mgl@1371
  3777
+
mgl@1371
  3778
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mgl@1371
  3779
+	    if (symbol_mentioned_p (XVECEXP (x, i, j)))
mgl@1371
  3780
+	      return 1;
mgl@1371
  3781
+	}
mgl@1371
  3782
+      else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
mgl@1371
  3783
+	return 1;
mgl@1371
  3784
+    }
mgl@1371
  3785
+
mgl@1371
  3786
+  return 0;
mgl@1371
  3787
+}
mgl@1371
  3788
+
mgl@1371
  3789
+/* Return TRUE if X references a LABEL_REF.  */
mgl@1371
  3790
+int
mgl@1371
  3791
+label_mentioned_p (rtx x)
mgl@1371
  3792
+{
mgl@1371
  3793
+  const char *fmt;
mgl@1371
  3794
+  int i;
mgl@1371
  3795
+
mgl@1371
  3796
+  if (GET_CODE (x) == LABEL_REF)
mgl@1371
  3797
+    return 1;
mgl@1371
  3798
+
mgl@1371
  3799
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
mgl@1371
  3800
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
mgl@1371
  3801
+    {
mgl@1371
  3802
+      if (fmt[i] == 'E')
mgl@1371
  3803
+	{
mgl@1371
  3804
+	  int j;
mgl@1371
  3805
+
mgl@1371
  3806
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mgl@1371
  3807
+	    if (label_mentioned_p (XVECEXP (x, i, j)))
mgl@1371
  3808
+	      return 1;
mgl@1371
  3809
+	}
mgl@1371
  3810
+      else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
mgl@1371
  3811
+	return 1;
mgl@1371
  3812
+    }
mgl@1371
  3813
+
mgl@1371
  3814
+  return 0;
mgl@1371
  3815
+}
mgl@1371
  3816
+
mgl@1371
  3817
+/* Return TRUE if X contains a MEM expression.  */
mgl@1371
  3818
+int
mgl@1371
  3819
+mem_mentioned_p (rtx x)
mgl@1371
  3820
+{
mgl@1371
  3821
+  const char *fmt;
mgl@1371
  3822
+  int i;
mgl@1371
  3823
+
mgl@1371
  3824
+  if (MEM_P (x))
mgl@1371
  3825
+    return 1;
mgl@1371
  3826
+
mgl@1371
  3827
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
mgl@1371
  3828
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
mgl@1371
  3829
+    {
mgl@1371
  3830
+      if (fmt[i] == 'E')
mgl@1371
  3831
+	{
mgl@1371
  3832
+	  int j;
mgl@1371
  3833
+
mgl@1371
  3834
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mgl@1371
  3835
+	    if (mem_mentioned_p (XVECEXP (x, i, j)))
mgl@1371
  3836
+	      return 1;
mgl@1371
  3837
+	}
mgl@1371
  3838
+      else if (fmt[i] == 'e' && mem_mentioned_p (XEXP (x, i)))
mgl@1371
  3839
+	return 1;
mgl@1371
  3840
+    }
mgl@1371
  3841
+
mgl@1371
  3842
+  return 0;
mgl@1371
  3843
+}
mgl@1371
  3844
+
mgl@1371
  3845
+int
mgl@1371
  3846
+avr32_legitimate_pic_operand_p (rtx x)
mgl@1371
  3847
+{
mgl@1371
  3848
+
mgl@1371
  3849
+  /* We can't have const, this must be broken down to a symbol. */
mgl@1371
  3850
+  if (GET_CODE (x) == CONST)
mgl@1371
  3851
+    return FALSE;
mgl@1371
  3852
+
mgl@1371
  3853
+  /* Can't access symbols or labels via the constant pool either */
mgl@1371
  3854
+  if ((GET_CODE (x) == SYMBOL_REF
mgl@1371
  3855
+       && CONSTANT_POOL_ADDRESS_P (x)
mgl@1371
  3856
+       && (symbol_mentioned_p (get_pool_constant (x))
mgl@1371
  3857
+	   || label_mentioned_p (get_pool_constant (x)))))
mgl@1371
  3858
+    return FALSE;
mgl@1371
  3859
+
mgl@1371
  3860
+  return TRUE;
mgl@1371
  3861
+}
mgl@1371
  3862
+
mgl@1371
  3863
+
mgl@1371
  3864
+rtx
mgl@1371
  3865
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
mgl@1371
  3866
+			rtx reg)
mgl@1371
  3867
+{
mgl@1371
  3868
+
mgl@1371
  3869
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
mgl@1371
  3870
+    {
mgl@1371
  3871
+      int subregs = 0;
mgl@1371
  3872
+
mgl@1371
  3873
+      if (reg == 0)
mgl@1371
  3874
+	{
mgl@1371
  3875
+	  if (no_new_pseudos)
mgl@1371
  3876
+	    abort ();
mgl@1371
  3877
+	  else
mgl@1371
  3878
+	    reg = gen_reg_rtx (Pmode);
mgl@1371
  3879
+
mgl@1371
  3880
+	  subregs = 1;
mgl@1371
  3881
+	}
mgl@1371
  3882
+
mgl@1371
  3883
+      emit_move_insn (reg, orig);
mgl@1371
  3884
+
mgl@1371
  3885
+      /* Only set current function as using pic offset table if flag_pic is
mgl@1371
  3886
+         set. This is because this function is also used if
mgl@1371
  3887
+         TARGET_HAS_ASM_ADDR_PSEUDOS is set. */
mgl@1371
  3888
+      if (flag_pic)
mgl@1371
  3889
+	current_function_uses_pic_offset_table = 1;
mgl@1371
  3890
+
mgl@1371
  3891
+      /* Put a REG_EQUAL note on this insn, so that it can be optimized by
mgl@1371
  3892
+         loop.  */
mgl@1371
  3893
+      return reg;
mgl@1371
  3894
+    }
mgl@1371
  3895
+  else if (GET_CODE (orig) == CONST)
mgl@1371
  3896
+    {
mgl@1371
  3897
+      rtx base, offset;
mgl@1371
  3898
+
mgl@1371
  3899
+      if (flag_pic
mgl@1371
  3900
+	  && GET_CODE (XEXP (orig, 0)) == PLUS
mgl@1371
  3901
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
mgl@1371
  3902
+	return orig;
mgl@1371
  3903
+
mgl@1371
  3904
+      if (reg == 0)
mgl@1371
  3905
+	{
mgl@1371
  3906
+	  if (no_new_pseudos)
mgl@1371
  3907
+	    abort ();
mgl@1371
  3908
+	  else
mgl@1371
  3909
+	    reg = gen_reg_rtx (Pmode);
mgl@1371
  3910
+	}
mgl@1371
  3911
+
mgl@1371
  3912
+      if (GET_CODE (XEXP (orig, 0)) == PLUS)
mgl@1371
  3913
+	{
mgl@1371
  3914
+	  base =
mgl@1371
  3915
+	    legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
mgl@1371
  3916
+	  offset =
mgl@1371
  3917
+	    legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
mgl@1371
  3918
+				    base == reg ? 0 : reg);
mgl@1371
  3919
+	}
mgl@1371
  3920
+      else
mgl@1371
  3921
+	abort ();
mgl@1371
  3922
+
mgl@1371
  3923
+      if (GET_CODE (offset) == CONST_INT)
mgl@1371
  3924
+	{
mgl@1371
  3925
+	  /* The base register doesn't really matter, we only want to test
mgl@1371
  3926
+	     the index for the appropriate mode.  */
mgl@1371
  3927
+	  if (!avr32_const_ok_for_constraint_p (INTVAL (offset), 'I', "Is21"))
mgl@1371
  3928
+	    {
mgl@1371
  3929
+	      if (!no_new_pseudos)
mgl@1371
  3930
+		offset = force_reg (Pmode, offset);
mgl@1371
  3931
+	      else
mgl@1371
  3932
+		abort ();
mgl@1371
  3933
+	    }
mgl@1371
  3934
+
mgl@1371
  3935
+	  if (GET_CODE (offset) == CONST_INT)
mgl@1371
  3936
+	    return plus_constant (base, INTVAL (offset));
mgl@1371
  3937
+	}
mgl@1371
  3938
+
mgl@1371
  3939
+      return gen_rtx_PLUS (Pmode, base, offset);
mgl@1371
  3940
+    }
mgl@1371
  3941
+
mgl@1371
  3942
+  return orig;
mgl@1371
  3943
+}
mgl@1371
  3944
+
mgl@1371
  3945
+/* Generate code to load the PIC register.  */
mgl@1371
  3946
+void
mgl@1371
  3947
+avr32_load_pic_register (void)
mgl@1371
  3948
+{
mgl@1371
  3949
+  rtx l1, pic_tmp;
mgl@1371
  3950
+  rtx global_offset_table;
mgl@1371
  3951
+
mgl@1371
  3952
+  if ((current_function_uses_pic_offset_table == 0) || TARGET_NO_INIT_GOT)
mgl@1371
  3953
+    return;
mgl@1371
  3954
+
mgl@1371
  3955
+  if (!flag_pic)
mgl@1371
  3956
+    abort ();
mgl@1371
  3957
+
mgl@1371
  3958
+  l1 = gen_label_rtx ();
mgl@1371
  3959
+
mgl@1371
  3960
+  global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
mgl@1371
  3961
+  pic_tmp =
mgl@1371
  3962
+    gen_rtx_CONST (Pmode,
mgl@1371
  3963
+		   gen_rtx_MINUS (SImode, gen_rtx_LABEL_REF (Pmode, l1),
mgl@1371
  3964
+				  global_offset_table));
mgl@1371
  3965
+  emit_insn (gen_pic_load_addr
mgl@1371
  3966
+	     (pic_offset_table_rtx, force_const_mem (SImode, pic_tmp)));
mgl@1371
  3967
+  emit_insn (gen_pic_compute_got_from_pc (pic_offset_table_rtx, l1));
mgl@1371
  3968
+
mgl@1371
  3969
+  /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp
mgl@1371
  3970
+     can cause life info to screw up.  */
mgl@1371
  3971
+  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
mgl@1371
  3972
+}
mgl@1371
  3973
+
mgl@1371
  3974
+
mgl@1371
  3975
+
mgl@1371
  3976
+/* This hook should return true if values of type type are returned at the most
mgl@1371
  3977
+   significant end of a register (in other words, if they are padded at the
mgl@1371
  3978
+   least significant end). You can assume that type is returned in a register;
mgl@1371
  3979
+   the caller is required to check this.  Note that the register provided by
mgl@1371
  3980
+   FUNCTION_VALUE must be able to hold the complete return value. For example,
mgl@1371
  3981
+   if a 1-, 2- or 3-byte structure is returned at the most significant end of a
mgl@1371
  3982
+   4-byte register, FUNCTION_VALUE should provide an SImode rtx. */
mgl@1371
  3983
+bool
mgl@1371
  3984
+avr32_return_in_msb (tree type ATTRIBUTE_UNUSED)
mgl@1371
  3985
+{
mgl@1371
  3986
+  /* if ( AGGREGATE_TYPE_P (type) ) if ((int_size_in_bytes(type) == 1) ||
mgl@1371
  3987
+     ((int_size_in_bytes(type) == 2) && TYPE_ALIGN_UNIT(type) >= 2)) return
mgl@1371
  3988
+     false; else return true; */
mgl@1371
  3989
+
mgl@1371
  3990
+  return false;
mgl@1371
  3991
+}
mgl@1371
  3992
+
mgl@1371
  3993
+
mgl@1371
  3994
+/*
mgl@1371
  3995
+  Returns one if a certain function value is going to be returned in memory
mgl@1371
  3996
+  and zero if it is going to be returned in a register.
mgl@1371
  3997
+
mgl@1371
  3998
+  BLKmode and all other modes that is larger than 64 bits are returned in
mgl@1371
  3999
+  memory.
mgl@1371
  4000
+*/
mgl@1371
  4001
+bool
mgl@1371
  4002
+avr32_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
mgl@1371
  4003
+{
mgl@1371
  4004
+  if (TYPE_MODE (type) == VOIDmode)
mgl@1371
  4005
+    return false;
mgl@1371
  4006
+
mgl@1371
  4007
+  if (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
mgl@1371
  4008
+      || int_size_in_bytes (type) == -1)
mgl@1371
  4009
+    {
mgl@1371
  4010
+      return true;
mgl@1371
  4011
+    }
mgl@1371
  4012
+
mgl@1371
  4013
+  /* If we have an aggregate then use the same mechanism as when checking if
mgl@1371
  4014
+     it should be passed on the stack. */
mgl@1371
  4015
+  if (type
mgl@1371
  4016
+      && AGGREGATE_TYPE_P (type)
mgl@1371
  4017
+      && (*targetm.calls.must_pass_in_stack) (TYPE_MODE (type), type))
mgl@1371
  4018
+    return true;
mgl@1371
  4019
+
mgl@1371
  4020
+  return false;
mgl@1371
  4021
+}
mgl@1371
  4022
+
mgl@1371
  4023
+
mgl@1371
  4024
+/* Output the constant part of the trampoline.
mgl@1371
  4025
+   lddpc    r0, pc[0x8:e] ; load static chain register
mgl@1371
  4026
+   lddpc    pc, pc[0x8:e] ; jump to subrutine
mgl@1371
  4027
+   .long    0		 ; Address to static chain,
mgl@1371
  4028
+			 ; filled in by avr32_initialize_trampoline()
mgl@1371
  4029
+   .long    0		 ; Address to subrutine,
mgl@1371
  4030
+			 ; filled in by avr32_initialize_trampoline()
mgl@1371
  4031
+*/
mgl@1371
  4032
+void
mgl@1371
  4033
+avr32_trampoline_template (FILE * file)
mgl@1371
  4034
+{
mgl@1371
  4035
+  fprintf (file, "\tlddpc    r0, pc[8]\n");
mgl@1371
  4036
+  fprintf (file, "\tlddpc    pc, pc[8]\n");
mgl@1371
  4037
+  /* make room for the address of the static chain. */
mgl@1371
  4038
+  fprintf (file, "\t.long\t0\n");
mgl@1371
  4039
+  /* make room for the address to the subrutine. */
mgl@1371
  4040
+  fprintf (file, "\t.long\t0\n");
mgl@1371
  4041
+}
mgl@1371
  4042
+
mgl@1371
  4043
+
mgl@1371
  4044
+/*
mgl@1371
  4045
+  Initialize the variable parts of a trampoline.
mgl@1371
  4046
+*/
mgl@1371
  4047
+void
mgl@1371
  4048
+avr32_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
mgl@1371
  4049
+{
mgl@1371
  4050
+  /* Store the address to the static chain. */
mgl@1371
  4051
+  emit_move_insn (gen_rtx_MEM
mgl@1371
  4052
+		  (SImode, plus_constant (addr, TRAMPOLINE_SIZE - 4)),
mgl@1371
  4053
+		  static_chain);
mgl@1371
  4054
+
mgl@1371
  4055
+  /* Store the address to the function. */
mgl@1371
  4056
+  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, TRAMPOLINE_SIZE)),
mgl@1371
  4057
+		  fnaddr);
mgl@1371
  4058
+
mgl@1371
  4059
+  emit_insn (gen_cache (gen_rtx_REG (SImode, 13),
mgl@1371
  4060
+			gen_rtx_CONST_INT (SImode,
mgl@1371
  4061
+					   AVR32_CACHE_INVALIDATE_ICACHE)));
mgl@1371
  4062
+}
mgl@1371
  4063
+
mgl@1371
  4064
+/* Return nonzero if X is valid as an addressing register.  */
mgl@1371
  4065
+int
mgl@1371
  4066
+avr32_address_register_rtx_p (rtx x, int strict_p)
mgl@1371
  4067
+{
mgl@1371
  4068
+  int regno;
mgl@1371
  4069
+
mgl@1371
  4070
+  if (!register_operand(x, GET_MODE(x)))
mgl@1371
  4071
+    return 0;
mgl@1371
  4072
+
mgl@1371
  4073
+  /* If strict we require the register to be a hard register. */
mgl@1371
  4074
+  if (strict_p
mgl@1371
  4075
+      && !REG_P(x))
mgl@1371
  4076
+    return 0;
mgl@1371
  4077
+
mgl@1371
  4078
+  regno = REGNO (x);
mgl@1371
  4079
+
mgl@1371
  4080
+  if (strict_p)
mgl@1371
  4081
+    return REGNO_OK_FOR_BASE_P (regno);
mgl@1371
  4082
+
mgl@1371
  4083
+  return (regno <= LAST_REGNUM || regno >= FIRST_PSEUDO_REGISTER);
mgl@1371
  4084
+}
mgl@1371
  4085
+
mgl@1371
  4086
+/* Return nonzero if INDEX is valid for an address index operand.  */
mgl@1371
  4087
+int
mgl@1371
  4088
+avr32_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
mgl@1371
  4089
+{
mgl@1371
  4090
+  enum rtx_code code = GET_CODE (index);
mgl@1371
  4091
+
mgl@1371
  4092
+  if (GET_MODE_SIZE (mode) > 8)
mgl@1371
  4093
+    return 0;
mgl@1371
  4094
+
mgl@1371
  4095
+  /* Standard coprocessor addressing modes.  */
mgl@1371
  4096
+  if (code == CONST_INT)
mgl@1371
  4097
+    {
mgl@1371
  4098
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
mgl@1371
  4099
+	/* Coprocessor mem insns has a smaller reach than ordinary mem insns */
mgl@1371
  4100
+	return CONST_OK_FOR_CONSTRAINT_P (INTVAL (index), 'K', "Ku14");
mgl@1371
  4101
+      else
mgl@1371
  4102
+	return CONST_OK_FOR_CONSTRAINT_P (INTVAL (index), 'K', "Ks16");
mgl@1371
  4103
+    }
mgl@1371
  4104
+
mgl@1371
  4105
+  if (avr32_address_register_rtx_p (index, strict_p))
mgl@1371
  4106
+    return 1;
mgl@1371
  4107
+
mgl@1371
  4108
+  if (code == MULT)
mgl@1371
  4109
+    {
mgl@1371
  4110
+      rtx xiop0 = XEXP (index, 0);
mgl@1371
  4111
+      rtx xiop1 = XEXP (index, 1);
mgl@1371
  4112
+      return ((avr32_address_register_rtx_p (xiop0, strict_p)
mgl@1371
  4113
+	       && power_of_two_operand (xiop1, SImode)
mgl@1371
  4114
+	       && (INTVAL (xiop1) <= 8))
mgl@1371
  4115
+	      || (avr32_address_register_rtx_p (xiop1, strict_p)
mgl@1371
  4116
+		  && power_of_two_operand (xiop0, SImode)
mgl@1371
  4117
+		  && (INTVAL (xiop0) <= 8)));
mgl@1371
  4118
+    }
mgl@1371
  4119
+  else if (code == ASHIFT)
mgl@1371
  4120
+    {
mgl@1371
  4121
+      rtx op = XEXP (index, 1);
mgl@1371
  4122
+
mgl@1371
  4123
+      return (avr32_address_register_rtx_p (XEXP (index, 0), strict_p)
mgl@1371
  4124
+	      && GET_CODE (op) == CONST_INT
mgl@1371
  4125
+	      && INTVAL (op) > 0 && INTVAL (op) <= 3);
mgl@1371
  4126
+    }
mgl@1371
  4127
+
mgl@1371
  4128
+  return 0;
mgl@1371
  4129
+}
mgl@1371
  4130
+
mgl@1371
  4131
+/*
mgl@1371
  4132
+  Used in the GO_IF_LEGITIMATE_ADDRESS macro. Returns a nonzero value if
mgl@1371
  4133
+  the RTX x is a legitimate memory address.
mgl@1371
  4134
+
mgl@1371
  4135
+  Returns NO_REGS if the address is not legatime, GENERAL_REGS or ALL_REGS
mgl@1371
  4136
+  if it is.
mgl@1371
  4137
+*/
mgl@1371
  4138
+
mgl@1371
  4139
+/* Forward declaration*/
mgl@1371
  4140
+int is_minipool_label (rtx label);
mgl@1371
  4141
+
mgl@1371
  4142
+int
mgl@1371
  4143
+avr32_legitimate_address (enum machine_mode mode, rtx x, int strict)
mgl@1371
  4144
+{
mgl@1371
  4145
+
mgl@1371
  4146
+  switch (GET_CODE (x))
mgl@1371
  4147
+    {
mgl@1371
  4148
+    case REG:
mgl@1371
  4149
+      return avr32_address_register_rtx_p (x, strict);
mgl@1371
  4150
+    case CONST_INT:
mgl@1371
  4151
+      return ((mode==SImode)
mgl@1371
  4152
+              && CONST_OK_FOR_CONSTRAINT_P(INTVAL(x), 'K', "Ks17"));
mgl@1371
  4153
+    case CONST:
mgl@1371
  4154
+      {
mgl@1371
  4155
+	rtx label = avr32_find_symbol (x);
mgl@1371
  4156
+	if (label
mgl@1371
  4157
+	    &&
mgl@1371
  4158
+	    ((CONSTANT_POOL_ADDRESS_P (label)
mgl@1371
  4159
+	      && !(flag_pic
mgl@1371
  4160
+		   && (symbol_mentioned_p (get_pool_constant (label))
mgl@1371
  4161
+		       || label_mentioned_p (get_pool_constant (label)))))
mgl@1371
  4162
+	     /* TODO! Can this ever happen??? */
mgl@1371
  4163
+	     || ((GET_CODE (label) == LABEL_REF)
mgl@1371
  4164
+		 && GET_CODE (XEXP (label, 0)) == CODE_LABEL
mgl@1371
  4165
+		 && is_minipool_label (XEXP (label, 0)))
mgl@1371
  4166
+             /*|| ((GET_CODE (label) == SYMBOL_REF)
mgl@1371
  4167
+                 && mode == SImode
mgl@1371
  4168
+                 && SYMBOL_REF_RMW_ADDR(label))*/))
mgl@1371
  4169
+	  {
mgl@1371
  4170
+	    return TRUE;
mgl@1371
  4171
+	  }
mgl@1371
  4172
+      }
mgl@1371
  4173
+      break;
mgl@1371
  4174
+    case LABEL_REF:
mgl@1371
  4175
+      if (GET_CODE (XEXP (x, 0)) == CODE_LABEL
mgl@1371
  4176
+	  && is_minipool_label (XEXP (x, 0)))
mgl@1371
  4177
+	{
mgl@1371
  4178
+	  return TRUE;
mgl@1371
  4179
+	}
mgl@1371
  4180
+      break;
mgl@1371
  4181
+    case SYMBOL_REF:
mgl@1371
  4182
+      {
mgl@1371
  4183
+	if (CONSTANT_POOL_ADDRESS_P (x)
mgl@1371
  4184
+	    && !(flag_pic
mgl@1371
  4185
+		 && (symbol_mentioned_p (get_pool_constant (x))
mgl@1371
  4186
+		     || label_mentioned_p (get_pool_constant (x)))))
mgl@1371
  4187
+	  return TRUE;
mgl@1371
  4188
+	else if (SYMBOL_REF_RCALL_FUNCTION_P (x)
mgl@1371
  4189
+                 || (mode == SImode
mgl@1371
  4190
+                     && SYMBOL_REF_RMW_ADDR (x)))
mgl@1371
  4191
+	  return TRUE;
mgl@1371
  4192
+	break;
mgl@1371
  4193
+      }
mgl@1371
  4194
+    case PRE_DEC:		/* (pre_dec (...)) */
mgl@1371
  4195
+    case POST_INC:		/* (post_inc (...)) */
mgl@1371
  4196
+      return avr32_address_register_rtx_p (XEXP (x, 0), strict);
mgl@1371
  4197
+    case PLUS:			/* (plus (...) (...)) */
mgl@1371
  4198
+      {
mgl@1371
  4199
+	rtx xop0 = XEXP (x, 0);
mgl@1371
  4200
+	rtx xop1 = XEXP (x, 1);
mgl@1371
  4201
+
mgl@1371
  4202
+	return ((avr32_address_register_rtx_p (xop0, strict)
mgl@1371
  4203
+		 && avr32_legitimate_index_p (mode, xop1, strict))
mgl@1371
  4204
+		|| (avr32_address_register_rtx_p (xop1, strict)
mgl@1371
  4205
+		    && avr32_legitimate_index_p (mode, xop0, strict)));
mgl@1371
  4206
+      }
mgl@1371
  4207
+    default:
mgl@1371
  4208
+      break;
mgl@1371
  4209
+    }
mgl@1371
  4210
+
mgl@1371
  4211
+  return FALSE;
mgl@1371
  4212
+}
mgl@1371
  4213
+
mgl@1371
  4214
+
mgl@1371
  4215
+int
mgl@1371
  4216
+avr32_const_ok_for_move (HOST_WIDE_INT c)
mgl@1371
  4217
+{
mgl@1371
  4218
+  if ( TARGET_V2_INSNS )
mgl@1371
  4219
+    return ( avr32_const_ok_for_constraint_p (c, 'K', "Ks21")
mgl@1371
  4220
+             /* movh instruction */
mgl@1371
  4221
+             || avr32_hi16_immediate_operand (GEN_INT(c), VOIDmode) );
mgl@1371
  4222
+  else
mgl@1371
  4223
+    return avr32_const_ok_for_constraint_p (c, 'K', "Ks21");
mgl@1371
  4224
+}
mgl@1371
  4225
+
mgl@1371
  4226
+int
mgl@1371
  4227
+avr32_const_double_immediate (rtx value)
mgl@1371
  4228
+{
mgl@1371
  4229
+  HOST_WIDE_INT hi, lo;
mgl@1371
  4230
+
mgl@1371
  4231
+  if (GET_CODE (value) != CONST_DOUBLE)
mgl@1371
  4232
+    return FALSE;
mgl@1371
  4233
+
mgl@1371
  4234
+  if (SCALAR_FLOAT_MODE_P (GET_MODE (value)))
mgl@1371
  4235
+    {
mgl@1371
  4236
+      HOST_WIDE_INT target_float[2];
mgl@1371
  4237
+      hi = lo = 0;
mgl@1371
  4238
+      real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (value),
mgl@1371
  4239
+		      GET_MODE (value));
mgl@1371
  4240
+      lo = target_float[0];
mgl@1371
  4241
+      hi = target_float[1];
mgl@1371
  4242
+    }
mgl@1371
  4243
+  else
mgl@1371
  4244
+    {
mgl@1371
  4245
+      hi = CONST_DOUBLE_HIGH (value);
mgl@1371
  4246
+      lo = CONST_DOUBLE_LOW (value);
mgl@1371
  4247
+    }
mgl@1371
  4248
+
mgl@1371
  4249
+  if (avr32_const_ok_for_constraint_p (lo, 'K', "Ks21")
mgl@1371
  4250
+      && (GET_MODE (value) == SFmode
mgl@1371
  4251
+	  || avr32_const_ok_for_constraint_p (hi, 'K', "Ks21")))
mgl@1371
  4252
+    {
mgl@1371
  4253
+      return TRUE;
mgl@1371
  4254
+    }
mgl@1371
  4255
+
mgl@1371
  4256
+  return FALSE;
mgl@1371
  4257
+}
mgl@1371
  4258
+
mgl@1371
  4259
+
mgl@1371
  4260
+int
mgl@1371
  4261
+avr32_legitimate_constant_p (rtx x)
mgl@1371
  4262
+{
mgl@1371
  4263
+  switch (GET_CODE (x))
mgl@1371
  4264
+    {
mgl@1371
  4265
+    case CONST_INT:
mgl@1371
  4266
+      /* Check if we should put large immediate into constant pool
mgl@1371
  4267
+       or load them directly with mov/orh.*/
mgl@1371
  4268
+      if (!avr32_imm_in_const_pool)
mgl@1371
  4269
+	return 1;
mgl@1371
  4270
+
mgl@1371
  4271
+      return avr32_const_ok_for_move (INTVAL (x));
mgl@1371
  4272
+    case CONST_DOUBLE:
mgl@1371
  4273
+      /* Check if we should put large immediate into constant pool
mgl@1371
  4274
+         or load them directly with mov/orh.*/
mgl@1371
  4275
+      if (!avr32_imm_in_const_pool)
mgl@1371
  4276
+	return 1;
mgl@1371
  4277
+
mgl@1371
  4278
+      if (GET_MODE (x) == SFmode
mgl@1371
  4279
+	  || GET_MODE (x) == DFmode || GET_MODE (x) == DImode)
mgl@1371
  4280
+	return avr32_const_double_immediate (x);
mgl@1371
  4281
+      else
mgl@1371
  4282
+	return 0;
mgl@1371
  4283
+    case LABEL_REF:
mgl@1371
  4284
+    case SYMBOL_REF:
mgl@1371
  4285
+      return avr32_find_symbol (x) && (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS);
mgl@1371
  4286
+    case CONST:
mgl@1371
  4287
+    case HIGH:
mgl@1371
  4288
+    case CONST_VECTOR:
mgl@1371
  4289
+      return 0;
mgl@1371
  4290
+    default:
mgl@1371
  4291
+      printf ("%s():\n", __FUNCTION__);
mgl@1371
  4292
+      debug_rtx (x);
mgl@1371
  4293
+      return 1;
mgl@1371
  4294
+    }
mgl@1371
  4295
+}
mgl@1371
  4296
+
mgl@1371
  4297
+
mgl@1371
  4298
+/* Strip any special encoding from labels */
mgl@1371
  4299
+const char *
mgl@1371
  4300
+avr32_strip_name_encoding (const char *name)
mgl@1371
  4301
+{
mgl@1371
  4302
+  const char *stripped = name;
mgl@1371
  4303
+
mgl@1371
  4304
+  while (1)
mgl@1371
  4305
+    {
mgl@1371
  4306
+      switch (stripped[0])
mgl@1371
  4307
+	{
mgl@1371
  4308
+	case '#':
mgl@1371
  4309
+	  stripped = strchr (name + 1, '#') + 1;
mgl@1371
  4310
+	  break;
mgl@1371
  4311
+	case '*':
mgl@1371
  4312
+	  stripped = &stripped[1];
mgl@1371
  4313
+	  break;
mgl@1371
  4314
+	default:
mgl@1371
  4315
+	  return stripped;
mgl@1371
  4316
+	}
mgl@1371
  4317
+    }
mgl@1371
  4318
+}
mgl@1371
  4319
+
mgl@1371
  4320
+
mgl@1371
  4321
+
mgl@1371
  4322
+/* Do anything needed before RTL is emitted for each function.  */
mgl@1371
  4323
+static struct machine_function *
mgl@1371
  4324
+avr32_init_machine_status (void)
mgl@1371
  4325
+{
mgl@1371
  4326
+  struct machine_function *machine;
mgl@1371
  4327
+  machine =
mgl@1371
  4328
+    (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
mgl@1371
  4329
+
mgl@1371
  4330
+#if AVR32_FT_UNKNOWN != 0
mgl@1371
  4331
+  machine->func_type = AVR32_FT_UNKNOWN;
mgl@1371
  4332
+#endif
mgl@1371
  4333
+
mgl@1371
  4334
+  machine->minipool_label_head = 0;
mgl@1371
  4335
+  machine->minipool_label_tail = 0;
mgl@1371
  4336
+  machine->ifcvt_after_reload = 0;
mgl@1371
  4337
+  return machine;
mgl@1371
  4338
+}
mgl@1371
  4339
+
mgl@1371
  4340
+void
mgl@1371
  4341
+avr32_init_expanders (void)
mgl@1371
  4342
+{
mgl@1371
  4343
+  /* Arrange to initialize and mark the machine per-function status.  */
mgl@1371
  4344
+  init_machine_status = avr32_init_machine_status;
mgl@1371
  4345
+}
mgl@1371
  4346
+
mgl@1371
  4347
+
mgl@1371
  4348
+/* Return an RTX indicating where the return address to the
mgl@1371
  4349
+   calling function can be found.  */
mgl@1371
  4350
+
mgl@1371
  4351
+rtx
mgl@1371
  4352
+avr32_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
mgl@1371
  4353
+{
mgl@1371
  4354
+  if (count != 0)
mgl@1371
  4355
+    return NULL_RTX;
mgl@1371
  4356
+
mgl@1371
  4357
+  return get_hard_reg_initial_val (Pmode, LR_REGNUM);
mgl@1371
  4358
+}
mgl@1371
  4359
+
mgl@1371
  4360
+
mgl@1371
  4361
+void
mgl@1371
  4362
+avr32_encode_section_info (tree decl, rtx rtl, int first)
mgl@1371
  4363
+{
mgl@1371
  4364
+  default_encode_section_info(decl, rtl, first);
mgl@1371
  4365
+
mgl@1371
  4366
+  if ( TREE_CODE (decl) == VAR_DECL
mgl@1371
  4367
+       && (GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF)
mgl@1371
  4368
+       && (lookup_attribute ("rmw_addressable", DECL_ATTRIBUTES (decl))
mgl@1371
  4369
+           || TARGET_RMW_ADDRESSABLE_DATA) ){
mgl@1371
  4370
+    if ( !TARGET_RMW || flag_pic )
mgl@1371
  4371
+      return;
mgl@1371
  4372
+    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT);
mgl@1371
  4373
+  }
mgl@1371
  4374
+}
mgl@1371
  4375
+
mgl@1371
  4376
+void
mgl@1371
  4377
+avr32_asm_output_label (FILE * stream, const char *name)
mgl@1371
  4378
+{
mgl@1371
  4379
+  name = avr32_strip_name_encoding (name);
mgl@1371
  4380
+
mgl@1371
  4381
+  /* Print the label. */
mgl@1371
  4382
+  assemble_name (stream, name);
mgl@1371
  4383
+  fprintf (stream, ":\n");
mgl@1371
  4384
+}
mgl@1371
  4385
+
mgl@1371
  4386
+
mgl@1371
  4387
+
mgl@1371
  4388
+void
mgl@1371
  4389
+avr32_asm_weaken_label (FILE * stream, const char *name)
mgl@1371
  4390
+{
mgl@1371
  4391
+  fprintf (stream, "\t.weak ");
mgl@1371
  4392
+  assemble_name (stream, name);
mgl@1371
  4393
+  fprintf (stream, "\n");
mgl@1371
  4394
+}
mgl@1371
  4395
+
mgl@1371
  4396
+/*
mgl@1371
  4397
+  Checks if a labelref is equal to a reserved word in the assembler. If it is,
mgl@1371
  4398
+  insert a '_' before the label name.
mgl@1371
  4399
+*/
mgl@1371
  4400
+void
mgl@1371
  4401
+avr32_asm_output_labelref (FILE * stream, const char *name)
mgl@1371
  4402
+{
mgl@1371
  4403
+  int verbatim = FALSE;
mgl@1371
  4404
+  const char *stripped = name;
mgl@1371
  4405
+  int strip_finished = FALSE;
mgl@1371
  4406
+
mgl@1371
  4407
+  while (!strip_finished)
mgl@1371
  4408
+    {
mgl@1371
  4409
+      switch (stripped[0])
mgl@1371
  4410
+	{
mgl@1371
  4411
+	case '#':
mgl@1371
  4412
+	  stripped = strchr (name + 1, '#') + 1;
mgl@1371
  4413
+	  break;
mgl@1371
  4414
+	case '*':
mgl@1371
  4415
+	  stripped = &stripped[1];
mgl@1371
  4416
+	  verbatim = TRUE;
mgl@1371
  4417
+	  break;
mgl@1371
  4418
+	default:
mgl@1371
  4419
+	  strip_finished = TRUE;
mgl@1371
  4420
+	  break;
mgl@1371
  4421
+	}
mgl@1371
  4422
+    }
mgl@1371
  4423
+
mgl@1371
  4424
+  if (verbatim)
mgl@1371
  4425
+    fputs (stripped, stream);
mgl@1371
  4426
+  else
mgl@1371
  4427
+    asm_fprintf (stream, "%U%s", stripped);
mgl@1371
  4428
+}
mgl@1371
  4429
+
mgl@1371
  4430
+
mgl@1371
  4431
+
mgl@1371
  4432
+/*
mgl@1371
  4433
+   Check if the comparison in compare_exp is redundant
mgl@1371
  4434
+   for the condition given in next_cond given that the
mgl@1371
  4435
+   needed flags are already set by an earlier instruction.
mgl@1371
  4436
+   Uses cc_prev_status to check this.
mgl@1371
  4437
+
mgl@1371
  4438
+   Returns NULL_RTX if the compare is not redundant
mgl@1371
  4439
+   or the new condition to use in the conditional
mgl@1371
  4440
+   instruction if the compare is redundant.
mgl@1371
  4441
+*/
mgl@1371
  4442
+static rtx
mgl@1371
  4443
+is_compare_redundant (rtx compare_exp, rtx next_cond)
mgl@1371
  4444
+{
mgl@1371
  4445
+  int z_flag_valid = FALSE;
mgl@1371
  4446
+  int n_flag_valid = FALSE;
mgl@1371
  4447
+  rtx new_cond;
mgl@1371
  4448
+
mgl@1371
  4449
+  if (GET_CODE (compare_exp) != COMPARE
mgl@1371
  4450
+      && GET_CODE (compare_exp) != AND)
mgl@1371
  4451
+    return NULL_RTX;
mgl@1371
  4452
+
mgl@1371
  4453
+
mgl@1371
  4454
+  if (rtx_equal_p (cc_prev_status.mdep.value, compare_exp))
mgl@1371
  4455
+    {
mgl@1371
  4456
+      /* cc0 already contains the correct comparison -> delete cmp insn */
mgl@1371
  4457
+      return next_cond;
mgl@1371
  4458
+    }
mgl@1371
  4459
+
mgl@1371
  4460
+  if (GET_MODE (compare_exp) != SImode)
mgl@1371
  4461
+    return NULL_RTX;
mgl@1371
  4462
+
mgl@1371
  4463
+  switch (cc_prev_status.mdep.flags)
mgl@1371
  4464
+    {
mgl@1371
  4465
+    case CC_SET_VNCZ:
mgl@1371
  4466
+    case CC_SET_NCZ:
mgl@1371
  4467
+      n_flag_valid = TRUE;
mgl@1371
  4468
+    case CC_SET_CZ:
mgl@1371
  4469
+    case CC_SET_Z:
mgl@1371
  4470
+      z_flag_valid = TRUE;
mgl@1371
  4471
+    }
mgl@1371
  4472
+
mgl@1371
  4473
+  if (cc_prev_status.mdep.value
mgl@1371
  4474
+      && GET_CODE (compare_exp) == COMPARE
mgl@1371
  4475
+      && REG_P (XEXP (compare_exp, 0))
mgl@1371
  4476
+      && REGNO (XEXP (compare_exp, 0)) == REGNO (cc_prev_status.mdep.value)
mgl@1371
  4477
+      && GET_CODE (XEXP (compare_exp, 1)) == CONST_INT
mgl@1371
  4478
+      && next_cond != NULL_RTX)
mgl@1371
  4479
+    {
mgl@1371
  4480
+      if (INTVAL (XEXP (compare_exp, 1)) == 0
mgl@1371
  4481
+	  && z_flag_valid
mgl@1371
  4482
+	  && (GET_CODE (next_cond) == EQ || GET_CODE (next_cond) == NE))
mgl@1371
  4483
+	/* We can skip comparison Z flag is already reflecting ops[0] */
mgl@1371
  4484
+	return next_cond;
mgl@1371
  4485
+      else if (n_flag_valid
mgl@1371
  4486
+	       && ((INTVAL (XEXP (compare_exp, 1)) == 0
mgl@1371
  4487
+		    && (GET_CODE (next_cond) == GE
mgl@1371
  4488
+			|| GET_CODE (next_cond) == LT))
mgl@1371
  4489
+		   || (INTVAL (XEXP (compare_exp, 1)) == -1
mgl@1371
  4490
+		       && (GET_CODE (next_cond) == GT
mgl@1371
  4491
+			   || GET_CODE (next_cond) == LE))))
mgl@1371
  4492
+	{
mgl@1371
  4493
+	  /* We can skip comparison N flag is already reflecting ops[0],
mgl@1371
  4494
+	     which means that we can use the mi/pl conditions to check if
mgl@1371
  4495
+	     ops[0] is GE or LT 0. */
mgl@1371
  4496
+	  if ((GET_CODE (next_cond) == GE) || (GET_CODE (next_cond) == GT))
mgl@1371
  4497
+	    new_cond =
mgl@1371
  4498
+	      gen_rtx_UNSPEC (GET_MODE (next_cond), gen_rtvec (2, cc0_rtx, const0_rtx),
mgl@1371
  4499
+			      UNSPEC_COND_PL);
mgl@1371
  4500
+	  else
mgl@1371
  4501
+	    new_cond =
mgl@1371
  4502
+	      gen_rtx_UNSPEC (GET_MODE (next_cond), gen_rtvec (2, cc0_rtx, const0_rtx),
mgl@1371
  4503
+			      UNSPEC_COND_MI);
mgl@1371
  4504
+	  return new_cond;
mgl@1371
  4505
+	}
mgl@1371
  4506
+    }
mgl@1371
  4507
+  return NULL_RTX;
mgl@1371
  4508
+}
mgl@1371
  4509
+
mgl@1371
  4510
+/* Updates cc_status.  */
mgl@1371
  4511
+void
mgl@1371
  4512
+avr32_notice_update_cc (rtx exp, rtx insn)
mgl@1371
  4513
+{
mgl@1371
  4514
+  enum attr_cc attr_cc = get_attr_cc (insn);
mgl@1371
  4515
+  
mgl@1371
  4516
+  if ( attr_cc == CC_SET_Z_IF_NOT_V2 )
mgl@1371
  4517
+    if (TARGET_V2_INSNS)
mgl@1371
  4518
+      attr_cc = CC_NONE;
mgl@1371
  4519
+    else
mgl@1371
  4520
+      attr_cc = CC_SET_Z;
mgl@1371
  4521
+  
mgl@1371
  4522
+  switch (attr_cc)
mgl@1371
  4523
+    {
mgl@1371
  4524
+    case CC_CALL_SET:
mgl@1371
  4525
+      CC_STATUS_INIT;
mgl@1371
  4526
+      FPCC_STATUS_INIT;
mgl@1371
  4527
+      /* Check if the function call returns a value in r12 */
mgl@1371
  4528
+      if (REG_P (recog_data.operand[0])
mgl@1371
  4529
+	  && REGNO (recog_data.operand[0]) == RETVAL_REGNUM)
mgl@1371
  4530
+	{
mgl@1371
  4531
+	  cc_status.flags = 0;
mgl@1371
  4532
+	  cc_status.mdep.value =
mgl@1371
  4533
+	    gen_rtx_COMPARE (SImode, recog_data.operand[0], const0_rtx);
mgl@1371
  4534
+	  cc_status.mdep.flags = CC_SET_VNCZ;
mgl@1371
  4535
+          cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4536
+
mgl@1371
  4537
+	}
mgl@1371
  4538
+      break;
mgl@1371
  4539
+    case CC_COMPARE:
mgl@1371
  4540
+      {
mgl@1371
  4541
+        /* Check that compare will not be optimized away if so nothing should
mgl@1371
  4542
+           be done */
mgl@1371
  4543
+        rtx compare_exp = SET_SRC (exp);
mgl@1371
  4544
+        /* Check if we have a tst expression. If so convert it to a
mgl@1371
  4545
+           compare with 0. */
mgl@1371
  4546
+        if ( REG_P (SET_SRC (exp)) )
mgl@1371
  4547
+          compare_exp = gen_rtx_COMPARE (GET_MODE (SET_SRC (exp)),
mgl@1371
  4548
+                                         SET_SRC (exp),
mgl@1371
  4549
+                                         const0_rtx);
mgl@1371
  4550
+
mgl@1371
  4551
+        if (is_compare_redundant (compare_exp, get_next_insn_cond (insn)) ==
mgl@1371
  4552
+            NULL_RTX)
mgl@1371
  4553
+          {
mgl@1371
  4554
+
mgl@1371
  4555
+            /* Reset the nonstandard flag */
mgl@1371
  4556
+            CC_STATUS_INIT;
mgl@1371
  4557
+            cc_status.flags = 0;
mgl@1371
  4558
+            cc_status.mdep.value = compare_exp;
mgl@1371
  4559
+            cc_status.mdep.flags = CC_SET_VNCZ;
mgl@1371
  4560
+            cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4561
+         }
mgl@1371
  4562
+      }
mgl@1371
  4563
+      break;
mgl@1371
  4564
+    case CC_CMP_COND_INSN:
mgl@1371
  4565
+      {
mgl@1371
  4566
+	/* Conditional insn that emit the compare itself. */
mgl@1371
  4567
+        rtx cmp;
mgl@1371
  4568
+        rtx cmp_op0, cmp_op1;
mgl@1371
  4569
+        rtx cond;
mgl@1371
  4570
+        rtx dest;
mgl@1371
  4571
+        rtx next_insn = next_nonnote_insn (insn);
mgl@1371
  4572
+
mgl@1371
  4573
+        if ( GET_CODE (exp) == COND_EXEC )
mgl@1371
  4574
+          {
mgl@1371
  4575
+            cmp_op0 = XEXP (COND_EXEC_TEST (exp), 0);
mgl@1371
  4576
+            cmp_op1 = XEXP (COND_EXEC_TEST (exp), 1);
mgl@1371
  4577
+            cond = COND_EXEC_TEST (exp);
mgl@1371
  4578
+            dest = SET_DEST (COND_EXEC_CODE (exp));
mgl@1371
  4579
+          }
mgl@1371
  4580
+        else
mgl@1371
  4581
+          {
mgl@1371
  4582
+            /* If then else conditional. compare operands are in operands
mgl@1371
  4583
+               4 and 5. */
mgl@1371
  4584
+            cmp_op0 = recog_data.operand[4];
mgl@1371
  4585
+            cmp_op1 = recog_data.operand[5];
mgl@1371
  4586
+            cond = recog_data.operand[1];
mgl@1371
  4587
+            dest = SET_DEST (exp);
mgl@1371
  4588
+          }
mgl@1371
  4589
+
mgl@1371
  4590
+        if ( GET_CODE (cmp_op0) == AND )
mgl@1371
  4591
+          cmp = cmp_op0;
mgl@1371
  4592
+        else
mgl@1371
  4593
+          cmp = gen_rtx_COMPARE (GET_MODE (cmp_op0),
mgl@1371
  4594
+                                 cmp_op0,
mgl@1371
  4595
+                                 cmp_op1);
mgl@1371
  4596
+
mgl@1371
  4597
+        /* Check if the conditional insns updates a register present
mgl@1371
  4598
+           in the comparison, if so then we must reset the cc_status. */
mgl@1371
  4599
+        if (REG_P (dest)
mgl@1371
  4600
+            && (reg_mentioned_p (dest, cmp_op0)
mgl@1371
  4601
+                || reg_mentioned_p (dest, cmp_op1))
mgl@1371
  4602
+            && GET_CODE (exp) != COND_EXEC )
mgl@1371
  4603
+          {
mgl@1371
  4604
+            CC_STATUS_INIT;
mgl@1371
  4605
+          }
mgl@1371
  4606
+	else if (is_compare_redundant (cmp, cond) == NULL_RTX)
mgl@1371
  4607
+	  {
mgl@1371
  4608
+	    /* Reset the nonstandard flag */
mgl@1371
  4609
+	    CC_STATUS_INIT;
mgl@1371
  4610
+            if ( GET_CODE (cmp_op0) == AND )
mgl@1371
  4611
+              {
mgl@1371
  4612
+                cc_status.flags = CC_INVERTED;
mgl@1371
  4613
+                cc_status.mdep.flags = CC_SET_Z;
mgl@1371
  4614
+              }
mgl@1371
  4615
+            else
mgl@1371
  4616
+              {
mgl@1371
  4617
+                cc_status.flags = 0;
mgl@1371
  4618
+                cc_status.mdep.flags = CC_SET_VNCZ;
mgl@1371
  4619
+              }
mgl@1371
  4620
+	    cc_status.mdep.value = cmp;
mgl@1371
  4621
+            cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4622
+	  }
mgl@1371
  4623
+
mgl@1371
  4624
+
mgl@1371
  4625
+        /* Check if we have a COND_EXEC insn which updates one
mgl@1371
  4626
+           of the registers in the compare status. */
mgl@1371
  4627
+        if (REG_P (dest)
mgl@1371
  4628
+            && (reg_mentioned_p (dest, cmp_op0)
mgl@1371
  4629
+                || reg_mentioned_p (dest, cmp_op1))
mgl@1371
  4630
+            && GET_CODE (exp) == COND_EXEC )
mgl@1371
  4631
+          cc_status.mdep.cond_exec_cmp_clobbered = 1;
mgl@1371
  4632
+        
mgl@1371
  4633
+        if ( cc_status.mdep.cond_exec_cmp_clobbered 
mgl@1371
  4634
+             && GET_CODE (exp) == COND_EXEC
mgl@1371
  4635
+             && next_insn != NULL
mgl@1371
  4636
+             && INSN_P (next_insn)
mgl@1371
  4637
+             && !(GET_CODE (PATTERN (next_insn)) == COND_EXEC
mgl@1371
  4638
+                  && rtx_equal_p (XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 0), cmp_op0)
mgl@1371
  4639
+                  && rtx_equal_p (XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 1), cmp_op1)
mgl@1371
  4640
+                  && (GET_CODE (COND_EXEC_TEST (PATTERN (next_insn))) == GET_CODE (cond)
mgl@1371
  4641
+                      || GET_CODE (COND_EXEC_TEST (PATTERN (next_insn))) == reverse_condition (GET_CODE (cond)))) )
mgl@1371
  4642
+          {
mgl@1371
  4643
+            /* We have a sequence of conditional insns where the compare status has been clobbered
mgl@1371
  4644
+               since the compare no longer reflects the content of the values to compare. */
mgl@1371
  4645
+            CC_STATUS_INIT;
mgl@1371
  4646
+            cc_status.mdep.cond_exec_cmp_clobbered = 1;
mgl@1371
  4647
+          }
mgl@1371
  4648
+        
mgl@1371
  4649
+      }
mgl@1371
  4650
+      break;
mgl@1371
  4651
+    case CC_FPCOMPARE:
mgl@1371
  4652
+      /* Check that floating-point compare will not be optimized away if so
mgl@1371
  4653
+         nothing should be done */
mgl@1371
  4654
+      if (!rtx_equal_p (cc_prev_status.mdep.fpvalue, SET_SRC (exp)))
mgl@1371
  4655
+	{
mgl@1371
  4656
+	  /* cc0 already contains the correct comparison -> delete cmp insn */
mgl@1371
  4657
+	  /* Reset the nonstandard flag */
mgl@1371
  4658
+	  cc_status.mdep.fpvalue = SET_SRC (exp);
mgl@1371
  4659
+	  cc_status.mdep.fpflags = CC_SET_CZ;
mgl@1371
  4660
+	}
mgl@1371
  4661
+      break;
mgl@1371
  4662
+    case CC_FROM_FPCC:
mgl@1371
  4663
+      /* Flags are updated with flags from Floating-point coprocessor, set
mgl@1371
  4664
+         CC_NOT_SIGNED flag since the flags are set so that unsigned
mgl@1371
  4665
+         condidion codes can be used directly. */
mgl@1371
  4666
+      CC_STATUS_INIT;
mgl@1371
  4667
+      cc_status.flags = CC_NOT_SIGNED;
mgl@1371
  4668
+      cc_status.mdep.value = cc_status.mdep.fpvalue;
mgl@1371
  4669
+      cc_status.mdep.flags = cc_status.mdep.fpflags;
mgl@1371
  4670
+      break;
mgl@1371
  4671
+    case CC_BLD:
mgl@1371
  4672
+      /* Bit load is kind of like an inverted testsi, because the Z flag is
mgl@1371
  4673
+         inverted */
mgl@1371
  4674
+      CC_STATUS_INIT;
mgl@1371
  4675
+      cc_status.flags = CC_INVERTED;
mgl@1371
  4676
+      cc_status.mdep.value = SET_SRC (exp);
mgl@1371
  4677
+      cc_status.mdep.flags = CC_SET_Z;
mgl@1371
  4678
+      cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4679
+      break;
mgl@1371
  4680
+    case CC_NONE:
mgl@1371
  4681
+      /* Insn does not affect CC at all. Check if the instruction updates
mgl@1371
  4682
+         some of the register currently reflected in cc0 */
mgl@1371
  4683
+
mgl@1371
  4684
+      if ((GET_CODE (exp) == SET)
mgl@1371
  4685
+	  && (cc_status.value1 || cc_status.value2 || cc_status.mdep.value)
mgl@1371
  4686
+	  && (reg_mentioned_p (SET_DEST (exp), cc_status.value1)
mgl@1371
  4687
+	      || reg_mentioned_p (SET_DEST (exp), cc_status.value2)
mgl@1371
  4688
+	      || reg_mentioned_p (SET_DEST (exp), cc_status.mdep.value)))
mgl@1371
  4689
+	{
mgl@1371
  4690
+	  CC_STATUS_INIT;
mgl@1371
  4691
+	}
mgl@1371
  4692
+
mgl@1371
  4693
+      /* If this is a parallel we must step through each of the parallel
mgl@1371
  4694
+         expressions */
mgl@1371
  4695
+      if (GET_CODE (exp) == PARALLEL)
mgl@1371
  4696
+	{
mgl@1371
  4697
+	  int i;
mgl@1371
  4698
+	  for (i = 0; i < XVECLEN (exp, 0); ++i)
mgl@1371
  4699
+	    {
mgl@1371
  4700
+	      rtx vec_exp = XVECEXP (exp, 0, i);
mgl@1371
  4701
+	      if ((GET_CODE (vec_exp) == SET)
mgl@1371
  4702
+		  && (cc_status.value1 || cc_status.value2
mgl@1371
  4703
+		      || cc_status.mdep.value)
mgl@1371
  4704
+		  && (reg_mentioned_p (SET_DEST (vec_exp), cc_status.value1)
mgl@1371
  4705
+		      || reg_mentioned_p (SET_DEST (vec_exp),
mgl@1371
  4706
+					  cc_status.value2)
mgl@1371
  4707
+		      || reg_mentioned_p (SET_DEST (vec_exp),
mgl@1371
  4708
+					  cc_status.mdep.value)))
mgl@1371
  4709
+		{
mgl@1371
  4710
+		  CC_STATUS_INIT;
mgl@1371
  4711
+		}
mgl@1371
  4712
+	    }
mgl@1371
  4713
+	}
mgl@1371
  4714
+
mgl@1371
  4715
+      /* Check if we have memory opartions with post_inc or pre_dec on the
mgl@1371
  4716
+         register currently reflected in cc0 */
mgl@1371
  4717
+      if (GET_CODE (exp) == SET
mgl@1371
  4718
+	  && GET_CODE (SET_SRC (exp)) == MEM
mgl@1371
  4719
+	  && (GET_CODE (XEXP (SET_SRC (exp), 0)) == POST_INC
mgl@1371
  4720
+	      || GET_CODE (XEXP (SET_SRC (exp), 0)) == PRE_DEC)
mgl@1371
  4721
+	  &&
mgl@1371
  4722
+	  (reg_mentioned_p
mgl@1371
  4723
+	   (XEXP (XEXP (SET_SRC (exp), 0), 0), cc_status.value1)
mgl@1371
  4724
+	   || reg_mentioned_p (XEXP (XEXP (SET_SRC (exp), 0), 0),
mgl@1371
  4725
+			       cc_status.value2)
mgl@1371
  4726
+	   || reg_mentioned_p (XEXP (XEXP (SET_SRC (exp), 0), 0),
mgl@1371
  4727
+			       cc_status.mdep.value)))
mgl@1371
  4728
+	CC_STATUS_INIT;
mgl@1371
  4729
+
mgl@1371
  4730
+      if (GET_CODE (exp) == SET
mgl@1371
  4731
+	  && GET_CODE (SET_DEST (exp)) == MEM
mgl@1371
  4732
+	  && (GET_CODE (XEXP (SET_DEST (exp), 0)) == POST_INC
mgl@1371
  4733
+	      || GET_CODE (XEXP (SET_DEST (exp), 0)) == PRE_DEC)
mgl@1371
  4734
+	  &&
mgl@1371
  4735
+	  (reg_mentioned_p
mgl@1371
  4736
+	   (XEXP (XEXP (SET_DEST (exp), 0), 0), cc_status.value1)
mgl@1371
  4737
+	   || reg_mentioned_p (XEXP (XEXP (SET_DEST (exp), 0), 0),
mgl@1371
  4738
+			       cc_status.value2)
mgl@1371
  4739
+	   || reg_mentioned_p (XEXP (XEXP (SET_DEST (exp), 0), 0),
mgl@1371
  4740
+			       cc_status.mdep.value)))
mgl@1371
  4741
+	CC_STATUS_INIT;
mgl@1371
  4742
+      break;
mgl@1371
  4743
+
mgl@1371
  4744
+    case CC_SET_VNCZ:
mgl@1371
  4745
+      CC_STATUS_INIT;
mgl@1371
  4746
+      cc_status.mdep.value = recog_data.operand[0];
mgl@1371
  4747
+      cc_status.mdep.flags = CC_SET_VNCZ;
mgl@1371
  4748
+      cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4749
+      break;
mgl@1371
  4750
+
mgl@1371
  4751
+    case CC_SET_NCZ:
mgl@1371
  4752
+      CC_STATUS_INIT;
mgl@1371
  4753
+      cc_status.mdep.value = recog_data.operand[0];
mgl@1371
  4754
+      cc_status.mdep.flags = CC_SET_NCZ;
mgl@1371
  4755
+      cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4756
+      break;
mgl@1371
  4757
+
mgl@1371
  4758
+    case CC_SET_CZ:
mgl@1371
  4759
+      CC_STATUS_INIT;
mgl@1371
  4760
+      cc_status.mdep.value = recog_data.operand[0];
mgl@1371
  4761
+      cc_status.mdep.flags = CC_SET_CZ;
mgl@1371
  4762
+      cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4763
+      break;
mgl@1371
  4764
+
mgl@1371
  4765
+    case CC_SET_Z:
mgl@1371
  4766
+      CC_STATUS_INIT;
mgl@1371
  4767
+      cc_status.mdep.value = recog_data.operand[0];
mgl@1371
  4768
+      cc_status.mdep.flags = CC_SET_Z;
mgl@1371
  4769
+      cc_status.mdep.cond_exec_cmp_clobbered = 0;
mgl@1371
  4770
+      break;
mgl@1371
  4771
+
mgl@1371
  4772
+    case CC_CLOBBER:
mgl@1371
  4773
+      CC_STATUS_INIT;
mgl@1371
  4774
+      break;
mgl@1371
  4775
+
mgl@1371
  4776
+    default:
mgl@1371
  4777
+      CC_STATUS_INIT;
mgl@1371
  4778
+    }
mgl@1371
  4779
+}
mgl@1371
  4780
+
mgl@1371
  4781
+
mgl@1371
  4782
+/*
mgl@1371
  4783
+  Outputs to stdio stream stream the assembler syntax for an instruction
mgl@1371
  4784
+  operand x. x is an RTL expression.
mgl@1371
  4785
+*/
mgl@1371
  4786
+void
mgl@1371
  4787
+avr32_print_operand (FILE * stream, rtx x, int code)
mgl@1371
  4788
+{
mgl@1371
  4789
+  int error = 0;
mgl@1371
  4790
+
mgl@1371
  4791
+  if ( code == '?' )
mgl@1371
  4792
+    {
mgl@1371
  4793
+      /* Predicable instruction, print condition code */
mgl@1371
  4794
+
mgl@1371
  4795
+      /* If the insn should not be conditional then do nothing. */
mgl@1371
  4796
+      if ( current_insn_predicate == NULL_RTX )
mgl@1371
  4797
+        return;
mgl@1371
  4798
+
mgl@1371
  4799
+      /* Set x to the predicate to force printing
mgl@1371
  4800
+         the condition later on. */
mgl@1371
  4801
+      x = current_insn_predicate;
mgl@1371
  4802
+
mgl@1371
  4803
+      /* Reverse condition if useing bld insn. */
mgl@1371
  4804
+      if ( GET_CODE (XEXP(current_insn_predicate,0)) == AND )
mgl@1371
  4805
+        x = reversed_condition (current_insn_predicate);
mgl@1371
  4806
+    }
mgl@1371
  4807
+  else if ( code == '!' )
mgl@1371
  4808
+    {
mgl@1371
  4809
+      /* Output compare for conditional insn if needed. */
mgl@1371
  4810
+      rtx new_cond;
mgl@1371
  4811
+      gcc_assert ( current_insn_predicate != NULL_RTX );
mgl@1371
  4812
+      new_cond = avr32_output_cmp(current_insn_predicate,
mgl@1371
  4813
+                                  GET_MODE(XEXP(current_insn_predicate,0)),
mgl@1371
  4814
+                                  XEXP(current_insn_predicate,0),
mgl@1371
  4815
+                                  XEXP(current_insn_predicate,1));
mgl@1371
  4816
+
mgl@1371
  4817
+      /* Check if the new condition is a special avr32 condition
mgl@1371
  4818
+         specified using UNSPECs. If so we must handle it differently. */
mgl@1371
  4819
+      if ( GET_CODE (new_cond) == UNSPEC )
mgl@1371
  4820
+        {
mgl@1371
  4821
+          current_insn_predicate =
mgl@1371
  4822
+            gen_rtx_UNSPEC (CCmode,
mgl@1371
  4823
+                            gen_rtvec (2,
mgl@1371
  4824
+                                       XEXP(current_insn_predicate,0),
mgl@1371
  4825
+                                       XEXP(current_insn_predicate,1)),
mgl@1371
  4826
+                            XINT (new_cond, 1));
mgl@1371
  4827
+        }
mgl@1371
  4828
+      else
mgl@1371
  4829
+        {
mgl@1371
  4830
+          PUT_CODE(current_insn_predicate, GET_CODE(new_cond));
mgl@1371
  4831
+        }
mgl@1371
  4832
+      return;
mgl@1371
  4833
+    }
mgl@1371
  4834
+
mgl@1371
  4835
+  switch (GET_CODE (x))
mgl@1371
  4836
+    {
mgl@1371
  4837
+    case UNSPEC:
mgl@1371
  4838
+      switch (XINT (x, 1))
mgl@1371
  4839
+	{
mgl@1371
  4840
+	case UNSPEC_COND_PL:
mgl@1371
  4841
+	  if (code == 'i')
mgl@1371
  4842
+	    fputs ("mi", stream);
mgl@1371
  4843
+	  else
mgl@1371
  4844
+	    fputs ("pl", stream);
mgl@1371
  4845
+	  break;
mgl@1371
  4846
+	case UNSPEC_COND_MI:
mgl@1371
  4847
+	  if (code == 'i')
mgl@1371
  4848
+	    fputs ("pl", stream);
mgl@1371
  4849
+	  else
mgl@1371
  4850
+	    fputs ("mi", stream);
mgl@1371
  4851
+	  break;
mgl@1371
  4852
+	default:
mgl@1371
  4853
+	  error = 1;
mgl@1371
  4854
+	}
mgl@1371
  4855
+      break;
mgl@1371
  4856
+    case EQ:
mgl@1371
  4857
+      if (code == 'i')
mgl@1371
  4858
+	fputs ("ne", stream);
mgl@1371
  4859
+      else
mgl@1371
  4860
+	fputs ("eq", stream);
mgl@1371
  4861
+      break;
mgl@1371
  4862
+    case NE:
mgl@1371
  4863
+      if (code == 'i')
mgl@1371
  4864
+	fputs ("eq", stream);
mgl@1371
  4865
+      else
mgl@1371
  4866
+	fputs ("ne", stream);
mgl@1371
  4867
+      break;
mgl@1371
  4868
+    case GT:
mgl@1371
  4869
+      if (code == 'i')
mgl@1371
  4870
+	fputs ("le", stream);
mgl@1371
  4871
+      else
mgl@1371
  4872
+	fputs ("gt", stream);
mgl@1371
  4873
+      break;
mgl@1371
  4874
+    case GTU:
mgl@1371
  4875
+      if (code == 'i')
mgl@1371
  4876
+	fputs ("ls", stream);
mgl@1371
  4877
+      else
mgl@1371
  4878
+	fputs ("hi", stream);
mgl@1371
  4879
+      break;
mgl@1371
  4880
+    case LT:
mgl@1371
  4881
+      if (code == 'i')
mgl@1371
  4882
+	fputs ("ge", stream);
mgl@1371
  4883
+      else
mgl@1371
  4884
+	fputs ("lt", stream);
mgl@1371
  4885
+      break;
mgl@1371
  4886
+    case LTU:
mgl@1371
  4887
+      if (code == 'i')
mgl@1371
  4888
+	fputs ("hs", stream);
mgl@1371
  4889
+      else
mgl@1371
  4890
+	fputs ("lo", stream);
mgl@1371
  4891
+      break;
mgl@1371
  4892
+    case GE:
mgl@1371
  4893
+      if (code == 'i')
mgl@1371
  4894
+	fputs ("lt", stream);
mgl@1371
  4895
+      else
mgl@1371
  4896
+	fputs ("ge", stream);
mgl@1371
  4897
+      break;
mgl@1371
  4898
+    case GEU:
mgl@1371
  4899
+      if (code == 'i')
mgl@1371
  4900
+	fputs ("lo", stream);
mgl@1371
  4901
+      else
mgl@1371
  4902
+	fputs ("hs", stream);
mgl@1371
  4903
+      break;
mgl@1371
  4904
+    case LE:
mgl@1371
  4905
+      if (code == 'i')
mgl@1371
  4906
+	fputs ("gt", stream);
mgl@1371
  4907
+      else
mgl@1371
  4908
+	fputs ("le", stream);
mgl@1371
  4909
+      break;
mgl@1371
  4910
+    case LEU:
mgl@1371
  4911
+      if (code == 'i')
mgl@1371
  4912
+	fputs ("hi", stream);
mgl@1371
  4913
+      else
mgl@1371
  4914
+	fputs ("ls", stream);
mgl@1371
  4915
+      break;
mgl@1371
  4916
+    case CONST_INT:
mgl@1371
  4917
+      {
mgl@1371
  4918
+        HOST_WIDE_INT value = INTVAL (x);
mgl@1371
  4919
+
mgl@1371
  4920
+        switch (code)
mgl@1371
  4921
+          {
mgl@1371
  4922
+          case 'm':
mgl@1371
  4923
+            if ( HOST_BITS_PER_WIDE_INT > BITS_PER_WORD )
mgl@1371
  4924
+              {
mgl@1371
  4925
+                /* A const_int can be used to represent DImode constants. */
mgl@1371
  4926
+                value >>= BITS_PER_WORD;
mgl@1371
  4927
+              }
mgl@1371
  4928
+            /* We might get a const_int immediate for setting a DI register,
mgl@1371
  4929
+               we then must then return the correct sign extended DI. The most
mgl@1371
  4930
+               significant word is just a sign extension. */
mgl@1371
  4931
+            else if (value < 0)
mgl@1371
  4932
+              value = -1;
mgl@1371
  4933
+            else
mgl@1371
  4934
+              value = 0;
mgl@1371
  4935
+            break;
mgl@1371
  4936
+          case 'i':
mgl@1371
  4937
+            value++;
mgl@1371
  4938
+            break;
mgl@1371
  4939
+          case 'p':
mgl@1371
  4940
+            {
mgl@1371
  4941
+              /* Set to bit position of first bit set in immediate */
mgl@1371
  4942
+              int i, bitpos = 32;
mgl@1371
  4943
+              for (i = 0; i < 32; i++)
mgl@1371
  4944
+                if (value & (1 << i))
mgl@1371
  4945
+                  {
mgl@1371
  4946
+                    bitpos = i;
mgl@1371
  4947
+                    break;
mgl@1371
  4948
+                  }
mgl@1371
  4949
+              value = bitpos;
mgl@1371
  4950
+            }
mgl@1371
  4951
+            break;
mgl@1371
  4952
+          case 'z':
mgl@1371
  4953
+            {
mgl@1371
  4954
+              /* Set to bit position of first bit cleared in immediate */
mgl@1371
  4955
+              int i, bitpos = 32;
mgl@1371
  4956
+              for (i = 0; i < 32; i++)
mgl@1371
  4957
+                if (!(value & (1 << i)))
mgl@1371
  4958
+                  {
mgl@1371
  4959
+                    bitpos = i;
mgl@1371
  4960
+                    break;
mgl@1371
  4961
+                  }
mgl@1371
  4962
+              value = bitpos;
mgl@1371
  4963
+            }
mgl@1371
  4964
+            break;
mgl@1371
  4965
+          case 'r':
mgl@1371
  4966
+            {
mgl@1371
  4967
+              /* Reglist 8 */
mgl@1371
  4968
+              char op[50];
mgl@1371
  4969
+              op[0] = '\0';
mgl@1371
  4970
+
mgl@1371
  4971
+              if (value & 0x01)
mgl@1371
  4972
+                sprintf (op, "r0-r3");
mgl@1371
  4973
+              if (value & 0x02)
mgl@1371
  4974
+                strlen (op) ? sprintf (op, "%s, r4-r7", op) : sprintf (op,
mgl@1371
  4975
+                                                                       "r4-r7");
mgl@1371
  4976
+              if (value & 0x04)
mgl@1371
  4977
+                strlen (op) ? sprintf (op, "%s, r8-r9", op) : sprintf (op,
mgl@1371
  4978
+                                                                       "r8-r9");
mgl@1371
  4979
+              if (value & 0x08)
mgl@1371
  4980
+                strlen (op) ? sprintf (op, "%s, r10", op) : sprintf (op,
mgl@1371
  4981
+                                                                     "r10");
mgl@1371
  4982
+              if (value & 0x10)
mgl@1371
  4983
+                strlen (op) ? sprintf (op, "%s, r11", op) : sprintf (op,
mgl@1371
  4984
+                                                                     "r11");
mgl@1371
  4985
+              if (value & 0x20)
mgl@1371
  4986
+                strlen (op) ? sprintf (op, "%s, r12", op) : sprintf (op,
mgl@1371
  4987
+                                                                     "r12");
mgl@1371
  4988
+              if (value & 0x40)
mgl@1371
  4989
+                strlen (op) ? sprintf (op, "%s, lr", op) : sprintf (op, "lr");
mgl@1371
  4990
+              if (value & 0x80)
mgl@1371
  4991
+                strlen (op) ? sprintf (op, "%s, pc", op) : sprintf (op, "pc");
mgl@1371
  4992
+
mgl@1371
  4993
+              fputs (op, stream);
mgl@1371
  4994
+              return;
mgl@1371
  4995
+            }
mgl@1371
  4996
+          case 's':
mgl@1371
  4997
+            {
mgl@1371
  4998
+              /* Reglist 16 */
mgl@1371
  4999
+              char reglist16_string[100];
mgl@1371
  5000
+              int i;
mgl@1371
  5001
+              reglist16_string[0] = '\0';
mgl@1371
  5002
+
mgl@1371
  5003
+	      for (i = 0; i < 16; ++i)
mgl@1371
  5004
+		{
mgl@1371
  5005
+		  if (value & (1 << i))
mgl@1371
  5006
+		    {
mgl@1371
  5007
+		      strlen (reglist16_string) ? sprintf (reglist16_string,
mgl@1371
  5008
+							   "%s, %s",
mgl@1371
  5009
+							   reglist16_string,
mgl@1371
  5010
+							   reg_names
mgl@1371
  5011
+							   [INTERNAL_REGNUM
mgl@1371
  5012
+							    (i)]) :
mgl@1371
  5013
+			sprintf (reglist16_string, "%s",
mgl@1371
  5014
+				 reg_names[INTERNAL_REGNUM (i)]);
mgl@1371
  5015
+		    }
mgl@1371
  5016
+		}
mgl@1371
  5017
+	      fputs (reglist16_string, stream);
mgl@1371
  5018
+	      return;
mgl@1371
  5019
+	    }
mgl@1371
  5020
+	  case 'C':
mgl@1371
  5021
+	    {
mgl@1371
  5022
+	      /* RegListCP8 */
mgl@1371
  5023
+	      char reglist_string[100];
mgl@1371
  5024
+	      avr32_make_fp_reglist_w (value, (char *) reglist_string);
mgl@1371
  5025
+	      fputs (reglist_string, stream);
mgl@1371
  5026
+	      return;
mgl@1371
  5027
+	    }
mgl@1371
  5028
+	  case 'D':
mgl@1371
  5029
+	    {
mgl@1371
  5030
+	      /* RegListCPD8 */
mgl@1371
  5031
+	      char reglist_string[100];
mgl@1371
  5032
+	      avr32_make_fp_reglist_d (value, (char *) reglist_string);
mgl@1371
  5033
+	      fputs (reglist_string, stream);
mgl@1371
  5034
+	      return;
mgl@1371
  5035
+	    }
mgl@1371
  5036
+	  case 'h':
mgl@1371
  5037
+	    /* Print halfword part of word */
mgl@1371
  5038
+	    fputs (value ? "b" : "t", stream);
mgl@1371
  5039
+	    return;
mgl@1371
  5040
+	  }
mgl@1371
  5041
+
mgl@1371
  5042
+	/* Print Value */
mgl@1371
  5043
+	fprintf (stream, "%d", value);
mgl@1371
  5044
+	break;
mgl@1371
  5045
+      }
mgl@1371
  5046
+    case CONST_DOUBLE:
mgl@1371
  5047
+      {
mgl@1371
  5048
+	HOST_WIDE_INT hi, lo;
mgl@1371
  5049
+	if (SCALAR_FLOAT_MODE_P (GET_MODE (x)))
mgl@1371
  5050
+	  {
mgl@1371
  5051
+	    HOST_WIDE_INT target_float[2];
mgl@1371
  5052
+	    hi = lo = 0;
mgl@1371
  5053
+	    real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (x),
mgl@1371
  5054
+			    GET_MODE (x));
mgl@1371
  5055
+	    /* For doubles the most significant part starts at index 0. */
mgl@1371
  5056
+	    if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
mgl@1371
  5057
+	      {
mgl@1371
  5058
+		hi = target_float[0];
mgl@1371
  5059
+		lo = target_float[1];
mgl@1371
  5060
+	      }
mgl@1371
  5061
+	    else
mgl@1371
  5062
+	      {
mgl@1371
  5063
+		lo = target_float[0];
mgl@1371
  5064
+	      }
mgl@1371
  5065
+	  }
mgl@1371
  5066
+	else
mgl@1371
  5067
+	  {
mgl@1371
  5068
+	    hi = CONST_DOUBLE_HIGH (x);
mgl@1371
  5069
+	    lo = CONST_DOUBLE_LOW (x);
mgl@1371
  5070
+	  }
mgl@1371
  5071
+
mgl@1371
  5072
+	if (code == 'm')
mgl@1371
  5073
+	  fprintf (stream, "%ld", hi);
mgl@1371
  5074
+	else
mgl@1371
  5075
+	  fprintf (stream, "%ld", lo);
mgl@1371
  5076
+
mgl@1371
  5077
+	break;
mgl@1371
  5078
+      }
mgl@1371
  5079
+    case CONST:
mgl@1371
  5080
+      output_addr_const (stream, XEXP (XEXP (x, 0), 0));
mgl@1371
  5081
+      fprintf (stream, "+%ld", INTVAL (XEXP (XEXP (x, 0), 1)));
mgl@1371
  5082
+      break;
mgl@1371
  5083
+    case REG:
mgl@1371
  5084
+      /* Swap register name if the register is DImode or DFmode. */
mgl@1371
  5085
+      if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
mgl@1371
  5086
+	{
mgl@1371
  5087
+	  /* Double register must have an even numbered address */
mgl@1371
  5088
+	  gcc_assert (!(REGNO (x) % 2));
mgl@1371
  5089
+	  if (code == 'm')
mgl@1371
  5090
+	    fputs (reg_names[true_regnum (x)], stream);
mgl@1371
  5091
+	  else
mgl@1371
  5092
+	    fputs (reg_names[true_regnum (x) + 1], stream);
mgl@1371
  5093
+	}
mgl@1371
  5094
+      else if (GET_MODE (x) == TImode)
mgl@1371
  5095
+	{
mgl@1371
  5096
+	  switch (code)
mgl@1371
  5097
+	    {
mgl@1371
  5098
+	    case 'T':
mgl@1371
  5099
+	      fputs (reg_names[true_regnum (x)], stream);
mgl@1371
  5100
+	      break;
mgl@1371
  5101
+	    case 'U':
mgl@1371
  5102
+	      fputs (reg_names[true_regnum (x) + 1], stream);
mgl@1371
  5103
+	      break;
mgl@1371
  5104
+	    case 'L':
mgl@1371
  5105
+	      fputs (reg_names[true_regnum (x) + 2], stream);
mgl@1371
  5106
+	      break;
mgl@1371
  5107
+	    case 'B':
mgl@1371
  5108
+	      fputs (reg_names[true_regnum (x) + 3], stream);
mgl@1371
  5109
+	      break;
mgl@1371
  5110
+	    default:
mgl@1371
  5111
+	      fprintf (stream, "%s, %s, %s, %s",
mgl@1371
  5112
+		       reg_names[true_regnum (x) + 3],
mgl@1371
  5113
+		       reg_names[true_regnum (x) + 2],
mgl@1371
  5114
+		       reg_names[true_regnum (x) + 1],
mgl@1371
  5115
+		       reg_names[true_regnum (x)]);
mgl@1371
  5116
+	      break;
mgl@1371
  5117
+	    }
mgl@1371
  5118
+	}
mgl@1371
  5119
+      else
mgl@1371
  5120
+	{
mgl@1371
  5121
+	  fputs (reg_names[true_regnum (x)], stream);
mgl@1371
  5122
+	}
mgl@1371
  5123
+      break;
mgl@1371
  5124
+    case CODE_LABEL:
mgl@1371
  5125
+    case LABEL_REF:
mgl@1371
  5126
+    case SYMBOL_REF:
mgl@1371
  5127
+      output_addr_const (stream, x);
mgl@1371
  5128
+      break;
mgl@1371
  5129
+    case MEM:
mgl@1371
  5130
+      switch (GET_CODE (XEXP (x, 0)))
mgl@1371
  5131
+	{
mgl@1371
  5132
+	case LABEL_REF:
mgl@1371
  5133
+	case SYMBOL_REF:
mgl@1371
  5134
+	  output_addr_const (stream, XEXP (x, 0));
mgl@1371
  5135
+	  break;
mgl@1371
  5136
+	case MEM:
mgl@1371
  5137
+	  switch (GET_CODE (XEXP (XEXP (x, 0), 0)))
mgl@1371
  5138
+	    {
mgl@1371
  5139
+	    case SYMBOL_REF:
mgl@1371
  5140
+	      output_addr_const (stream, XEXP (XEXP (x, 0), 0));
mgl@1371
  5141
+	      break;
mgl@1371
  5142
+	    default:
mgl@1371
  5143
+	      error = 1;
mgl@1371
  5144
+	      break;
mgl@1371
  5145
+	    }
mgl@1371
  5146
+	  break;
mgl@1371
  5147
+	case REG:
mgl@1371
  5148
+	  avr32_print_operand (stream, XEXP (x, 0), 0);
mgl@1371
  5149
+	  if (code != 'p')
mgl@1371
  5150
+	    fputs ("[0]", stream);
mgl@1371
  5151
+	  break;
mgl@1371
  5152
+	case PRE_DEC:
mgl@1371
  5153
+	  fputs ("--", stream);
mgl@1371
  5154
+	  avr32_print_operand (stream, XEXP (XEXP (x, 0), 0), 0);
mgl@1371
  5155
+	  break;
mgl@1371
  5156
+	case POST_INC:
mgl@1371
  5157
+	  avr32_print_operand (stream, XEXP (XEXP (x, 0), 0), 0);
mgl@1371
  5158
+	  fputs ("++", stream);
mgl@1371
  5159
+	  break;
mgl@1371
  5160
+	case PLUS:
mgl@1371
  5161
+	  {
mgl@1371
  5162
+	    rtx op0 = XEXP (XEXP (x, 0), 0);
mgl@1371
  5163
+	    rtx op1 = XEXP (XEXP (x, 0), 1);
mgl@1371
  5164
+	    rtx base = NULL_RTX, offset = NULL_RTX;
mgl@1371
  5165
+
mgl@1371
  5166
+	    if (avr32_address_register_rtx_p (op0, 1))
mgl@1371
  5167
+	      {
mgl@1371
  5168
+		base = op0;
mgl@1371
  5169
+		offset = op1;
mgl@1371
  5170
+	      }
mgl@1371
  5171
+	    else if (avr32_address_register_rtx_p (op1, 1))
mgl@1371
  5172
+	      {
mgl@1371
  5173
+		/* Operands are switched. */
mgl@1371
  5174
+		base = op1;
mgl@1371
  5175
+		offset = op0;
mgl@1371
  5176
+	      }
mgl@1371
  5177
+
mgl@1371
  5178
+	    gcc_assert (base && offset
mgl@1371
  5179
+			&& avr32_address_register_rtx_p (base, 1)
mgl@1371
  5180
+			&& avr32_legitimate_index_p (GET_MODE (x), offset,
mgl@1371
  5181
+						     1));
mgl@1371
  5182
+
mgl@1371
  5183
+	    avr32_print_operand (stream, base, 0);
mgl@1371
  5184
+	    fputs ("[", stream);
mgl@1371
  5185
+	    avr32_print_operand (stream, offset, 0);
mgl@1371
  5186
+	    fputs ("]", stream);
mgl@1371
  5187
+	    break;
mgl@1371
  5188
+	  }
mgl@1371
  5189
+	case CONST:
mgl@1371
  5190
+	  output_addr_const (stream, XEXP (XEXP (XEXP (x, 0), 0), 0));
mgl@1371
  5191
+	  fprintf (stream, " + %ld",
mgl@1371
  5192
+		   INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)));
mgl@1371
  5193
+	  break;
mgl@1371
  5194
+        case CONST_INT:
mgl@1371
  5195
+	  avr32_print_operand (stream, XEXP (x, 0), 0);
mgl@1371
  5196
+          break;
mgl@1371
  5197
+	default:
mgl@1371
  5198
+	  error = 1;
mgl@1371
  5199
+	}
mgl@1371
  5200
+      break;
mgl@1371
  5201
+    case MULT:
mgl@1371
  5202
+      {
mgl@1371
  5203
+	int value = INTVAL (XEXP (x, 1));
mgl@1371
  5204
+
mgl@1371
  5205
+	/* Convert immediate in multiplication into a shift immediate */
mgl@1371
  5206
+	switch (value)
mgl@1371
  5207
+	  {
mgl@1371
  5208
+	  case 2:
mgl@1371
  5209
+	    value = 1;
mgl@1371
  5210
+	    break;
mgl@1371
  5211
+	  case 4:
mgl@1371
  5212
+	    value = 2;
mgl@1371
  5213
+	    break;
mgl@1371
  5214
+	  case 8:
mgl@1371
  5215
+	    value = 3;
mgl@1371
  5216
+	    break;
mgl@1371
  5217
+	  default:
mgl@1371
  5218
+	    value = 0;
mgl@1371
  5219
+	  }
mgl@1371
  5220
+	fprintf (stream, "%s << %i", reg_names[true_regnum (XEXP (x, 0))],
mgl@1371
  5221
+		 value);
mgl@1371
  5222
+	break;
mgl@1371
  5223
+      }
mgl@1371
  5224
+    case ASHIFT:
mgl@1371
  5225
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
mgl@1371
  5226
+	fprintf (stream, "%s << %i", reg_names[true_regnum (XEXP (x, 0))],
mgl@1371
  5227
+		 (int) INTVAL (XEXP (x, 1)));
mgl@1371
  5228
+      else if (REG_P (XEXP (x, 1)))
mgl@1371
  5229
+	fprintf (stream, "%s << %s", reg_names[true_regnum (XEXP (x, 0))],
mgl@1371
  5230
+		 reg_names[true_regnum (XEXP (x, 1))]);
mgl@1371
  5231
+      else
mgl@1371
  5232
+	{
mgl@1371
  5233
+	  error = 1;
mgl@1371
  5234
+	}
mgl@1371
  5235
+      break;
mgl@1371
  5236
+    case LSHIFTRT:
mgl@1371
  5237
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
mgl@1371
  5238
+	fprintf (stream, "%s >> %i", reg_names[true_regnum (XEXP (x, 0))],
mgl@1371
  5239
+		 (int) INTVAL (XEXP (x, 1)));
mgl@1371
  5240
+      else if (REG_P (XEXP (x, 1)))
mgl@1371
  5241
+	fprintf (stream, "%s >> %s", reg_names[true_regnum (XEXP (x, 0))],
mgl@1371
  5242
+		 reg_names[true_regnum (XEXP (x, 1))]);
mgl@1371
  5243
+      else
mgl@1371
  5244
+	{
mgl@1371
  5245
+	  error = 1;
mgl@1371
  5246
+	}
mgl@1371
  5247
+      fprintf (stream, ">>");
mgl@1371
  5248
+      break;
mgl@1371
  5249
+    case PARALLEL:
mgl@1371
  5250
+      {
mgl@1371
  5251
+	/* Load store multiple */
mgl@1371
  5252
+	int i;
mgl@1371
  5253
+	int count = XVECLEN (x, 0);
mgl@1371
  5254
+	int reglist16 = 0;
mgl@1371
  5255
+	char reglist16_string[100];
mgl@1371
  5256
+
mgl@1371
  5257
+	for (i = 0; i < count; ++i)
mgl@1371
  5258
+	  {
mgl@1371
  5259
+	    rtx vec_elm = XVECEXP (x, 0, i);
mgl@1371
  5260
+	    if (GET_MODE (vec_elm) != SET)
mgl@1371
  5261
+	      {
mgl@1371
  5262
+		debug_rtx (vec_elm);
mgl@1371
  5263
+		internal_error ("Unknown element in parallel expression!");
mgl@1371
  5264
+	      }
mgl@1371
  5265
+	    if (GET_MODE (XEXP (vec_elm, 0)) == REG)
mgl@1371
  5266
+	      {
mgl@1371
  5267
+		/* Load multiple */
mgl@1371
  5268
+		reglist16 |= 1 << ASM_REGNUM (REGNO (XEXP (vec_elm, 0)));
mgl@1371
  5269
+	      }
mgl@1371
  5270
+	    else
mgl@1371
  5271
+	      {
mgl@1371
  5272
+		/* Store multiple */
mgl@1371
  5273
+		reglist16 |= 1 << ASM_REGNUM (REGNO (XEXP (vec_elm, 1)));
mgl@1371
  5274
+	      }
mgl@1371
  5275
+	  }
mgl@1371
  5276
+
mgl@1371
  5277
+	avr32_make_reglist16 (reglist16, reglist16_string);
mgl@1371
  5278
+	fputs (reglist16_string, stream);
mgl@1371
  5279
+
mgl@1371
  5280
+	break;
mgl@1371
  5281
+      }
mgl@1371
  5282
+
mgl@1371
  5283
+    case PLUS:
mgl@1371
  5284
+      {
mgl@1371
  5285
+        rtx op0 = XEXP (x, 0);
mgl@1371
  5286
+        rtx op1 = XEXP (x, 1);
mgl@1371
  5287
+        rtx base = NULL_RTX, offset = NULL_RTX;
mgl@1371
  5288
+
mgl@1371
  5289
+        if (avr32_address_register_rtx_p (op0, 1))
mgl@1371
  5290
+          {
mgl@1371
  5291
+            base = op0;
mgl@1371
  5292
+            offset = op1;
mgl@1371
  5293
+          }
mgl@1371
  5294
+        else if (avr32_address_register_rtx_p (op1, 1))
mgl@1371
  5295
+          {
mgl@1371
  5296
+            /* Operands are switched. */
mgl@1371
  5297
+            base = op1;
mgl@1371
  5298
+            offset = op0;
mgl@1371
  5299
+          }
mgl@1371
  5300
+
mgl@1371
  5301
+        gcc_assert (base && offset
mgl@1371
  5302
+                    && avr32_address_register_rtx_p (base, 1)
mgl@1371
  5303
+                    && avr32_legitimate_index_p (GET_MODE (x), offset, 1));
mgl@1371
  5304
+
mgl@1371
  5305
+        avr32_print_operand (stream, base, 0);
mgl@1371
  5306
+        fputs ("[", stream);
mgl@1371
  5307
+        avr32_print_operand (stream, offset, 0);
mgl@1371
  5308
+        fputs ("]", stream);
mgl@1371
  5309
+        break;
mgl@1371
  5310
+      }
mgl@1371
  5311
+
mgl@1371
  5312
+    default:
mgl@1371
  5313
+      error = 1;
mgl@1371
  5314
+    }
mgl@1371
  5315
+
mgl@1371
  5316
+  if (error)
mgl@1371
  5317
+    {
mgl@1371
  5318
+      debug_rtx (x);
mgl@1371
  5319
+      internal_error ("Illegal expression for avr32_print_operand");
mgl@1371
  5320
+    }
mgl@1371
  5321
+}
mgl@1371
  5322
+
mgl@1371
  5323
+rtx
mgl@1371
  5324
+avr32_get_note_reg_equiv (rtx insn)
mgl@1371
  5325
+{
mgl@1371
  5326
+  rtx note;
mgl@1371
  5327
+
mgl@1371
  5328
+  note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
mgl@1371
  5329
+
mgl@1371
  5330
+  if (note != NULL_RTX)
mgl@1371
  5331
+    return XEXP (note, 0);
mgl@1371
  5332
+  else
mgl@1371
  5333
+    return NULL_RTX;
mgl@1371
  5334
+}
mgl@1371
  5335
+
mgl@1371
  5336
+/*
mgl@1371
  5337
+  Outputs to stdio stream stream the assembler syntax for an instruction
mgl@1371
  5338
+  operand that is a memory reference whose address is x. x is an RTL
mgl@1371
  5339
+  expression.
mgl@1371
  5340
+
mgl@1371
  5341
+  ToDo: fixme.
mgl@1371
  5342
+*/
mgl@1371
  5343
+void
mgl@1371
  5344
+avr32_print_operand_address (FILE * stream, rtx x)
mgl@1371
  5345
+{
mgl@1371
  5346
+  fprintf (stream, "(%d) /* address */", REGNO (x));
mgl@1371
  5347
+}
mgl@1371
  5348
+
mgl@1371
  5349
+/* Return true if _GLOBAL_OFFSET_TABLE_ symbol is mentioned.  */
mgl@1371
  5350
+bool
mgl@1371
  5351
+avr32_got_mentioned_p (rtx addr)
mgl@1371
  5352
+{
mgl@1371
  5353
+  if (GET_CODE (addr) == MEM)
mgl@1371
  5354
+    addr = XEXP (addr, 0);
mgl@1371
  5355
+  while (GET_CODE (addr) == CONST)
mgl@1371
  5356
+    addr = XEXP (addr, 0);
mgl@1371
  5357
+  if (GET_CODE (addr) == SYMBOL_REF)
mgl@1371
  5358
+    {
mgl@1371
  5359
+      return streq (XSTR (addr, 0), "_GLOBAL_OFFSET_TABLE_");
mgl@1371
  5360
+    }
mgl@1371
  5361
+  if (GET_CODE (addr) == PLUS || GET_CODE (addr) == MINUS)
mgl@1371
  5362
+    {
mgl@1371
  5363
+      bool l1, l2;
mgl@1371
  5364
+
mgl@1371
  5365
+      l1 = avr32_got_mentioned_p (XEXP (addr, 0));
mgl@1371
  5366
+      l2 = avr32_got_mentioned_p (XEXP (addr, 1));
mgl@1371
  5367
+      return l1 || l2;
mgl@1371
  5368
+    }
mgl@1371
  5369
+  return false;
mgl@1371
  5370
+}
mgl@1371
  5371
+
mgl@1371
  5372
+
mgl@1371
  5373
+/* Find the symbol in an address expression.  */
mgl@1371
  5374
+
mgl@1371
  5375
+rtx
mgl@1371
  5376
+avr32_find_symbol (rtx addr)
mgl@1371
  5377
+{
mgl@1371
  5378
+  if (GET_CODE (addr) == MEM)
mgl@1371
  5379
+    addr = XEXP (addr, 0);
mgl@1371
  5380
+
mgl@1371
  5381
+  while (GET_CODE (addr) == CONST)
mgl@1371
  5382
+    addr = XEXP (addr, 0);
mgl@1371
  5383
+
mgl@1371
  5384
+  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
mgl@1371
  5385
+    return addr;
mgl@1371
  5386
+  if (GET_CODE (addr) == PLUS)
mgl@1371
  5387
+    {
mgl@1371
  5388
+      rtx l1, l2;
mgl@1371
  5389
+
mgl@1371
  5390
+      l1 = avr32_find_symbol (XEXP (addr, 0));
mgl@1371
  5391
+      l2 = avr32_find_symbol (XEXP (addr, 1));
mgl@1371
  5392
+      if (l1 != NULL_RTX && l2 == NULL_RTX)
mgl@1371
  5393
+	return l1;
mgl@1371
  5394
+      else if (l1 == NULL_RTX && l2 != NULL_RTX)
mgl@1371
  5395
+	return l2;
mgl@1371
  5396
+    }
mgl@1371
  5397
+
mgl@1371
  5398
+  return NULL_RTX;
mgl@1371
  5399
+}
mgl@1371
  5400
+
mgl@1371
  5401
+
mgl@1371
  5402
+/* Routines for manipulation of the constant pool.  */
mgl@1371
  5403
+
mgl@1371
  5404
+/* AVR32 instructions cannot load a large constant directly into a
mgl@1371
  5405
+   register; they have to come from a pc relative load.  The constant
mgl@1371
  5406
+   must therefore be placed in the addressable range of the pc
mgl@1371
  5407
+   relative load.  Depending on the precise pc relative load
mgl@1371
  5408
+   instruction the range is somewhere between 256 bytes and 4k.  This
mgl@1371
  5409
+   means that we often have to dump a constant inside a function, and
mgl@1371
  5410
+   generate code to branch around it.
mgl@1371
  5411
+
mgl@1371
  5412
+   It is important to minimize this, since the branches will slow
mgl@1371
  5413
+   things down and make the code larger.
mgl@1371
  5414
+
mgl@1371
  5415
+   Normally we can hide the table after an existing unconditional
mgl@1371
  5416
+   branch so that there is no interruption of the flow, but in the
mgl@1371
  5417
+   worst case the code looks like this:
mgl@1371
  5418
+
mgl@1371
  5419
+	lddpc	rn, L1
mgl@1371
  5420
+	...
mgl@1371
  5421
+	rjmp	L2
mgl@1371
  5422
+	align
mgl@1371
  5423
+	L1:	.long value
mgl@1371
  5424
+	L2:
mgl@1371
  5425
+	...
mgl@1371
  5426
+
mgl@1371
  5427
+	lddpc	rn, L3
mgl@1371
  5428
+	...
mgl@1371
  5429
+	rjmp	L4
mgl@1371
  5430
+	align
mgl@1371
  5431
+	L3:	.long value
mgl@1371
  5432
+	L4:
mgl@1371
  5433
+	...
mgl@1371
  5434
+
mgl@1371
  5435
+   We fix this by performing a scan after scheduling, which notices
mgl@1371
  5436
+   which instructions need to have their operands fetched from the
mgl@1371
  5437
+   constant table and builds the table.
mgl@1371
  5438
+
mgl@1371
  5439
+   The algorithm starts by building a table of all the constants that
mgl@1371
  5440
+   need fixing up and all the natural barriers in the function (places
mgl@1371
  5441
+   where a constant table can be dropped without breaking the flow).
mgl@1371
  5442
+   For each fixup we note how far the pc-relative replacement will be
mgl@1371
  5443
+   able to reach and the offset of the instruction into the function.
mgl@1371
  5444
+
mgl@1371
  5445
+   Having built the table we then group the fixes together to form
mgl@1371
  5446
+   tables that are as large as possible (subject to addressing
mgl@1371
  5447
+   constraints) and emit each table of constants after the last
mgl@1371
  5448
+   barrier that is within range of all the instructions in the group.
mgl@1371
  5449
+   If a group does not contain a barrier, then we forcibly create one
mgl@1371
  5450
+   by inserting a jump instruction into the flow.  Once the table has
mgl@1371
  5451
+   been inserted, the insns are then modified to reference the
mgl@1371
  5452
+   relevant entry in the pool.
mgl@1371
  5453
+
mgl@1371
  5454
+   Possible enhancements to the algorithm (not implemented) are:
mgl@1371
  5455
+
mgl@1371
  5456
+   1) For some processors and object formats, there may be benefit in
mgl@1371
  5457
+   aligning the pools to the start of cache lines; this alignment
mgl@1371
  5458
+   would need to be taken into account when calculating addressability
mgl@1371
  5459
+   of a pool.  */
mgl@1371
  5460
+
mgl@1371
  5461
+/* These typedefs are located at the start of this file, so that
mgl@1371
  5462
+   they can be used in the prototypes there.  This comment is to
mgl@1371
  5463
+   remind readers of that fact so that the following structures
mgl@1371
  5464
+   can be understood more easily.
mgl@1371
  5465
+
mgl@1371
  5466
+     typedef struct minipool_node    Mnode;
mgl@1371
  5467
+     typedef struct minipool_fixup   Mfix;  */
mgl@1371
  5468
+
mgl@1371
  5469
+struct minipool_node
mgl@1371
  5470
+{
mgl@1371
  5471
+  /* Doubly linked chain of entries.  */
mgl@1371
  5472
+  Mnode *next;
mgl@1371
  5473
+  Mnode *prev;
mgl@1371
  5474
+  /* The maximum offset into the code that this entry can be placed.  While
mgl@1371
  5475
+     pushing fixes for forward references, all entries are sorted in order of
mgl@1371
  5476
+     increasing max_address.  */
mgl@1371
  5477
+  HOST_WIDE_INT max_address;
mgl@1371
  5478
+  /* Similarly for an entry inserted for a backwards ref.  */
mgl@1371
  5479
+  HOST_WIDE_INT min_address;
mgl@1371
  5480
+  /* The number of fixes referencing this entry.  This can become zero if we
mgl@1371
  5481
+     "unpush" an entry.  In this case we ignore the entry when we come to
mgl@1371
  5482
+     emit the code.  */
mgl@1371
  5483
+  int refcount;
mgl@1371
  5484
+  /* The offset from the start of the minipool.  */
mgl@1371
  5485
+  HOST_WIDE_INT offset;
mgl@1371
  5486
+  /* The value in table.  */
mgl@1371
  5487
+  rtx value;
mgl@1371
  5488
+  /* The mode of value.  */
mgl@1371
  5489
+  enum machine_mode mode;
mgl@1371
  5490
+  /* The size of the value.  */
mgl@1371
  5491
+  int fix_size;
mgl@1371
  5492
+};
mgl@1371
  5493
+
mgl@1371
  5494
+struct minipool_fixup
mgl@1371
  5495
+{
mgl@1371
  5496
+  Mfix *next;
mgl@1371
  5497
+  rtx insn;
mgl@1371
  5498
+  HOST_WIDE_INT address;
mgl@1371
  5499
+  rtx *loc;
mgl@1371
  5500
+  enum machine_mode mode;
mgl@1371
  5501
+  int fix_size;
mgl@1371
  5502
+  rtx value;
mgl@1371
  5503
+  Mnode *minipool;
mgl@1371
  5504
+  HOST_WIDE_INT forwards;
mgl@1371
  5505
+  HOST_WIDE_INT backwards;
mgl@1371
  5506
+};
mgl@1371
  5507
+
mgl@1371
  5508
+
mgl@1371
  5509
+/* Fixes less than a word need padding out to a word boundary.  */
mgl@1371
  5510
+#define MINIPOOL_FIX_SIZE(mode, value)                          \
mgl@1371
  5511
+  (IS_FORCE_MINIPOOL(value) ? 0 :                               \
mgl@1371
  5512
+   (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4))
mgl@1371
  5513
+
mgl@1371
  5514
+#define IS_FORCE_MINIPOOL(x)                    \
mgl@1371
  5515
+  (GET_CODE(x) == UNSPEC &&                     \
mgl@1371
  5516
+   XINT(x, 1) == UNSPEC_FORCE_MINIPOOL)
mgl@1371
  5517
+
mgl@1371
  5518
+static Mnode *minipool_vector_head;
mgl@1371
  5519
+static Mnode *minipool_vector_tail;
mgl@1371
  5520
+
mgl@1371
  5521
+/* The linked list of all minipool fixes required for this function.  */
mgl@1371
  5522
+Mfix *minipool_fix_head;
mgl@1371
  5523
+Mfix *minipool_fix_tail;
mgl@1371
  5524
+/* The fix entry for the current minipool, once it has been placed.  */
mgl@1371
  5525
+Mfix *minipool_barrier;
mgl@1371
  5526
+
mgl@1371
  5527
+/* Determines if INSN is the start of a jump table.  Returns the end
mgl@1371
  5528
+   of the TABLE or NULL_RTX.  */
mgl@1371
  5529
+static rtx
mgl@1371
  5530
+is_jump_table (rtx insn)
mgl@1371
  5531
+{
mgl@1371
  5532
+  rtx table;
mgl@1371
  5533
+
mgl@1371
  5534
+  if (GET_CODE (insn) == JUMP_INSN
mgl@1371
  5535
+      && JUMP_LABEL (insn) != NULL
mgl@1371
  5536
+      && ((table = next_real_insn (JUMP_LABEL (insn)))
mgl@1371
  5537
+	  == next_real_insn (insn))
mgl@1371
  5538
+      && table != NULL
mgl@1371
  5539
+      && GET_CODE (table) == JUMP_INSN
mgl@1371
  5540
+      && (GET_CODE (PATTERN (table)) == ADDR_VEC
mgl@1371
  5541
+	  || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
mgl@1371
  5542
+    return table;
mgl@1371
  5543
+
mgl@1371
  5544
+  return NULL_RTX;
mgl@1371
  5545
+}
mgl@1371
  5546
+
mgl@1371
  5547
+static HOST_WIDE_INT
mgl@1371
  5548
+get_jump_table_size (rtx insn)
mgl@1371
  5549
+{
mgl@1371
  5550
+  /* ADDR_VECs only take room if read-only data does into the text section.  */
mgl@1371
  5551
+  if (JUMP_TABLES_IN_TEXT_SECTION
mgl@1371
  5552
+#if !defined(READONLY_DATA_SECTION_ASM_OP)
mgl@1371
  5553
+      || 1
mgl@1371
  5554
+#endif
mgl@1371
  5555
+    )
mgl@1371
  5556
+    {
mgl@1371
  5557
+      rtx body = PATTERN (insn);
mgl@1371
  5558
+      int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
mgl@1371
  5559
+
mgl@1371
  5560
+      return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
mgl@1371
  5561
+    }
mgl@1371
  5562
+
mgl@1371
  5563
+  return 0;
mgl@1371
  5564
+}
mgl@1371
  5565
+
mgl@1371
  5566
+/* Move a minipool fix MP from its current location to before MAX_MP.
mgl@1371
  5567
+   If MAX_MP is NULL, then MP doesn't need moving, but the addressing
mgl@1371
  5568
+   constraints may need updating.  */
mgl@1371
  5569
+static Mnode *
mgl@1371
  5570
+move_minipool_fix_forward_ref (Mnode * mp, Mnode * max_mp,
mgl@1371
  5571
+			       HOST_WIDE_INT max_address)
mgl@1371
  5572
+{
mgl@1371
  5573
+  /* This should never be true and the code below assumes these are
mgl@1371
  5574
+     different.  */
mgl@1371
  5575
+  if (mp == max_mp)
mgl@1371
  5576
+    abort ();
mgl@1371
  5577
+
mgl@1371
  5578
+  if (max_mp == NULL)
mgl@1371
  5579
+    {
mgl@1371
  5580
+      if (max_address < mp->max_address)
mgl@1371
  5581
+	mp->max_address = max_address;
mgl@1371
  5582
+    }
mgl@1371
  5583
+  else
mgl@1371
  5584
+    {
mgl@1371
  5585
+      if (max_address > max_mp->max_address - mp->fix_size)
mgl@1371
  5586
+	mp->max_address = max_mp->max_address - mp->fix_size;
mgl@1371
  5587
+      else
mgl@1371
  5588
+	mp->max_address = max_address;
mgl@1371
  5589
+
mgl@1371
  5590
+      /* Unlink MP from its current position.  Since max_mp is non-null,
mgl@1371
  5591
+         mp->prev must be non-null.  */
mgl@1371
  5592
+      mp->prev->next = mp->next;
mgl@1371
  5593
+      if (mp->next != NULL)
mgl@1371
  5594
+	mp->next->prev = mp->prev;
mgl@1371
  5595
+      else
mgl@1371
  5596
+	minipool_vector_tail = mp->prev;
mgl@1371
  5597
+
mgl@1371
  5598
+      /* Re-insert it before MAX_MP.  */
mgl@1371
  5599
+      mp->next = max_mp;
mgl@1371
  5600
+      mp->prev = max_mp->prev;
mgl@1371
  5601
+      max_mp->prev = mp;
mgl@1371
  5602
+
mgl@1371
  5603
+      if (mp->prev != NULL)
mgl@1371
  5604
+	mp->prev->next = mp;
mgl@1371
  5605
+      else
mgl@1371
  5606
+	minipool_vector_head = mp;
mgl@1371
  5607
+    }
mgl@1371
  5608
+
mgl@1371
  5609
+  /* Save the new entry.  */
mgl@1371
  5610
+  max_mp = mp;
mgl@1371
  5611
+
mgl@1371
  5612
+  /* Scan over the preceding entries and adjust their addresses as required.
mgl@1371
  5613
+   */
mgl@1371
  5614
+  while (mp->prev != NULL
mgl@1371
  5615
+	 && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
mgl@1371
  5616
+    {
mgl@1371
  5617
+      mp->prev->max_address = mp->max_address - mp->prev->fix_size;
mgl@1371
  5618
+      mp = mp->prev;
mgl@1371
  5619
+    }
mgl@1371
  5620
+
mgl@1371
  5621
+  return max_mp;
mgl@1371
  5622
+}
mgl@1371
  5623
+
mgl@1371
  5624
+/* Add a constant to the minipool for a forward reference.  Returns the
mgl@1371
  5625
+   node added or NULL if the constant will not fit in this pool.  */
mgl@1371
  5626
+static Mnode *
mgl@1371
  5627
+add_minipool_forward_ref (Mfix * fix)
mgl@1371
  5628
+{
mgl@1371
  5629
+  /* If set, max_mp is the first pool_entry that has a lower constraint than
mgl@1371
  5630
+     the one we are trying to add.  */
mgl@1371
  5631
+  Mnode *max_mp = NULL;
mgl@1371
  5632
+  HOST_WIDE_INT max_address = fix->address + fix->forwards;
mgl@1371
  5633
+  Mnode *mp;
mgl@1371
  5634
+
mgl@1371
  5635
+  /* If this fix's address is greater than the address of the first entry,
mgl@1371
  5636
+     then we can't put the fix in this pool.  We subtract the size of the
mgl@1371
  5637
+     current fix to ensure that if the table is fully packed we still have
mgl@1371
  5638
+     enough room to insert this value by suffling the other fixes forwards.  */
mgl@1371
  5639
+  if (minipool_vector_head &&
mgl@1371
  5640
+      fix->address >= minipool_vector_head->max_address - fix->fix_size)
mgl@1371
  5641
+    return NULL;
mgl@1371
  5642
+
mgl@1371
  5643
+  /* Scan the pool to see if a constant with the same value has already been
mgl@1371
  5644
+     added.  While we are doing this, also note the location where we must
mgl@1371
  5645
+     insert the constant if it doesn't already exist.  */
mgl@1371
  5646
+  for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
mgl@1371
  5647
+    {
mgl@1371
  5648
+      if (GET_CODE (fix->value) == GET_CODE (mp->value)
mgl@1371
  5649
+	  && fix->mode == mp->mode
mgl@1371
  5650
+	  && (GET_CODE (fix->value) != CODE_LABEL
mgl@1371
  5651
+	      || (CODE_LABEL_NUMBER (fix->value)
mgl@1371
  5652
+		  == CODE_LABEL_NUMBER (mp->value)))
mgl@1371
  5653
+	  && rtx_equal_p (fix->value, mp->value))
mgl@1371
  5654
+	{
mgl@1371
  5655
+	  /* More than one fix references this entry.  */
mgl@1371
  5656
+	  mp->refcount++;
mgl@1371
  5657
+	  return move_minipool_fix_forward_ref (mp, max_mp, max_address);
mgl@1371
  5658
+	}
mgl@1371
  5659
+
mgl@1371
  5660
+      /* Note the insertion point if necessary.  */
mgl@1371
  5661
+      if (max_mp == NULL && mp->max_address > max_address)
mgl@1371
  5662
+	max_mp = mp;
mgl@1371
  5663
+
mgl@1371
  5664
+    }
mgl@1371
  5665
+
mgl@1371
  5666
+  /* The value is not currently in the minipool, so we need to create a new
mgl@1371
  5667
+     entry for it.  If MAX_MP is NULL, the entry will be put on the end of
mgl@1371
  5668
+     the list since the placement is less constrained than any existing
mgl@1371
  5669
+     entry.  Otherwise, we insert the new fix before MAX_MP and, if
mgl@1371
  5670
+     necessary, adjust the constraints on the other entries.  */
mgl@1371
  5671
+  mp = xmalloc (sizeof (*mp));
mgl@1371
  5672
+  mp->fix_size = fix->fix_size;
mgl@1371
  5673
+  mp->mode = fix->mode;
mgl@1371
  5674
+  mp->value = fix->value;
mgl@1371
  5675
+  mp->refcount = 1;
mgl@1371
  5676
+  /* Not yet required for a backwards ref.  */
mgl@1371
  5677
+  mp->min_address = -65536;
mgl@1371
  5678
+
mgl@1371
  5679
+  if (max_mp == NULL)
mgl@1371
  5680
+    {
mgl@1371
  5681
+      mp->max_address = max_address;
mgl@1371
  5682
+      mp->next = NULL;
mgl@1371
  5683
+      mp->prev = minipool_vector_tail;
mgl@1371
  5684
+
mgl@1371
  5685
+      if (mp->prev == NULL)
mgl@1371
  5686
+	{
mgl@1371
  5687
+	  minipool_vector_head = mp;
mgl@1371
  5688
+	  minipool_vector_label = gen_label_rtx ();
mgl@1371
  5689
+	}
mgl@1371
  5690
+      else
mgl@1371
  5691
+	mp->prev->next = mp;
mgl@1371
  5692
+
mgl@1371
  5693
+      minipool_vector_tail = mp;
mgl@1371
  5694
+    }
mgl@1371
  5695
+  else
mgl@1371
  5696
+    {
mgl@1371
  5697
+      if (max_address > max_mp->max_address - mp->fix_size)
mgl@1371
  5698
+	mp->max_address = max_mp->max_address - mp->fix_size;
mgl@1371
  5699
+      else
mgl@1371
  5700
+	mp->max_address = max_address;
mgl@1371
  5701
+
mgl@1371
  5702
+      mp->next = max_mp;
mgl@1371
  5703
+      mp->prev = max_mp->prev;
mgl@1371
  5704
+      max_mp->prev = mp;
mgl@1371
  5705
+      if (mp->prev != NULL)
mgl@1371
  5706
+	mp->prev->next = mp;
mgl@1371
  5707
+      else
mgl@1371
  5708
+	minipool_vector_head = mp;
mgl@1371
  5709
+    }
mgl@1371
  5710
+
mgl@1371
  5711
+  /* Save the new entry.  */
mgl@1371
  5712
+  max_mp = mp;
mgl@1371
  5713
+
mgl@1371
  5714
+  /* Scan over the preceding entries and adjust their addresses as required.
mgl@1371
  5715
+   */
mgl@1371
  5716
+  while (mp->prev != NULL
mgl@1371
  5717
+	 && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
mgl@1371
  5718
+    {
mgl@1371
  5719
+      mp->prev->max_address = mp->max_address - mp->prev->fix_size;
mgl@1371
  5720
+      mp = mp->prev;
mgl@1371
  5721
+    }
mgl@1371
  5722
+
mgl@1371
  5723
+  return max_mp;
mgl@1371
  5724
+}
mgl@1371
  5725
+
mgl@1371
  5726
+static Mnode *
mgl@1371
  5727
+move_minipool_fix_backward_ref (Mnode * mp, Mnode * min_mp,
mgl@1371
  5728
+				HOST_WIDE_INT min_address)
mgl@1371
  5729
+{
mgl@1371
  5730
+  HOST_WIDE_INT offset;
mgl@1371
  5731
+
mgl@1371
  5732
+  /* This should never be true, and the code below assumes these are
mgl@1371
  5733
+     different.  */
mgl@1371
  5734
+  if (mp == min_mp)
mgl@1371
  5735
+    abort ();
mgl@1371
  5736
+
mgl@1371
  5737
+  if (min_mp == NULL)
mgl@1371
  5738
+    {
mgl@1371
  5739
+      if (min_address > mp->min_address)
mgl@1371
  5740
+	mp->min_address = min_address;
mgl@1371
  5741
+    }
mgl@1371
  5742
+  else
mgl@1371
  5743
+    {
mgl@1371
  5744
+      /* We will adjust this below if it is too loose.  */
mgl@1371
  5745
+      mp->min_address = min_address;
mgl@1371
  5746
+
mgl@1371
  5747
+      /* Unlink MP from its current position.  Since min_mp is non-null,
mgl@1371
  5748
+         mp->next must be non-null.  */
mgl@1371
  5749
+      mp->next->prev = mp->prev;
mgl@1371
  5750
+      if (mp->prev != NULL)
mgl@1371
  5751
+	mp->prev->next = mp->next;
mgl@1371
  5752
+      else
mgl@1371
  5753
+	minipool_vector_head = mp->next;
mgl@1371
  5754
+
mgl@1371
  5755
+      /* Reinsert it after MIN_MP.  */
mgl@1371
  5756
+      mp->prev = min_mp;
mgl@1371
  5757
+      mp->next = min_mp->next;
mgl@1371
  5758
+      min_mp->next = mp;
mgl@1371
  5759
+      if (mp->next != NULL)
mgl@1371
  5760
+	mp->next->prev = mp;
mgl@1371
  5761
+      else
mgl@1371
  5762
+	minipool_vector_tail = mp;
mgl@1371
  5763
+    }
mgl@1371
  5764
+
mgl@1371
  5765
+  min_mp = mp;
mgl@1371
  5766
+
mgl@1371
  5767
+  offset = 0;
mgl@1371
  5768
+  for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
mgl@1371
  5769
+    {
mgl@1371
  5770
+      mp->offset = offset;
mgl@1371
  5771
+      if (mp->refcount > 0)
mgl@1371
  5772
+	offset += mp->fix_size;
mgl@1371
  5773
+
mgl@1371
  5774
+      if (mp->next && mp->next->min_address < mp->min_address + mp->fix_size)
mgl@1371
  5775
+	mp->next->min_address = mp->min_address + mp->fix_size;
mgl@1371
  5776
+    }
mgl@1371
  5777
+
mgl@1371
  5778
+  return min_mp;
mgl@1371
  5779
+}
mgl@1371
  5780
+
mgl@1371
  5781
+/* Add a constant to the minipool for a backward reference.  Returns the
mgl@1371
  5782
+   node added or NULL if the constant will not fit in this pool.
mgl@1371
  5783
+
mgl@1371
  5784
+   Note that the code for insertion for a backwards reference can be
mgl@1371
  5785
+   somewhat confusing because the calculated offsets for each fix do
mgl@1371
  5786
+   not take into account the size of the pool (which is still under
mgl@1371
  5787
+   construction.  */
mgl@1371
  5788
+static Mnode *
mgl@1371
  5789
+add_minipool_backward_ref (Mfix * fix)
mgl@1371
  5790
+{
mgl@1371
  5791
+  /* If set, min_mp is the last pool_entry that has a lower constraint than
mgl@1371
  5792
+     the one we are trying to add.  */
mgl@1371
  5793
+  Mnode *min_mp = NULL;
mgl@1371
  5794
+  /* This can be negative, since it is only a constraint.  */
mgl@1371
  5795
+  HOST_WIDE_INT min_address = fix->address - fix->backwards;
mgl@1371
  5796
+  Mnode *mp;
mgl@1371
  5797
+
mgl@1371
  5798
+  /* If we can't reach the current pool from this insn, or if we can't insert
mgl@1371
  5799
+     this entry at the end of the pool without pushing other fixes out of
mgl@1371
  5800
+     range, then we don't try.  This ensures that we can't fail later on.  */
mgl@1371
  5801
+  if (min_address >= minipool_barrier->address
mgl@1371
  5802
+      || (minipool_vector_tail->min_address + fix->fix_size
mgl@1371
  5803
+	  >= minipool_barrier->address))
mgl@1371
  5804
+    return NULL;
mgl@1371
  5805
+
mgl@1371
  5806
+  /* Scan the pool to see if a constant with the same value has already been
mgl@1371
  5807
+     added.  While we are doing this, also note the location where we must
mgl@1371
  5808
+     insert the constant if it doesn't already exist.  */
mgl@1371
  5809
+  for (mp = minipool_vector_tail; mp != NULL; mp = mp->prev)
mgl@1371
  5810
+    {
mgl@1371
  5811
+      if (GET_CODE (fix->value) == GET_CODE (mp->value)
mgl@1371
  5812
+	  && fix->mode == mp->mode
mgl@1371
  5813
+	  && (GET_CODE (fix->value) != CODE_LABEL
mgl@1371
  5814
+	      || (CODE_LABEL_NUMBER (fix->value)
mgl@1371
  5815
+		  == CODE_LABEL_NUMBER (mp->value)))
mgl@1371
  5816
+	  && rtx_equal_p (fix->value, mp->value)
mgl@1371
  5817
+	  /* Check that there is enough slack to move this entry to the end
mgl@1371
  5818
+	     of the table (this is conservative).  */
mgl@1371
  5819
+	  && (mp->max_address
mgl@1371
  5820
+	      > (minipool_barrier->address
mgl@1371
  5821
+		 + minipool_vector_tail->offset
mgl@1371
  5822
+		 + minipool_vector_tail->fix_size)))
mgl@1371
  5823
+	{
mgl@1371
  5824
+	  mp->refcount++;
mgl@1371
  5825
+	  return move_minipool_fix_backward_ref (mp, min_mp, min_address);
mgl@1371
  5826
+	}
mgl@1371
  5827
+
mgl@1371
  5828
+      if (min_mp != NULL)
mgl@1371
  5829
+	mp->min_address += fix->fix_size;
mgl@1371
  5830
+      else
mgl@1371
  5831
+	{
mgl@1371
  5832
+	  /* Note the insertion point if necessary.  */
mgl@1371
  5833
+	  if (mp->min_address < min_address)
mgl@1371
  5834
+	    {
mgl@1371
  5835
+	      min_mp = mp;
mgl@1371
  5836
+	    }
mgl@1371
  5837
+	  else if (mp->max_address
mgl@1371
  5838
+		   < minipool_barrier->address + mp->offset + fix->fix_size)
mgl@1371
  5839
+	    {
mgl@1371
  5840
+	      /* Inserting before this entry would push the fix beyond its
mgl@1371
  5841
+	         maximum address (which can happen if we have re-located a
mgl@1371
  5842
+	         forwards fix); force the new fix to come after it.  */
mgl@1371
  5843
+	      min_mp = mp;
mgl@1371
  5844
+	      min_address = mp->min_address + fix->fix_size;
mgl@1371
  5845
+	    }
mgl@1371
  5846
+	}
mgl@1371
  5847
+    }
mgl@1371
  5848
+
mgl@1371
  5849
+  /* We need to create a new entry.  */
mgl@1371
  5850
+  mp = xmalloc (sizeof (*mp));
mgl@1371
  5851
+  mp->fix_size = fix->fix_size;
mgl@1371
  5852
+  mp->mode = fix->mode;
mgl@1371
  5853
+  mp->value = fix->value;
mgl@1371
  5854
+  mp->refcount = 1;
mgl@1371
  5855
+  mp->max_address = minipool_barrier->address + 65536;
mgl@1371
  5856
+
mgl@1371
  5857
+  mp->min_address = min_address;
mgl@1371
  5858
+
mgl@1371
  5859
+  if (min_mp == NULL)
mgl@1371
  5860
+    {
mgl@1371
  5861
+      mp->prev = NULL;
mgl@1371
  5862
+      mp->next = minipool_vector_head;
mgl@1371
  5863
+
mgl@1371
  5864
+      if (mp->next == NULL)
mgl@1371
  5865
+	{
mgl@1371
  5866
+	  minipool_vector_tail = mp;
mgl@1371
  5867
+	  minipool_vector_label = gen_label_rtx ();
mgl@1371
  5868
+	}
mgl@1371
  5869
+      else
mgl@1371
  5870
+	mp->next->prev = mp;
mgl@1371
  5871
+
mgl@1371
  5872
+      minipool_vector_head = mp;
mgl@1371
  5873
+    }
mgl@1371
  5874
+  else
mgl@1371
  5875
+    {
mgl@1371
  5876
+      mp->next = min_mp->next;
mgl@1371
  5877
+      mp->prev = min_mp;
mgl@1371
  5878
+      min_mp->next = mp;
mgl@1371
  5879
+
mgl@1371
  5880
+      if (mp->next != NULL)
mgl@1371
  5881
+	mp->next->prev = mp;
mgl@1371
  5882
+      else
mgl@1371
  5883
+	minipool_vector_tail = mp;
mgl@1371
  5884
+    }
mgl@1371
  5885
+
mgl@1371
  5886
+  /* Save the new entry.  */
mgl@1371
  5887
+  min_mp = mp;
mgl@1371
  5888
+
mgl@1371
  5889
+  if (mp->prev)
mgl@1371
  5890
+    mp = mp->prev;
mgl@1371
  5891
+  else
mgl@1371
  5892
+    mp->offset = 0;
mgl@1371
  5893
+
mgl@1371
  5894
+  /* Scan over the following entries and adjust their offsets.  */
mgl@1371
  5895
+  while (mp->next != NULL)
mgl@1371
  5896
+    {
mgl@1371
  5897
+      if (mp->next->min_address < mp->min_address + mp->fix_size)
mgl@1371
  5898
+	mp->next->min_address = mp->min_address + mp->fix_size;
mgl@1371
  5899
+
mgl@1371
  5900
+      if (mp->refcount)
mgl@1371
  5901
+	mp->next->offset = mp->offset + mp->fix_size;
mgl@1371
  5902
+      else
mgl@1371
  5903
+	mp->next->offset = mp->offset;
mgl@1371
  5904
+
mgl@1371
  5905
+      mp = mp->next;
mgl@1371
  5906
+    }
mgl@1371
  5907
+
mgl@1371
  5908
+  return min_mp;
mgl@1371
  5909
+}
mgl@1371
  5910
+
mgl@1371
  5911
+static void
mgl@1371
  5912
+assign_minipool_offsets (Mfix * barrier)
mgl@1371
  5913
+{
mgl@1371
  5914
+  HOST_WIDE_INT offset = 0;
mgl@1371
  5915
+  Mnode *mp;
mgl@1371
  5916
+
mgl@1371
  5917
+  minipool_barrier = barrier;
mgl@1371
  5918
+
mgl@1371
  5919
+  for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
mgl@1371
  5920
+    {
mgl@1371
  5921
+      mp->offset = offset;
mgl@1371
  5922
+
mgl@1371
  5923
+      if (mp->refcount > 0)
mgl@1371
  5924
+	offset += mp->fix_size;
mgl@1371
  5925
+    }
mgl@1371
  5926
+}
mgl@1371
  5927
+
mgl@1371
  5928
+/* Print a symbolic form of X to the debug file, F.  */
mgl@1371
  5929
+static void
mgl@1371
  5930
+avr32_print_value (FILE * f, rtx x)
mgl@1371
  5931
+{
mgl@1371
  5932
+  switch (GET_CODE (x))
mgl@1371
  5933
+    {
mgl@1371
  5934
+    case CONST_INT:
mgl@1371
  5935
+      fprintf (f, "0x%x", (int) INTVAL (x));
mgl@1371
  5936
+      return;
mgl@1371
  5937
+
mgl@1371
  5938
+    case CONST_DOUBLE:
mgl@1371
  5939
+      fprintf (f, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
mgl@1371
  5940
+      return;
mgl@1371
  5941
+
mgl@1371
  5942
+    case CONST_VECTOR:
mgl@1371
  5943
+      {
mgl@1371
  5944
+	int i;
mgl@1371
  5945
+
mgl@1371
  5946
+	fprintf (f, "<");
mgl@1371
  5947
+	for (i = 0; i < CONST_VECTOR_NUNITS (x); i++)
mgl@1371
  5948
+	  {
mgl@1371
  5949
+	    fprintf (f, "0x%x", (int) INTVAL (CONST_VECTOR_ELT (x, i)));
mgl@1371
  5950
+	    if (i < (CONST_VECTOR_NUNITS (x) - 1))
mgl@1371
  5951
+	      fputc (',', f);
mgl@1371
  5952
+	  }
mgl@1371
  5953
+	fprintf (f, ">");
mgl@1371
  5954
+      }
mgl@1371
  5955
+      return;
mgl@1371
  5956
+
mgl@1371
  5957
+    case CONST_STRING:
mgl@1371
  5958
+      fprintf (f, "\"%s\"", XSTR (x, 0));
mgl@1371
  5959
+      return;
mgl@1371
  5960
+
mgl@1371
  5961
+    case SYMBOL_REF:
mgl@1371
  5962
+      fprintf (f, "`%s'", XSTR (x, 0));
mgl@1371
  5963
+      return;
mgl@1371
  5964
+
mgl@1371
  5965
+    case LABEL_REF:
mgl@1371
  5966
+      fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
mgl@1371
  5967
+      return;
mgl@1371
  5968
+
mgl@1371
  5969
+    case CONST:
mgl@1371
  5970
+      avr32_print_value (f, XEXP (x, 0));
mgl@1371
  5971
+      return;
mgl@1371
  5972
+
mgl@1371
  5973
+    case PLUS:
mgl@1371
  5974
+      avr32_print_value (f, XEXP (x, 0));
mgl@1371
  5975
+      fprintf (f, "+");
mgl@1371
  5976
+      avr32_print_value (f, XEXP (x, 1));
mgl@1371
  5977
+      return;
mgl@1371
  5978
+
mgl@1371
  5979
+    case PC:
mgl@1371
  5980
+      fprintf (f, "pc");
mgl@1371
  5981
+      return;
mgl@1371
  5982
+
mgl@1371
  5983
+    default:
mgl@1371
  5984
+      fprintf (f, "????");
mgl@1371
  5985
+      return;
mgl@1371
  5986
+    }
mgl@1371
  5987
+}
mgl@1371
  5988
+
mgl@1371
  5989
+int
mgl@1371
  5990
+is_minipool_label (rtx label)
mgl@1371
  5991
+{
mgl@1371
  5992
+  minipool_labels *cur_mp_label = cfun->machine->minipool_label_head;
mgl@1371
  5993
+
mgl@1371
  5994
+  if (GET_CODE (label) != CODE_LABEL)
mgl@1371
  5995
+    return FALSE;
mgl@1371
  5996
+
mgl@1371
  5997
+  while (cur_mp_label)
mgl@1371
  5998
+    {
mgl@1371
  5999
+      if (CODE_LABEL_NUMBER (label)
mgl@1371
  6000
+	  == CODE_LABEL_NUMBER (cur_mp_label->label))
mgl@1371
  6001
+	return TRUE;
mgl@1371
  6002
+      cur_mp_label = cur_mp_label->next;
mgl@1371
  6003
+    }
mgl@1371
  6004
+  return FALSE;
mgl@1371
  6005
+}
mgl@1371
  6006
+
mgl@1371
  6007
+static void
mgl@1371
  6008
+new_minipool_label (rtx label)
mgl@1371
  6009
+{
mgl@1371
  6010
+  if (!cfun->machine->minipool_label_head)
mgl@1371
  6011
+    {
mgl@1371
  6012
+      cfun->machine->minipool_label_head =
mgl@1371
  6013
+	ggc_alloc (sizeof (minipool_labels));
mgl@1371
  6014
+      cfun->machine->minipool_label_tail = cfun->machine->minipool_label_head;
mgl@1371
  6015
+      cfun->machine->minipool_label_head->label = label;
mgl@1371
  6016
+      cfun->machine->minipool_label_head->next = 0;
mgl@1371
  6017
+      cfun->machine->minipool_label_head->prev = 0;
mgl@1371
  6018
+    }
mgl@1371
  6019
+  else
mgl@1371
  6020
+    {
mgl@1371
  6021
+      cfun->machine->minipool_label_tail->next =
mgl@1371
  6022
+	ggc_alloc (sizeof (minipool_labels));
mgl@1371
  6023
+      cfun->machine->minipool_label_tail->next->label = label;
mgl@1371
  6024
+      cfun->machine->minipool_label_tail->next->next = 0;
mgl@1371
  6025
+      cfun->machine->minipool_label_tail->next->prev =
mgl@1371
  6026
+	cfun->machine->minipool_label_tail;
mgl@1371
  6027
+      cfun->machine->minipool_label_tail =
mgl@1371
  6028
+	cfun->machine->minipool_label_tail->next;
mgl@1371
  6029
+    }
mgl@1371
  6030
+}
mgl@1371
  6031
+
mgl@1371
  6032
+/* Output the literal table */
mgl@1371
  6033
+static void
mgl@1371
  6034
+dump_minipool (rtx scan)
mgl@1371
  6035
+{
mgl@1371
  6036
+  Mnode *mp;
mgl@1371
  6037
+  Mnode *nmp;
mgl@1371
  6038
+
mgl@1371
  6039
+  if (dump_file)
mgl@1371
  6040
+    fprintf (dump_file,
mgl@1371
  6041
+	     ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
mgl@1371
  6042
+	     INSN_UID (scan), (unsigned long) minipool_barrier->address, 4);
mgl@1371
  6043
+
mgl@1371
  6044
+  scan = emit_insn_after (gen_consttable_start (), scan);
mgl@1371
  6045
+  scan = emit_insn_after (gen_align_4 (), scan);
mgl@1371
  6046
+  scan = emit_label_after (minipool_vector_label, scan);
mgl@1371
  6047
+  new_minipool_label (minipool_vector_label);
mgl@1371
  6048
+
mgl@1371
  6049
+  for (mp = minipool_vector_head; mp != NULL; mp = nmp)
mgl@1371
  6050
+    {
mgl@1371
  6051
+      if (mp->refcount > 0)
mgl@1371
  6052
+	{
mgl@1371
  6053
+	  if (dump_file)
mgl@1371
  6054
+	    {
mgl@1371
  6055
+	      fprintf (dump_file,
mgl@1371
  6056
+		       ";;  Offset %u, min %ld, max %ld ",
mgl@1371
  6057
+		       (unsigned) mp->offset, (unsigned long) mp->min_address,
mgl@1371
  6058
+		       (unsigned long) mp->max_address);
mgl@1371
  6059
+	      avr32_print_value (dump_file, mp->value);
mgl@1371
  6060
+	      fputc ('\n', dump_file);
mgl@1371
  6061
+	    }
mgl@1371
  6062
+
mgl@1371
  6063
+	  switch (mp->fix_size)
mgl@1371
  6064
+	    {
mgl@1371
  6065
+#ifdef HAVE_consttable_4
mgl@1371
  6066
+	    case 4:
mgl@1371
  6067
+	      scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
mgl@1371
  6068
+	      break;
mgl@1371
  6069
+
mgl@1371
  6070
+#endif
mgl@1371
  6071
+#ifdef HAVE_consttable_8
mgl@1371
  6072
+	    case 8:
mgl@1371
  6073
+	      scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
mgl@1371
  6074
+	      break;
mgl@1371
  6075
+
mgl@1371
  6076
+#endif
mgl@1371
  6077
+#ifdef HAVE_consttable_16
mgl@1371
  6078
+            case 16:
mgl@1371
  6079
+              scan = emit_insn_after (gen_consttable_16 (mp->value), scan);
mgl@1371
  6080
+              break;
mgl@1371
  6081
+
mgl@1371
  6082
+#endif
mgl@1371
  6083
+            case 0:
mgl@1371
  6084
+              /* This can happen for force-minipool entries which just are
mgl@1371
  6085
+	         there to force the minipool to be generate. */
mgl@1371
  6086
+	      break;
mgl@1371
  6087
+	    default:
mgl@1371
  6088
+	      abort ();
mgl@1371
  6089
+	      break;
mgl@1371
  6090
+	    }
mgl@1371
  6091
+	}
mgl@1371
  6092
+
mgl@1371
  6093
+      nmp = mp->next;
mgl@1371
  6094
+      free (mp);
mgl@1371
  6095
+    }
mgl@1371
  6096
+
mgl@1371
  6097
+  minipool_vector_head = minipool_vector_tail = NULL;
mgl@1371
  6098
+  scan = emit_insn_after (gen_consttable_end (), scan);
mgl@1371
  6099
+  scan = emit_barrier_after (scan);
mgl@1371
  6100
+}
mgl@1371
  6101
+
mgl@1371
  6102
+/* Return the cost of forcibly inserting a barrier after INSN.  */
mgl@1371
  6103
+static int
mgl@1371
  6104
+avr32_barrier_cost (rtx insn)
mgl@1371
  6105
+{
mgl@1371
  6106
+  /* Basing the location of the pool on the loop depth is preferable, but at
mgl@1371
  6107
+     the moment, the basic block information seems to be corrupt by this
mgl@1371
  6108
+     stage of the compilation.  */
mgl@1371
  6109
+  int base_cost = 50;
mgl@1371
  6110
+  rtx next = next_nonnote_insn (insn);
mgl@1371
  6111
+
mgl@1371
  6112
+  if (next != NULL && GET_CODE (next) == CODE_LABEL)
mgl@1371
  6113
+    base_cost -= 20;
mgl@1371
  6114
+
mgl@1371
  6115
+  switch (GET_CODE (insn))
mgl@1371
  6116
+    {
mgl@1371
  6117
+    case CODE_LABEL:
mgl@1371
  6118
+      /* It will always be better to place the table before the label, rather
mgl@1371
  6119
+         than after it.  */
mgl@1371
  6120
+      return 50;
mgl@1371
  6121
+
mgl@1371
  6122
+    case INSN:
mgl@1371
  6123
+    case CALL_INSN:
mgl@1371
  6124
+      return base_cost;
mgl@1371
  6125
+
mgl@1371
  6126
+    case JUMP_INSN:
mgl@1371
  6127
+      return base_cost - 10;
mgl@1371
  6128
+
mgl@1371
  6129
+    default:
mgl@1371
  6130
+      return base_cost + 10;
mgl@1371
  6131
+    }
mgl@1371
  6132
+}
mgl@1371
  6133
+
mgl@1371
  6134
+/* Find the best place in the insn stream in the range
mgl@1371
  6135
+   (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
mgl@1371
  6136
+   Create the barrier by inserting a jump and add a new fix entry for
mgl@1371
  6137
+   it.  */
mgl@1371
  6138
+static Mfix *
mgl@1371
  6139
+create_fix_barrier (Mfix * fix, HOST_WIDE_INT max_address)
mgl@1371
  6140
+{
mgl@1371
  6141
+  HOST_WIDE_INT count = 0;
mgl@1371
  6142
+  rtx barrier;
mgl@1371
  6143
+  rtx from = fix->insn;
mgl@1371
  6144
+  rtx selected = from;
mgl@1371
  6145
+  int selected_cost;
mgl@1371
  6146
+  HOST_WIDE_INT selected_address;
mgl@1371
  6147
+  Mfix *new_fix;
mgl@1371
  6148
+  HOST_WIDE_INT max_count = max_address - fix->address;
mgl@1371
  6149
+  rtx label = gen_label_rtx ();
mgl@1371
  6150
+
mgl@1371
  6151
+  selected_cost = avr32_barrier_cost (from);
mgl@1371
  6152
+  selected_address = fix->address;
mgl@1371
  6153
+
mgl@1371
  6154
+  while (from && count < max_count)
mgl@1371
  6155
+    {
mgl@1371
  6156
+      rtx tmp;
mgl@1371
  6157
+      int new_cost;
mgl@1371
  6158
+
mgl@1371
  6159
+      /* This code shouldn't have been called if there was a natural barrier
mgl@1371
  6160
+         within range.  */
mgl@1371
  6161
+      if (GET_CODE (from) == BARRIER)
mgl@1371
  6162
+	abort ();
mgl@1371
  6163
+
mgl@1371
  6164
+      /* Count the length of this insn.  */
mgl@1371
  6165
+      count += get_attr_length (from);
mgl@1371
  6166
+
mgl@1371
  6167
+      /* If there is a jump table, add its length.  */
mgl@1371
  6168
+      tmp = is_jump_table (from);
mgl@1371
  6169
+      if (tmp != NULL)
mgl@1371
  6170
+	{
mgl@1371
  6171
+	  count += get_jump_table_size (tmp);
mgl@1371
  6172
+
mgl@1371
  6173
+	  /* Jump tables aren't in a basic block, so base the cost on the
mgl@1371
  6174
+	     dispatch insn.  If we select this location, we will still put
mgl@1371
  6175
+	     the pool after the table.  */
mgl@1371
  6176
+	  new_cost = avr32_barrier_cost (from);
mgl@1371
  6177
+
mgl@1371
  6178
+	  if (count < max_count && new_cost <= selected_cost)
mgl@1371
  6179
+	    {
mgl@1371
  6180
+	      selected = tmp;
mgl@1371
  6181
+	      selected_cost = new_cost;
mgl@1371
  6182
+	      selected_address = fix->address + count;
mgl@1371
  6183
+	    }
mgl@1371
  6184
+
mgl@1371
  6185
+	  /* Continue after the dispatch table.  */
mgl@1371
  6186
+	  from = NEXT_INSN (tmp);
mgl@1371
  6187
+	  continue;
mgl@1371
  6188
+	}
mgl@1371
  6189
+
mgl@1371
  6190
+      new_cost = avr32_barrier_cost (from);
mgl@1371
  6191
+
mgl@1371
  6192
+      if (count < max_count && new_cost <= selected_cost)
mgl@1371
  6193
+	{
mgl@1371
  6194
+	  selected = from;
mgl@1371
  6195
+	  selected_cost = new_cost;
mgl@1371
  6196
+	  selected_address = fix->address + count;
mgl@1371
  6197
+	}
mgl@1371
  6198
+
mgl@1371
  6199
+      from = NEXT_INSN (from);
mgl@1371
  6200
+    }
mgl@1371
  6201
+
mgl@1371
  6202
+  /* Create a new JUMP_INSN that branches around a barrier.  */
mgl@1371
  6203
+  from = emit_jump_insn_after (gen_jump (label), selected);
mgl@1371
  6204
+  JUMP_LABEL (from) = label;
mgl@1371
  6205
+  barrier = emit_barrier_after (from);
mgl@1371
  6206
+  emit_label_after (label, barrier);
mgl@1371
  6207
+
mgl@1371
  6208
+  /* Create a minipool barrier entry for the new barrier.  */
mgl@1371
  6209
+  new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*new_fix));
mgl@1371
  6210
+  new_fix->insn = barrier;
mgl@1371
  6211
+  new_fix->address = selected_address;
mgl@1371
  6212
+  new_fix->next = fix->next;
mgl@1371
  6213
+  fix->next = new_fix;
mgl@1371
  6214
+
mgl@1371
  6215
+  return new_fix;
mgl@1371
  6216
+}
mgl@1371
  6217
+
mgl@1371
  6218
+/* Record that there is a natural barrier in the insn stream at
mgl@1371
  6219
+   ADDRESS.  */
mgl@1371
  6220
+static void
mgl@1371
  6221
+push_minipool_barrier (rtx insn, HOST_WIDE_INT address)
mgl@1371
  6222
+{
mgl@1371
  6223
+  Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
mgl@1371
  6224
+
mgl@1371
  6225
+  fix->insn = insn;
mgl@1371
  6226
+  fix->address = address;
mgl@1371
  6227
+
mgl@1371
  6228
+  fix->next = NULL;
mgl@1371
  6229
+  if (minipool_fix_head != NULL)
mgl@1371
  6230
+    minipool_fix_tail->next = fix;
mgl@1371
  6231
+  else
mgl@1371
  6232
+    minipool_fix_head = fix;
mgl@1371
  6233
+
mgl@1371
  6234
+  minipool_fix_tail = fix;
mgl@1371
  6235
+}
mgl@1371
  6236
+
mgl@1371
  6237
+/* Record INSN, which will need fixing up to load a value from the
mgl@1371
  6238
+   minipool.  ADDRESS is the offset of the insn since the start of the
mgl@1371
  6239
+   function; LOC is a pointer to the part of the insn which requires
mgl@1371
  6240
+   fixing; VALUE is the constant that must be loaded, which is of type
mgl@1371
  6241
+   MODE.  */
mgl@1371
  6242
+static void
mgl@1371
  6243
+push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx * loc,
mgl@1371
  6244
+		   enum machine_mode mode, rtx value)
mgl@1371
  6245
+{
mgl@1371
  6246
+  Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
mgl@1371
  6247
+  rtx body = PATTERN (insn);
mgl@1371
  6248
+
mgl@1371
  6249
+  fix->insn = insn;
mgl@1371
  6250
+  fix->address = address;
mgl@1371
  6251
+  fix->loc = loc;
mgl@1371
  6252
+  fix->mode = mode;
mgl@1371
  6253
+  fix->fix_size = MINIPOOL_FIX_SIZE (mode, value);
mgl@1371
  6254
+  fix->value = value;
mgl@1371
  6255
+
mgl@1371
  6256
+  if (GET_CODE (body) == PARALLEL)
mgl@1371
  6257
+    {
mgl@1371
  6258
+      /* Mcall : Ks16 << 2 */
mgl@1371
  6259
+      fix->forwards = ((1 << 15) - 1) << 2;
mgl@1371
  6260
+      fix->backwards = (1 << 15) << 2;
mgl@1371
  6261
+    }
mgl@1371
  6262
+  else if (GET_CODE (body) == SET
mgl@1371
  6263
+           && GET_MODE_SIZE (GET_MODE (SET_DEST (body))) == 4)
mgl@1371
  6264
+    {
mgl@1371
  6265
+        /* Word Load */
mgl@1371
  6266
+      if (TARGET_HARD_FLOAT
mgl@1371
  6267
+          && GET_MODE_CLASS (GET_MODE (SET_DEST (body))) == MODE_FLOAT)
mgl@1371
  6268
+        {
mgl@1371
  6269
+          /* Ldc0.w : Ku12 << 2 */
mgl@1371
  6270
+          fix->forwards = ((1 << 12) - 1) << 2;
mgl@1371
  6271
+          fix->backwards = 0;
mgl@1371
  6272
+        }
mgl@1371
  6273
+      else
mgl@1371
  6274
+        {
mgl@1371
  6275
+          if (optimize_size)
mgl@1371
  6276
+            {
mgl@1371
  6277
+              /* Lddpc : Ku7 << 2 */
mgl@1371
  6278
+              fix->forwards = ((1 << 7) - 1) << 2;
mgl@1371
  6279
+              fix->backwards = 0;
mgl@1371
  6280
+            }
mgl@1371
  6281
+          else
mgl@1371
  6282
+            {
mgl@1371
  6283
+              /* Ld.w : Ks16 */
mgl@1371
  6284
+              fix->forwards = ((1 << 15) - 4);
mgl@1371
  6285
+              fix->backwards = (1 << 15);
mgl@1371
  6286
+            }
mgl@1371
  6287
+        }
mgl@1371
  6288
+    }
mgl@1371
  6289
+  else if (GET_CODE (body) == SET
mgl@1371
  6290
+           && GET_MODE_SIZE (GET_MODE (SET_DEST (body))) == 8)
mgl@1371
  6291
+    {
mgl@1371
  6292
+      /* Double word load */
mgl@1371
  6293
+      if (TARGET_HARD_FLOAT
mgl@1371
  6294
+          && GET_MODE_CLASS (GET_MODE (SET_DEST (body))) == MODE_FLOAT)
mgl@1371
  6295
+        {
mgl@1371
  6296
+          /* Ldc0.d : Ku12 << 2 */
mgl@1371
  6297
+          fix->forwards = ((1 << 12) - 1) << 2;
mgl@1371
  6298
+          fix->backwards = 0;
mgl@1371
  6299
+        }
mgl@1371
  6300
+      else
mgl@1371
  6301
+        {
mgl@1371
  6302
+          /* Ld.d : Ks16 */
mgl@1371
  6303
+          fix->forwards = ((1 << 15) - 4);
mgl@1371
  6304
+          fix->backwards = (1 << 15);
mgl@1371
  6305
+        }
mgl@1371
  6306
+    }
mgl@1371
  6307
+  else if (GET_CODE (body) == UNSPEC_VOLATILE
mgl@1371
  6308
+           && XINT (body, 1) == VUNSPEC_MVRC)
mgl@1371
  6309
+    {
mgl@1371
  6310
+      /* Coprocessor load */
mgl@1371
  6311
+      /* Ldc : Ku8 << 2 */
mgl@1371
  6312
+      fix->forwards = ((1 << 8) - 1) << 2;
mgl@1371
  6313
+      fix->backwards = 0;
mgl@1371
  6314
+    }
mgl@1371
  6315
+  else
mgl@1371
  6316
+    {
mgl@1371
  6317
+      /* Assume worst case which is lddpc insn. */
mgl@1371
  6318
+      fix->forwards = ((1 << 7) - 1) << 2;
mgl@1371
  6319
+      fix->backwards = 0;
mgl@1371
  6320
+    }
mgl@1371
  6321
+
mgl@1371
  6322
+  fix->minipool = NULL;
mgl@1371
  6323
+
mgl@1371
  6324
+  /* If an insn doesn't have a range defined for it, then it isn't expecting
mgl@1371
  6325
+     to be reworked by this code.  Better to abort now than to generate duff
mgl@1371
  6326
+     assembly code.  */
mgl@1371
  6327
+  if (fix->forwards == 0 && fix->backwards == 0)
mgl@1371
  6328
+    abort ();
mgl@1371
  6329
+
mgl@1371
  6330
+  if (dump_file)
mgl@1371
  6331
+    {
mgl@1371
  6332
+      fprintf (dump_file,
mgl@1371
  6333
+	       ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
mgl@1371
  6334
+	       GET_MODE_NAME (mode),
mgl@1371
  6335
+	       INSN_UID (insn), (unsigned long) address,
mgl@1371
  6336
+	       -1 * (long) fix->backwards, (long) fix->forwards);
mgl@1371
  6337
+      avr32_print_value (dump_file, fix->value);
mgl@1371
  6338
+      fprintf (dump_file, "\n");
mgl@1371
  6339
+    }
mgl@1371
  6340
+
mgl@1371
  6341
+  /* Add it to the chain of fixes.  */
mgl@1371
  6342
+  fix->next = NULL;
mgl@1371
  6343
+
mgl@1371
  6344
+  if (minipool_fix_head != NULL)
mgl@1371
  6345
+    minipool_fix_tail->next = fix;
mgl@1371
  6346
+  else
mgl@1371
  6347
+    minipool_fix_head = fix;
mgl@1371
  6348
+
mgl@1371
  6349
+  minipool_fix_tail = fix;
mgl@1371
  6350
+}
mgl@1371
  6351
+
mgl@1371
  6352
+/* Scan INSN and note any of its operands that need fixing.
mgl@1371
  6353
+   If DO_PUSHES is false we do not actually push any of the fixups
mgl@1371
  6354
+   needed.  The function returns TRUE is any fixups were needed/pushed.
mgl@1371
  6355
+   This is used by avr32_memory_load_p() which needs to know about loads
mgl@1371
  6356
+   of constants that will be converted into minipool loads.  */
mgl@1371
  6357
+static bool
mgl@1371
  6358
+note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
mgl@1371
  6359
+{
mgl@1371
  6360
+  bool result = false;
mgl@1371
  6361
+  int opno;
mgl@1371
  6362
+
mgl@1371
  6363
+  extract_insn (insn);
mgl@1371
  6364
+
mgl@1371
  6365
+  if (!constrain_operands (1))
mgl@1371
  6366
+    fatal_insn_not_found (insn);
mgl@1371
  6367
+
mgl@1371
  6368
+  if (recog_data.n_alternatives == 0)
mgl@1371
  6369
+    return false;
mgl@1371
  6370
+
mgl@1371
  6371
+  /* Fill in recog_op_alt with information about the constraints of this
mgl@1371
  6372
+     insn.  */
mgl@1371
  6373
+  preprocess_constraints ();
mgl@1371
  6374
+
mgl@1371
  6375
+  for (opno = 0; opno < recog_data.n_operands; opno++)
mgl@1371
  6376
+    {
mgl@1371
  6377
+      rtx op;
mgl@1371
  6378
+
mgl@1371
  6379
+      /* Things we need to fix can only occur in inputs.  */
mgl@1371
  6380
+      if (recog_data.operand_type[opno] != OP_IN)
mgl@1371
  6381
+	continue;
mgl@1371
  6382
+
mgl@1371
  6383
+      op = recog_data.operand[opno];
mgl@1371
  6384
+
mgl@1371
  6385
+      if (avr32_const_pool_ref_operand (op, GET_MODE (op)))
mgl@1371
  6386
+	{
mgl@1371
  6387
+	  if (do_pushes)
mgl@1371
  6388
+	    {
mgl@1371
  6389
+	      rtx cop = avoid_constant_pool_reference (op);
mgl@1371
  6390
+
mgl@1371
  6391
+	      /* Casting the address of something to a mode narrower than a
mgl@1371
  6392
+	         word can cause avoid_constant_pool_reference() to return the
mgl@1371
  6393
+	         pool reference itself.  That's no good to us here.  Lets
mgl@1371
  6394
+	         just hope that we can use the constant pool value directly.
mgl@1371
  6395
+	       */
mgl@1371
  6396
+	      if (op == cop)
mgl@1371
  6397
+		cop = get_pool_constant (XEXP (op, 0));
mgl@1371
  6398
+
mgl@1371
  6399
+	      push_minipool_fix (insn, address,
mgl@1371
  6400
+				 recog_data.operand_loc[opno],
mgl@1371
  6401
+				 recog_data.operand_mode[opno], cop);
mgl@1371
  6402
+	    }
mgl@1371
  6403
+
mgl@1371
  6404
+	  result = true;
mgl@1371
  6405
+	}
mgl@1371
  6406
+      else if (TARGET_HAS_ASM_ADDR_PSEUDOS
mgl@1371
  6407
+	       && avr32_address_operand (op, GET_MODE (op)))
mgl@1371
  6408
+	{
mgl@1371
  6409
+	  /* Handle pseudo instructions using a direct address. These pseudo
mgl@1371
  6410
+	     instructions might need entries in the constant pool and we must
mgl@1371
  6411
+	     therefor create a constant pool for them, in case the
mgl@1371
  6412
+	     assembler/linker needs to insert entries. */
mgl@1371
  6413
+	  if (do_pushes)
mgl@1371
  6414
+	    {
mgl@1371
  6415
+	      /* Push a dummy constant pool entry so that the .cpool
mgl@1371
  6416
+	         directive should be inserted on the appropriate place in the
mgl@1371
  6417
+	         code even if there are no real constant pool entries. This
mgl@1371
  6418
+	         is used by the assembler and linker to know where to put
mgl@1371
  6419
+	         generated constant pool entries. */
mgl@1371
  6420
+	      push_minipool_fix (insn, address,
mgl@1371
  6421
+				 recog_data.operand_loc[opno],
mgl@1371
  6422
+				 recog_data.operand_mode[opno],
mgl@1371
  6423
+				 gen_rtx_UNSPEC (VOIDmode,
mgl@1371
  6424
+						 gen_rtvec (1, const0_rtx),
mgl@1371
  6425
+						 UNSPEC_FORCE_MINIPOOL));
mgl@1371
  6426
+	      result = true;
mgl@1371
  6427
+	    }
mgl@1371
  6428
+	}
mgl@1371
  6429
+    }
mgl@1371
  6430
+  return result;
mgl@1371
  6431
+}
mgl@1371
  6432
+
mgl@1371
  6433
+
mgl@1371
  6434
+static int
mgl@1371
  6435
+avr32_insn_is_cast (rtx insn)
mgl@1371
  6436
+{
mgl@1371
  6437
+
mgl@1371
  6438
+  if (NONJUMP_INSN_P (insn)
mgl@1371
  6439
+      && GET_CODE (PATTERN (insn)) == SET
mgl@1371
  6440
+      && (GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTEND
mgl@1371
  6441
+	  || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTEND)
mgl@1371
  6442
+      && REG_P (XEXP (SET_SRC (PATTERN (insn)), 0))
mgl@1371
  6443
+      && REG_P (SET_DEST (PATTERN (insn))))
mgl@1371
  6444
+    return true;
mgl@1371
  6445
+  return false;
mgl@1371
  6446
+}
mgl@1371
  6447
+
mgl@1371
  6448
+/*
mgl@1371
  6449
+ Replace all occurances of reg FROM with reg TO in X */
mgl@1371
  6450
+
mgl@1371
  6451
+rtx
mgl@1371
  6452
+avr32_replace_reg (rtx x, rtx from, rtx to)
mgl@1371
  6453
+{
mgl@1371
  6454
+  int i, j;
mgl@1371
  6455
+  const char *fmt;
mgl@1371
  6456
+
mgl@1371
  6457
+  gcc_assert ( REG_P (from) && REG_P (to) );
mgl@1371
  6458
+
mgl@1371
  6459
+  /* Allow this function to make replacements in EXPR_LISTs.  */
mgl@1371
  6460
+  if (x == 0)
mgl@1371
  6461
+    return 0;
mgl@1371
  6462
+
mgl@1371
  6463
+  if (rtx_equal_p (x, from))
mgl@1371
  6464
+    return to;
mgl@1371
  6465
+
mgl@1371
  6466
+  if (GET_CODE (x) == SUBREG)
mgl@1371
  6467
+    {
mgl@1371
  6468
+      rtx new = avr32_replace_reg (SUBREG_REG (x), from, to);
mgl@1371
  6469
+
mgl@1371
  6470
+      if (GET_CODE (new) == CONST_INT)
mgl@1371
  6471
+	{
mgl@1371
  6472
+	  x = simplify_subreg (GET_MODE (x), new,
mgl@1371
  6473
+			       GET_MODE (SUBREG_REG (x)),
mgl@1371
  6474
+			       SUBREG_BYTE (x));
mgl@1371
  6475
+	  gcc_assert (x);
mgl@1371
  6476
+	}
mgl@1371
  6477
+      else
mgl@1371
  6478
+	SUBREG_REG (x) = new;
mgl@1371
  6479
+
mgl@1371
  6480
+      return x;
mgl@1371
  6481
+    }
mgl@1371
  6482
+  else if (GET_CODE (x) == ZERO_EXTEND)
mgl@1371
  6483
+    {
mgl@1371
  6484
+      rtx new = avr32_replace_reg (XEXP (x, 0), from, to);
mgl@1371
  6485
+
mgl@1371
  6486
+      if (GET_CODE (new) == CONST_INT)
mgl@1371
  6487
+	{
mgl@1371
  6488
+	  x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
mgl@1371
  6489
+					new, GET_MODE (XEXP (x, 0)));
mgl@1371
  6490
+	  gcc_assert (x);
mgl@1371
  6491
+	}
mgl@1371
  6492
+      else
mgl@1371
  6493
+	XEXP (x, 0) = new;
mgl@1371
  6494
+
mgl@1371
  6495
+      return x;
mgl@1371
  6496
+    }
mgl@1371
  6497
+
mgl@1371
  6498
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
mgl@1371
  6499
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
mgl@1371
  6500
+    {
mgl@1371
  6501
+      if (fmt[i] == 'e')
mgl@1371
  6502
+	XEXP (x, i) = avr32_replace_reg (XEXP (x, i), from, to);
mgl@1371
  6503
+      else if (fmt[i] == 'E')
mgl@1371
  6504
+	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mgl@1371
  6505
+	  XVECEXP (x, i, j) = avr32_replace_reg (XVECEXP (x, i, j), from, to);
mgl@1371
  6506
+    }
mgl@1371
  6507
+
mgl@1371
  6508
+  return x;
mgl@1371
  6509
+}
mgl@1371
  6510
+
mgl@1371
  6511
+
mgl@1371
  6512
+/* FIXME: The level of nesting in this function is way too deep. It needs to be
mgl@1371
  6513
+   torn apart.  */
mgl@1371
  6514
+static void
mgl@1371
  6515
+avr32_reorg_optimization (void)
mgl@1371
  6516
+{
mgl@1371
  6517
+  rtx first = get_first_nonnote_insn ();
mgl@1371
  6518
+  rtx insn;
mgl@1371
  6519
+
mgl@1371
  6520
+  if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
mgl@1371
  6521
+    {
mgl@1371
  6522
+
mgl@1371
  6523
+      /* Scan through all insns looking for cast operations. */
mgl@1371
  6524
+      if (dump_file)
mgl@1371
  6525
+	{
mgl@1371
  6526
+	  fprintf (dump_file, ";; Deleting redundant cast operations:\n");
mgl@1371
  6527
+	}
mgl@1371
  6528
+      for (insn = first; insn; insn = NEXT_INSN (insn))
mgl@1371
  6529
+	{
mgl@1371
  6530
+	  rtx reg, src_reg, scan;
mgl@1371
  6531
+	  enum machine_mode mode;
mgl@1371
  6532
+	  int unused_cast;
mgl@1371
  6533
+	  rtx label_ref;
mgl@1371
  6534
+
mgl@1371
  6535
+	  if (avr32_insn_is_cast (insn)
mgl@1371
  6536
+	      && (GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == QImode
mgl@1371
  6537
+		  || GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == HImode))
mgl@1371
  6538
+	    {
mgl@1371
  6539
+	      mode = GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0));
mgl@1371
  6540
+	      reg = SET_DEST (PATTERN (insn));
mgl@1371
  6541
+	      src_reg = XEXP (SET_SRC (PATTERN (insn)), 0);
mgl@1371
  6542
+	    }
mgl@1371
  6543
+	  else
mgl@1371
  6544
+	    {
mgl@1371
  6545
+	      continue;
mgl@1371
  6546
+	    }
mgl@1371
  6547
+
mgl@1371
  6548
+	  unused_cast = false;
mgl@1371
  6549
+	  label_ref = NULL_RTX;
mgl@1371
  6550
+	  for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
mgl@1371
  6551
+	    {
mgl@1371
  6552
+	      /* Check if we have reached the destination of a simple
mgl@1371
  6553
+	         conditional jump which we have already scanned past. If so,
mgl@1371
  6554
+	         we can safely continue scanning. */
mgl@1371
  6555
+	      if (LABEL_P (scan) && label_ref != NULL_RTX)
mgl@1371
  6556
+		{
mgl@1371
  6557
+		  if (CODE_LABEL_NUMBER (scan) ==
mgl@1371
  6558
+		      CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
mgl@1371
  6559
+		    label_ref = NULL_RTX;
mgl@1371
  6560
+		  else
mgl@1371
  6561
+		    break;
mgl@1371
  6562
+		}
mgl@1371
  6563
+
mgl@1371
  6564
+	      if (!INSN_P (scan))
mgl@1371
  6565
+		continue;
mgl@1371
  6566
+
mgl@1371
  6567
+	      /* For conditional jumps we can manage to keep on scanning if
mgl@1371
  6568
+	         we meet the destination label later on before any new jump
mgl@1371
  6569
+	         insns occure. */
mgl@1371
  6570
+	      if (GET_CODE (scan) == JUMP_INSN)
mgl@1371
  6571
+		{
mgl@1371
  6572
+		  if (any_condjump_p (scan) && label_ref == NULL_RTX)
mgl@1371
  6573
+		    label_ref = condjump_label (scan);
mgl@1371
  6574
+		  else
mgl@1371
  6575
+		    break;
mgl@1371
  6576
+		}
mgl@1371
  6577
+
mgl@1371
  6578
+              /* Check if we have a call and the register is used as an argument. */
mgl@1371
  6579
+              if (CALL_P (scan)
mgl@1371
  6580
+                  && find_reg_fusage (scan, USE, reg) )
mgl@1371
  6581
+                break;
mgl@1371
  6582
+
mgl@1371
  6583
+	      if (!reg_mentioned_p (reg, PATTERN (scan)))
mgl@1371
  6584
+		continue;
mgl@1371
  6585
+
mgl@1371
  6586
+	      /* Check if casted register is used in this insn */
mgl@1371
  6587
+	      if ((regno_use_in (REGNO (reg), PATTERN (scan)) != NULL_RTX)
mgl@1371
  6588
+		  && (GET_MODE (regno_use_in (REGNO (reg), PATTERN (scan))) ==
mgl@1371
  6589
+		      GET_MODE (reg)))
mgl@1371
  6590
+		{
mgl@1371
  6591
+		  /* If not used in the source to the set or in a memory
mgl@1371
  6592
+		     expression in the destiantion then the register is used
mgl@1371
  6593
+		     as a destination and is really dead. */
mgl@1371
  6594
+		  if (single_set (scan)
mgl@1371
  6595
+		      && GET_CODE (PATTERN (scan)) == SET
mgl@1371
  6596
+		      && REG_P (SET_DEST (PATTERN (scan)))
mgl@1371
  6597
+		      && !regno_use_in (REGNO (reg), SET_SRC (PATTERN (scan)))
mgl@1371
  6598
+		      && label_ref == NULL_RTX)
mgl@1371
  6599
+		    {
mgl@1371
  6600
+		      unused_cast = true;
mgl@1371
  6601
+		    }
mgl@1371
  6602
+		  break;
mgl@1371
  6603
+		}
mgl@1371
  6604
+
mgl@1371
  6605
+	      /* Check if register is dead or set in this insn */
mgl@1371
  6606
+	      if (dead_or_set_p (scan, reg))
mgl@1371
  6607
+		{
mgl@1371
  6608
+		  unused_cast = true;
mgl@1371
  6609
+		  break;
mgl@1371
  6610
+		}
mgl@1371
  6611
+	    }
mgl@1371
  6612
+
mgl@1371
  6613
+	  /* Check if we have unresolved conditional jumps */
mgl@1371
  6614
+	  if (label_ref != NULL_RTX)
mgl@1371
  6615
+	    continue;
mgl@1371
  6616
+
mgl@1371
  6617
+	  if (unused_cast)
mgl@1371
  6618
+	    {
mgl@1371
  6619
+	      if (REGNO (reg) == REGNO (XEXP (SET_SRC (PATTERN (insn)), 0)))
mgl@1371
  6620
+		{
mgl@1371
  6621
+		  /* One operand cast, safe to delete */
mgl@1371
  6622
+		  if (dump_file)
mgl@1371
  6623
+		    {
mgl@1371
  6624
+		      fprintf (dump_file,
mgl@1371
  6625
+			       ";;  INSN %i removed, casted register %i value not used.\n",
mgl@1371
  6626
+			       INSN_UID (insn), REGNO (reg));
mgl@1371
  6627
+		    }
mgl@1371
  6628
+		  SET_INSN_DELETED (insn);
mgl@1371
  6629
+		  /* Force the instruction to be recognized again */
mgl@1371
  6630
+		  INSN_CODE (insn) = -1;
mgl@1371
  6631
+		}
mgl@1371
  6632
+	      else
mgl@1371
  6633
+		{
mgl@1371
  6634
+		  /* Two operand cast, which really could be substituted with
mgl@1371
  6635
+		     a move, if the source register is dead after the cast
mgl@1371
  6636
+		     insn and then the insn which sets the source register
mgl@1371
  6637
+		     could instead directly set the destination register for
mgl@1371
  6638
+		     the cast. As long as there are no insns in between which
mgl@1371
  6639
+		     uses the register. */
mgl@1371
  6640
+		  rtx link = NULL_RTX;
mgl@1371
  6641
+		  rtx set;
mgl@1371
  6642
+		  rtx src_reg = XEXP (SET_SRC (PATTERN (insn)), 0);
mgl@1371
  6643
+		  unused_cast = false;
mgl@1371
  6644
+
mgl@1371
  6645
+		  if (!find_reg_note (insn, REG_DEAD, src_reg))
mgl@1371
  6646
+		    continue;
mgl@1371
  6647
+
mgl@1371
  6648
+		  /* Search for the insn which sets the source register */
mgl@1371
  6649
+		  for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
mgl@1371
  6650
+		    {
mgl@1371
  6651
+		      if (REG_NOTE_KIND (link) != 0)
mgl@1371
  6652
+			continue;
mgl@1371
  6653
+		      set = single_set (XEXP (link, 0));
mgl@1371
  6654
+		      if (set && rtx_equal_p (src_reg, SET_DEST (set)))
mgl@1371
  6655
+			{
mgl@1371
  6656
+			  link = XEXP (link, 0);
mgl@1371
  6657
+			  break;
mgl@1371
  6658
+			}
mgl@1371
  6659
+		    }
mgl@1371
  6660
+
mgl@1371
  6661
+		  /* Found no link or link is a call insn where we can not
mgl@1371
  6662
+		     change the destination register */
mgl@1371
  6663
+		  if (link == NULL_RTX || CALL_P (link))
mgl@1371
  6664
+		    continue;
mgl@1371
  6665
+
mgl@1371
  6666
+		  /* Scan through all insn between link and insn */
mgl@1371
  6667
+		  for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
mgl@1371
  6668
+		    {
mgl@1371
  6669
+		      /* Don't try to trace forward past a CODE_LABEL if we
mgl@1371
  6670
+		         haven't seen INSN yet.  Ordinarily, we will only
mgl@1371
  6671
+		         find the setting insn in LOG_LINKS if it is in the
mgl@1371
  6672
+		         same basic block.  However, cross-jumping can insert
mgl@1371
  6673
+		         code labels in between the load and the call, and
mgl@1371
  6674
+		         can result in situations where a single call insn
mgl@1371
  6675
+		         may have two targets depending on where we came
mgl@1371
  6676
+		         from.  */
mgl@1371
  6677
+
mgl@1371
  6678
+		      if (GET_CODE (scan) == CODE_LABEL)
mgl@1371
  6679
+			break;
mgl@1371
  6680
+
mgl@1371
  6681
+		      if (!INSN_P (scan))
mgl@1371
  6682
+			continue;
mgl@1371
  6683
+
mgl@1371
  6684
+		      /* Don't try to trace forward past a JUMP.  To optimize
mgl@1371
  6685
+		         safely, we would have to check that all the
mgl@1371
  6686
+		         instructions at the jump destination did not use REG.
mgl@1371
  6687
+		       */
mgl@1371
  6688
+
mgl@1371
  6689
+		      if (GET_CODE (scan) == JUMP_INSN)
mgl@1371
  6690
+			{
mgl@1371
  6691
+			  break;
mgl@1371
  6692
+			}
mgl@1371
  6693
+
mgl@1371
  6694
+		      if (!reg_mentioned_p (src_reg, PATTERN (scan)))
mgl@1371
  6695
+			continue;
mgl@1371
  6696
+
mgl@1371
  6697
+		      /* We have reached the cast insn */
mgl@1371
  6698
+		      if (scan == insn)
mgl@1371
  6699
+			{
mgl@1371
  6700
+			  /* We can remove cast and replace the destination
mgl@1371
  6701
+			     register of the link insn with the destination
mgl@1371
  6702
+			     of the cast */
mgl@1371
  6703
+			  if (dump_file)
mgl@1371
  6704
+			    {
mgl@1371
  6705
+			      fprintf (dump_file,
mgl@1371
  6706
+				       ";;  INSN %i removed, casted value unused. "
mgl@1371
  6707
+				       "Destination of removed cast operation: register %i,  folded into INSN %i.\n",
mgl@1371
  6708
+				       INSN_UID (insn), REGNO (reg),
mgl@1371
  6709
+				       INSN_UID (link));
mgl@1371
  6710
+			    }
mgl@1371
  6711
+			  /* Update link insn */
mgl@1371
  6712
+			  SET_DEST (PATTERN (link)) =
mgl@1371
  6713
+			    gen_rtx_REG (mode, REGNO (reg));
mgl@1371
  6714
+			  /* Force the instruction to be recognized again */
mgl@1371
  6715
+			  INSN_CODE (link) = -1;
mgl@1371
  6716
+
mgl@1371
  6717
+			  /* Delete insn */
mgl@1371
  6718
+			  SET_INSN_DELETED (insn);
mgl@1371
  6719
+			  /* Force the instruction to be recognized again */
mgl@1371
  6720
+			  INSN_CODE (insn) = -1;
mgl@1371
  6721
+			  break;
mgl@1371
  6722
+			}
mgl@1371
  6723
+		    }
mgl@1371
  6724
+		}
mgl@1371
  6725
+	    }
mgl@1371
  6726
+	}
mgl@1371
  6727
+    }
mgl@1371
  6728
+
mgl@1371
  6729
+  if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
mgl@1371
  6730
+    {
mgl@1371
  6731
+
mgl@1371
  6732
+      /* Scan through all insns looking for shifted add operations */
mgl@1371
  6733
+      if (dump_file)
mgl@1371
  6734
+	{
mgl@1371
  6735
+	  fprintf (dump_file,
mgl@1371
  6736
+		   ";; Deleting redundant shifted add operations:\n");
mgl@1371
  6737
+	}
mgl@1371
  6738
+      for (insn = first; insn; insn = NEXT_INSN (insn))
mgl@1371
  6739
+	{
mgl@1371
  6740
+	  rtx reg, mem_expr, scan, op0, op1;
mgl@1371
  6741
+	  int add_only_used_as_pointer;
mgl@1371
  6742
+
mgl@1371
  6743
+	  if (INSN_P (insn)
mgl@1371
  6744
+	      && GET_CODE (PATTERN (insn)) == SET
mgl@1371
  6745
+	      && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
mgl@1371
  6746
+	      && (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MULT
mgl@1371
  6747
+		  || GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == ASHIFT)
mgl@1371
  6748
+	      && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1)) ==
mgl@1371
  6749
+	      CONST_INT && REG_P (SET_DEST (PATTERN (insn)))
mgl@1371
  6750
+	      && REG_P (XEXP (SET_SRC (PATTERN (insn)), 1))
mgl@1371
  6751
+	      && REG_P (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)))
mgl@1371
  6752
+	    {
mgl@1371
  6753
+	      reg = SET_DEST (PATTERN (insn));
mgl@1371
  6754
+	      mem_expr = SET_SRC (PATTERN (insn));
mgl@1371
  6755
+	      op0 = XEXP (XEXP (mem_expr, 0), 0);
mgl@1371
  6756
+	      op1 = XEXP (mem_expr, 1);
mgl@1371
  6757
+	    }
mgl@1371
  6758
+	  else
mgl@1371
  6759
+	    {
mgl@1371
  6760
+	      continue;
mgl@1371
  6761
+	    }
mgl@1371
  6762
+
mgl@1371
  6763
+	  /* Scan forward the check if the result of the shifted add
mgl@1371
  6764
+	     operation is only used as an address in memory operations and
mgl@1371
  6765
+	     that the operands to the shifted add are not clobbered. */
mgl@1371
  6766
+	  add_only_used_as_pointer = false;
mgl@1371
  6767
+	  for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
mgl@1371
  6768
+	    {
mgl@1371
  6769
+	      if (!INSN_P (scan))
mgl@1371
  6770
+		continue;
mgl@1371
  6771
+
mgl@1371
  6772
+	      /* Don't try to trace forward past a JUMP or CALL.  To optimize
mgl@1371
  6773
+	         safely, we would have to check that all the instructions at
mgl@1371
  6774
+	         the jump destination did not use REG.  */
mgl@1371
  6775
+
mgl@1371
  6776
+	      if (GET_CODE (scan) == JUMP_INSN)
mgl@1371
  6777
+		{
mgl@1371
  6778
+		  break;
mgl@1371
  6779
+		}
mgl@1371
  6780
+
mgl@1371
  6781
+	      /* If used in a call insn then we cannot optimize it away */
mgl@1371
  6782
+	      if (CALL_P (scan) && find_regno_fusage (scan, USE, REGNO (reg)))
mgl@1371
  6783
+		break;
mgl@1371
  6784
+
mgl@1371
  6785
+	      /* If any of the operands of the shifted add are clobbered we
mgl@1371
  6786
+	         cannot optimize the shifted adda away */
mgl@1371
  6787
+	      if ((reg_set_p (op0, scan) && (REGNO (op0) != REGNO (reg)))
mgl@1371
  6788
+		  || (reg_set_p (op1, scan) && (REGNO (op1) != REGNO (reg))))
mgl@1371
  6789
+		break;
mgl@1371
  6790
+
mgl@1371
  6791
+	      if (!reg_mentioned_p (reg, PATTERN (scan)))
mgl@1371
  6792
+		continue;
mgl@1371
  6793
+
mgl@1371
  6794
+	      /* If used any other place than as a pointer or as the
mgl@1371
  6795
+	         destination register we failed */
mgl@1371
  6796
+              if (!(single_set (scan)
mgl@1371
  6797
+                    && GET_CODE (PATTERN (scan)) == SET
mgl@1371
  6798
+                    && ((MEM_P (SET_DEST (PATTERN (scan)))
mgl@1371
  6799
+                         && REG_P (XEXP (SET_DEST (PATTERN (scan)), 0))
mgl@1371
  6800
+                         && REGNO (XEXP (SET_DEST (PATTERN (scan)), 0)) == REGNO (reg))
mgl@1371
  6801
+                        || (MEM_P (SET_SRC (PATTERN (scan)))
mgl@1371
  6802
+                            && REG_P (XEXP (SET_SRC (PATTERN (scan)), 0))
mgl@1371
  6803
+                            && REGNO (XEXP
mgl@1371
  6804
+                                      (SET_SRC (PATTERN (scan)), 0)) == REGNO (reg))))
mgl@1371
  6805
+                  && !(GET_CODE (PATTERN (scan)) == SET
mgl@1371
  6806
+                       && REG_P (SET_DEST (PATTERN (scan)))
mgl@1371
  6807
+                       && !regno_use_in (REGNO (reg),
mgl@1371
  6808
+                                         SET_SRC (PATTERN (scan)))))
mgl@1371
  6809
+                break;
mgl@1371
  6810
+
mgl@1371
  6811
+              /* We cannot replace the pointer in TImode insns
mgl@1371
  6812
+                 as these has a differene addressing mode than the other
mgl@1371
  6813
+                 memory insns. */
mgl@1371
  6814
+              if ( GET_MODE (SET_DEST (PATTERN (scan))) == TImode )
mgl@1371
  6815
+                break;
mgl@1371
  6816
+
mgl@1371
  6817
+	      /* Check if register is dead or set in this insn */
mgl@1371
  6818
+	      if (dead_or_set_p (scan, reg))
mgl@1371
  6819
+		{
mgl@1371
  6820
+		  add_only_used_as_pointer = true;
mgl@1371
  6821
+		  break;
mgl@1371
  6822
+		}
mgl@1371
  6823
+	    }
mgl@1371
  6824
+
mgl@1371
  6825
+	  if (add_only_used_as_pointer)
mgl@1371
  6826
+	    {
mgl@1371
  6827
+	      /* Lets delete the add insn and replace all memory references
mgl@1371
  6828
+	         which uses the pointer with the full expression. */
mgl@1371
  6829
+	      if (dump_file)
mgl@1371
  6830
+		{
mgl@1371
  6831
+		  fprintf (dump_file,
mgl@1371
  6832
+			   ";; Deleting INSN %i since address expression can be folded into all "
mgl@1371
  6833
+			   "memory references using this expression\n",
mgl@1371
  6834
+			   INSN_UID (insn));
mgl@1371
  6835
+		}
mgl@1371
  6836
+	      SET_INSN_DELETED (insn);
mgl@1371
  6837
+	      /* Force the instruction to be recognized again */
mgl@1371
  6838
+	      INSN_CODE (insn) = -1;
mgl@1371
  6839
+
mgl@1371
  6840
+	      for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
mgl@1371
  6841
+		{
mgl@1371
  6842
+		  if (!INSN_P (scan))
mgl@1371
  6843
+		    continue;
mgl@1371
  6844
+
mgl@1371
  6845
+		  if (!reg_mentioned_p (reg, PATTERN (scan)))
mgl@1371
  6846
+		    continue;
mgl@1371
  6847
+
mgl@1371
  6848
+		  /* If used any other place than as a pointer or as the
mgl@1371
  6849
+		     destination register we failed */
mgl@1371
  6850
+		  if ((single_set (scan)
mgl@1371
  6851
+		       && GET_CODE (PATTERN (scan)) == SET
mgl@1371
  6852
+		       && ((MEM_P (SET_DEST (PATTERN (scan)))
mgl@1371
  6853
+			    && REG_P (XEXP (SET_DEST (PATTERN (scan)), 0))
mgl@1371
  6854
+			    && REGNO (XEXP (SET_DEST (PATTERN (scan)), 0)) ==
mgl@1371
  6855
+			    REGNO (reg)) || (MEM_P (SET_SRC (PATTERN (scan)))
mgl@1371
  6856
+					     &&
mgl@1371
  6857
+					     REG_P (XEXP
mgl@1371
  6858
+						    (SET_SRC (PATTERN (scan)),
mgl@1371
  6859
+						     0))
mgl@1371
  6860
+					     &&
mgl@1371
  6861
+					     REGNO (XEXP
mgl@1371
  6862
+						    (SET_SRC (PATTERN (scan)),
mgl@1371
  6863
+						     0)) == REGNO (reg)))))
mgl@1371
  6864
+		    {
mgl@1371
  6865
+		      if (dump_file)
mgl@1371
  6866
+			{
mgl@1371
  6867
+			  fprintf (dump_file,
mgl@1371
  6868
+				   ";; Register %i replaced by indexed address in INSN %i\n",
mgl@1371
  6869
+				   REGNO (reg), INSN_UID (scan));
mgl@1371
  6870
+			}
mgl@1371
  6871
+		      if (MEM_P (SET_DEST (PATTERN (scan))))
mgl@1371
  6872
+			XEXP (SET_DEST (PATTERN (scan)), 0) = mem_expr;
mgl@1371
  6873
+		      else
mgl@1371
  6874
+			XEXP (SET_SRC (PATTERN (scan)), 0) = mem_expr;
mgl@1371
  6875
+		    }
mgl@1371
  6876
+
mgl@1371
  6877
+		  /* Check if register is dead or set in this insn */
mgl@1371
  6878
+		  if (dead_or_set_p (scan, reg))
mgl@1371
  6879
+		    {
mgl@1371
  6880
+		      break;
mgl@1371
  6881
+		    }
mgl@1371
  6882
+
mgl@1371
  6883
+		}
mgl@1371
  6884
+	    }
mgl@1371
  6885
+	}
mgl@1371
  6886
+    }
mgl@1371
  6887
+
mgl@1371
  6888
+
mgl@1371
  6889
+  if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
mgl@1371
  6890
+    {
mgl@1371
  6891
+
mgl@1371
  6892
+      /* Scan through all insns looking for conditional register to
mgl@1371
  6893
+         register move operations */
mgl@1371
  6894
+      if (dump_file)
mgl@1371
  6895
+	{
mgl@1371
  6896
+	  fprintf (dump_file,
mgl@1371
  6897
+		   ";; Folding redundant conditional move operations:\n");
mgl@1371
  6898
+	}
mgl@1371
  6899
+      for (insn = first; insn; insn = next_nonnote_insn (insn))
mgl@1371
  6900
+	{
mgl@1371
  6901
+	  rtx src_reg, dst_reg, scan, test;
mgl@1371
  6902
+
mgl@1371
  6903
+	  if (INSN_P (insn)
mgl@1371
  6904
+              && GET_CODE (PATTERN (insn)) == COND_EXEC
mgl@1371
  6905
+	      && GET_CODE (COND_EXEC_CODE (PATTERN (insn))) == SET
mgl@1371
  6906
+	      && REG_P (SET_SRC (COND_EXEC_CODE (PATTERN (insn))))
mgl@1371
  6907
+	      && REG_P (SET_DEST (COND_EXEC_CODE (PATTERN (insn))))
mgl@1371
  6908
+              && find_reg_note (insn, REG_DEAD, SET_SRC (COND_EXEC_CODE (PATTERN (insn)))))
mgl@1371
  6909
+	    {
mgl@1371
  6910
+	      src_reg = SET_SRC (COND_EXEC_CODE (PATTERN (insn)));
mgl@1371
  6911
+	      dst_reg = SET_DEST (COND_EXEC_CODE (PATTERN (insn)));
mgl@1371
  6912
+              test = COND_EXEC_TEST (PATTERN (insn));
mgl@1371
  6913
+	    }
mgl@1371
  6914
+	  else
mgl@1371
  6915
+	    {
mgl@1371
  6916
+	      continue;
mgl@1371
  6917
+	    }
mgl@1371
  6918
+
mgl@1371
  6919
+          /* Scan backward through the rest of insns in this if-then or if-else
mgl@1371
  6920
+             block and check if we can fold the move into another of the conditional
mgl@1371
  6921
+             insns in the same block. */
mgl@1371
  6922
+          scan = prev_nonnote_insn (insn);
mgl@1371
  6923
+          while (INSN_P (scan)
mgl@1371
  6924
+                 && GET_CODE (PATTERN (scan)) == COND_EXEC
mgl@1371
  6925
+                 && rtx_equal_p (COND_EXEC_TEST (PATTERN (scan)), test))
mgl@1371
  6926
+            {
mgl@1371
  6927
+              rtx pattern = COND_EXEC_CODE (PATTERN (scan));
mgl@1371
  6928
+              if ( GET_CODE (pattern) == PARALLEL )
mgl@1371
  6929
+                pattern = XVECEXP (pattern, 0, 0);
mgl@1371
  6930
+
mgl@1371
  6931
+              if ( reg_set_p (src_reg, pattern) )
mgl@1371
  6932
+                {
mgl@1371
  6933
+                  /* Fold in the destination register for the cond. move
mgl@1371
  6934
+                     into this insn. */
mgl@1371
  6935
+                  SET_DEST (pattern) = dst_reg;
mgl@1371
  6936
+                  if (dump_file)
mgl@1371
  6937
+                    {
mgl@1371
  6938
+                      fprintf (dump_file,
mgl@1371
  6939
+                               ";; Deleting INSN %i since this operation can be folded into INSN %i\n",
mgl@1371
  6940
+                               INSN_UID (insn), INSN_UID (scan));
mgl@1371
  6941
+                    }
mgl@1371
  6942
+
mgl@1371
  6943
+                  /* Scan and check if any of the insns in between uses the src_reg. We
mgl@1371
  6944
+                     must then replace it with the dst_reg. */
mgl@1371
  6945
+                  while ( (scan = next_nonnote_insn (scan)) != insn ){
mgl@1371
  6946
+                    avr32_replace_reg (scan, src_reg, dst_reg);
mgl@1371
  6947
+                  }
mgl@1371
  6948
+                  /* Delete the insn. */
mgl@1371
  6949
+                  SET_INSN_DELETED (insn);
mgl@1371
  6950
+
mgl@1371
  6951
+                  /* Force the instruction to be recognized again */
mgl@1371
  6952
+                  INSN_CODE (insn) = -1;
mgl@1371
  6953
+                  break;
mgl@1371
  6954
+                }
mgl@1371
  6955
+
mgl@1371
  6956
+              /* If the destination register is used but not set in this insn
mgl@1371
  6957
+                 we cannot fold. */
mgl@1371
  6958
+              if ( reg_mentioned_p (dst_reg, pattern) )
mgl@1371
  6959
+                break;
mgl@1371
  6960
+
mgl@1371
  6961
+              scan = prev_nonnote_insn (scan);
mgl@1371
  6962
+            }
mgl@1371
  6963
+        }
mgl@1371
  6964
+    }
mgl@1371
  6965
+
mgl@1371
  6966
+}
mgl@1371
  6967
+
mgl@1371
  6968
+/* Exported to toplev.c.
mgl@1371
  6969
+
mgl@1371
  6970
+   Do a final pass over the function, just before delayed branch
mgl@1371
  6971
+   scheduling.  */
mgl@1371
  6972
+
mgl@1371
  6973
+static void
mgl@1371
  6974
+avr32_reorg (void)
mgl@1371
  6975
+{
mgl@1371
  6976
+  rtx insn;
mgl@1371
  6977
+  HOST_WIDE_INT address = 0;
mgl@1371
  6978
+  Mfix *fix;
mgl@1371
  6979
+
mgl@1371
  6980
+  minipool_fix_head = minipool_fix_tail = NULL;
mgl@1371
  6981
+
mgl@1371
  6982
+  /* The first insn must always be a note, or the code below won't scan it
mgl@1371
  6983
+     properly.  */
mgl@1371
  6984
+  insn = get_insns ();
mgl@1371
  6985
+  if (GET_CODE (insn) != NOTE)
mgl@1371
  6986
+    abort ();
mgl@1371
  6987
+
mgl@1371
  6988
+  /* Scan all the insns and record the operands that will need fixing.  */
mgl@1371
  6989
+  for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn))
mgl@1371
  6990
+    {
mgl@1371
  6991
+      if (GET_CODE (insn) == BARRIER)
mgl@1371
  6992
+	push_minipool_barrier (insn, address);
mgl@1371
  6993
+      else if (INSN_P (insn))
mgl@1371
  6994
+	{
mgl@1371
  6995
+	  rtx table;
mgl@1371
  6996
+
mgl@1371
  6997
+	  note_invalid_constants (insn, address, true);
mgl@1371
  6998
+	  address += get_attr_length (insn);
mgl@1371
  6999
+
mgl@1371
  7000
+	  /* If the insn is a vector jump, add the size of the table and skip
mgl@1371
  7001
+	     the table.  */
mgl@1371
  7002
+	  if ((table = is_jump_table (insn)) != NULL)
mgl@1371
  7003
+	    {
mgl@1371
  7004
+	      address += get_jump_table_size (table);
mgl@1371
  7005
+	      insn = table;
mgl@1371
  7006
+	    }
mgl@1371
  7007
+	}
mgl@1371
  7008
+    }
mgl@1371
  7009
+
mgl@1371
  7010
+  fix = minipool_fix_head;
mgl@1371
  7011
+
mgl@1371
  7012
+  /* Now scan the fixups and perform the required changes.  */
mgl@1371
  7013
+  while (fix)
mgl@1371
  7014
+    {
mgl@1371
  7015
+      Mfix *ftmp;
mgl@1371
  7016
+      Mfix *fdel;
mgl@1371
  7017
+      Mfix *last_added_fix;
mgl@1371
  7018
+      Mfix *last_barrier = NULL;
mgl@1371
  7019
+      Mfix *this_fix;
mgl@1371
  7020
+
mgl@1371
  7021
+      /* Skip any further barriers before the next fix.  */
mgl@1371
  7022
+      while (fix && GET_CODE (fix->insn) == BARRIER)
mgl@1371
  7023
+	fix = fix->next;
mgl@1371
  7024
+
mgl@1371
  7025
+      /* No more fixes.  */
mgl@1371
  7026
+      if (fix == NULL)
mgl@1371
  7027
+	break;
mgl@1371
  7028
+
mgl@1371
  7029
+      last_added_fix = NULL;
mgl@1371
  7030
+
mgl@1371
  7031
+      for (ftmp = fix; ftmp; ftmp = ftmp->next)
mgl@1371
  7032
+	{
mgl@1371
  7033
+	  if (GET_CODE (ftmp->insn) == BARRIER)
mgl@1371
  7034
+	    {
mgl@1371
  7035
+	      if (ftmp->address >= minipool_vector_head->max_address)
mgl@1371
  7036
+		break;
mgl@1371
  7037
+
mgl@1371
  7038
+	      last_barrier = ftmp;
mgl@1371
  7039
+	    }
mgl@1371
  7040
+	  else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL)
mgl@1371
  7041
+	    break;
mgl@1371
  7042
+
mgl@1371
  7043
+	  last_added_fix = ftmp;	/* Keep track of the last fix added.
mgl@1371
  7044
+					 */
mgl@1371
  7045
+	}
mgl@1371
  7046
+
mgl@1371
  7047
+      /* If we found a barrier, drop back to that; any fixes that we could
mgl@1371
  7048
+         have reached but come after the barrier will now go in the next
mgl@1371
  7049
+         mini-pool.  */
mgl@1371
  7050
+      if (last_barrier != NULL)
mgl@1371
  7051
+	{
mgl@1371
  7052
+	  /* Reduce the refcount for those fixes that won't go into this pool
mgl@1371
  7053
+	     after all.  */
mgl@1371
  7054
+	  for (fdel = last_barrier->next;
mgl@1371
  7055
+	       fdel && fdel != ftmp; fdel = fdel->next)
mgl@1371
  7056
+	    {
mgl@1371
  7057
+	      fdel->minipool->refcount--;
mgl@1371
  7058
+	      fdel->minipool = NULL;
mgl@1371
  7059
+	    }
mgl@1371
  7060
+
mgl@1371
  7061
+	  ftmp = last_barrier;
mgl@1371
  7062
+	}
mgl@1371
  7063
+      else
mgl@1371
  7064
+	{
mgl@1371
  7065
+	  /* ftmp is first fix that we can't fit into this pool and there no
mgl@1371
  7066
+	     natural barriers that we could use.  Insert a new barrier in the
mgl@1371
  7067
+	     code somewhere between the previous fix and this one, and
mgl@1371
  7068
+	     arrange to jump around it.  */
mgl@1371
  7069
+	  HOST_WIDE_INT max_address;
mgl@1371
  7070
+
mgl@1371
  7071
+	  /* The last item on the list of fixes must be a barrier, so we can
mgl@1371
  7072
+	     never run off the end of the list of fixes without last_barrier
mgl@1371
  7073
+	     being set.  */
mgl@1371
  7074
+	  if (ftmp == NULL)
mgl@1371
  7075
+	    abort ();
mgl@1371
  7076
+
mgl@1371
  7077
+	  max_address = minipool_vector_head->max_address;
mgl@1371
  7078
+	  /* Check that there isn't another fix that is in range that we
mgl@1371
  7079
+	     couldn't fit into this pool because the pool was already too
mgl@1371
  7080
+	     large: we need to put the pool before such an instruction.  */
mgl@1371
  7081
+	  if (ftmp->address < max_address)
mgl@1371
  7082
+	    max_address = ftmp->address;
mgl@1371
  7083
+
mgl@1371
  7084
+	  last_barrier = create_fix_barrier (last_added_fix, max_address);
mgl@1371
  7085
+	}
mgl@1371
  7086
+
mgl@1371
  7087
+      assign_minipool_offsets (last_barrier);
mgl@1371
  7088
+
mgl@1371
  7089
+      while (ftmp)
mgl@1371
  7090
+	{
mgl@1371
  7091
+	  if (GET_CODE (ftmp->insn) != BARRIER
mgl@1371
  7092
+	      && ((ftmp->minipool = add_minipool_backward_ref (ftmp))
mgl@1371
  7093
+		  == NULL))
mgl@1371
  7094
+	    break;
mgl@1371
  7095
+
mgl@1371
  7096
+	  ftmp = ftmp->next;
mgl@1371
  7097
+	}
mgl@1371
  7098
+
mgl@1371
  7099
+      /* Scan over the fixes we have identified for this pool, fixing them up
mgl@1371
  7100
+         and adding the constants to the pool itself.  */
mgl@1371
  7101
+        for (this_fix = fix; this_fix && ftmp != this_fix;
mgl@1371
  7102
+             this_fix = this_fix->next)
mgl@1371
  7103
+          if (GET_CODE (this_fix->insn) != BARRIER
mgl@1371
  7104
+              /* Do nothing for entries present just to force the insertion of
mgl@1371
  7105
+	       a minipool. */
mgl@1371
  7106
+	    && !IS_FORCE_MINIPOOL (this_fix->value))
mgl@1371
  7107
+	  {
mgl@1371
  7108
+	    rtx addr = plus_constant (gen_rtx_LABEL_REF (VOIDmode,
mgl@1371
  7109
+							 minipool_vector_label),
mgl@1371
  7110
+				      this_fix->minipool->offset);
mgl@1371
  7111
+	    *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
mgl@1371
  7112
+	  }
mgl@1371
  7113
+
mgl@1371
  7114
+      dump_minipool (last_barrier->insn);
mgl@1371
  7115
+      fix = ftmp;
mgl@1371
  7116
+    }
mgl@1371
  7117
+
mgl@1371
  7118
+  /* Free the minipool memory.  */
mgl@1371
  7119
+  obstack_free (&minipool_obstack, minipool_startobj);
mgl@1371
  7120
+
mgl@1371
  7121
+  avr32_reorg_optimization ();
mgl@1371
  7122
+}
mgl@1371
  7123
+
mgl@1371
  7124
+
mgl@1371
  7125
+/*
mgl@1371
  7126
+ Hook for doing some final scanning of instructions. Does nothing yet...*/
mgl@1371
  7127
+void
mgl@1371
  7128
+avr32_final_prescan_insn (rtx insn ATTRIBUTE_UNUSED,
mgl@1371
  7129
+			  rtx * opvec ATTRIBUTE_UNUSED,
mgl@1371
  7130
+			  int noperands ATTRIBUTE_UNUSED)
mgl@1371
  7131
+{
mgl@1371
  7132
+  return;
mgl@1371
  7133
+}
mgl@1371
  7134
+
mgl@1371
  7135
+
mgl@1371
  7136
+/* Function for changing the condition on the next instruction,
mgl@1371
  7137
+   should be used when emmiting compare instructions and
mgl@1371
  7138
+   the condition of the next instruction needs to change.
mgl@1371
  7139
+*/
mgl@1371
  7140
+int
mgl@1371
  7141
+set_next_insn_cond (rtx cur_insn, rtx new_cond)
mgl@1371
  7142
+{
mgl@1371
  7143
+  rtx next_insn = next_nonnote_insn (cur_insn);
mgl@1371
  7144
+   if ((next_insn != NULL_RTX)
mgl@1371
  7145
+       && (INSN_P (next_insn)))
mgl@1371
  7146
+     {
mgl@1371
  7147
+       if ((GET_CODE (PATTERN (next_insn)) == SET)
mgl@1371
  7148
+           && (GET_CODE (SET_SRC (PATTERN (next_insn))) == IF_THEN_ELSE))
mgl@1371
  7149
+         {
mgl@1371
  7150
+           /* Branch instructions */
mgl@1371
  7151
+           XEXP (SET_SRC (PATTERN (next_insn)), 0) = new_cond;
mgl@1371
  7152
+           /* Force the instruction to be recognized again */
mgl@1371
  7153
+           INSN_CODE (next_insn) = -1;
mgl@1371
  7154
+           return TRUE;
mgl@1371
  7155
+         }
mgl@1371
  7156
+       else if ((GET_CODE (PATTERN (next_insn)) == SET)
mgl@1371
  7157
+                && avr32_comparison_operator (SET_SRC (PATTERN (next_insn)),
mgl@1371
  7158
+                                              GET_MODE (SET_SRC (PATTERN (next_insn)))))
mgl@1371
  7159
+         {
mgl@1371
  7160
+           /* scc with no compare */
mgl@1371
  7161
+           SET_SRC (PATTERN (next_insn)) = new_cond;
mgl@1371
  7162
+           /* Force the instruction to be recognized again */
mgl@1371
  7163
+           INSN_CODE (next_insn) = -1;
mgl@1371
  7164
+           return TRUE;
mgl@1371
  7165
+         }
mgl@1371
  7166
+       else if (GET_CODE (PATTERN (next_insn)) == COND_EXEC)
mgl@1371
  7167
+         {
mgl@1371
  7168
+           if ( GET_CODE (new_cond) == UNSPEC )
mgl@1371
  7169
+             {
mgl@1371
  7170
+               COND_EXEC_TEST (PATTERN (next_insn)) =
mgl@1371
  7171
+                 gen_rtx_UNSPEC (CCmode,
mgl@1371
  7172
+                                 gen_rtvec (2,
mgl@1371
  7173
+                                            XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 0),
mgl@1371
  7174
+                                            XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 1)),
mgl@1371
  7175
+                                 XINT (new_cond, 1));
mgl@1371
  7176
+             }
mgl@1371
  7177
+           else
mgl@1371
  7178
+             {
mgl@1371
  7179
+               PUT_CODE(COND_EXEC_TEST (PATTERN (next_insn)), GET_CODE(new_cond));
mgl@1371
  7180
+             }
mgl@1371
  7181
+         }
mgl@1371
  7182
+     }
mgl@1371
  7183
+
mgl@1371
  7184
+  return FALSE;
mgl@1371
  7185
+}
mgl@1371
  7186
+
mgl@1371
  7187
+/* Function for obtaining the condition for the next instruction
mgl@1371
  7188
+   after cur_insn.
mgl@1371
  7189
+*/
mgl@1371
  7190
+rtx
mgl@1371
  7191
+get_next_insn_cond (rtx cur_insn)
mgl@1371
  7192
+{
mgl@1371
  7193
+  rtx next_insn = next_nonnote_insn (cur_insn);
mgl@1371
  7194
+  rtx cond = NULL_RTX;
mgl@1371
  7195
+  if (next_insn != NULL_RTX
mgl@1371
  7196
+      && INSN_P (next_insn))
mgl@1371
  7197
+    {
mgl@1371
  7198
+      if ((GET_CODE (PATTERN (next_insn)) == SET)
mgl@1371
  7199
+          && (GET_CODE (SET_SRC (PATTERN (next_insn))) == IF_THEN_ELSE))
mgl@1371
  7200
+        {
mgl@1371
  7201
+          /* Branch and cond if then else instructions */
mgl@1371
  7202
+          cond = XEXP (SET_SRC (PATTERN (next_insn)), 0);
mgl@1371
  7203
+        }
mgl@1371
  7204
+      else if ((GET_CODE (PATTERN (next_insn)) == SET)
mgl@1371
  7205
+               && avr32_comparison_operator (SET_SRC (PATTERN (next_insn)),
mgl@1371
  7206
+                                             GET_MODE (SET_SRC (PATTERN (next_insn)))))
mgl@1371
  7207
+        {
mgl@1371
  7208
+          /* scc with no compare */
mgl@1371
  7209
+          cond = SET_SRC (PATTERN (next_insn));
mgl@1371
  7210
+        }
mgl@1371
  7211
+      else if (GET_CODE (PATTERN (next_insn)) == COND_EXEC)
mgl@1371
  7212
+        {
mgl@1371
  7213
+          cond = COND_EXEC_TEST (PATTERN (next_insn));
mgl@1371
  7214
+        }
mgl@1371
  7215
+    }
mgl@1371
  7216
+  return cond;
mgl@1371
  7217
+}
mgl@1371
  7218
+
mgl@1371
  7219
+
mgl@1371
  7220
+rtx
mgl@1371
  7221
+avr32_output_cmp (rtx cond, enum machine_mode mode, rtx op0, rtx op1)
mgl@1371
  7222
+{
mgl@1371
  7223
+
mgl@1371
  7224
+  rtx new_cond = NULL_RTX;
mgl@1371
  7225
+  rtx ops[2];
mgl@1371
  7226
+  rtx compare_pattern;
mgl@1371
  7227
+  ops[0] = op0;
mgl@1371
  7228
+  ops[1] = op1;
mgl@1371
  7229
+
mgl@1371
  7230
+  if ( GET_CODE (op0) == AND )
mgl@1371
  7231
+    compare_pattern = op0;
mgl@1371
  7232
+  else
mgl@1371
  7233
+    compare_pattern = gen_rtx_COMPARE (mode, op0, op1);
mgl@1371
  7234
+
mgl@1371
  7235
+  new_cond = is_compare_redundant (compare_pattern, cond);
mgl@1371
  7236
+
mgl@1371
  7237
+  if (new_cond != NULL_RTX)
mgl@1371
  7238
+    return new_cond;
mgl@1371
  7239
+
mgl@1371
  7240
+  /* Check if we are inserting a bit-load instead of a compare. */
mgl@1371
  7241
+  if ( GET_CODE (op0) == AND )
mgl@1371
  7242
+    {
mgl@1371
  7243
+      ops[0] = XEXP (op0, 0);
mgl@1371
  7244
+      ops[1] = XEXP (op0, 1);
mgl@1371
  7245
+      output_asm_insn ("bld\t%0, %p1", ops);
mgl@1371
  7246
+      return cond;
mgl@1371
  7247
+    }
mgl@1371
  7248
+
mgl@1371
  7249
+  /* Insert compare */
mgl@1371
  7250
+  switch (mode)
mgl@1371
  7251
+    {
mgl@1371
  7252
+    case QImode:
mgl@1371
  7253
+      output_asm_insn ("cp.b\t%0, %1", ops);
mgl@1371
  7254
+      break;
mgl@1371
  7255
+    case HImode:
mgl@1371
  7256
+      output_asm_insn ("cp.h\t%0, %1", ops);
mgl@1371
  7257
+      break;
mgl@1371
  7258
+    case SImode:
mgl@1371
  7259
+      output_asm_insn ("cp.w\t%0, %1", ops);
mgl@1371
  7260
+      break;
mgl@1371
  7261
+    case DImode:
mgl@1371
  7262
+      if (GET_CODE (op1) != REG)
mgl@1371
  7263
+	output_asm_insn ("cp.w\t%0, %1\ncpc\t%m0", ops);
mgl@1371
  7264
+      else
mgl@1371
  7265
+	output_asm_insn ("cp.w\t%0, %1\ncpc\t%m0, %m1", ops);
mgl@1371
  7266
+      break;
mgl@1371
  7267
+    default:
mgl@1371
  7268
+      internal_error ("Unknown comparison mode");
mgl@1371
  7269
+      break;
mgl@1371
  7270
+    }
mgl@1371
  7271
+
mgl@1371
  7272
+  return cond;
mgl@1371
  7273
+}
mgl@1371
  7274
+
mgl@1371
  7275
+int
mgl@1371
  7276
+avr32_load_multiple_operation (rtx op,
mgl@1371
  7277
+			       enum machine_mode mode ATTRIBUTE_UNUSED)
mgl@1371
  7278
+{
mgl@1371
  7279
+  int count = XVECLEN (op, 0);
mgl@1371
  7280
+  unsigned int dest_regno;
mgl@1371
  7281
+  rtx src_addr;
mgl@1371
  7282
+  rtx elt;
mgl@1371
  7283
+  int i = 1, base = 0;
mgl@1371
  7284
+
mgl@1371
  7285
+  if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
mgl@1371
  7286
+    return 0;
mgl@1371
  7287
+
mgl@1371
  7288
+  /* Check to see if this might be a write-back.  */
mgl@1371
  7289
+  if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
mgl@1371
  7290
+    {
mgl@1371
  7291
+      i++;
mgl@1371
  7292
+      base = 1;
mgl@1371
  7293
+
mgl@1371
  7294
+      /* Now check it more carefully.  */
mgl@1371
  7295
+      if (GET_CODE (SET_DEST (elt)) != REG
mgl@1371
  7296
+	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
mgl@1371
  7297
+	  || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
mgl@1371
  7298
+	  || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
mgl@1371
  7299
+	return 0;
mgl@1371
  7300
+    }
mgl@1371
  7301
+
mgl@1371
  7302
+  /* Perform a quick check so we don't blow up below.  */
mgl@1371
  7303
+  if (count <= 1
mgl@1371
  7304
+      || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
mgl@1371
  7305
+      || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
mgl@1371
  7306
+      || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != UNSPEC)
mgl@1371
  7307
+    return 0;
mgl@1371
  7308
+
mgl@1371
  7309
+  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
mgl@1371
  7310
+  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
mgl@1371
  7311
+
mgl@1371
  7312
+  for (; i < count; i++)
mgl@1371
  7313
+    {
mgl@1371
  7314
+      elt = XVECEXP (op, 0, i);
mgl@1371
  7315
+
mgl@1371
  7316
+      if (GET_CODE (elt) != SET
mgl@1371
  7317
+	  || GET_CODE (SET_DEST (elt)) != REG
mgl@1371
  7318
+	  || GET_MODE (SET_DEST (elt)) != SImode
mgl@1371
  7319
+	  || GET_CODE (SET_SRC (elt)) != UNSPEC)
mgl@1371
  7320
+	return 0;
mgl@1371
  7321
+    }
mgl@1371
  7322
+
mgl@1371
  7323
+  return 1;
mgl@1371
  7324
+}
mgl@1371
  7325
+
mgl@1371
  7326
+int
mgl@1371
  7327
+avr32_store_multiple_operation (rtx op,
mgl@1371
  7328
+				enum machine_mode mode ATTRIBUTE_UNUSED)
mgl@1371
  7329
+{
mgl@1371
  7330
+  int count = XVECLEN (op, 0);
mgl@1371
  7331
+  int src_regno;
mgl@1371
  7332
+  rtx dest_addr;
mgl@1371
  7333
+  rtx elt;
mgl@1371
  7334
+  int i = 1;
mgl@1371
  7335
+
mgl@1371
  7336
+  if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
mgl@1371
  7337
+    return 0;
mgl@1371
  7338
+
mgl@1371
  7339
+  /* Perform a quick check so we don't blow up below.  */
mgl@1371
  7340
+  if (count <= i
mgl@1371
  7341
+      || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
mgl@1371
  7342
+      || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
mgl@1371
  7343
+      || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != UNSPEC)
mgl@1371
  7344
+    return 0;
mgl@1371
  7345
+
mgl@1371
  7346
+  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
mgl@1371
  7347
+  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
mgl@1371
  7348
+
mgl@1371
  7349
+  for (; i < count; i++)
mgl@1371
  7350
+    {
mgl@1371
  7351
+      elt = XVECEXP (op, 0, i);
mgl@1371
  7352
+
mgl@1371
  7353
+      if (GET_CODE (elt) != SET
mgl@1371
  7354
+	  || GET_CODE (SET_DEST (elt)) != MEM
mgl@1371
  7355
+	  || GET_MODE (SET_DEST (elt)) != SImode
mgl@1371
  7356
+	  || GET_CODE (SET_SRC (elt)) != UNSPEC)
mgl@1371
  7357
+	return 0;
mgl@1371
  7358
+    }
mgl@1371
  7359
+
mgl@1371
  7360
+  return 1;
mgl@1371
  7361
+}
mgl@1371
  7362
+
mgl@1371
  7363
+int
mgl@1371
  7364
+avr32_valid_macmac_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7365
+{
mgl@1371
  7366
+  /* Check if they use the same accumulator */
mgl@1371
  7367
+  if (rtx_equal_p
mgl@1371
  7368
+      (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
mgl@1371
  7369
+    {
mgl@1371
  7370
+      return TRUE;
mgl@1371
  7371
+    }
mgl@1371
  7372
+
mgl@1371
  7373
+  return FALSE;
mgl@1371
  7374
+}
mgl@1371
  7375
+
mgl@1371
  7376
+int
mgl@1371
  7377
+avr32_valid_mulmac_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7378
+{
mgl@1371
  7379
+  /*
mgl@1371
  7380
+     Check if the mul instruction produces the accumulator for the mac
mgl@1371
  7381
+     instruction. */
mgl@1371
  7382
+  if (rtx_equal_p
mgl@1371
  7383
+      (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
mgl@1371
  7384
+    {
mgl@1371
  7385
+      return TRUE;
mgl@1371
  7386
+    }
mgl@1371
  7387
+  return FALSE;
mgl@1371
  7388
+}
mgl@1371
  7389
+
mgl@1371
  7390
+int
mgl@1371
  7391
+avr32_store_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7392
+{
mgl@1371
  7393
+  /* Only valid bypass if the output result is used as an src in the store
mgl@1371
  7394
+     instruction, NOT if used as a pointer or base. */
mgl@1371
  7395
+  if (rtx_equal_p
mgl@1371
  7396
+      (SET_DEST (PATTERN (insn_out)), SET_SRC (PATTERN (insn_in))))
mgl@1371
  7397
+    {
mgl@1371
  7398
+      return TRUE;
mgl@1371
  7399
+    }
mgl@1371
  7400
+
mgl@1371
  7401
+  return FALSE;
mgl@1371
  7402
+}
mgl@1371
  7403
+
mgl@1371
  7404
+int
mgl@1371
  7405
+avr32_mul_waw_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7406
+{
mgl@1371
  7407
+  /* Check if the register holding the result from the mul instruction is
mgl@1371
  7408
+     used as a result register in the input instruction. */
mgl@1371
  7409
+  if (rtx_equal_p
mgl@1371
  7410
+      (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
mgl@1371
  7411
+    {
mgl@1371
  7412
+      return TRUE;
mgl@1371
  7413
+    }
mgl@1371
  7414
+
mgl@1371
  7415
+  return FALSE;
mgl@1371
  7416
+}
mgl@1371
  7417
+
mgl@1371
  7418
+int
mgl@1371
  7419
+avr32_valid_load_double_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7420
+{
mgl@1371
  7421
+  /* Check if the first loaded word in insn_out is used in insn_in. */
mgl@1371
  7422
+  rtx dst_reg;
mgl@1371
  7423
+  rtx second_loaded_reg;
mgl@1371
  7424
+
mgl@1371
  7425
+  /* If this is a double alu operation then the bypass is not valid */
mgl@1371
  7426
+  if ((get_attr_type (insn_in) == TYPE_ALU
mgl@1371
  7427
+       || get_attr_type (insn_in) == TYPE_ALU2)
mgl@1371
  7428
+      && (GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (insn_out)))) > 4))
mgl@1371
  7429
+    return FALSE;
mgl@1371
  7430
+
mgl@1371
  7431
+  /* Get the destination register in the load */
mgl@1371
  7432
+  if (!REG_P (SET_DEST (PATTERN (insn_out))))
mgl@1371
  7433
+    return FALSE;
mgl@1371
  7434
+
mgl@1371
  7435
+  dst_reg = SET_DEST (PATTERN (insn_out));
mgl@1371
  7436
+  second_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 1);
mgl@1371
  7437
+
mgl@1371
  7438
+  if (!reg_mentioned_p (second_loaded_reg, PATTERN (insn_in)))
mgl@1371
  7439
+    return TRUE;
mgl@1371
  7440
+
mgl@1371
  7441
+  return FALSE;
mgl@1371
  7442
+}
mgl@1371
  7443
+
mgl@1371
  7444
+
mgl@1371
  7445
+int
mgl@1371
  7446
+avr32_valid_load_quad_bypass (rtx insn_out, rtx insn_in)
mgl@1371
  7447
+{
mgl@1371
  7448
+  /*
mgl@1371
  7449
+     Check if the two first loaded word in insn_out are used in insn_in. */
mgl@1371
  7450
+  rtx dst_reg;
mgl@1371
  7451
+  rtx third_loaded_reg, fourth_loaded_reg;
mgl@1371
  7452
+
mgl@1371
  7453
+  /* Get the destination register in the load */
mgl@1371
  7454
+  if (!REG_P (SET_DEST (PATTERN (insn_out))))
mgl@1371
  7455
+    return FALSE;
mgl@1371
  7456
+
mgl@1371
  7457
+  dst_reg = SET_DEST (PATTERN (insn_out));
mgl@1371
  7458
+  third_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 2);
mgl@1371
  7459
+  fourth_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 3);
mgl@1371
  7460
+
mgl@1371
  7461
+  if (!reg_mentioned_p (third_loaded_reg, PATTERN (insn_in))
mgl@1371
  7462
+      && !reg_mentioned_p (fourth_loaded_reg, PATTERN (insn_in)))
mgl@1371
  7463
+    {
mgl@1371
  7464
+      return TRUE;
mgl@1371
  7465
+    }
mgl@1371
  7466
+
mgl@1371
  7467
+  return FALSE;
mgl@1371
  7468
+}
mgl@1371
  7469
+
mgl@1371
  7470
+
mgl@1371
  7471
+
mgl@1371
  7472
+rtx
mgl@1371
  7473
+avr32_ifcvt_modify_test (ce_if_block_t *ce_info,
mgl@1371
  7474
+                         rtx test ){
mgl@1371
  7475
+  rtx branch_insn;
mgl@1371
  7476
+  rtx cmp_test;
mgl@1371
  7477
+  rtx compare_op0;
mgl@1371
  7478
+  rtx compare_op1;
mgl@1371
  7479
+
mgl@1371
  7480
+
mgl@1371
  7481
+  if ( !ce_info
mgl@1371
  7482
+       || test == NULL_RTX
mgl@1371
  7483
+       || !reg_mentioned_p (cc0_rtx, test))
mgl@1371
  7484
+    return test;
mgl@1371
  7485
+
mgl@1371
  7486
+  branch_insn = BB_END (ce_info->test_bb);
mgl@1371
  7487
+  cmp_test = PATTERN(prev_nonnote_insn (branch_insn));
mgl@1371
  7488
+
mgl@1371
  7489
+  if (GET_CODE(cmp_test) != SET
mgl@1371
  7490
+      || !CC0_P(XEXP(cmp_test, 0)) )
mgl@1371
  7491
+    return cmp_test;
mgl@1371
  7492
+
mgl@1371
  7493
+  if ( GET_CODE(SET_SRC(cmp_test)) == COMPARE ){
mgl@1371
  7494
+    compare_op0 = XEXP(SET_SRC(cmp_test), 0);
mgl@1371
  7495
+    compare_op1 = XEXP(SET_SRC(cmp_test), 1);
mgl@1371
  7496
+  } else {
mgl@1371
  7497
+    compare_op0 = SET_SRC(cmp_test);
mgl@1371
  7498
+    compare_op1 = const0_rtx;
mgl@1371
  7499
+  }
mgl@1371
  7500
+
mgl@1371
  7501
+  return gen_rtx_fmt_ee (GET_CODE(test), GET_MODE (compare_op0),
mgl@1371
  7502
+                         compare_op0, compare_op1);
mgl@1371
  7503
+}
mgl@1371
  7504
+
mgl@1371
  7505
+
mgl@1371
  7506
+
mgl@1371
  7507
+rtx
mgl@1371
  7508
+avr32_ifcvt_modify_insn (ce_if_block_t *ce_info,
mgl@1371
  7509
+                         rtx pattern,
mgl@1371
  7510
+                         rtx insn,
mgl@1371
  7511
+                         int *num_true_changes){
mgl@1371
  7512
+  rtx test = COND_EXEC_TEST(pattern);
mgl@1371
  7513
+  rtx op = COND_EXEC_CODE(pattern);
mgl@1371
  7514
+  rtx cmp_insn;
mgl@1371
  7515
+  rtx cond_exec_insn;
mgl@1371
  7516
+  int inputs_set_outside_ifblock = 1;
mgl@1371
  7517
+  basic_block current_bb = BLOCK_FOR_INSN (insn);
mgl@1371
  7518
+  rtx bb_insn ;
mgl@1371
  7519
+  enum machine_mode mode = GET_MODE (XEXP (op, 0));
mgl@1371
  7520
+
mgl@1371
  7521
+  if (CC0_P(XEXP(test, 0)))
mgl@1371
  7522
+    test = avr32_ifcvt_modify_test (ce_info,
mgl@1371
  7523
+                                    test );
mgl@1371
  7524
+
mgl@1371
  7525
+  pattern = gen_rtx_COND_EXEC (VOIDmode, test, op);
mgl@1371
  7526
+
mgl@1371
  7527
+  if ( !reload_completed )
mgl@1371
  7528
+    {
mgl@1371
  7529
+      rtx start;
mgl@1371
  7530
+      int num_insns;
mgl@1371
  7531
+      int max_insns = MAX_CONDITIONAL_EXECUTE;
mgl@1371
  7532
+
mgl@1371
  7533
+      if ( !ce_info )
mgl@1371
  7534
+        return op;
mgl@1371
  7535
+
mgl@1371
  7536
+      /* Check if the insn is not suitable for conditional
mgl@1371
  7537
+         execution. */
mgl@1371
  7538
+      start_sequence ();
mgl@1371
  7539
+      cond_exec_insn = emit_insn (pattern);
mgl@1371
  7540
+      if ( recog_memoized (cond_exec_insn) < 0
mgl@1371
  7541
+           && !no_new_pseudos )
mgl@1371
  7542
+        {
mgl@1371
  7543
+          /* Insn is not suitable for conditional execution, try
mgl@1371
  7544
+             to fix it up by using an extra scratch register or
mgl@1371
  7545
+             by pulling the operation outside the if-then-else
mgl@1371
  7546
+             and then emiting a conditional move inside the if-then-else. */
mgl@1371
  7547
+          end_sequence ();
mgl@1371
  7548
+          if ( GET_CODE (op) != SET
mgl@1371
  7549
+               || !REG_P (SET_DEST (op))
mgl@1371
  7550
+               || GET_CODE (SET_SRC (op)) == IF_THEN_ELSE
mgl@1371
  7551
+               || GET_MODE_SIZE (mode) > UNITS_PER_WORD )
mgl@1371
  7552
+            return NULL_RTX;
mgl@1371
  7553
+
mgl@1371
  7554
+          /* Check if any of the input operands to the insn is set inside the
mgl@1371
  7555
+             current block. */
mgl@1371
  7556
+          if ( current_bb->index == ce_info->then_bb->index )
mgl@1371
  7557
+            start = PREV_INSN (BB_HEAD (ce_info->then_bb));
mgl@1371
  7558
+          else
mgl@1371
  7559
+            start = PREV_INSN (BB_HEAD (ce_info->else_bb));
mgl@1371
  7560
+
mgl@1371
  7561
+
mgl@1371
  7562
+          for ( bb_insn = next_nonnote_insn (start); bb_insn != insn; bb_insn = next_nonnote_insn (bb_insn) )
mgl@1371
  7563
+            {
mgl@1371
  7564
+              rtx set = single_set (bb_insn);
mgl@1371
  7565
+
mgl@1371
  7566
+              if ( set && reg_mentioned_p (SET_DEST (set), SET_SRC (op)))
mgl@1371
  7567
+                {
mgl@1371
  7568
+                  inputs_set_outside_ifblock = 0;
mgl@1371
  7569
+                  break;
mgl@1371
  7570
+                }
mgl@1371
  7571
+            }
mgl@1371
  7572
+
mgl@1371
  7573
+          cmp_insn = prev_nonnote_insn (BB_END (ce_info->test_bb));
mgl@1371
  7574
+
mgl@1371
  7575
+
mgl@1371
  7576
+          /* Check if we can insert more insns. */
mgl@1371
  7577
+          num_insns = ( ce_info->num_then_insns +
mgl@1371
  7578
+                        ce_info->num_else_insns +
mgl@1371
  7579
+                        ce_info->num_cond_clobber_insns +
mgl@1371
  7580
+                        ce_info->num_extra_move_insns );
mgl@1371
  7581
+
mgl@1371
  7582
+          if ( ce_info->num_else_insns != 0 )
mgl@1371
  7583
+            max_insns *=2;
mgl@1371
  7584
+
mgl@1371
  7585
+          if ( num_insns >= max_insns )
mgl@1371
  7586
+            return NULL_RTX;
mgl@1371
  7587
+
mgl@1371
  7588
+          /* Check if we have an instruction which might be converted to
mgl@1371
  7589
+             conditional form if we give it a scratch register to clobber. */
mgl@1371
  7590
+          {
mgl@1371
  7591
+            rtx clobber_insn;
mgl@1371
  7592
+            rtx scratch_reg = gen_reg_rtx (mode);
mgl@1371
  7593
+            rtx new_pattern = copy_rtx (pattern);
mgl@1371
  7594
+            rtx set_src = SET_SRC (COND_EXEC_CODE (new_pattern));
mgl@1371
  7595
+
mgl@1371
  7596
+            rtx clobber = gen_rtx_CLOBBER (mode, scratch_reg);
mgl@1371
  7597
+            rtx vec[2] = { COND_EXEC_CODE (new_pattern), clobber };
mgl@1371
  7598
+            COND_EXEC_CODE (new_pattern) = gen_rtx_PARALLEL (mode, gen_rtvec_v (2, vec));
mgl@1371
  7599
+
mgl@1371
  7600
+            start_sequence ();
mgl@1371
  7601
+            clobber_insn = emit_insn (new_pattern);
mgl@1371
  7602
+
mgl@1371
  7603
+            if ( recog_memoized (clobber_insn) >= 0
mgl@1371
  7604
+                 && ( ( GET_RTX_LENGTH (GET_CODE (set_src)) == 2
mgl@1371
  7605
+                        && CONST_INT_P (XEXP (set_src, 1))
mgl@1371
  7606
+                        && avr32_const_ok_for_constraint_p (INTVAL (XEXP (set_src, 1)), 'K', "Ks08") )
mgl@1371
  7607
+                      || !ce_info->else_bb
mgl@1371
  7608
+                      || current_bb->index == ce_info->else_bb->index ))
mgl@1371
  7609
+              {
mgl@1371
  7610
+                end_sequence ();
mgl@1371
  7611
+                /* Force the insn to be recognized again. */
mgl@1371
  7612
+                INSN_CODE (insn) = -1;
mgl@1371
  7613
+
mgl@1371
  7614
+                /* If this is the first change in this IF-block then
mgl@1371
  7615
+                   signal that we have made a change. */
mgl@1371
  7616
+                if ( ce_info->num_cond_clobber_insns == 0
mgl@1371
  7617
+                     && ce_info->num_extra_move_insns == 0 )
mgl@1371
  7618
+                  *num_true_changes += 1;
mgl@1371
  7619
+
mgl@1371
  7620
+                ce_info->num_cond_clobber_insns++;
mgl@1371
  7621
+
mgl@1371
  7622
+                if (dump_file)
mgl@1371
  7623
+                  fprintf (dump_file,
mgl@1371
  7624
+                           "\nReplacing INSN %d with an insn using a scratch register for later ifcvt passes...\n",
mgl@1371
  7625
+                           INSN_UID (insn));
mgl@1371
  7626
+
mgl@1371
  7627
+                return COND_EXEC_CODE (new_pattern);
mgl@1371
  7628
+              }
mgl@1371
  7629
+            end_sequence ();
mgl@1371
  7630
+          }
mgl@1371
  7631
+
mgl@1371
  7632
+          if ( inputs_set_outside_ifblock )
mgl@1371
  7633
+            {
mgl@1371
  7634
+              /* Check if the insn before the cmp is an and which used
mgl@1371
  7635
+                 together with the cmp can be optimized into a bld. If
mgl@1371
  7636
+                 so then we should try to put the insn before the and
mgl@1371
  7637
+                 so that we can catch the bld peephole. */
mgl@1371
  7638
+              rtx set;
mgl@1371
  7639
+              rtx insn_before_cmp_insn = prev_nonnote_insn (cmp_insn);
mgl@1371
  7640
+              if (insn_before_cmp_insn
mgl@1371
  7641
+                  && (set = single_set (insn_before_cmp_insn))
mgl@1371
  7642
+                  && GET_CODE (SET_SRC (set)) == AND
mgl@1371
  7643
+                  && one_bit_set_operand (XEXP (SET_SRC (set), 1), SImode)
mgl@1371
  7644
+                  /* Also make sure that the insn does not set any
mgl@1371
  7645
+                     of the input operands to the insn we are pulling out. */
mgl@1371
  7646
+                  && !reg_mentioned_p (SET_DEST (set), SET_SRC (op)) )
mgl@1371
  7647
+                cmp_insn = prev_nonnote_insn (cmp_insn);
mgl@1371
  7648
+
mgl@1371
  7649
+              /* We can try to put the operation outside the if-then-else
mgl@1371
  7650
+                 blocks and insert a move. */
mgl@1371
  7651
+              if ( !insn_invalid_p (insn)
mgl@1371
  7652
+                   /* Do not allow conditional insns to be moved outside the
mgl@1371
  7653
+                      if-then-else. */
mgl@1371
  7654
+                   && !reg_mentioned_p (cc0_rtx, insn)
mgl@1371
  7655
+                   /* We cannot move memory loads outside of the if-then-else
mgl@1371
  7656
+                      since the memory access should not be perfomed if the
mgl@1371
  7657
+                      condition is not met. */
mgl@1371
  7658
+                   && !mem_mentioned_p (SET_SRC (op)) )
mgl@1371
  7659
+                {
mgl@1371
  7660
+                  rtx scratch_reg = gen_reg_rtx (mode);
mgl@1371
  7661
+                  rtx op_pattern = copy_rtx (op);
mgl@1371
  7662
+                  rtx new_insn, seq;
mgl@1371
  7663
+                  rtx link, prev_link;
mgl@1371
  7664
+                  op = copy_rtx (op);
mgl@1371
  7665
+                  /* Emit the operation to a temp reg before the compare,
mgl@1371
  7666
+                     and emit a move inside the if-then-else, hoping that the
mgl@1371
  7667
+                     whole if-then-else can be converted to conditional
mgl@1371
  7668
+                     execution. */
mgl@1371
  7669
+                  SET_DEST (op_pattern) = scratch_reg;
mgl@1371
  7670
+                  start_sequence ();
mgl@1371
  7671
+                  new_insn = emit_insn (op_pattern);
mgl@1371
  7672
+                  seq = get_insns();
mgl@1371
  7673
+                  end_sequence ();
mgl@1371
  7674
+
mgl@1371
  7675
+                  /* Check again that the insn is valid. For some insns the insn might
mgl@1371
  7676
+                     become invalid if the destination register is changed. Ie. for mulacc
mgl@1371
  7677
+                     operations. */
mgl@1371
  7678
+                  if ( insn_invalid_p (new_insn) )
mgl@1371
  7679
+                    return NULL_RTX;
mgl@1371
  7680
+
mgl@1371
  7681
+                  emit_insn_before_setloc (seq, cmp_insn, INSN_LOCATOR (insn));
mgl@1371
  7682
+
mgl@1371
  7683
+                  if (dump_file)
mgl@1371
  7684
+                    fprintf (dump_file,
mgl@1371
  7685
+                             "\nMoving INSN %d out of IF-block by adding INSN %d...\n",
mgl@1371
  7686
+                             INSN_UID (insn), INSN_UID (new_insn));
mgl@1371
  7687
+
mgl@1371
  7688
+                  ce_info->extra_move_insns[ce_info->num_extra_move_insns] = insn;
mgl@1371
  7689
+                  ce_info->moved_insns[ce_info->num_extra_move_insns] = new_insn;
mgl@1371
  7690
+                  XEXP (op, 1) = scratch_reg;
mgl@1371
  7691
+                  /* Force the insn to be recognized again. */
mgl@1371
  7692
+                  INSN_CODE (insn) = -1;
mgl@1371
  7693
+
mgl@1371
  7694
+                  /* Move REG_DEAD notes to the moved insn. */
mgl@1371
  7695
+                  prev_link = NULL_RTX;
mgl@1371
  7696
+                  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
mgl@1371
  7697
+                    {
mgl@1371
  7698
+                      if (REG_NOTE_KIND (link) == REG_DEAD)
mgl@1371
  7699
+                        {
mgl@1371
  7700
+                          /* Add the REG_DEAD note to the new insn. */
mgl@1371
  7701
+                          rtx dead_reg = XEXP (link, 0);
mgl@1371
  7702
+                          REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_DEAD, dead_reg, REG_NOTES (new_insn));
mgl@1371
  7703
+                          /* Remove the REG_DEAD note from the insn we convert to a move. */
mgl@1371
  7704
+                          if ( prev_link )
mgl@1371
  7705
+                            XEXP (prev_link, 1) = XEXP (link, 1);
mgl@1371
  7706
+                          else
mgl@1371
  7707
+                            REG_NOTES (insn) = XEXP (link, 1);
mgl@1371
  7708
+                        }
mgl@1371
  7709
+                      else
mgl@1371
  7710
+                        {
mgl@1371
  7711
+                          prev_link = link;
mgl@1371
  7712
+                        }
mgl@1371
  7713
+                    }
mgl@1371
  7714
+                  /* Add a REG_DEAD note to signal that the scratch register is dead. */
mgl@1371
  7715
+                  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, scratch_reg, REG_NOTES (insn));
mgl@1371
  7716
+
mgl@1371
  7717
+                  /* If this is the first change in this IF-block then
mgl@1371
  7718
+                     signal that we have made a change. */
mgl@1371
  7719
+                  if ( ce_info->num_cond_clobber_insns == 0
mgl@1371
  7720
+                       && ce_info->num_extra_move_insns == 0 )
mgl@1371
  7721
+                    *num_true_changes += 1;
mgl@1371
  7722
+
mgl@1371
  7723
+                  ce_info->num_extra_move_insns++;
mgl@1371
  7724
+                  return op;
mgl@1371
  7725
+                }
mgl@1371
  7726
+            }
mgl@1371
  7727
+
mgl@1371
  7728
+          /* We failed to fixup the insns, so this if-then-else can not be made
mgl@1371
  7729
+             conditional. Just return NULL_RTX so that the if-then-else conversion
mgl@1371
  7730
+             for this if-then-else will be cancelled. */
mgl@1371
  7731
+          return NULL_RTX;
mgl@1371
  7732
+        }
mgl@1371
  7733
+      end_sequence ();
mgl@1371
  7734
+      return op;
mgl@1371
  7735
+    }
mgl@1371
  7736
+
mgl@1371
  7737
+  /* Signal that we have started if conversion after reload, which means
mgl@1371
  7738
+     that it should be safe to split all the predicable clobber insns which
mgl@1371
  7739
+     did not become cond_exec back into a simpler form if possible. */
mgl@1371
  7740
+  cfun->machine->ifcvt_after_reload = 1;
mgl@1371
  7741
+
mgl@1371
  7742
+  return pattern;
mgl@1371
  7743
+}
mgl@1371
  7744
+
mgl@1371
  7745
+
mgl@1371
  7746
+void
mgl@1371
  7747
+avr32_ifcvt_modify_cancel ( ce_if_block_t *ce_info,
mgl@1371
  7748
+                            int *num_true_changes)
mgl@1371
  7749
+{
mgl@1371
  7750
+  int n;
mgl@1371
  7751
+
mgl@1371
  7752
+  if ( ce_info->num_extra_move_insns > 0
mgl@1371
  7753
+       && ce_info->num_cond_clobber_insns == 0)
mgl@1371
  7754
+    /* Signal that we did not do any changes after all. */
mgl@1371
  7755
+    *num_true_changes -= 1;
mgl@1371
  7756
+
mgl@1371
  7757
+  /* Remove any inserted move insns. */
mgl@1371
  7758
+  for ( n = 0; n < ce_info->num_extra_move_insns; n++ )
mgl@1371
  7759
+    {
mgl@1371
  7760
+      rtx link, prev_link;
mgl@1371
  7761
+
mgl@1371
  7762
+      /* Remove REG_DEAD note since we are not needing the scratch register anyway. */
mgl@1371
  7763
+      prev_link = NULL_RTX;
mgl@1371
  7764
+      for (link = REG_NOTES (ce_info->extra_move_insns[n]); link; link = XEXP (link, 1))
mgl@1371
  7765
+        {
mgl@1371
  7766
+          if (REG_NOTE_KIND (link) == REG_DEAD)
mgl@1371
  7767
+            {
mgl@1371
  7768
+              if ( prev_link )
mgl@1371
  7769
+                XEXP (prev_link, 1) = XEXP (link, 1);
mgl@1371
  7770
+              else
mgl@1371
  7771
+                REG_NOTES (ce_info->extra_move_insns[n]) = XEXP (link, 1);
mgl@1371
  7772
+            }
mgl@1371
  7773
+          else
mgl@1371
  7774
+            {
mgl@1371
  7775
+              prev_link = link;
mgl@1371
  7776
+            }
mgl@1371
  7777
+        }
mgl@1371
  7778
+
mgl@1371
  7779
+      /* Revert all reg_notes for the moved insn. */
mgl@1371
  7780
+      for (link = REG_NOTES (ce_info->moved_insns[n]); link; link = XEXP (link, 1))
mgl@1371
  7781
+        {
mgl@1371
  7782
+          REG_NOTES (ce_info->extra_move_insns[n]) = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
mgl@1371
  7783
+                                                                        XEXP (link, 0),
mgl@1371
  7784
+                                                                        REG_NOTES (ce_info->extra_move_insns[n]));
mgl@1371
  7785
+        }
mgl@1371
  7786
+
mgl@1371
  7787
+      /* Remove the moved insn. */
mgl@1371
  7788
+      remove_insn ( ce_info->moved_insns[n] );
mgl@1371
  7789
+    }
mgl@1371
  7790
+}
mgl@1371
  7791
+
mgl@1371
  7792
+/* Function returning TRUE if INSN with OPERANDS is a splittable
mgl@1371
  7793
+   conditional immediate clobber insn. We assume that the insn is
mgl@1371
  7794
+   already a conditional immediate clobber insns and do not check
mgl@1371
  7795
+   for that. */
mgl@1371
  7796
+int
mgl@1371
  7797
+avr32_cond_imm_clobber_splittable (rtx insn,
mgl@1371
  7798
+                                   rtx operands[])
mgl@1371
  7799
+{
mgl@1371
  7800
+  if ( (REGNO (operands[0]) != REGNO (operands[1]))
mgl@1371
  7801
+       && (logical_binary_operator (SET_SRC (XVECEXP (PATTERN (insn),0,0)), VOIDmode)
mgl@1371
  7802
+           || (GET_CODE (SET_SRC (XVECEXP (PATTERN (insn),0,0))) == PLUS
mgl@1371
  7803
+               && !avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'I', "Is16"))
mgl@1371
  7804
+           || (GET_CODE (SET_SRC (XVECEXP (PATTERN (insn),0,0))) == MINUS
mgl@1371
  7805
+               && !avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks16"))) )
mgl@1371
  7806
+    return FALSE;
mgl@1371
  7807
+
mgl@1371
  7808
+  return TRUE;
mgl@1371
  7809
+}
mgl@1371
  7810
+
mgl@1371
  7811
+/* Function for getting an integer value from a const_int or const_double
mgl@1371
  7812
+   expression regardless of the HOST_WIDE_INT size. Each target cpu word
mgl@1371
  7813
+   will be put into the val array where the LSW will be stored at the lowest
mgl@1371
  7814
+   address and so forth. Assumes that const_expr is either a const_int or
mgl@1371
  7815
+   const_double. Only valid for modes which have sizes that are a multiple
mgl@1371
  7816
+   of the word size.
mgl@1371
  7817
+*/
mgl@1371
  7818
+void
mgl@1371
  7819
+avr32_get_intval (enum machine_mode mode,
mgl@1371
  7820
+                  rtx const_expr,
mgl@1371
  7821
+                  HOST_WIDE_INT *val)
mgl@1371
  7822
+{
mgl@1371
  7823
+  int words_in_mode = GET_MODE_SIZE (mode)/UNITS_PER_WORD;
mgl@1371
  7824
+  const int words_in_const_int = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
mgl@1371
  7825
+
mgl@1371
  7826
+  if ( GET_CODE(const_expr) == CONST_DOUBLE ){
mgl@1371
  7827
+    HOST_WIDE_INT hi = CONST_DOUBLE_HIGH(const_expr);
mgl@1371
  7828
+    HOST_WIDE_INT lo = CONST_DOUBLE_LOW(const_expr);
mgl@1371
  7829
+    /* Evaluate hi and lo values of const_double. */
mgl@1371
  7830
+    avr32_get_intval (mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0),
mgl@1371
  7831
+                      GEN_INT (lo),
mgl@1371
  7832
+                      &val[0]);
mgl@1371
  7833
+    avr32_get_intval (mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0),
mgl@1371
  7834
+                      GEN_INT (hi),
mgl@1371
  7835
+                      &val[words_in_const_int]);
mgl@1371
  7836
+  } else if ( GET_CODE(const_expr) == CONST_INT ){
mgl@1371
  7837
+    HOST_WIDE_INT value = INTVAL(const_expr);
mgl@1371
  7838
+    int word;
mgl@1371
  7839
+    for ( word = 0; (word < words_in_mode) && (word < words_in_const_int); word++ ){
mgl@1371
  7840
+      /* Shift word up to the MSW and shift down again to extract the
mgl@1371
  7841
+         word and sign-extend. */
mgl@1371
  7842
+      int lshift = (words_in_const_int - word - 1) * BITS_PER_WORD;
mgl@1371
  7843
+      int rshift = (words_in_const_int-1) * BITS_PER_WORD;
mgl@1371
  7844
+      val[word] = (value << lshift) >> rshift;
mgl@1371
  7845
+    }
mgl@1371
  7846
+
mgl@1371
  7847
+    for ( ; word < words_in_mode; word++ ){
mgl@1371
  7848
+      /* Just put the sign bits in the remaining words. */
mgl@1371
  7849
+      val[word] = value < 0 ? -1 : 0;
mgl@1371
  7850
+    }
mgl@1371
  7851
+  }
mgl@1371
  7852
+}
mgl@1371
  7853
+
mgl@1371
  7854
+void
mgl@1371
  7855
+avr32_split_const_expr (enum machine_mode mode,
mgl@1371
  7856
+                        enum machine_mode new_mode,
mgl@1371
  7857
+                        rtx expr,
mgl@1371
  7858
+                        rtx *split_expr)
mgl@1371
  7859
+{
mgl@1371
  7860
+  int i, word;
mgl@1371
  7861
+  int words_in_intval = GET_MODE_SIZE (mode)/UNITS_PER_WORD;
mgl@1371
  7862
+  int words_in_split_values = GET_MODE_SIZE (new_mode)/UNITS_PER_WORD;
mgl@1371
  7863
+  const int words_in_const_int = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
mgl@1371
  7864
+  HOST_WIDE_INT *val = alloca (words_in_intval * UNITS_PER_WORD);
mgl@1371
  7865
+
mgl@1371
  7866
+  avr32_get_intval (mode, expr, val);
mgl@1371
  7867
+
mgl@1371
  7868
+  for ( i=0; i < (words_in_intval/words_in_split_values); i++ )
mgl@1371
  7869
+    {
mgl@1371
  7870
+      HOST_WIDE_INT value_lo = 0, value_hi = 0;
mgl@1371
  7871
+      for ( word = 0; word < words_in_split_values; word++ )
mgl@1371
  7872
+        {
mgl@1371
  7873
+          if ( word >= words_in_const_int )
mgl@1371
  7874
+            value_hi |= ((val[i * words_in_split_values + word] &
mgl@1371
  7875
+                          (((HOST_WIDE_INT)1 << BITS_PER_WORD)-1))
mgl@1371
  7876
+                         << (BITS_PER_WORD * (word - words_in_const_int)));
mgl@1371
  7877
+          else
mgl@1371
  7878
+            value_lo |= ((val[i * words_in_split_values + word] &
mgl@1371
  7879
+                          (((HOST_WIDE_INT)1 << BITS_PER_WORD)-1))
mgl@1371
  7880
+                         << (BITS_PER_WORD * word));
mgl@1371
  7881
+        }
mgl@1371
  7882
+      split_expr[i] = immed_double_const(value_lo, value_hi, new_mode);
mgl@1371
  7883
+    }
mgl@1371
  7884
+}
mgl@1371
  7885
+
mgl@1371
  7886
+
mgl@1371
  7887
+/* Set up library functions to comply to AVR32 ABI  */
mgl@1371
  7888
+
mgl@1371
  7889
+static void
mgl@1371
  7890
+avr32_init_libfuncs (void)
mgl@1371
  7891
+{
mgl@1371
  7892
+  /* Convert gcc run-time function names to AVR32 ABI names */
mgl@1371
  7893
+
mgl@1371
  7894
+  /* Double-precision floating-point arithmetic. */
mgl@1371
  7895
+  set_optab_libfunc (neg_optab, DFmode, NULL);
mgl@1371
  7896
+
mgl@1371
  7897
+  /* Double-precision comparisons.  */
mgl@1371
  7898
+  set_optab_libfunc (eq_optab, DFmode, "__avr32_f64_cmp_eq");
mgl@1371
  7899
+  set_optab_libfunc (ne_optab, DFmode, NULL);
mgl@1371
  7900
+  set_optab_libfunc (lt_optab, DFmode, "__avr32_f64_cmp_lt");
mgl@1371
  7901
+  set_optab_libfunc (le_optab, DFmode, NULL);
mgl@1371
  7902
+  set_optab_libfunc (ge_optab, DFmode, "__avr32_f64_cmp_ge");
mgl@1371
  7903
+  set_optab_libfunc (gt_optab, DFmode, NULL);
mgl@1371
  7904
+
mgl@1371
  7905
+  /* Single-precision floating-point arithmetic. */
mgl@1371
  7906
+  set_optab_libfunc (smul_optab, SFmode, "__avr32_f32_mul");
mgl@1371
  7907
+  set_optab_libfunc (neg_optab, SFmode, NULL);
mgl@1371
  7908
+
mgl@1371
  7909
+  /* Single-precision comparisons.  */
mgl@1371
  7910
+  set_optab_libfunc (eq_optab, SFmode, "__avr32_f32_cmp_eq");
mgl@1371
  7911
+  set_optab_libfunc (ne_optab, SFmode, NULL);
mgl@1371
  7912
+  set_optab_libfunc (lt_optab, SFmode, "__avr32_f32_cmp_lt");
mgl@1371
  7913
+  set_optab_libfunc (le_optab, SFmode, NULL);
mgl@1371
  7914
+  set_optab_libfunc (ge_optab, SFmode, "__avr32_f32_cmp_ge");
mgl@1371
  7915
+  set_optab_libfunc (gt_optab, SFmode, NULL);
mgl@1371
  7916
+
mgl@1371
  7917
+  /* Floating-point to integer conversions. */
mgl@1371
  7918
+  set_conv_libfunc (sfix_optab, SImode, DFmode, "__avr32_f64_to_s32");
mgl@1371
  7919
+  set_conv_libfunc (ufix_optab, SImode, DFmode, "__avr32_f64_to_u32");
mgl@1371
  7920
+  set_conv_libfunc (sfix_optab, DImode, DFmode, "__avr32_f64_to_s64");
mgl@1371
  7921
+  set_conv_libfunc (ufix_optab, DImode, DFmode, "__avr32_f64_to_u64");
mgl@1371
  7922
+  set_conv_libfunc (sfix_optab, SImode, SFmode, "__avr32_f32_to_s32");
mgl@1371
  7923
+  set_conv_libfunc (ufix_optab, SImode, SFmode, "__avr32_f32_to_u32");
mgl@1371
  7924
+  set_conv_libfunc (sfix_optab, DImode, SFmode, "__avr32_f32_to_s64");
mgl@1371
  7925
+  set_conv_libfunc (ufix_optab, DImode, SFmode, "__avr32_f32_to_u64");
mgl@1371
  7926
+
mgl@1371
  7927
+  /* Conversions between floating types.  */
mgl@1371
  7928
+  set_conv_libfunc (trunc_optab, SFmode, DFmode, "__avr32_f64_to_f32");
mgl@1371
  7929
+  set_conv_libfunc (sext_optab, DFmode, SFmode, "__avr32_f32_to_f64");
mgl@1371
  7930
+
mgl@1371
  7931
+  /* Integer to floating-point conversions.  Table 8.  */
mgl@1371
  7932
+  set_conv_libfunc (sfloat_optab, DFmode, SImode, "__avr32_s32_to_f64");
mgl@1371
  7933
+  set_conv_libfunc (sfloat_optab, DFmode, DImode, "__avr32_s64_to_f64");
mgl@1371
  7934
+  set_conv_libfunc (sfloat_optab, SFmode, SImode, "__avr32_s32_to_f32");
mgl@1371
  7935
+  set_conv_libfunc (sfloat_optab, SFmode, DImode, "__avr32_s64_to_f32");
mgl@1371
  7936
+  set_conv_libfunc (ufloat_optab, DFmode, SImode, "__avr32_u32_to_f64");
mgl@1371
  7937
+  set_conv_libfunc (ufloat_optab, SFmode, SImode, "__avr32_u32_to_f32");
mgl@1371
  7938
+  /* TODO: Add these to gcc library functions */
mgl@1371
  7939
+  //set_conv_libfunc (ufloat_optab, DFmode, DImode, NULL);
mgl@1371
  7940
+  //set_conv_libfunc (ufloat_optab, SFmode, DImode, NULL);
mgl@1371
  7941
+
mgl@1371
  7942
+  /* Long long.  Table 9.  */
mgl@1371
  7943
+  set_optab_libfunc (smul_optab, DImode, "__avr32_mul64");
mgl@1371
  7944
+  set_optab_libfunc (sdiv_optab, DImode, "__avr32_sdiv64");
mgl@1371
  7945
+  set_optab_libfunc (udiv_optab, DImode, "__avr32_udiv64");
mgl@1371
  7946
+  set_optab_libfunc (smod_optab, DImode, "__avr32_smod64");
mgl@1371
  7947
+  set_optab_libfunc (umod_optab, DImode, "__avr32_umod64");
mgl@1371
  7948
+  set_optab_libfunc (ashl_optab, DImode, "__avr32_lsl64");
mgl@1371
  7949
+  set_optab_libfunc (lshr_optab, DImode, "__avr32_lsr64");
mgl@1371
  7950
+  set_optab_libfunc (ashr_optab, DImode, "__avr32_asr64");
mgl@1371
  7951
+
mgl@1371
  7952
+  /* Floating point library functions which have fast versions. */
mgl@1371
  7953
+  if ( TARGET_FAST_FLOAT )
mgl@1371
  7954
+    {
mgl@1371
  7955
+      set_optab_libfunc (sdiv_optab, DFmode, "__avr32_f64_div_fast");
mgl@1371
  7956
+      set_optab_libfunc (smul_optab, DFmode, "__avr32_f64_mul_fast");
mgl@1371
  7957
+      set_optab_libfunc (add_optab, DFmode, "__avr32_f64_add_fast");
mgl@1371
  7958
+      set_optab_libfunc (sub_optab, DFmode, "__avr32_f64_sub_fast");
mgl@1371
  7959
+      set_optab_libfunc (add_optab, SFmode, "__avr32_f32_add_fast");
mgl@1371
  7960
+      set_optab_libfunc (sub_optab, SFmode, "__avr32_f32_sub_fast");
mgl@1371
  7961
+      set_optab_libfunc (sdiv_optab, SFmode, "__avr32_f32_div_fast");
mgl@1371
  7962
+    }
mgl@1371
  7963
+  else
mgl@1371
  7964
+    {
mgl@1371
  7965
+      set_optab_libfunc (sdiv_optab, DFmode, "__avr32_f64_div");
mgl@1371
  7966
+      set_optab_libfunc (smul_optab, DFmode, "__avr32_f64_mul");
mgl@1371
  7967
+      set_optab_libfunc (add_optab, DFmode, "__avr32_f64_add");
mgl@1371
  7968
+      set_optab_libfunc (sub_optab, DFmode, "__avr32_f64_sub");
mgl@1371
  7969
+      set_optab_libfunc (add_optab, SFmode, "__avr32_f32_add");
mgl@1371
  7970
+      set_optab_libfunc (sub_optab, SFmode, "__avr32_f32_sub");
mgl@1371
  7971
+      set_optab_libfunc (sdiv_optab, SFmode, "__avr32_f32_div");
mgl@1371
  7972
+    }
mgl@1371
  7973
+}
mgl@1371
  7974
--- /dev/null
mgl@1371
  7975
+++ b/gcc/config/avr32/avr32-elf.h
mgl@1371
  7976
@@ -0,0 +1,84 @@
mgl@1371
  7977
+/*
mgl@1371
  7978
+   Elf specific definitions.
mgl@1371
  7979
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
  7980
+
mgl@1371
  7981
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
  7982
+
mgl@1371
  7983
+   This file is part of GCC.
mgl@1371
  7984
+
mgl@1371
  7985
+   This program is free software; you can redistribute it and/or modify
mgl@1371
  7986
+   it under the terms of the GNU General Public License as published by
mgl@1371
  7987
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
  7988
+   (at your option) any later version.
mgl@1371
  7989
+
mgl@1371
  7990
+   This program is distributed in the hope that it will be useful,
mgl@1371
  7991
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
  7992
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
  7993
+   GNU General Public License for more details.
mgl@1371
  7994
+
mgl@1371
  7995
+   You should have received a copy of the GNU General Public License
mgl@1371
  7996
+   along with this program; if not, write to the Free Software
mgl@1371
  7997
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
  7998
+
mgl@1371
  7999
+
mgl@1371
  8000
+/*****************************************************************************
mgl@1371
  8001
+ * Controlling the Compilator Driver, 'gcc'
mgl@1371
  8002
+ *****************************************************************************/
mgl@1371
  8003
+
mgl@1371
  8004
+/* Run-time Target Specification.  */
mgl@1371
  8005
+#undef  TARGET_VERSION
mgl@1371
  8006
+#define TARGET_VERSION  fputs (" (AVR32 GNU with ELF)", stderr);
mgl@1371
  8007
+
mgl@1371
  8008
+/*
mgl@1371
  8009
+Another C string constant used much like LINK_SPEC.  The
mgl@1371
  8010
+difference between the two is that STARTFILE_SPEC is used at
mgl@1371
  8011
+the very beginning of the command given to the linker.
mgl@1371
  8012
+
mgl@1371
  8013
+If this macro is not defined, a default is provided that loads the
mgl@1371
  8014
+standard C startup file from the usual place.  See gcc.c.
mgl@1371
  8015
+*/
mgl@1371
  8016
+#undef  STARTFILE_SPEC
mgl@1371
  8017
+#define STARTFILE_SPEC "crt0%O%s crti%O%s crtbegin%O%s"
mgl@1371
  8018
+
mgl@1371
  8019
+#undef LINK_SPEC
mgl@1371
  8020
+#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_%*}"
mgl@1371
  8021
+
mgl@1371
  8022
+
mgl@1371
  8023
+/*
mgl@1371
  8024
+Another C string constant used much like LINK_SPEC.  The
mgl@1371
  8025
+difference between the two is that ENDFILE_SPEC is used at
mgl@1371
  8026
+the very end of the command given to the linker.
mgl@1371
  8027
+
mgl@1371
  8028
+Do not define this macro if it does not need to do anything.
mgl@1371
  8029
+*/
mgl@1371
  8030
+#undef  ENDFILE_SPEC
mgl@1371
  8031
+#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
mgl@1371
  8032
+
mgl@1371
  8033
+
mgl@1371
  8034
+/* Target CPU builtins.  */
mgl@1371
  8035
+#define TARGET_CPU_CPP_BUILTINS()				\
mgl@1371
  8036
+  do								\
mgl@1371
  8037
+    {								\
mgl@1371
  8038
+      builtin_define ("__avr32__");				\
mgl@1371
  8039
+      builtin_define ("__AVR32__");				\
mgl@1371
  8040
+      builtin_define ("__AVR32_ELF__");	       	        	\
mgl@1371
  8041
+      builtin_define (avr32_part->macro);			\
mgl@1371
  8042
+      builtin_define (avr32_arch->macro);			\
mgl@1371
  8043
+      if (avr32_arch->uarch_type == UARCH_TYPE_AVR32A)		\
mgl@1371
  8044
+	builtin_define ("__AVR32_AVR32A__");			\
mgl@1371
  8045
+      else							\
mgl@1371
  8046
+	builtin_define ("__AVR32_AVR32B__");			\
mgl@1371
  8047
+      if (TARGET_UNALIGNED_WORD)				\
mgl@1371
  8048
+	builtin_define ("__AVR32_HAS_UNALIGNED_WORD__");	\
mgl@1371
  8049
+      if (TARGET_SIMD)						\
mgl@1371
  8050
+	builtin_define ("__AVR32_HAS_SIMD__");			\
mgl@1371
  8051
+      if (TARGET_DSP)						\
mgl@1371
  8052
+	builtin_define ("__AVR32_HAS_DSP__");			\
mgl@1371
  8053
+      if (TARGET_RMW)						\
mgl@1371
  8054
+	builtin_define ("__AVR32_HAS_RMW__");			\
mgl@1371
  8055
+      if (TARGET_BRANCH_PRED)					\
mgl@1371
  8056
+	builtin_define ("__AVR32_HAS_BRANCH_PRED__");		\
mgl@1371
  8057
+      if (TARGET_FAST_FLOAT)                                    \
mgl@1371
  8058
+        builtin_define ("__AVR32_FAST_FLOAT__");                \
mgl@1371
  8059
+    }								\
mgl@1371
  8060
+  while (0)
mgl@1371
  8061
--- /dev/null
mgl@1371
  8062
+++ b/gcc/config/avr32/avr32.h
mgl@1371
  8063
@@ -0,0 +1,3347 @@
mgl@1371
  8064
+/*
mgl@1371
  8065
+   Definitions of target machine for AVR32.
mgl@1371
  8066
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
  8067
+
mgl@1371
  8068
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
  8069
+   Initial porting by Anders �dland.
mgl@1371
  8070
+
mgl@1371
  8071
+   This file is part of GCC.
mgl@1371
  8072
+
mgl@1371
  8073
+   This program is free software; you can redistribute it and/or modify
mgl@1371
  8074
+   it under the terms of the GNU General Public License as published by
mgl@1371
  8075
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
  8076
+   (at your option) any later version.
mgl@1371
  8077
+
mgl@1371
  8078
+   This program is distributed in the hope that it will be useful,
mgl@1371
  8079
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
  8080
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
  8081
+   GNU General Public License for more details.
mgl@1371
  8082
+
mgl@1371
  8083
+   You should have received a copy of the GNU General Public License
mgl@1371
  8084
+   along with this program; if not, write to the Free Software
mgl@1371
  8085
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
  8086
+
mgl@1371
  8087
+#ifndef GCC_AVR32_H
mgl@1371
  8088
+#define GCC_AVR32_H
mgl@1371
  8089
+
mgl@1371
  8090
+
mgl@1371
  8091
+#ifndef OBJECT_FORMAT_ELF
mgl@1371
  8092
+#error avr32.h included before elfos.h
mgl@1371
  8093
+#endif
mgl@1371
  8094
+
mgl@1371
  8095
+#ifndef LOCAL_LABEL_PREFIX
mgl@1371
  8096
+#define LOCAL_LABEL_PREFIX "."
mgl@1371
  8097
+#endif
mgl@1371
  8098
+
mgl@1371
  8099
+#ifndef SUBTARGET_CPP_SPEC
mgl@1371
  8100
+#define SUBTARGET_CPP_SPEC  "-D__ELF__"
mgl@1371
  8101
+#endif
mgl@1371
  8102
+
mgl@1371
  8103
+
mgl@1371
  8104
+extern struct rtx_def *avr32_compare_op0;
mgl@1371
  8105
+extern struct rtx_def *avr32_compare_op1;
mgl@1371
  8106
+
mgl@1371
  8107
+
mgl@1371
  8108
+extern struct rtx_def *avr32_acc_cache;
mgl@1371
  8109
+
mgl@1371
  8110
+/* cache instruction op5 codes */
mgl@1371
  8111
+#define AVR32_CACHE_INVALIDATE_ICACHE 1
mgl@1371
  8112
+
mgl@1371
  8113
+/* These bits describe the different types of function supported
mgl@1371
  8114
+   by the AVR32 backend.  They are exclusive.  ie a function cannot be both a
mgl@1371
  8115
+   normal function and an interworked function, for example.  Knowing the
mgl@1371
  8116
+   type of a function is important for determining its prologue and
mgl@1371
  8117
+   epilogue sequences.
mgl@1371
  8118
+   Note value 7 is currently unassigned.  Also note that the interrupt
mgl@1371
  8119
+   function types all have bit 2 set, so that they can be tested for easily.
mgl@1371
  8120
+   Note that 0 is deliberately chosen for AVR32_FT_UNKNOWN so that when the
mgl@1371
  8121
+   machine_function structure is initialized (to zero) func_type will
mgl@1371
  8122
+   default to unknown.  This will force the first use of avr32_current_func_type
mgl@1371
  8123
+   to call avr32_compute_func_type.  */
mgl@1371
  8124
+#define AVR32_FT_UNKNOWN	 0	/* Type has not yet been determined.
mgl@1371
  8125
+					   */
mgl@1371
  8126
+#define AVR32_FT_NORMAL		 1	/* Your normal, straightforward
mgl@1371
  8127
+					   function.  */
mgl@1371
  8128
+#define AVR32_FT_ACALL	         2	/* An acall function.  */
mgl@1371
  8129
+#define AVR32_FT_EXCEPTION_HANDLER 3	/* A C++ exception handler.  */
mgl@1371
  8130
+#define AVR32_FT_ISR_FULL	 4	/* A fully shadowed interrupt mode.  */
mgl@1371
  8131
+#define AVR32_FT_ISR_HALF	 5	/* A half shadowed interrupt mode.  */
mgl@1371
  8132
+#define AVR32_FT_ISR_NONE	 6	/* No shadow registers.  */
mgl@1371
  8133
+
mgl@1371
  8134
+#define AVR32_FT_TYPE_MASK	((1 << 3) - 1)
mgl@1371
  8135
+
mgl@1371
  8136
+/* In addition functions can have several type modifiers,
mgl@1371
  8137
+   outlined by these bit masks:  */
mgl@1371
  8138
+#define AVR32_FT_INTERRUPT	(1 << 2)	/* Note overlap with FT_ISR
mgl@1371
  8139
+						   and above.  */
mgl@1371
  8140
+#define AVR32_FT_NAKED		(1 << 3)	/* No prologue or epilogue.  */
mgl@1371
  8141
+#define AVR32_FT_VOLATILE	(1 << 4)	/* Does not return.  */
mgl@1371
  8142
+#define AVR32_FT_NESTED		(1 << 5)	/* Embedded inside another
mgl@1371
  8143
+						   func. */
mgl@1371
  8144
+
mgl@1371
  8145
+/* Some macros to test these flags.  */
mgl@1371
  8146
+#define AVR32_FUNC_TYPE(t)	(t & AVR32_FT_TYPE_MASK)
mgl@1371
  8147
+#define IS_INTERRUPT(t)		(t & AVR32_FT_INTERRUPT)
mgl@1371
  8148
+#define IS_VOLATILE(t)     	(t & AVR32_FT_VOLATILE)
mgl@1371
  8149
+#define IS_NAKED(t)        	(t & AVR32_FT_NAKED)
mgl@1371
  8150
+#define IS_NESTED(t)       	(t & AVR32_FT_NESTED)
mgl@1371
  8151
+
mgl@1371
  8152
+#define SYMBOL_FLAG_RMW_ADDR_SHIFT    SYMBOL_FLAG_MACH_DEP_SHIFT
mgl@1371
  8153
+#define SYMBOL_REF_RMW_ADDR(RTX)                                        \
mgl@1371
  8154
+  ((SYMBOL_REF_FLAGS (RTX) & (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT)) != 0)
mgl@1371
  8155
+
mgl@1371
  8156
+
mgl@1371
  8157
+typedef struct minipool_labels
mgl@1371
  8158
+GTY ((chain_next ("%h.next"), chain_prev ("%h.prev")))
mgl@1371
  8159
+{
mgl@1371
  8160
+  rtx label;
mgl@1371
  8161
+  struct minipool_labels *prev;
mgl@1371
  8162
+  struct minipool_labels *next;
mgl@1371
  8163
+} minipool_labels;
mgl@1371
  8164
+
mgl@1371
  8165
+/* A C structure for machine-specific, per-function data.
mgl@1371
  8166
+   This is added to the cfun structure.  */
mgl@1371
  8167
+
mgl@1371
  8168
+typedef struct machine_function
mgl@1371
  8169
+GTY (())
mgl@1371
  8170
+{
mgl@1371
  8171
+  /* Records the type of the current function.  */
mgl@1371
  8172
+  unsigned long func_type;
mgl@1371
  8173
+  /* List of minipool labels, use for checking if code label is valid in a
mgl@1371
  8174
+     memory expression */
mgl@1371
  8175
+  minipool_labels *minipool_label_head;
mgl@1371
  8176
+  minipool_labels *minipool_label_tail;
mgl@1371
  8177
+  int ifcvt_after_reload;
mgl@1371
  8178
+} machine_function;
mgl@1371
  8179
+
mgl@1371
  8180
+/* Initialize data used by insn expanders.  This is called from insn_emit,
mgl@1371
  8181
+   once for every function before code is generated.  */
mgl@1371
  8182
+#define INIT_EXPANDERS avr32_init_expanders ()
mgl@1371
  8183
+
mgl@1371
  8184
+/******************************************************************************
mgl@1371
  8185
+ * SPECS
mgl@1371
  8186
+ *****************************************************************************/
mgl@1371
  8187
+
mgl@1371
  8188
+#ifndef ASM_SPEC
mgl@1371
  8189
+#define ASM_SPEC "%{fpic:--pic} %{mrelax|O*:%{mno-relax|O0|O1: ;:--linkrelax}} %{march=ucr2nomul:-march=ucr2;:%{march=*:-march=%*}} %{mpart=uc3a3revd:-mpart=uc3a3256s;:%{mpart=*:-mpart=%*}}"
mgl@1371
  8190
+#endif
mgl@1371
  8191
+
mgl@1371
  8192
+#ifndef MULTILIB_DEFAULTS
mgl@1371
  8193
+#define MULTILIB_DEFAULTS { "march=ap", "" }
mgl@1371
  8194
+#endif
mgl@1371
  8195
+
mgl@1371
  8196
+/******************************************************************************
mgl@1371
  8197
+ * Run-time Target Specification
mgl@1371
  8198
+ *****************************************************************************/
mgl@1371
  8199
+#ifndef TARGET_VERSION
mgl@1371
  8200
+#define TARGET_VERSION fprintf(stderr, " (AVR32, GNU assembler syntax)");
mgl@1371
  8201
+#endif
mgl@1371
  8202
+
mgl@1371
  8203
+
mgl@1371
  8204
+/* Part types. Keep this in sync with the order of avr32_part_types in avr32.c*/
mgl@1371
  8205
+enum part_type
mgl@1371
  8206
+{
mgl@1371
  8207
+  PART_TYPE_AVR32_NONE,
mgl@1371
  8208
+  PART_TYPE_AVR32_AP7000,
mgl@1371
  8209
+  PART_TYPE_AVR32_AP7001,
mgl@1371
  8210
+  PART_TYPE_AVR32_AP7002,
mgl@1371
  8211
+  PART_TYPE_AVR32_AP7200,
mgl@1371
  8212
+  PART_TYPE_AVR32_UC3A0128,
mgl@1371
  8213
+  PART_TYPE_AVR32_UC3A0256,
mgl@1371
  8214
+  PART_TYPE_AVR32_UC3A0512,
mgl@1371
  8215
+  PART_TYPE_AVR32_UC3A0512ES,
mgl@1371
  8216
+  PART_TYPE_AVR32_UC3A1128,
mgl@1371
  8217
+  PART_TYPE_AVR32_UC3A1256,
mgl@1371
  8218
+  PART_TYPE_AVR32_UC3A1512,
mgl@1371
  8219
+  PART_TYPE_AVR32_UC3A1512ES,
mgl@1371
  8220
+  PART_TYPE_AVR32_UC3A3REVD,
mgl@1371
  8221
+  PART_TYPE_AVR32_UC3A364,
mgl@1371
  8222
+  PART_TYPE_AVR32_UC3A364S,
mgl@1371
  8223
+  PART_TYPE_AVR32_UC3A3128,
mgl@1371
  8224
+  PART_TYPE_AVR32_UC3A3128S,
mgl@1371
  8225
+  PART_TYPE_AVR32_UC3A3256,
mgl@1371
  8226
+  PART_TYPE_AVR32_UC3A3256S,
mgl@1371
  8227
+  PART_TYPE_AVR32_UC3B064,
mgl@1371
  8228
+  PART_TYPE_AVR32_UC3B0128,
mgl@1371
  8229
+  PART_TYPE_AVR32_UC3B0256,
mgl@1371
  8230
+  PART_TYPE_AVR32_UC3B0256ES,
mgl@1371
  8231
+  PART_TYPE_AVR32_UC3B164,
mgl@1371
  8232
+  PART_TYPE_AVR32_UC3B1128,
mgl@1371
  8233
+  PART_TYPE_AVR32_UC3B1256,
mgl@1371
  8234
+  PART_TYPE_AVR32_UC3B1256ES
mgl@1371
  8235
+};
mgl@1371
  8236
+
mgl@1371
  8237
+/* Microarchitectures. */
mgl@1371
  8238
+enum microarchitecture_type
mgl@1371
  8239
+{
mgl@1371
  8240
+  UARCH_TYPE_AVR32A,
mgl@1371
  8241
+  UARCH_TYPE_AVR32B,
mgl@1371
  8242
+  UARCH_TYPE_NONE
mgl@1371
  8243
+};
mgl@1371
  8244
+
mgl@1371
  8245
+/* Architectures types which specifies the pipeline.
mgl@1371
  8246
+ Keep this in sync with avr32_arch_types in avr32.c
mgl@1371
  8247
+ and the pipeline attribute in avr32.md */
mgl@1371
  8248
+enum architecture_type
mgl@1371
  8249
+{
mgl@1371
  8250
+  ARCH_TYPE_AVR32_AP,
mgl@1371
  8251
+  ARCH_TYPE_AVR32_UCR1,
mgl@1371
  8252
+  ARCH_TYPE_AVR32_UCR2,
mgl@1371
  8253
+  ARCH_TYPE_AVR32_UCR2NOMUL,
mgl@1371
  8254
+  ARCH_TYPE_AVR32_NONE
mgl@1371
  8255
+};
mgl@1371
  8256
+
mgl@1371
  8257
+/* Flag specifying if the cpu has support for DSP instructions.*/
mgl@1371
  8258
+#define FLAG_AVR32_HAS_DSP (1 << 0)
mgl@1371
  8259
+/* Flag specifying if the cpu has support for Read-Modify-Write
mgl@1371
  8260
+   instructions.*/
mgl@1371
  8261
+#define FLAG_AVR32_HAS_RMW (1 << 1)
mgl@1371
  8262
+/* Flag specifying if the cpu has support for SIMD instructions. */
mgl@1371
  8263
+#define FLAG_AVR32_HAS_SIMD (1 << 2)
mgl@1371
  8264
+/* Flag specifying if the cpu has support for unaligned memory word access. */
mgl@1371
  8265
+#define FLAG_AVR32_HAS_UNALIGNED_WORD (1 << 3)
mgl@1371
  8266
+/* Flag specifying if the cpu has support for branch prediction. */
mgl@1371
  8267
+#define FLAG_AVR32_HAS_BRANCH_PRED (1 << 4)
mgl@1371
  8268
+/* Flag specifying if the cpu has support for a return stack. */
mgl@1371
  8269
+#define FLAG_AVR32_HAS_RETURN_STACK (1 << 5)
mgl@1371
  8270
+/* Flag specifying if the cpu has caches. */
mgl@1371
  8271
+#define FLAG_AVR32_HAS_CACHES (1 << 6)
mgl@1371
  8272
+/* Flag specifying if the cpu has support for v2 insns. */
mgl@1371
  8273
+#define FLAG_AVR32_HAS_V2_INSNS (1 << 7)
mgl@1371
  8274
+/* Flag specifying that the cpu has buggy mul insns. */
mgl@1371
  8275
+#define FLAG_AVR32_HAS_NO_MUL_INSNS (1 << 8)
mgl@1371
  8276
+
mgl@1371
  8277
+/* Structure for holding information about different avr32 CPUs/parts */
mgl@1371
  8278
+struct part_type_s
mgl@1371
  8279
+{
mgl@1371
  8280
+  const char *const name;
mgl@1371
  8281
+  enum part_type part_type;
mgl@1371
  8282
+  enum architecture_type arch_type;
mgl@1371
  8283
+  /* Must lie outside user's namespace.  NULL == no macro.  */
mgl@1371
  8284
+  const char *const macro;
mgl@1371
  8285
+};
mgl@1371
  8286
+
mgl@1371
  8287
+/* Structure for holding information about different avr32 pipeline
mgl@1371
  8288
+ architectures. */
mgl@1371
  8289
+struct arch_type_s
mgl@1371
  8290
+{
mgl@1371
  8291
+  const char *const name;
mgl@1371
  8292
+  enum architecture_type arch_type;
mgl@1371
  8293
+  enum microarchitecture_type uarch_type;
mgl@1371
  8294
+  const unsigned long feature_flags;
mgl@1371
  8295
+  /* Must lie outside user's namespace.  NULL == no macro.  */
mgl@1371
  8296
+  const char *const macro;
mgl@1371
  8297
+};
mgl@1371
  8298
+
mgl@1371
  8299
+extern const struct part_type_s *avr32_part;
mgl@1371
  8300
+extern const struct arch_type_s *avr32_arch;
mgl@1371
  8301
+
mgl@1371
  8302
+#define TARGET_SIMD  (avr32_arch->feature_flags & FLAG_AVR32_HAS_SIMD)
mgl@1371
  8303
+#define TARGET_DSP  (avr32_arch->feature_flags & FLAG_AVR32_HAS_DSP)
mgl@1371
  8304
+#define TARGET_RMW  (avr32_arch->feature_flags & FLAG_AVR32_HAS_RMW)
mgl@1371
  8305
+#define TARGET_UNALIGNED_WORD  (avr32_arch->feature_flags & FLAG_AVR32_HAS_UNALIGNED_WORD)
mgl@1371
  8306
+#define TARGET_BRANCH_PRED  (avr32_arch->feature_flags & FLAG_AVR32_HAS_BRANCH_PRED)
mgl@1371
  8307
+#define TARGET_RETURN_STACK  (avr32_arch->feature_flags & FLAG_AVR32_HAS_RETURN_STACK)
mgl@1371
  8308
+#define TARGET_V2_INSNS  (avr32_arch->feature_flags & FLAG_AVR32_HAS_V2_INSNS)
mgl@1371
  8309
+#define TARGET_CACHES  (avr32_arch->feature_flags & FLAG_AVR32_HAS_CACHES)
mgl@1371
  8310
+#define TARGET_NO_MUL_INSNS  (avr32_arch->feature_flags & FLAG_AVR32_HAS_NO_MUL_INSNS)
mgl@1371
  8311
+#define TARGET_ARCH_AP (avr32_arch->arch_type == ARCH_TYPE_AVR32_AP)
mgl@1371
  8312
+#define TARGET_ARCH_UCR1 (avr32_arch->arch_type == ARCH_TYPE_AVR32_UCR1)
mgl@1371
  8313
+#define TARGET_ARCH_UCR2 (avr32_arch->arch_type == ARCH_TYPE_AVR32_UCR2)
mgl@1371
  8314
+#define TARGET_ARCH_UC (TARGET_ARCH_UCR1 || TARGET_ARCH_UCR2)
mgl@1371
  8315
+#define TARGET_UARCH_AVR32A (avr32_arch->uarch_type == UARCH_TYPE_AVR32A)
mgl@1371
  8316
+#define TARGET_UARCH_AVR32B (avr32_arch->uarch_type == UARCH_TYPE_AVR32B)
mgl@1371
  8317
+
mgl@1371
  8318
+#define CAN_DEBUG_WITHOUT_FP
mgl@1371
  8319
+
mgl@1371
  8320
+
mgl@1371
  8321
+
mgl@1371
  8322
+
mgl@1371
  8323
+/******************************************************************************
mgl@1371
  8324
+ * Storage Layout
mgl@1371
  8325
+ *****************************************************************************/
mgl@1371
  8326
+
mgl@1371
  8327
+/*
mgl@1371
  8328
+Define this macro to have the value 1 if the most significant bit in a
mgl@1371
  8329
+byte has the lowest number; otherwise define it to have the value zero.
mgl@1371
  8330
+This means that bit-field instructions count from the most significant
mgl@1371
  8331
+bit.  If the machine has no bit-field instructions, then this must still
mgl@1371
  8332
+be defined, but it doesn't matter which value it is defined to.  This
mgl@1371
  8333
+macro need not be a constant.
mgl@1371
  8334
+
mgl@1371
  8335
+This macro does not affect the way structure fields are packed into
mgl@1371
  8336
+bytes or words; that is controlled by BYTES_BIG_ENDIAN.
mgl@1371
  8337
+*/
mgl@1371
  8338
+#define BITS_BIG_ENDIAN 0
mgl@1371
  8339
+
mgl@1371
  8340
+/*
mgl@1371
  8341
+Define this macro to have the value 1 if the most significant byte in a
mgl@1371
  8342
+word has the lowest number. This macro need not be a constant.
mgl@1371
  8343
+*/
mgl@1371
  8344
+/*
mgl@1371
  8345
+  Data is stored in an big-endian way.
mgl@1371
  8346
+*/
mgl@1371
  8347
+#define BYTES_BIG_ENDIAN 1
mgl@1371
  8348
+
mgl@1371
  8349
+/*
mgl@1371
  8350
+Define this macro to have the value 1 if, in a multiword object, the
mgl@1371
  8351
+most significant word has the lowest number.  This applies to both
mgl@1371
  8352
+memory locations and registers; GCC fundamentally assumes that the
mgl@1371
  8353
+order of words in memory is the same as the order in registers.  This
mgl@1371
  8354
+macro need not be a constant.
mgl@1371
  8355
+*/
mgl@1371
  8356
+/*
mgl@1371
  8357
+  Data is stored in an bin-endian way.
mgl@1371
  8358
+*/
mgl@1371
  8359
+#define WORDS_BIG_ENDIAN 1
mgl@1371
  8360
+
mgl@1371
  8361
+/*
mgl@1371
  8362
+Define this macro if WORDS_BIG_ENDIAN is not constant.  This must be a
mgl@1371
  8363
+constant value with the same meaning as WORDS_BIG_ENDIAN, which will be
mgl@1371
  8364
+used only when compiling libgcc2.c.  Typically the value will be set
mgl@1371
  8365
+based on preprocessor defines.
mgl@1371
  8366
+*/
mgl@1371
  8367
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
mgl@1371
  8368
+
mgl@1371
  8369
+/*
mgl@1371
  8370
+Define this macro to have the value 1 if DFmode, XFmode or
mgl@1371
  8371
+TFmode floating point numbers are stored in memory with the word
mgl@1371
  8372
+containing the sign bit at the lowest address; otherwise define it to
mgl@1371
  8373
+have the value 0.  This macro need not be a constant.
mgl@1371
  8374
+
mgl@1371
  8375
+You need not define this macro if the ordering is the same as for
mgl@1371
  8376
+multi-word integers.
mgl@1371
  8377
+*/
mgl@1371
  8378
+/* #define FLOAT_WORDS_BIG_ENDIAN 1 */
mgl@1371
  8379
+
mgl@1371
  8380
+/*
mgl@1371
  8381
+Define this macro to be the number of bits in an addressable storage
mgl@1371
  8382
+unit (byte); normally 8.
mgl@1371
  8383
+*/
mgl@1371
  8384
+#define BITS_PER_UNIT 8
mgl@1371
  8385
+
mgl@1371
  8386
+/*
mgl@1371
  8387
+Number of bits in a word; normally 32.
mgl@1371
  8388
+*/
mgl@1371
  8389
+#define BITS_PER_WORD 32
mgl@1371
  8390
+
mgl@1371
  8391
+/*
mgl@1371
  8392
+Maximum number of bits in a word.  If this is undefined, the default is
mgl@1371
  8393
+BITS_PER_WORD.  Otherwise, it is the constant value that is the
mgl@1371
  8394
+largest value that BITS_PER_WORD can have at run-time.
mgl@1371
  8395
+*/
mgl@1371
  8396
+/* MAX_BITS_PER_WORD not defined*/
mgl@1371
  8397
+
mgl@1371
  8398
+/*
mgl@1371
  8399
+Number of storage units in a word; normally 4.
mgl@1371
  8400
+*/
mgl@1371
  8401
+#define UNITS_PER_WORD 4
mgl@1371
  8402
+
mgl@1371
  8403
+/*
mgl@1371
  8404
+Minimum number of units in a word.  If this is undefined, the default is
mgl@1371
  8405
+UNITS_PER_WORD.  Otherwise, it is the constant value that is the
mgl@1371
  8406
+smallest value that UNITS_PER_WORD can have at run-time.
mgl@1371
  8407
+*/
mgl@1371
  8408
+/* MIN_UNITS_PER_WORD not defined */
mgl@1371
  8409
+
mgl@1371
  8410
+/*
mgl@1371
  8411
+Width of a pointer, in bits.  You must specify a value no wider than the
mgl@1371
  8412
+width of Pmode.  If it is not equal to the width of Pmode,
mgl@1371
  8413
+you must define POINTERS_EXTEND_UNSIGNED.
mgl@1371
  8414
+*/
mgl@1371
  8415
+#define POINTER_SIZE 32
mgl@1371
  8416
+
mgl@1371
  8417
+/*
mgl@1371
  8418
+A C expression whose value is greater than zero if pointers that need to be
mgl@1371
  8419
+extended from being POINTER_SIZE bits wide to Pmode are to
mgl@1371
  8420
+be zero-extended and zero if they are to be sign-extended.  If the value
mgl@1371
  8421
+is less then zero then there must be an "ptr_extend" instruction that
mgl@1371
  8422
+extends a pointer from POINTER_SIZE to Pmode.
mgl@1371
  8423
+
mgl@1371
  8424
+You need not define this macro if the POINTER_SIZE is equal
mgl@1371
  8425
+to the width of Pmode.
mgl@1371
  8426
+*/
mgl@1371
  8427
+/* #define POINTERS_EXTEND_UNSIGNED */
mgl@1371
  8428
+
mgl@1371
  8429
+/*
mgl@1371
  8430
+A Macro to update M and UNSIGNEDP when an object whose type
mgl@1371
  8431
+is TYPE and which has the specified mode and signedness is to be
mgl@1371
  8432
+stored in a register.  This macro is only called when TYPE is a
mgl@1371
  8433
+scalar type.
mgl@1371
  8434
+
mgl@1371
  8435
+On most RISC machines, which only have operations that operate on a full
mgl@1371
  8436
+register, define this macro to set M to word_mode if
mgl@1371
  8437
+M is an integer mode narrower than BITS_PER_WORD.  In most
mgl@1371
  8438
+cases, only integer modes should be widened because wider-precision
mgl@1371
  8439
+floating-point operations are usually more expensive than their narrower
mgl@1371
  8440
+counterparts.
mgl@1371
  8441
+
mgl@1371
  8442
+For most machines, the macro definition does not change UNSIGNEDP.
mgl@1371
  8443
+However, some machines, have instructions that preferentially handle
mgl@1371
  8444
+either signed or unsigned quantities of certain modes.  For example, on
mgl@1371
  8445
+the DEC Alpha, 32-bit loads from memory and 32-bit add instructions
mgl@1371
  8446
+sign-extend the result to 64 bits.  On such machines, set
mgl@1371
  8447
+UNSIGNEDP according to which kind of extension is more efficient.
mgl@1371
  8448
+
mgl@1371
  8449
+Do not define this macro if it would never modify M.
mgl@1371
  8450
+*/
mgl@1371
  8451
+#define PROMOTE_MODE(M, UNSIGNEDP, TYPE)	\
mgl@1371
  8452
+    {						\
mgl@1371
  8453
+      if (GET_MODE_CLASS (M) == MODE_INT	\
mgl@1371
  8454
+	  && GET_MODE_SIZE (M) < 4)		\
mgl@1371
  8455
+	{					\
mgl@1371
  8456
+          if (M == QImode)                     \
mgl@1371
  8457
+            UNSIGNEDP = 1;                      \
mgl@1371
  8458
+          else if (M == SImode)                 \
mgl@1371
  8459
+            UNSIGNEDP = 0;                      \
mgl@1371
  8460
+	  (M) = SImode;				\
mgl@1371
  8461
+	}					\
mgl@1371
  8462
+    }
mgl@1371
  8463
+
mgl@1371
  8464
+#define PROMOTE_FUNCTION_MODE(M, UNSIGNEDP, TYPE)        \
mgl@1371
  8465
+  {                                                      \
mgl@1371
  8466
+    if (GET_MODE_CLASS (M) == MODE_INT                   \
mgl@1371
  8467
+        && GET_MODE_SIZE (M) < 4)                        \
mgl@1371
  8468
+      {                                                  \
mgl@1371
  8469
+        (M) = SImode;                                    \
mgl@1371
  8470
+      }                                                  \
mgl@1371
  8471
+  }
mgl@1371
  8472
+
mgl@1371
  8473
+/* Define if operations between registers always perform the operation
mgl@1371
  8474
+   on the full register even if a narrower mode is specified.  */
mgl@1371
  8475
+#define WORD_REGISTER_OPERATIONS
mgl@1371
  8476
+
mgl@1371
  8477
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
mgl@1371
  8478
+   will either zero-extend or sign-extend.  The value of this macro should
mgl@1371
  8479
+   be the code that says which one of the two operations is implicitly
mgl@1371
  8480
+   done, UNKNOWN if not known.  */
mgl@1371
  8481
+#define LOAD_EXTEND_OP(MODE)				\
mgl@1371
  8482
+   (((MODE) == QImode) ? ZERO_EXTEND			\
mgl@1371
  8483
+   : ((MODE) == HImode) ? SIGN_EXTEND : UNKNOWN)
mgl@1371
  8484
+
mgl@1371
  8485
+
mgl@1371
  8486
+/*
mgl@1371
  8487
+Define this macro if the promotion described by PROMOTE_MODE
mgl@1371
  8488
+should only be performed for outgoing function arguments or
mgl@1371
  8489
+function return values, as specified by PROMOTE_FUNCTION_ARGS
mgl@1371
  8490
+and PROMOTE_FUNCTION_RETURN, respectively.
mgl@1371
  8491
+*/
mgl@1371
  8492
+/* #define PROMOTE_FOR_CALL_ONLY */
mgl@1371
  8493
+
mgl@1371
  8494
+/*
mgl@1371
  8495
+Normal alignment required for function parameters on the stack, in
mgl@1371
  8496
+bits.  All stack parameters receive at least this much alignment
mgl@1371
  8497
+regardless of data type.  On most machines, this is the same as the
mgl@1371
  8498
+size of an integer.
mgl@1371
  8499
+*/
mgl@1371
  8500
+#define PARM_BOUNDARY 32
mgl@1371
  8501
+
mgl@1371
  8502
+/*
mgl@1371
  8503
+Define this macro to the minimum alignment enforced by hardware for the
mgl@1371
  8504
+stack pointer on this machine.  The definition is a C expression for the
mgl@1371
  8505
+desired alignment (measured in bits).  This value is used as a default
mgl@1371
  8506
+if PREFERRED_STACK_BOUNDARY is not defined.  On most machines,
mgl@1371
  8507
+this should be the same as PARM_BOUNDARY.
mgl@1371
  8508
+*/
mgl@1371
  8509
+#define STACK_BOUNDARY 32
mgl@1371
  8510
+
mgl@1371
  8511
+/*
mgl@1371
  8512
+Define this macro if you wish to preserve a certain alignment for the
mgl@1371
  8513
+stack pointer, greater than what the hardware enforces.  The definition
mgl@1371
  8514
+is a C expression for the desired alignment (measured in bits).  This
mgl@1371
  8515
+macro must evaluate to a value equal to or larger than
mgl@1371
  8516
+STACK_BOUNDARY.
mgl@1371
  8517
+*/
mgl@1371
  8518
+#define PREFERRED_STACK_BOUNDARY (TARGET_FORCE_DOUBLE_ALIGN ? 64 : 32 )
mgl@1371
  8519
+
mgl@1371
  8520
+/*
mgl@1371
  8521
+Alignment required for a function entry point, in bits.
mgl@1371
  8522
+*/
mgl@1371
  8523
+#define FUNCTION_BOUNDARY 16
mgl@1371
  8524
+
mgl@1371
  8525
+/*
mgl@1371
  8526
+Biggest alignment that any data type can require on this machine, in bits.
mgl@1371
  8527
+*/
mgl@1371
  8528
+#define BIGGEST_ALIGNMENT  (TARGET_FORCE_DOUBLE_ALIGN ? 64 : 32 )
mgl@1371
  8529
+
mgl@1371
  8530
+/*
mgl@1371
  8531
+If defined, the smallest alignment, in bits, that can be given to an
mgl@1371
  8532
+object that can be referenced in one operation, without disturbing any
mgl@1371
  8533
+nearby object.  Normally, this is BITS_PER_UNIT, but may be larger
mgl@1371
  8534
+on machines that don't have byte or half-word store operations.
mgl@1371
  8535
+*/
mgl@1371
  8536
+#define MINIMUM_ATOMIC_ALIGNMENT BITS_PER_UNIT
mgl@1371
  8537
+
mgl@1371
  8538
+
mgl@1371
  8539
+/*
mgl@1371
  8540
+An integer expression for the size in bits of the largest integer machine mode that
mgl@1371
  8541
+should actually be used. All integer machine modes of this size or smaller can be
mgl@1371
  8542
+used for structures and unions with the appropriate sizes. If this macro is undefined,
mgl@1371
  8543
+GET_MODE_BITSIZE (DImode) is assumed.*/
mgl@1371
  8544
+#define MAX_FIXED_MODE_SIZE  GET_MODE_BITSIZE (DImode)
mgl@1371
  8545
+
mgl@1371
  8546
+
mgl@1371
  8547
+/*
mgl@1371
  8548
+If defined, a C expression to compute the alignment given to a constant
mgl@1371
  8549
+that is being placed in memory.  CONSTANT is the constant and
mgl@1371
  8550
+BASIC_ALIGN is the alignment that the object would ordinarily
mgl@1371
  8551
+have.  The value of this macro is used instead of that alignment to
mgl@1371
  8552
+align the object.
mgl@1371
  8553
+
mgl@1371
  8554
+If this macro is not defined, then BASIC_ALIGN is used.
mgl@1371
  8555
+
mgl@1371
  8556
+The typical use of this macro is to increase alignment for string
mgl@1371
  8557
+constants to be word aligned so that strcpy calls that copy
mgl@1371
  8558
+constants can be done inline.
mgl@1371
  8559
+*/
mgl@1371
  8560
+#define CONSTANT_ALIGNMENT(CONSTANT, BASIC_ALIGN) \
mgl@1371
  8561
+ ((TREE_CODE(CONSTANT) == STRING_CST) ? BITS_PER_WORD : BASIC_ALIGN)
mgl@1371
  8562
+
mgl@1371
  8563
+/* Try to align string to a word. */
mgl@1371
  8564
+#define DATA_ALIGNMENT(TYPE, ALIGN)                                     \
mgl@1371
  8565
+  ({(TREE_CODE (TYPE) == ARRAY_TYPE                                     \
mgl@1371
  8566
+     && TYPE_MODE (TREE_TYPE (TYPE)) == QImode                          \
mgl@1371
  8567
+     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN));})
mgl@1371
  8568
+
mgl@1371
  8569
+/* Try to align local store strings to a word. */
mgl@1371
  8570
+#define LOCAL_ALIGNMENT(TYPE, ALIGN)                                    \
mgl@1371
  8571
+  ({(TREE_CODE (TYPE) == ARRAY_TYPE                                     \
mgl@1371
  8572
+     && TYPE_MODE (TREE_TYPE (TYPE)) == QImode                          \
mgl@1371
  8573
+     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN));})
mgl@1371
  8574
+
mgl@1371
  8575
+/*
mgl@1371
  8576
+Define this macro to be the value 1 if instructions will fail to work
mgl@1371
  8577
+if given data not on the nominal alignment.  If instructions will merely
mgl@1371
  8578
+go slower in that case, define this macro as 0.
mgl@1371
  8579
+*/
mgl@1371
  8580
+#define STRICT_ALIGNMENT 1
mgl@1371
  8581
+
mgl@1371
  8582
+/*
mgl@1371
  8583
+Define this if you wish to imitate the way many other C compilers handle
mgl@1371
  8584
+alignment of bit-fields and the structures that contain them.
mgl@1371
  8585
+
mgl@1371
  8586
+The behavior is that the type written for a bit-field (int,
mgl@1371
  8587
+short, or other integer type) imposes an alignment for the
mgl@1371
  8588
+entire structure, as if the structure really did contain an ordinary
mgl@1371
  8589
+field of that type.  In addition, the bit-field is placed within the
mgl@1371
  8590
+structure so that it would fit within such a field, not crossing a
mgl@1371
  8591
+boundary for it.
mgl@1371
  8592
+
mgl@1371
  8593
+Thus, on most machines, a bit-field whose type is written as int
mgl@1371
  8594
+would not cross a four-byte boundary, and would force four-byte
mgl@1371
  8595
+alignment for the whole structure.  (The alignment used may not be four
mgl@1371
  8596
+bytes; it is controlled by the other alignment parameters.)
mgl@1371
  8597
+
mgl@1371
  8598
+If the macro is defined, its definition should be a C expression;
mgl@1371
  8599
+a nonzero value for the expression enables this behavior.
mgl@1371
  8600
+
mgl@1371
  8601
+Note that if this macro is not defined, or its value is zero, some
mgl@1371
  8602
+bit-fields may cross more than one alignment boundary.  The compiler can
mgl@1371
  8603
+support such references if there are insv, extv, and
mgl@1371
  8604
+extzv insns that can directly reference memory.
mgl@1371
  8605
+
mgl@1371
  8606
+The other known way of making bit-fields work is to define
mgl@1371
  8607
+STRUCTURE_SIZE_BOUNDARY as large as BIGGEST_ALIGNMENT.
mgl@1371
  8608
+Then every structure can be accessed with fullwords.
mgl@1371
  8609
+
mgl@1371
  8610
+Unless the machine has bit-field instructions or you define
mgl@1371
  8611
+STRUCTURE_SIZE_BOUNDARY that way, you must define
mgl@1371
  8612
+PCC_BITFIELD_TYPE_MATTERS to have a nonzero value.
mgl@1371
  8613
+
mgl@1371
  8614
+If your aim is to make GCC use the same conventions for laying out
mgl@1371
  8615
+bit-fields as are used by another compiler, here is how to investigate
mgl@1371
  8616
+what the other compiler does.  Compile and run this program:
mgl@1371
  8617
+
mgl@1371
  8618
+struct foo1
mgl@1371
  8619
+{
mgl@1371
  8620
+  char x;
mgl@1371
  8621
+  char :0;
mgl@1371
  8622
+  char y;
mgl@1371
  8623
+};
mgl@1371
  8624
+
mgl@1371
  8625
+struct foo2
mgl@1371
  8626
+{
mgl@1371
  8627
+  char x;
mgl@1371
  8628
+  int :0;
mgl@1371
  8629
+  char y;
mgl@1371
  8630
+};
mgl@1371
  8631
+
mgl@1371
  8632
+main ()
mgl@1371
  8633
+{
mgl@1371
  8634
+  printf ("Size of foo1 is %d\n",
mgl@1371
  8635
+          sizeof (struct foo1));
mgl@1371
  8636
+  printf ("Size of foo2 is %d\n",
mgl@1371
  8637
+          sizeof (struct foo2));
mgl@1371
  8638
+  exit (0);
mgl@1371
  8639
+}
mgl@1371
  8640
+
mgl@1371
  8641
+If this prints 2 and 5, then the compiler's behavior is what you would
mgl@1371
  8642
+get from PCC_BITFIELD_TYPE_MATTERS.
mgl@1371
  8643
+*/
mgl@1371
  8644
+#define PCC_BITFIELD_TYPE_MATTERS 1
mgl@1371
  8645
+
mgl@1371
  8646
+
mgl@1371
  8647
+/******************************************************************************
mgl@1371
  8648
+ * Layout of Source Language Data Types
mgl@1371
  8649
+ *****************************************************************************/
mgl@1371
  8650
+
mgl@1371
  8651
+/*
mgl@1371
  8652
+A C expression for the size in bits of the type int on the
mgl@1371
  8653
+target machine.  If you don't define this, the default is one word.
mgl@1371
  8654
+*/
mgl@1371
  8655
+#define INT_TYPE_SIZE 32
mgl@1371
  8656
+
mgl@1371
  8657
+/*
mgl@1371
  8658
+A C expression for the size in bits of the type short on the
mgl@1371
  8659
+target machine.  If you don't define this, the default is half a word. (If
mgl@1371
  8660
+this would be less than one storage unit, it is rounded up to one unit.)
mgl@1371
  8661
+*/
mgl@1371
  8662
+#define SHORT_TYPE_SIZE 16
mgl@1371
  8663
+
mgl@1371
  8664
+/*
mgl@1371
  8665
+A C expression for the size in bits of the type long on the
mgl@1371
  8666
+target machine.  If you don't define this, the default is one word.
mgl@1371
  8667
+*/
mgl@1371
  8668
+#define LONG_TYPE_SIZE 32
mgl@1371
  8669
+
mgl@1371
  8670
+
mgl@1371
  8671
+/*
mgl@1371
  8672
+A C expression for the size in bits of the type long long on the
mgl@1371
  8673
+target machine.  If you don't define this, the default is two
mgl@1371
  8674
+words.  If you want to support GNU Ada on your machine, the value of this
mgl@1371
  8675
+macro must be at least 64.
mgl@1371
  8676
+*/
mgl@1371
  8677
+#define LONG_LONG_TYPE_SIZE 64
mgl@1371
  8678
+
mgl@1371
  8679
+/*
mgl@1371
  8680
+A C expression for the size in bits of the type char on the
mgl@1371
  8681
+target machine.  If you don't define this, the default is
mgl@1371
  8682
+BITS_PER_UNIT.
mgl@1371
  8683
+*/
mgl@1371
  8684
+#define CHAR_TYPE_SIZE 8
mgl@1371
  8685
+
mgl@1371
  8686
+
mgl@1371
  8687
+/*
mgl@1371
  8688
+A C expression for the size in bits of the C++ type bool and
mgl@1371
  8689
+C99 type _Bool on the target machine.  If you don't define
mgl@1371
  8690
+this, and you probably shouldn't, the default is CHAR_TYPE_SIZE.
mgl@1371
  8691
+*/
mgl@1371
  8692
+#define BOOL_TYPE_SIZE 8
mgl@1371
  8693
+
mgl@1371
  8694
+
mgl@1371
  8695
+/*
mgl@1371
  8696
+An expression whose value is 1 or 0, according to whether the type
mgl@1371
  8697
+char should be signed or unsigned by default.  The user can
mgl@1371
  8698
+always override this default with the options -fsigned-char
mgl@1371
  8699
+and -funsigned-char.
mgl@1371
  8700
+*/
mgl@1371
  8701
+/* We are using unsigned char */
mgl@1371
  8702
+#define DEFAULT_SIGNED_CHAR 0
mgl@1371
  8703
+
mgl@1371
  8704
+
mgl@1371
  8705
+/*
mgl@1371
  8706
+A C expression for a string describing the name of the data type to use
mgl@1371
  8707
+for size values.  The typedef name size_t is defined using the
mgl@1371
  8708
+contents of the string.
mgl@1371
  8709
+
mgl@1371
  8710
+The string can contain more than one keyword.  If so, separate them with
mgl@1371
  8711
+spaces, and write first any length keyword, then unsigned if
mgl@1371
  8712
+appropriate, and finally int.  The string must exactly match one
mgl@1371
  8713
+of the data type names defined in the function
mgl@1371
  8714
+init_decl_processing in the file c-decl.c.  You may not
mgl@1371
  8715
+omit int or change the order - that would cause the compiler to
mgl@1371
  8716
+crash on startup.
mgl@1371
  8717
+
mgl@1371
  8718
+If you don't define this macro, the default is "long unsigned int".
mgl@1371
  8719
+*/
mgl@1371
  8720
+#define SIZE_TYPE "long unsigned int"
mgl@1371
  8721
+
mgl@1371
  8722
+/*
mgl@1371
  8723
+A C expression for a string describing the name of the data type to use
mgl@1371
  8724
+for the result of subtracting two pointers.  The typedef name
mgl@1371
  8725
+ptrdiff_t is defined using the contents of the string.  See
mgl@1371
  8726
+SIZE_TYPE above for more information.
mgl@1371
  8727
+
mgl@1371
  8728
+If you don't define this macro, the default is "long int".
mgl@1371
  8729
+*/
mgl@1371
  8730
+#define PTRDIFF_TYPE "long int"
mgl@1371
  8731
+
mgl@1371
  8732
+
mgl@1371
  8733
+/*
mgl@1371
  8734
+A C expression for the size in bits of the data type for wide
mgl@1371
  8735
+characters.  This is used in cpp, which cannot make use of
mgl@1371
  8736
+WCHAR_TYPE.
mgl@1371
  8737
+*/
mgl@1371
  8738
+#define WCHAR_TYPE_SIZE 32
mgl@1371
  8739
+
mgl@1371
  8740
+
mgl@1371
  8741
+/*
mgl@1371
  8742
+A C expression for a string describing the name of the data type to
mgl@1371
  8743
+use for wide characters passed to printf and returned from
mgl@1371
  8744
+getwc.  The typedef name wint_t is defined using the
mgl@1371
  8745
+contents of the string.  See SIZE_TYPE above for more
mgl@1371
  8746
+information.
mgl@1371
  8747
+
mgl@1371
  8748
+If you don't define this macro, the default is "unsigned int".
mgl@1371
  8749
+*/
mgl@1371
  8750
+#define WINT_TYPE "unsigned int"
mgl@1371
  8751
+
mgl@1371
  8752
+/*
mgl@1371
  8753
+A C expression for a string describing the name of the data type that
mgl@1371
  8754
+can represent any value of any standard or extended signed integer type.
mgl@1371
  8755
+The typedef name intmax_t is defined using the contents of the
mgl@1371
  8756
+string.  See SIZE_TYPE above for more information.
mgl@1371
  8757
+
mgl@1371
  8758
+If you don't define this macro, the default is the first of
mgl@1371
  8759
+"int", "long int", or "long long int" that has as
mgl@1371
  8760
+much precision as long long int.
mgl@1371
  8761
+*/
mgl@1371
  8762
+#define INTMAX_TYPE "long long int"
mgl@1371
  8763
+
mgl@1371
  8764
+/*
mgl@1371
  8765
+A C expression for a string describing the name of the data type that
mgl@1371
  8766
+can represent any value of any standard or extended unsigned integer
mgl@1371
  8767
+type.  The typedef name uintmax_t is defined using the contents
mgl@1371
  8768
+of the string.  See SIZE_TYPE above for more information.
mgl@1371
  8769
+
mgl@1371
  8770
+If you don't define this macro, the default is the first of
mgl@1371
  8771
+"unsigned int", "long unsigned int", or "long long unsigned int"
mgl@1371
  8772
+that has as much precision as long long unsigned int.
mgl@1371
  8773
+*/
mgl@1371
  8774
+#define UINTMAX_TYPE "long long unsigned int"
mgl@1371
  8775
+
mgl@1371
  8776
+
mgl@1371
  8777
+/******************************************************************************
mgl@1371
  8778
+ * Register Usage
mgl@1371
  8779
+ *****************************************************************************/
mgl@1371
  8780
+
mgl@1371
  8781
+/* Convert from gcc internal register number to register number
mgl@1371
  8782
+   used in assembly code */
mgl@1371
  8783
+#define ASM_REGNUM(reg) (LAST_REGNUM - (reg))
mgl@1371
  8784
+#define ASM_FP_REGNUM(reg) (LAST_FP_REGNUM - (reg))
mgl@1371
  8785
+
mgl@1371
  8786
+/* Convert between register number used in assembly to gcc
mgl@1371
  8787
+   internal register number  */
mgl@1371
  8788
+#define INTERNAL_REGNUM(reg) (LAST_REGNUM - (reg))
mgl@1371
  8789
+#define INTERNAL_FP_REGNUM(reg) (LAST_FP_REGNUM - (reg))
mgl@1371
  8790
+
mgl@1371
  8791
+/** Basic Characteristics of Registers **/
mgl@1371
  8792
+
mgl@1371
  8793
+/*
mgl@1371
  8794
+Number of hardware registers known to the compiler.  They receive
mgl@1371
  8795
+numbers 0 through FIRST_PSEUDO_REGISTER-1; thus, the first
mgl@1371
  8796
+pseudo register's number really is assigned the number
mgl@1371
  8797
+FIRST_PSEUDO_REGISTER.
mgl@1371
  8798
+*/
mgl@1371
  8799
+#define FIRST_PSEUDO_REGISTER (LAST_FP_REGNUM + 1)
mgl@1371
  8800
+
mgl@1371
  8801
+#define FIRST_REGNUM 0
mgl@1371
  8802
+#define LAST_REGNUM 15
mgl@1371
  8803
+#define NUM_FP_REGS 16
mgl@1371
  8804
+#define FIRST_FP_REGNUM 16
mgl@1371
  8805
+#define LAST_FP_REGNUM (16+NUM_FP_REGS-1)
mgl@1371
  8806
+
mgl@1371
  8807
+/*
mgl@1371
  8808
+An initializer that says which registers are used for fixed purposes
mgl@1371
  8809
+all throughout the compiled code and are therefore not available for
mgl@1371
  8810
+general allocation.  These would include the stack pointer, the frame
mgl@1371
  8811
+pointer (except on machines where that can be used as a general
mgl@1371
  8812
+register when no frame pointer is needed), the program counter on
mgl@1371
  8813
+machines where that is considered one of the addressable registers,
mgl@1371
  8814
+and any other numbered register with a standard use.
mgl@1371
  8815
+
mgl@1371
  8816
+This information is expressed as a sequence of numbers, separated by
mgl@1371
  8817
+commas and surrounded by braces.  The nth number is 1 if
mgl@1371
  8818
+register n is fixed, 0 otherwise.
mgl@1371
  8819
+
mgl@1371
  8820
+The table initialized from this macro, and the table initialized by
mgl@1371
  8821
+the following one, may be overridden at run time either automatically,
mgl@1371
  8822
+by the actions of the macro CONDITIONAL_REGISTER_USAGE, or by
mgl@1371
  8823
+the user with the command options -ffixed-[reg],
mgl@1371
  8824
+-fcall-used-[reg] and -fcall-saved-[reg].
mgl@1371
  8825
+*/
mgl@1371
  8826
+
mgl@1371
  8827
+/* The internal gcc register numbers are reversed
mgl@1371
  8828
+   compared to the real register numbers since
mgl@1371
  8829
+   gcc expects data types stored over multiple
mgl@1371
  8830
+   registers in the register file to be big endian
mgl@1371
  8831
+   if the memory layout is big endian. But this
mgl@1371
  8832
+   is not the case for avr32 so we fake a big
mgl@1371
  8833
+   endian register file. */
mgl@1371
  8834
+
mgl@1371
  8835
+#define FIXED_REGISTERS {	\
mgl@1371
  8836
+  1, /* Program Counter */	\
mgl@1371
  8837
+  0, /* Link Register */	\
mgl@1371
  8838
+  1, /* Stack Pointer */	\
mgl@1371
  8839
+  0, /* r12 */			\
mgl@1371
  8840
+  0, /* r11 */			\
mgl@1371
  8841
+  0, /* r10 */			\
mgl@1371
  8842
+  0, /* r9 */			\
mgl@1371
  8843
+  0, /* r8 */			\
mgl@1371
  8844
+  0, /* r7 */			\
mgl@1371
  8845
+  0, /* r6 */			\
mgl@1371
  8846
+  0, /* r5 */			\
mgl@1371
  8847
+  0, /* r4 */			\
mgl@1371
  8848
+  0, /* r3 */			\
mgl@1371
  8849
+  0, /* r2 */			\
mgl@1371
  8850
+  0, /* r1 */			\
mgl@1371
  8851
+  0, /* r0 */			\
mgl@1371
  8852
+  0, /* f15 */			\
mgl@1371
  8853
+  0, /* f14 */			\
mgl@1371
  8854
+  0, /* f13 */			\
mgl@1371
  8855
+  0, /* f12 */			\
mgl@1371
  8856
+  0, /* f11 */			\
mgl@1371
  8857
+  0, /* f10 */			\
mgl@1371
  8858
+  0, /* f9 */			\
mgl@1371
  8859
+  0, /* f8 */			\
mgl@1371
  8860
+  0, /* f7 */			\
mgl@1371
  8861
+  0, /* f6 */			\
mgl@1371
  8862
+  0, /* f5 */			\
mgl@1371
  8863
+  0, /* f4 */			\
mgl@1371
  8864
+  0, /* f3 */			\
mgl@1371
  8865
+  0, /* f2*/			\
mgl@1371
  8866
+  0, /* f1 */			\
mgl@1371
  8867
+  0  /* f0 */			\
mgl@1371
  8868
+}
mgl@1371
  8869
+
mgl@1371
  8870
+/*
mgl@1371
  8871
+Like FIXED_REGISTERS but has 1 for each register that is
mgl@1371
  8872
+clobbered (in general) by function calls as well as for fixed
mgl@1371
  8873
+registers.  This macro therefore identifies the registers that are not
mgl@1371
  8874
+available for general allocation of values that must live across
mgl@1371
  8875
+function calls.
mgl@1371
  8876
+
mgl@1371
  8877
+If a register has 0 in CALL_USED_REGISTERS, the compiler
mgl@1371
  8878
+automatically saves it on function entry and restores it on function
mgl@1371
  8879
+exit, if the register is used within the function.
mgl@1371
  8880
+*/
mgl@1371
  8881
+#define CALL_USED_REGISTERS {	\
mgl@1371
  8882
+  1, /* Program Counter */	\
mgl@1371
  8883
+  0, /* Link Register */	\
mgl@1371
  8884
+  1, /* Stack Pointer */	\
mgl@1371
  8885
+  1, /* r12 */			\
mgl@1371
  8886
+  1, /* r11 */			\
mgl@1371
  8887
+  1, /* r10 */			\
mgl@1371
  8888
+  1, /* r9 */			\
mgl@1371
  8889
+  1, /* r8 */			\
mgl@1371
  8890
+  0, /* r7 */			\
mgl@1371
  8891
+  0, /* r6 */			\
mgl@1371
  8892
+  0, /* r5 */			\
mgl@1371
  8893
+  0, /* r4 */			\
mgl@1371
  8894
+  0, /* r3 */			\
mgl@1371
  8895
+  0, /* r2 */			\
mgl@1371
  8896
+  0, /* r1 */			\
mgl@1371
  8897
+  0, /* r0 */			\
mgl@1371
  8898
+  1, /* f15 */			\
mgl@1371
  8899
+  1, /* f14 */			\
mgl@1371
  8900
+  1, /* f13 */			\
mgl@1371
  8901
+  1, /* f12 */			\
mgl@1371
  8902
+  1, /* f11 */			\
mgl@1371
  8903
+  1, /* f10 */			\
mgl@1371
  8904
+  1, /* f9 */			\
mgl@1371
  8905
+  1, /* f8 */			\
mgl@1371
  8906
+  0, /* f7 */			\
mgl@1371
  8907
+  0, /* f6 */			\
mgl@1371
  8908
+  0, /* f5 */			\
mgl@1371
  8909
+  0, /* f4 */			\
mgl@1371
  8910
+  0, /* f3 */			\
mgl@1371
  8911
+  0, /* f2*/			\
mgl@1371
  8912
+  0, /* f1*/			\
mgl@1371
  8913
+  0, /* f0 */			\
mgl@1371
  8914
+}
mgl@1371
  8915
+
mgl@1371
  8916
+/* Interrupt functions can only use registers that have already been
mgl@1371
  8917
+   saved by the prologue, even if they would normally be
mgl@1371
  8918
+   call-clobbered.  */
mgl@1371
  8919
+#define HARD_REGNO_RENAME_OK(SRC, DST)					\
mgl@1371
  8920
+	(! IS_INTERRUPT (cfun->machine->func_type) ||			\
mgl@1371
  8921
+		regs_ever_live[DST])
mgl@1371
  8922
+
mgl@1371
  8923
+
mgl@1371
  8924
+/*
mgl@1371
  8925
+Zero or more C statements that may conditionally modify five variables
mgl@1371
  8926
+fixed_regs, call_used_regs, global_regs,
mgl@1371
  8927
+reg_names, and reg_class_contents, to take into account
mgl@1371
  8928
+any dependence of these register sets on target flags.  The first three
mgl@1371
  8929
+of these are of type char [] (interpreted as Boolean vectors).
mgl@1371
  8930
+global_regs is a const char *[], and
mgl@1371
  8931
+reg_class_contents is a HARD_REG_SET.  Before the macro is
mgl@1371
  8932
+called, fixed_regs, call_used_regs,
mgl@1371
  8933
+reg_class_contents, and reg_names have been initialized
mgl@1371
  8934
+from FIXED_REGISTERS, CALL_USED_REGISTERS,
mgl@1371
  8935
+REG_CLASS_CONTENTS, and REGISTER_NAMES, respectively.
mgl@1371
  8936
+global_regs has been cleared, and any -ffixed-[reg],
mgl@1371
  8937
+-fcall-used-[reg] and -fcall-saved-[reg]
mgl@1371
  8938
+command options have been applied.
mgl@1371
  8939
+
mgl@1371
  8940
+You need not define this macro if it has no work to do.
mgl@1371
  8941
+
mgl@1371
  8942
+If the usage of an entire class of registers depends on the target
mgl@1371
  8943
+flags, you may indicate this to GCC by using this macro to modify
mgl@1371
  8944
+fixed_regs and call_used_regs to 1 for each of the
mgl@1371
  8945
+registers in the classes which should not be used by GCC.  Also define
mgl@1371
  8946
+the macro REG_CLASS_FROM_LETTER to return NO_REGS if it
mgl@1371
  8947
+is called with a letter for a class that shouldn't be used.
mgl@1371
  8948
+
mgl@1371
  8949
+ (However, if this class is not included in GENERAL_REGS and all
mgl@1371
  8950
+of the insn patterns whose constraints permit this class are
mgl@1371
  8951
+controlled by target switches, then GCC will automatically avoid using
mgl@1371
  8952
+these registers when the target switches are opposed to them.)
mgl@1371
  8953
+*/
mgl@1371
  8954
+#define CONDITIONAL_REGISTER_USAGE                              \
mgl@1371
  8955
+  do								\
mgl@1371
  8956
+    {								\
mgl@1371
  8957
+      int regno;						\
mgl@1371
  8958
+								\
mgl@1371
  8959
+      if (TARGET_SOFT_FLOAT)			                \
mgl@1371
  8960
+	{							\
mgl@1371
  8961
+	  for (regno = FIRST_FP_REGNUM;				\
mgl@1371
  8962
+	       regno <= LAST_FP_REGNUM; ++regno)	        \
mgl@1371
  8963
+	    fixed_regs[regno] = call_used_regs[regno] = 1;	\
mgl@1371
  8964
+	}							\
mgl@1371
  8965
+      if (flag_pic)						\
mgl@1371
  8966
+	{							\
mgl@1371
  8967
+	  fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;		\
mgl@1371
  8968
+	  call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;		\
mgl@1371
  8969
+	}							\
mgl@1371
  8970
+    }								\
mgl@1371
  8971
+  while (0)
mgl@1371
  8972
+
mgl@1371
  8973
+
mgl@1371
  8974
+/*
mgl@1371
  8975
+If the program counter has a register number, define this as that
mgl@1371
  8976
+register number.  Otherwise, do not define it.
mgl@1371
  8977
+*/
mgl@1371
  8978
+
mgl@1371
  8979
+#define LAST_AVR32_REGNUM 16
mgl@1371
  8980
+
mgl@1371
  8981
+
mgl@1371
  8982
+/** Order of Allocation of Registers **/
mgl@1371
  8983
+
mgl@1371
  8984
+/*
mgl@1371
  8985
+If defined, an initializer for a vector of integers, containing the
mgl@1371
  8986
+numbers of hard registers in the order in which GCC should prefer
mgl@1371
  8987
+to use them (from most preferred to least).
mgl@1371
  8988
+
mgl@1371
  8989
+If this macro is not defined, registers are used lowest numbered first
mgl@1371
  8990
+(all else being equal).
mgl@1371
  8991
+
mgl@1371
  8992
+One use of this macro is on machines where the highest numbered
mgl@1371
  8993
+registers must always be saved and the save-multiple-registers
mgl@1371
  8994
+instruction supports only sequences of consecutive registers.  On such
mgl@1371
  8995
+machines, define REG_ALLOC_ORDER to be an initializer that lists
mgl@1371
  8996
+the highest numbered allocable register first.
mgl@1371
  8997
+*/
mgl@1371
  8998
+#define REG_ALLOC_ORDER 	\
mgl@1371
  8999
+{				\
mgl@1371
  9000
+  INTERNAL_REGNUM(8),		\
mgl@1371
  9001
+  INTERNAL_REGNUM(9),		\
mgl@1371
  9002
+  INTERNAL_REGNUM(10),		\
mgl@1371
  9003
+  INTERNAL_REGNUM(11),		\
mgl@1371
  9004
+  INTERNAL_REGNUM(12),		\
mgl@1371
  9005
+  LR_REGNUM,			\
mgl@1371
  9006
+  INTERNAL_REGNUM(7),		\
mgl@1371
  9007
+  INTERNAL_REGNUM(6),		\
mgl@1371
  9008
+  INTERNAL_REGNUM(5),		\
mgl@1371
  9009
+  INTERNAL_REGNUM(4),		\
mgl@1371
  9010
+  INTERNAL_REGNUM(3),		\
mgl@1371
  9011
+  INTERNAL_REGNUM(2),		\
mgl@1371
  9012
+  INTERNAL_REGNUM(1),		\
mgl@1371
  9013
+  INTERNAL_REGNUM(0),		\
mgl@1371
  9014
+  INTERNAL_FP_REGNUM(15),	\
mgl@1371
  9015
+  INTERNAL_FP_REGNUM(14),	\
mgl@1371
  9016
+  INTERNAL_FP_REGNUM(13),	\
mgl@1371
  9017
+  INTERNAL_FP_REGNUM(12),	\
mgl@1371
  9018
+  INTERNAL_FP_REGNUM(11),	\
mgl@1371
  9019
+  INTERNAL_FP_REGNUM(10),	\
mgl@1371
  9020
+  INTERNAL_FP_REGNUM(9),	\
mgl@1371
  9021
+  INTERNAL_FP_REGNUM(8),	\
mgl@1371
  9022
+  INTERNAL_FP_REGNUM(7),	\
mgl@1371
  9023
+  INTERNAL_FP_REGNUM(6),	\
mgl@1371
  9024
+  INTERNAL_FP_REGNUM(5),	\
mgl@1371
  9025
+  INTERNAL_FP_REGNUM(4),	\
mgl@1371
  9026
+  INTERNAL_FP_REGNUM(3),	\
mgl@1371
  9027
+  INTERNAL_FP_REGNUM(2),	\
mgl@1371
  9028
+  INTERNAL_FP_REGNUM(1),	\
mgl@1371
  9029
+  INTERNAL_FP_REGNUM(0),	\
mgl@1371
  9030
+  SP_REGNUM,           		\
mgl@1371
  9031
+  PC_REGNUM			\
mgl@1371
  9032
+}
mgl@1371
  9033
+
mgl@1371
  9034
+
mgl@1371
  9035
+/** How Values Fit in Registers **/
mgl@1371
  9036
+
mgl@1371
  9037
+/*
mgl@1371
  9038
+A C expression for the number of consecutive hard registers, starting
mgl@1371
  9039
+at register number REGNO, required to hold a value of mode
mgl@1371
  9040
+MODE.
mgl@1371
  9041
+
mgl@1371
  9042
+On a machine where all registers are exactly one word, a suitable
mgl@1371
  9043
+definition of this macro is
mgl@1371
  9044
+
mgl@1371
  9045
+#define HARD_REGNO_NREGS(REGNO, MODE)            \
mgl@1371
  9046
+   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
mgl@1371
  9047
+    / UNITS_PER_WORD)
mgl@1371
  9048
+*/
mgl@1371
  9049
+#define HARD_REGNO_NREGS(REGNO, MODE) \
mgl@1371
  9050
+  ((unsigned int)((GET_MODE_SIZE(MODE) + UNITS_PER_WORD -1 ) / UNITS_PER_WORD))
mgl@1371
  9051
+
mgl@1371
  9052
+/*
mgl@1371
  9053
+A C expression that is nonzero if it is permissible to store a value
mgl@1371
  9054
+of mode MODE in hard register number REGNO (or in several
mgl@1371
  9055
+registers starting with that one).  For a machine where all registers
mgl@1371
  9056
+are equivalent, a suitable definition is
mgl@1371
  9057
+
mgl@1371
  9058
+  #define HARD_REGNO_MODE_OK(REGNO, MODE) 1
mgl@1371
  9059
+
mgl@1371
  9060
+You need not include code to check for the numbers of fixed registers,
mgl@1371
  9061
+because the allocation mechanism considers them to be always occupied.
mgl@1371
  9062
+
mgl@1371
  9063
+On some machines, double-precision values must be kept in even/odd
mgl@1371
  9064
+register pairs.  You can implement that by defining this macro to reject
mgl@1371
  9065
+odd register numbers for such modes.
mgl@1371
  9066
+
mgl@1371
  9067
+The minimum requirement for a mode to be OK in a register is that the
mgl@1371
  9068
+mov[mode] instruction pattern support moves between the
mgl@1371
  9069
+register and other hard register in the same class and that moving a
mgl@1371
  9070
+value into the register and back out not alter it.
mgl@1371
  9071
+
mgl@1371
  9072
+Since the same instruction used to move word_mode will work for
mgl@1371
  9073
+all narrower integer modes, it is not necessary on any machine for
mgl@1371
  9074
+HARD_REGNO_MODE_OK to distinguish between these modes, provided
mgl@1371
  9075
+you define patterns movhi, etc., to take advantage of this.  This
mgl@1371
  9076
+is useful because of the interaction between HARD_REGNO_MODE_OK
mgl@1371
  9077
+and MODES_TIEABLE_P; it is very desirable for all integer modes
mgl@1371
  9078
+to be tieable.
mgl@1371
  9079
+
mgl@1371
  9080
+Many machines have special registers for floating point arithmetic.
mgl@1371
  9081
+Often people assume that floating point machine modes are allowed only
mgl@1371
  9082
+in floating point registers.  This is not true.  Any registers that
mgl@1371
  9083
+can hold integers can safely hold a floating point machine
mgl@1371
  9084
+mode, whether or not floating arithmetic can be done on it in those
mgl@1371
  9085
+registers.  Integer move instructions can be used to move the values.
mgl@1371
  9086
+
mgl@1371
  9087
+On some machines, though, the converse is true: fixed-point machine
mgl@1371
  9088
+modes may not go in floating registers.  This is true if the floating
mgl@1371
  9089
+registers normalize any value stored in them, because storing a
mgl@1371
  9090
+non-floating value there would garble it.  In this case,
mgl@1371
  9091
+HARD_REGNO_MODE_OK should reject fixed-point machine modes in
mgl@1371
  9092
+floating registers.  But if the floating registers do not automatically
mgl@1371
  9093
+normalize, if you can store any bit pattern in one and retrieve it
mgl@1371
  9094
+unchanged without a trap, then any machine mode may go in a floating
mgl@1371
  9095
+register, so you can define this macro to say so.
mgl@1371
  9096
+
mgl@1371
  9097
+The primary significance of special floating registers is rather that
mgl@1371
  9098
+they are the registers acceptable in floating point arithmetic
mgl@1371
  9099
+instructions.  However, this is of no concern to
mgl@1371
  9100
+HARD_REGNO_MODE_OK.  You handle it by writing the proper
mgl@1371
  9101
+constraints for those instructions.
mgl@1371
  9102
+
mgl@1371
  9103
+On some machines, the floating registers are especially slow to access,
mgl@1371
  9104
+so that it is better to store a value in a stack frame than in such a
mgl@1371
  9105
+register if floating point arithmetic is not being done.  As long as the
mgl@1371
  9106
+floating registers are not in class GENERAL_REGS, they will not
mgl@1371
  9107
+be used unless some pattern's constraint asks for one.
mgl@1371
  9108
+*/
mgl@1371
  9109
+#define HARD_REGNO_MODE_OK(REGNO, MODE) avr32_hard_regno_mode_ok(REGNO, MODE)
mgl@1371
  9110
+
mgl@1371
  9111
+/*
mgl@1371
  9112
+A C expression that is nonzero if a value of mode
mgl@1371
  9113
+MODE1 is accessible in mode MODE2 without copying.
mgl@1371
  9114
+
mgl@1371
  9115
+If HARD_REGNO_MODE_OK(R, MODE1) and
mgl@1371
  9116
+HARD_REGNO_MODE_OK(R, MODE2) are always the same for
mgl@1371
  9117
+any R, then MODES_TIEABLE_P(MODE1, MODE2)
mgl@1371
  9118
+should be nonzero.  If they differ for any R, you should define
mgl@1371
  9119
+this macro to return zero unless some other mechanism ensures the
mgl@1371
  9120
+accessibility of the value in a narrower mode.
mgl@1371
  9121
+
mgl@1371
  9122
+You should define this macro to return nonzero in as many cases as
mgl@1371
  9123
+possible since doing so will allow GCC to perform better register
mgl@1371
  9124
+allocation.
mgl@1371
  9125
+*/
mgl@1371
  9126
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
mgl@1371
  9127
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
mgl@1371
  9128
+
mgl@1371
  9129
+
mgl@1371
  9130
+
mgl@1371
  9131
+/******************************************************************************
mgl@1371
  9132
+ * Register Classes
mgl@1371
  9133
+ *****************************************************************************/
mgl@1371
  9134
+
mgl@1371
  9135
+/*
mgl@1371
  9136
+An enumeral type that must be defined with all the register class names
mgl@1371
  9137
+as enumeral values.  NO_REGS must be first.  ALL_REGS
mgl@1371
  9138
+must be the last register class, followed by one more enumeral value,
mgl@1371
  9139
+LIM_REG_CLASSES, which is not a register class but rather
mgl@1371
  9140
+tells how many classes there are.
mgl@1371
  9141
+
mgl@1371
  9142
+Each register class has a number, which is the value of casting
mgl@1371
  9143
+the class name to type int.  The number serves as an index
mgl@1371
  9144
+in many of the tables described below.
mgl@1371
  9145
+*/
mgl@1371
  9146
+enum reg_class
mgl@1371
  9147
+{
mgl@1371
  9148
+  NO_REGS,
mgl@1371
  9149
+  GENERAL_REGS,
mgl@1371
  9150
+  FP_REGS,
mgl@1371
  9151
+  ALL_REGS,
mgl@1371
  9152
+  LIM_REG_CLASSES
mgl@1371
  9153
+};
mgl@1371
  9154
+
mgl@1371
  9155
+/*
mgl@1371
  9156
+The number of distinct register classes, defined as follows:
mgl@1371
  9157
+  #define N_REG_CLASSES (int) LIM_REG_CLASSES
mgl@1371
  9158
+*/
mgl@1371
  9159
+#define N_REG_CLASSES (int)LIM_REG_CLASSES
mgl@1371
  9160
+
mgl@1371
  9161
+/*
mgl@1371
  9162
+An initializer containing the names of the register classes as C string
mgl@1371
  9163
+constants.  These names are used in writing some of the debugging dumps.
mgl@1371
  9164
+*/
mgl@1371
  9165
+#define REG_CLASS_NAMES		\
mgl@1371
  9166
+{				\
mgl@1371
  9167
+  "NO_REGS",			\
mgl@1371
  9168
+  "GENERAL_REGS",		\
mgl@1371
  9169
+  "FLOATING_POINT_REGS",	\
mgl@1371
  9170
+  "ALL_REGS"			\
mgl@1371
  9171
+}
mgl@1371
  9172
+
mgl@1371
  9173
+/*
mgl@1371
  9174
+An initializer containing the contents of the register classes, as integers
mgl@1371
  9175
+which are bit masks.  The nth integer specifies the contents of class
mgl@1371
  9176
+n.  The way the integer mask is interpreted is that
mgl@1371
  9177
+register r is in the class if mask & (1 << r) is 1.
mgl@1371
  9178
+
mgl@1371
  9179
+When the machine has more than 32 registers, an integer does not suffice.
mgl@1371
  9180
+Then the integers are replaced by sub-initializers, braced groupings containing
mgl@1371
  9181
+several integers.  Each sub-initializer must be suitable as an initializer
mgl@1371
  9182
+for the type HARD_REG_SET which is defined in hard-reg-set.h.
mgl@1371
  9183
+In this situation, the first integer in each sub-initializer corresponds to
mgl@1371
  9184
+registers 0 through 31, the second integer to registers 32 through 63, and
mgl@1371
  9185
+so on.
mgl@1371
  9186
+*/
mgl@1371
  9187
+#define REG_CLASS_CONTENTS {		\
mgl@1371
  9188
+  {0x00000000}, /* NO_REGS */		\
mgl@1371
  9189
+  {0x0000FFFF}, /* GENERAL_REGS */	\
mgl@1371
  9190
+  {0xFFFF0000}, /* FP_REGS */		\
mgl@1371
  9191
+  {0x7FFFFFFF}, /* ALL_REGS */		\
mgl@1371
  9192
+}
mgl@1371
  9193
+
mgl@1371
  9194
+
mgl@1371
  9195
+/*
mgl@1371
  9196
+A C expression whose value is a register class containing hard register
mgl@1371
  9197
+REGNO.  In general there is more than one such class; choose a class
mgl@1371
  9198
+which is minimal, meaning that no smaller class also contains the
mgl@1371
  9199
+register.
mgl@1371
  9200
+*/
mgl@1371
  9201
+#define REGNO_REG_CLASS(REGNO) ((REGNO < 16) ? GENERAL_REGS : FP_REGS)
mgl@1371
  9202
+
mgl@1371
  9203
+/*
mgl@1371
  9204
+A macro whose definition is the name of the class to which a valid
mgl@1371
  9205
+base register must belong.  A base register is one used in an address
mgl@1371
  9206
+which is the register value plus a displacement.
mgl@1371
  9207
+*/
mgl@1371
  9208
+#define BASE_REG_CLASS GENERAL_REGS
mgl@1371
  9209
+
mgl@1371
  9210
+/*
mgl@1371
  9211
+This is a variation of the BASE_REG_CLASS macro which allows
mgl@1371
  9212
+the selection of a base register in a mode depenedent manner.  If
mgl@1371
  9213
+mode is VOIDmode then it should return the same value as
mgl@1371
  9214
+BASE_REG_CLASS.
mgl@1371
  9215
+*/
mgl@1371
  9216
+#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
mgl@1371
  9217
+
mgl@1371
  9218
+/*
mgl@1371
  9219
+A macro whose definition is the name of the class to which a valid
mgl@1371
  9220
+index register must belong.  An index register is one used in an
mgl@1371
  9221
+address where its value is either multiplied by a scale factor or
mgl@1371
  9222
+added to another register (as well as added to a displacement).
mgl@1371
  9223
+*/
mgl@1371
  9224
+#define INDEX_REG_CLASS BASE_REG_CLASS
mgl@1371
  9225
+
mgl@1371
  9226
+/*
mgl@1371
  9227
+A C expression which defines the machine-dependent operand constraint
mgl@1371
  9228
+letters for register classes.  If CHAR is such a letter, the
mgl@1371
  9229
+value should be the register class corresponding to it.  Otherwise,
mgl@1371
  9230
+the value should be NO_REGS.  The register letter r,
mgl@1371
  9231
+corresponding to class GENERAL_REGS, will not be passed
mgl@1371
  9232
+to this macro; you do not need to handle it.
mgl@1371
  9233
+*/
mgl@1371
  9234
+#define REG_CLASS_FROM_LETTER(CHAR) ((CHAR) == 'f' ? FP_REGS : NO_REGS)
mgl@1371
  9235
+
mgl@1371
  9236
+
mgl@1371
  9237
+/* These assume that REGNO is a hard or pseudo reg number.
mgl@1371
  9238
+   They give nonzero only if REGNO is a hard reg of the suitable class
mgl@1371
  9239
+   or a pseudo reg currently allocated to a suitable hard reg.
mgl@1371
  9240
+   Since they use reg_renumber, they are safe only once reg_renumber
mgl@1371
  9241
+   has been allocated, which happens in local-alloc.c.  */
mgl@1371
  9242
+#define TEST_REGNO(R, TEST, VALUE) \
mgl@1371
  9243
+  ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE))
mgl@1371
  9244
+
mgl@1371
  9245
+/*
mgl@1371
  9246
+A C expression which is nonzero if register number num is suitable for use as a base
mgl@1371
  9247
+register in operand addresses. It may be either a suitable hard register or a pseudo
mgl@1371
  9248
+register that has been allocated such a hard register.
mgl@1371
  9249
+*/
mgl@1371
  9250
+#define REGNO_OK_FOR_BASE_P(NUM)  TEST_REGNO(NUM, <=, LAST_REGNUM)
mgl@1371
  9251
+
mgl@1371
  9252
+/*
mgl@1371
  9253
+A C expression which is nonzero if register number NUM is
mgl@1371
  9254
+suitable for use as an index register in operand addresses.  It may be
mgl@1371
  9255
+either a suitable hard register or a pseudo register that has been
mgl@1371
  9256
+allocated such a hard register.
mgl@1371
  9257
+
mgl@1371
  9258
+The difference between an index register and a base register is that
mgl@1371
  9259
+the index register may be scaled.  If an address involves the sum of
mgl@1371
  9260
+two registers, neither one of them scaled, then either one may be
mgl@1371
  9261
+labeled the ``base'' and the other the ``index''; but whichever
mgl@1371
  9262
+labeling is used must fit the machine's constraints of which registers
mgl@1371
  9263
+may serve in each capacity.  The compiler will try both labelings,
mgl@1371
  9264
+looking for one that is valid, and will reload one or both registers
mgl@1371
  9265
+only if neither labeling works.
mgl@1371
  9266
+*/
mgl@1371
  9267
+#define REGNO_OK_FOR_INDEX_P(NUM) TEST_REGNO(NUM, <=, LAST_REGNUM)
mgl@1371
  9268
+
mgl@1371
  9269
+/*
mgl@1371
  9270
+A C expression that places additional restrictions on the register class
mgl@1371
  9271
+to use when it is necessary to copy value X into a register in class
mgl@1371
  9272
+CLASS.  The value is a register class; perhaps CLASS, or perhaps
mgl@1371
  9273
+another, smaller class.  On many machines, the following definition is
mgl@1371
  9274
+safe: #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
mgl@1371
  9275
+
mgl@1371
  9276
+Sometimes returning a more restrictive class makes better code.  For
mgl@1371
  9277
+example, on the 68000, when X is an integer constant that is in range
mgl@1371
  9278
+for a 'moveq' instruction, the value of this macro is always
mgl@1371
  9279
+DATA_REGS as long as CLASS includes the data registers.
mgl@1371
  9280
+Requiring a data register guarantees that a 'moveq' will be used.
mgl@1371
  9281
+
mgl@1371
  9282
+If X is a const_double, by returning NO_REGS
mgl@1371
  9283
+you can force X into a memory constant.  This is useful on
mgl@1371
  9284
+certain machines where immediate floating values cannot be loaded into
mgl@1371
  9285
+certain kinds of registers.
mgl@1371
  9286
+*/
mgl@1371
  9287
+#define PREFERRED_RELOAD_CLASS(X, CLASS)  CLASS
mgl@1371
  9288
+
mgl@1371
  9289
+
mgl@1371
  9290
+
mgl@1371
  9291
+/*
mgl@1371
  9292
+A C expression for the maximum number of consecutive registers
mgl@1371
  9293
+of class CLASS needed to hold a value of mode MODE.
mgl@1371
  9294
+
mgl@1371
  9295
+This is closely related to the macro HARD_REGNO_NREGS.  In fact,
mgl@1371
  9296
+the value of the macro CLASS_MAX_NREGS(CLASS, MODE)
mgl@1371
  9297
+should be the maximum value of HARD_REGNO_NREGS(REGNO, MODE)
mgl@1371
  9298
+for all REGNO values in the class CLASS.
mgl@1371
  9299
+
mgl@1371
  9300
+This macro helps control the handling of multiple-word values
mgl@1371
  9301
+in the reload pass.
mgl@1371
  9302
+*/
mgl@1371
  9303
+#define CLASS_MAX_NREGS(CLASS, MODE) /* ToDo:fixme */ \
mgl@1371
  9304
+  (unsigned int)((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
mgl@1371
  9305
+
mgl@1371
  9306
+
mgl@1371
  9307
+/*
mgl@1371
  9308
+  Using CONST_OK_FOR_CONSTRAINT_P instead of CONS_OK_FOR_LETTER_P
mgl@1371
  9309
+  in order to support constraints with more than one letter.
mgl@1371
  9310
+  Only two letters are then used for constant constraints,
mgl@1371
  9311
+  the letter 'K' and the letter 'I'. The constraint starting with
mgl@1371
  9312
+  these letters must consist of four characters. The character following
mgl@1371
  9313
+  'K' or 'I' must be either 'u' (unsigned) or 's' (signed) to specify
mgl@1371
  9314
+  if the constant is zero or sign extended. The last two characters specify
mgl@1371
  9315
+  the length in bits of the constant. The base constraint letter 'I' means
mgl@1371
  9316
+  that this is an negated constant, meaning that actually -VAL should be
mgl@1371
  9317
+  checked to lie withing the valid range instead of VAL which is used when
mgl@1371
  9318
+  'K' is the base constraint letter.
mgl@1371
  9319
+
mgl@1371
  9320
+*/
mgl@1371
  9321
+
mgl@1371
  9322
+#define CONSTRAINT_LEN(C, STR)				\
mgl@1371
  9323
+  ( ((C) == 'K' || (C) == 'I') ?  4 :			\
mgl@1371
  9324
+    ((C) == 'R') ?  5 :					\
mgl@1371
  9325
+    ((C) == 'P') ? -1 :                                 \
mgl@1371
  9326
+    DEFAULT_CONSTRAINT_LEN((C), (STR)) )
mgl@1371
  9327
+
mgl@1371
  9328
+#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR)	\
mgl@1371
  9329
+  avr32_const_ok_for_constraint_p(VALUE, C, STR)
mgl@1371
  9330
+
mgl@1371
  9331
+/*
mgl@1371
  9332
+A C expression that defines the machine-dependent operand constraint
mgl@1371
  9333
+letters that specify particular ranges of const_double values ('G' or 'H').
mgl@1371
  9334
+
mgl@1371
  9335
+If C is one of those letters, the expression should check that
mgl@1371
  9336
+VALUE, an RTX of code const_double, is in the appropriate
mgl@1371
  9337
+range and return 1 if so, 0 otherwise.  If C is not one of those
mgl@1371
  9338
+letters, the value should be 0 regardless of VALUE.
mgl@1371
  9339
+
mgl@1371
  9340
+const_double is used for all floating-point constants and for
mgl@1371
  9341
+DImode fixed-point constants.  A given letter can accept either
mgl@1371
  9342
+or both kinds of values.  It can use GET_MODE to distinguish
mgl@1371
  9343
+between these kinds.
mgl@1371
  9344
+*/
mgl@1371
  9345
+#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \
mgl@1371
  9346
+  ((C) == 'G' ? avr32_const_double_immediate(OP) : 0)
mgl@1371
  9347
+
mgl@1371
  9348
+/*
mgl@1371
  9349
+A C expression that defines the optional machine-dependent constraint
mgl@1371
  9350
+letters that can be used to segregate specific types of operands, usually
mgl@1371
  9351
+memory references, for the target machine.  Any letter that is not
mgl@1371
  9352
+elsewhere defined and not matched by REG_CLASS_FROM_LETTER
mgl@1371
  9353
+may be used.  Normally this macro will not be defined.
mgl@1371
  9354
+
mgl@1371
  9355
+If it is required for a particular target machine, it should return 1
mgl@1371
  9356
+if VALUE corresponds to the operand type represented by the
mgl@1371
  9357
+constraint letter C.  If C is not defined as an extra
mgl@1371
  9358
+constraint, the value returned should be 0 regardless of VALUE.
mgl@1371
  9359
+
mgl@1371
  9360
+For example, on the ROMP, load instructions cannot have their output
mgl@1371
  9361
+in r0 if the memory reference contains a symbolic address.  Constraint
mgl@1371
  9362
+letter 'Q' is defined as representing a memory address that does
mgl@1371
  9363
+not contain a symbolic address.  An alternative is specified with
mgl@1371
  9364
+a 'Q' constraint on the input and 'r' on the output.  The next
mgl@1371
  9365
+alternative specifies 'm' on the input and a register class that
mgl@1371
  9366
+does not include r0 on the output.
mgl@1371
  9367
+*/
mgl@1371
  9368
+#define EXTRA_CONSTRAINT_STR(OP, C, STR)				\
mgl@1371
  9369
+  ((C) == 'W' ? avr32_address_operand(OP, GET_MODE(OP)) :		\
mgl@1371
  9370
+   (C) == 'R' ? (avr32_indirect_register_operand(OP, GET_MODE(OP)) ||	\
mgl@1371
  9371
+                 (avr32_imm_disp_memory_operand(OP, GET_MODE(OP))	\
mgl@1371
  9372
+                  && avr32_const_ok_for_constraint_p(			\
mgl@1371
  9373
+				INTVAL(XEXP(XEXP(OP, 0), 1)),		\
mgl@1371
  9374
+				(STR)[1], &(STR)[1]))) :		\
mgl@1371
  9375
+   (C) == 'S' ? avr32_indexed_memory_operand(OP, GET_MODE(OP)) :	\
mgl@1371
  9376
+   (C) == 'T' ? avr32_const_pool_ref_operand(OP, GET_MODE(OP)) :	\
mgl@1371
  9377
+   (C) == 'U' ? SYMBOL_REF_RCALL_FUNCTION_P(OP) :			\
mgl@1371
  9378
+   (C) == 'Z' ? avr32_cop_memory_operand(OP, GET_MODE(OP)) :		\
mgl@1371
  9379
+   (C) == 'Q' ? avr32_non_rmw_memory_operand(OP, GET_MODE(OP)) :		\
mgl@1371
  9380
+   (C) == 'Y' ? avr32_rmw_memory_operand(OP, GET_MODE(OP)) :            \
mgl@1371
  9381
+   0)
mgl@1371
  9382
+
mgl@1371
  9383
+
mgl@1371
  9384
+#define EXTRA_MEMORY_CONSTRAINT(C, STR) ( ((C) == 'R') ||               \
mgl@1371
  9385
+                                          ((C) == 'Q') ||               \
mgl@1371
  9386
+                                          ((C) == 'S') ||               \
mgl@1371
  9387
+                                          ((C) == 'Y') ||               \
mgl@1371
  9388
+                                          ((C) == 'Z') )
mgl@1371
  9389
+
mgl@1371
  9390
+
mgl@1371
  9391
+/* Returns nonzero if op is a function SYMBOL_REF which
mgl@1371
  9392
+   can be called using an rcall instruction */
mgl@1371
  9393
+#define SYMBOL_REF_RCALL_FUNCTION_P(op)  \
mgl@1371
  9394
+  ( GET_CODE(op) == SYMBOL_REF           \
mgl@1371
  9395
+    && SYMBOL_REF_FUNCTION_P(op)         \
mgl@1371
  9396
+    && SYMBOL_REF_LOCAL_P(op)            \
mgl@1371
  9397
+    && !SYMBOL_REF_EXTERNAL_P(op)        \
mgl@1371
  9398
+    && !TARGET_HAS_ASM_ADDR_PSEUDOS )
mgl@1371
  9399
+
mgl@1371
  9400
+/******************************************************************************
mgl@1371
  9401
+ * Stack Layout and Calling Conventions
mgl@1371
  9402
+ *****************************************************************************/
mgl@1371
  9403
+
mgl@1371
  9404
+/** Basic Stack Layout **/
mgl@1371
  9405
+
mgl@1371
  9406
+/*
mgl@1371
  9407
+Define this macro if pushing a word onto the stack moves the stack
mgl@1371
  9408
+pointer to a smaller address.
mgl@1371
  9409
+
mgl@1371
  9410
+When we say, ``define this macro if ...,'' it means that the
mgl@1371
  9411
+compiler checks this macro only with #ifdef so the precise
mgl@1371
  9412
+definition used does not matter.
mgl@1371
  9413
+*/
mgl@1371
  9414
+/* pushm decrece SP: *(--SP) <-- Rx */
mgl@1371
  9415
+#define STACK_GROWS_DOWNWARD
mgl@1371
  9416
+
mgl@1371
  9417
+/*
mgl@1371
  9418
+This macro defines the operation used when something is pushed
mgl@1371
  9419
+on the stack.  In RTL, a push operation will be
mgl@1371
  9420
+(set (mem (STACK_PUSH_CODE (reg sp))) ...)
mgl@1371
  9421
+
mgl@1371
  9422
+The choices are PRE_DEC, POST_DEC, PRE_INC,
mgl@1371
  9423
+and POST_INC.  Which of these is correct depends on
mgl@1371
  9424
+the stack direction and on whether the stack pointer points
mgl@1371
  9425
+to the last item on the stack or whether it points to the
mgl@1371
  9426
+space for the next item on the stack.
mgl@1371
  9427
+
mgl@1371
  9428
+The default is PRE_DEC when STACK_GROWS_DOWNWARD is
mgl@1371
  9429
+defined, which is almost always right, and PRE_INC otherwise,
mgl@1371
  9430
+which is often wrong.
mgl@1371
  9431
+*/
mgl@1371
  9432
+/* pushm: *(--SP) <-- Rx */
mgl@1371
  9433
+#define STACK_PUSH_CODE PRE_DEC
mgl@1371
  9434
+
mgl@1371
  9435
+/* Define this to nonzero if the nominal address of the stack frame
mgl@1371
  9436
+   is at the high-address end of the local variables;
mgl@1371
  9437
+   that is, each additional local variable allocated
mgl@1371
  9438
+   goes at a more negative offset in the frame.  */
mgl@1371
  9439
+#define FRAME_GROWS_DOWNWARD 1
mgl@1371
  9440
+
mgl@1371
  9441
+
mgl@1371
  9442
+/*
mgl@1371
  9443
+Offset from the frame pointer to the first local variable slot to be allocated.
mgl@1371
  9444
+
mgl@1371
  9445
+If FRAME_GROWS_DOWNWARD, find the next slot's offset by
mgl@1371
  9446
+subtracting the first slot's length from STARTING_FRAME_OFFSET.
mgl@1371
  9447
+Otherwise, it is found by adding the length of the first slot to the
mgl@1371
  9448
+value STARTING_FRAME_OFFSET.
mgl@1371
  9449
+  (i'm not sure if the above is still correct.. had to change it to get
mgl@1371
  9450
+   rid of an overfull.  --mew 2feb93 )
mgl@1371
  9451
+*/
mgl@1371
  9452
+#define STARTING_FRAME_OFFSET 0
mgl@1371
  9453
+
mgl@1371
  9454
+/*
mgl@1371
  9455
+Offset from the stack pointer register to the first location at which
mgl@1371
  9456
+outgoing arguments are placed.  If not specified, the default value of
mgl@1371
  9457
+zero is used.  This is the proper value for most machines.
mgl@1371
  9458
+
mgl@1371
  9459
+If ARGS_GROW_DOWNWARD, this is the offset to the location above
mgl@1371
  9460
+the first location at which outgoing arguments are placed.
mgl@1371
  9461
+*/
mgl@1371
  9462
+#define STACK_POINTER_OFFSET 0
mgl@1371
  9463
+
mgl@1371
  9464
+/*
mgl@1371
  9465
+Offset from the argument pointer register to the first argument's
mgl@1371
  9466
+address.  On some machines it may depend on the data type of the
mgl@1371
  9467
+function.
mgl@1371
  9468
+
mgl@1371
  9469
+If ARGS_GROW_DOWNWARD, this is the offset to the location above
mgl@1371
  9470
+the first argument's address.
mgl@1371
  9471
+*/
mgl@1371
  9472
+#define FIRST_PARM_OFFSET(FUNDECL) 0
mgl@1371
  9473
+
mgl@1371
  9474
+
mgl@1371
  9475
+/*
mgl@1371
  9476
+A C expression whose value is RTL representing the address in a stack
mgl@1371
  9477
+frame where the pointer to the caller's frame is stored.  Assume that
mgl@1371
  9478
+FRAMEADDR is an RTL expression for the address of the stack frame
mgl@1371
  9479
+itself.
mgl@1371
  9480
+
mgl@1371
  9481
+If you don't define this macro, the default is to return the value
mgl@1371
  9482
+of FRAMEADDR - that is, the stack frame address is also the
mgl@1371
  9483
+address of the stack word that points to the previous frame.
mgl@1371
  9484
+*/
mgl@1371
  9485
+#define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) plus_constant ((FRAMEADDR), 4)
mgl@1371
  9486
+
mgl@1371
  9487
+
mgl@1371
  9488
+/*
mgl@1371
  9489
+A C expression whose value is RTL representing the value of the return
mgl@1371
  9490
+address for the frame COUNT steps up from the current frame, after
mgl@1371
  9491
+the prologue.  FRAMEADDR is the frame pointer of the COUNT
mgl@1371
  9492
+frame, or the frame pointer of the COUNT - 1 frame if
mgl@1371
  9493
+RETURN_ADDR_IN_PREVIOUS_FRAME is defined.
mgl@1371
  9494
+
mgl@1371
  9495
+The value of the expression must always be the correct address when
mgl@1371
  9496
+COUNT is zero, but may be NULL_RTX if there is not way to
mgl@1371
  9497
+determine the return address of other frames.
mgl@1371
  9498
+*/
mgl@1371
  9499
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) avr32_return_addr(COUNT, FRAMEADDR)
mgl@1371
  9500
+
mgl@1371
  9501
+
mgl@1371
  9502
+/*
mgl@1371
  9503
+A C expression whose value is RTL representing the location of the
mgl@1371
  9504
+incoming return address at the beginning of any function, before the
mgl@1371
  9505
+prologue.  This RTL is either a REG, indicating that the return
mgl@1371
  9506
+value is saved in 'REG', or a MEM representing a location in
mgl@1371
  9507
+the stack.
mgl@1371
  9508
+
mgl@1371
  9509
+You only need to define this macro if you want to support call frame
mgl@1371
  9510
+debugging information like that provided by DWARF 2.
mgl@1371
  9511
+
mgl@1371
  9512
+If this RTL is a REG, you should also define
mgl@1371
  9513
+DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM (REGNO).
mgl@1371
  9514
+*/
mgl@1371
  9515
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LR_REGNUM)
mgl@1371
  9516
+
mgl@1371
  9517
+
mgl@1371
  9518
+
mgl@1371
  9519
+/*
mgl@1371
  9520
+A C expression whose value is an integer giving the offset, in bytes,
mgl@1371
  9521
+from the value of the stack pointer register to the top of the stack
mgl@1371
  9522
+frame at the beginning of any function, before the prologue.  The top of
mgl@1371
  9523
+the frame is defined to be the value of the stack pointer in the
mgl@1371
  9524
+previous frame, just before the call instruction.
mgl@1371
  9525
+
mgl@1371
  9526
+You only need to define this macro if you want to support call frame
mgl@1371
  9527
+debugging information like that provided by DWARF 2.
mgl@1371
  9528
+*/
mgl@1371
  9529
+#define INCOMING_FRAME_SP_OFFSET 0
mgl@1371
  9530
+
mgl@1371
  9531
+
mgl@1371
  9532
+/** Exception Handling Support **/
mgl@1371
  9533
+
mgl@1371
  9534
+/* Use setjump/longjump for exception handling. */
mgl@1371
  9535
+#define DWARF2_UNWIND_INFO 0
mgl@1371
  9536
+#define MUST_USE_SJLJ_EXCEPTIONS 1
mgl@1371
  9537
+
mgl@1371
  9538
+/*
mgl@1371
  9539
+A C expression whose value is the Nth register number used for
mgl@1371
  9540
+data by exception handlers, or INVALID_REGNUM if fewer than
mgl@1371
  9541
+N registers are usable.
mgl@1371
  9542
+
mgl@1371
  9543
+The exception handling library routines communicate with the exception
mgl@1371
  9544
+handlers via a set of agreed upon registers.  Ideally these registers
mgl@1371
  9545
+should be call-clobbered; it is possible to use call-saved registers,
mgl@1371
  9546
+but may negatively impact code size.  The target must support at least
mgl@1371
  9547
+2 data registers, but should define 4 if there are enough free registers.
mgl@1371
  9548
+
mgl@1371
  9549
+You must define this macro if you want to support call frame exception
mgl@1371
  9550
+handling like that provided by DWARF 2.
mgl@1371
  9551
+*/
mgl@1371
  9552
+/*
mgl@1371
  9553
+  Use r9-r11
mgl@1371
  9554
+*/
mgl@1371
  9555
+#define EH_RETURN_DATA_REGNO(N)                                         \
mgl@1371
  9556
+  ((N<3) ? INTERNAL_REGNUM(N+9) : INVALID_REGNUM)
mgl@1371
  9557
+
mgl@1371
  9558
+/*
mgl@1371
  9559
+A C expression whose value is RTL representing a location in which
mgl@1371
  9560
+to store a stack adjustment to be applied before function return.
mgl@1371
  9561
+This is used to unwind the stack to an exception handler's call frame.
mgl@1371
  9562
+It will be assigned zero on code paths that return normally.
mgl@1371
  9563
+
mgl@1371
  9564
+Typically this is a call-clobbered hard register that is otherwise
mgl@1371
  9565
+untouched by the epilogue, but could also be a stack slot.
mgl@1371
  9566
+
mgl@1371
  9567
+You must define this macro if you want to support call frame exception
mgl@1371
  9568
+handling like that provided by DWARF 2.
mgl@1371
  9569
+*/
mgl@1371
  9570
+/*
mgl@1371
  9571
+  Use r8
mgl@1371
  9572
+*/
mgl@1371
  9573
+#define EH_RETURN_STACKADJ_REGNO INTERNAL_REGNUM(8)
mgl@1371
  9574
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG(SImode, EH_RETURN_STACKADJ_REGNO)
mgl@1371
  9575
+
mgl@1371
  9576
+/*
mgl@1371
  9577
+A C expression whose value is RTL representing a location in which
mgl@1371
  9578
+to store the address of an exception handler to which we should
mgl@1371
  9579
+return.  It will not be assigned on code paths that return normally.
mgl@1371
  9580
+
mgl@1371
  9581
+Typically this is the location in the call frame at which the normal
mgl@1371
  9582
+return address is stored.  For targets that return by popping an
mgl@1371
  9583
+address off the stack, this might be a memory address just below
mgl@1371
  9584
+the target call frame rather than inside the current call
mgl@1371
  9585
+frame.  EH_RETURN_STACKADJ_RTX will have already been assigned,
mgl@1371
  9586
+so it may be used to calculate the location of the target call frame.
mgl@1371
  9587
+
mgl@1371
  9588
+Some targets have more complex requirements than storing to an
mgl@1371
  9589
+address calculable during initial code generation.  In that case
mgl@1371
  9590
+the eh_return instruction pattern should be used instead.
mgl@1371
  9591
+
mgl@1371
  9592
+If you want to support call frame exception handling, you must
mgl@1371
  9593
+define either this macro or the eh_return instruction pattern.
mgl@1371
  9594
+*/
mgl@1371
  9595
+/*
mgl@1371
  9596
+  We define the eh_return instruction pattern, so this isn't needed.
mgl@1371
  9597
+*/
mgl@1371
  9598
+/* #define EH_RETURN_HANDLER_RTX gen_rtx_REG(Pmode, RET_REGISTER) */
mgl@1371
  9599
+
mgl@1371
  9600
+/*
mgl@1371
  9601
+  This macro chooses the encoding of pointers embedded in the
mgl@1371
  9602
+  exception handling sections. If at all possible, this should be
mgl@1371
  9603
+  defined such that the exception handling section will not require
mgl@1371
  9604
+  dynamic relocations, and so may be read-only.
mgl@1371
  9605
+
mgl@1371
  9606
+  code is 0 for data, 1 for code labels, 2 for function
mgl@1371
  9607
+  pointers. global is true if the symbol may be affected by dynamic
mgl@1371
  9608
+  relocations. The macro should return a combination of the DW_EH_PE_*
mgl@1371
  9609
+  defines as found in dwarf2.h.
mgl@1371
  9610
+
mgl@1371
  9611
+  If this macro is not defined, pointers will not be encoded but
mgl@1371
  9612
+  represented directly.
mgl@1371
  9613
+*/
mgl@1371
  9614
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)	\
mgl@1371
  9615
+  ((flag_pic && (GLOBAL) ? DW_EH_PE_indirect : 0)	\
mgl@1371
  9616
+   | (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr)	\
mgl@1371
  9617
+   | DW_EH_PE_sdata4)
mgl@1371
  9618
+
mgl@1371
  9619
+/* ToDo: The rest of this subsection */
mgl@1371
  9620
+
mgl@1371
  9621
+/** Specifying How Stack Checking is Done **/
mgl@1371
  9622
+/* ToDo: All in this subsection */
mgl@1371
  9623
+
mgl@1371
  9624
+/** Registers That Address the Stack Frame **/
mgl@1371
  9625
+
mgl@1371
  9626
+/*
mgl@1371
  9627
+The register number of the stack pointer register, which must also be a
mgl@1371
  9628
+fixed register according to FIXED_REGISTERS.  On most machines,
mgl@1371
  9629
+the hardware determines which register this is.
mgl@1371
  9630
+*/
mgl@1371
  9631
+/* Using r13 as stack pointer. */
mgl@1371
  9632
+#define STACK_POINTER_REGNUM INTERNAL_REGNUM(13)
mgl@1371
  9633
+
mgl@1371
  9634
+/*
mgl@1371
  9635
+The register number of the frame pointer register, which is used to
mgl@1371
  9636
+access automatic variables in the stack frame.  On some machines, the
mgl@1371
  9637
+hardware determines which register this is.  On other machines, you can
mgl@1371
  9638
+choose any register you wish for this purpose.
mgl@1371
  9639
+*/
mgl@1371
  9640
+/* Use r7 */
mgl@1371
  9641
+#define FRAME_POINTER_REGNUM INTERNAL_REGNUM(7)
mgl@1371
  9642
+
mgl@1371
  9643
+
mgl@1371
  9644
+
mgl@1371
  9645
+/*
mgl@1371
  9646
+The register number of the arg pointer register, which is used to access
mgl@1371
  9647
+the function's argument list.  On some machines, this is the same as the
mgl@1371
  9648
+frame pointer register.  On some machines, the hardware determines which
mgl@1371
  9649
+register this is.  On other machines, you can choose any register you
mgl@1371
  9650
+wish for this purpose.  If this is not the same register as the frame
mgl@1371
  9651
+pointer register, then you must mark it as a fixed register according to
mgl@1371
  9652
+FIXED_REGISTERS, or arrange to be able to eliminate it (see Section
mgl@1371
  9653
+10.10.5 [Elimination], page 224).
mgl@1371
  9654
+*/
mgl@1371
  9655
+/* Using r5 */
mgl@1371
  9656
+#define ARG_POINTER_REGNUM INTERNAL_REGNUM(4)
mgl@1371
  9657
+
mgl@1371
  9658
+
mgl@1371
  9659
+/*
mgl@1371
  9660
+Register numbers used for passing a function's static chain pointer.  If
mgl@1371
  9661
+register windows are used, the register number as seen by the called
mgl@1371
  9662
+function is STATIC_CHAIN_INCOMING_REGNUM, while the register
mgl@1371
  9663
+number as seen by the calling function is STATIC_CHAIN_REGNUM.  If
mgl@1371
  9664
+these registers are the same, STATIC_CHAIN_INCOMING_REGNUM need
mgl@1371
  9665
+not be defined.
mgl@1371
  9666
+
mgl@1371
  9667
+The static chain register need not be a fixed register.
mgl@1371
  9668
+
mgl@1371
  9669
+If the static chain is passed in memory, these macros should not be
mgl@1371
  9670
+defined; instead, the next two macros should be defined.
mgl@1371
  9671
+*/
mgl@1371
  9672
+/* Using r0 */
mgl@1371
  9673
+#define STATIC_CHAIN_REGNUM INTERNAL_REGNUM(0)
mgl@1371
  9674
+
mgl@1371
  9675
+
mgl@1371
  9676
+/** Eliminating Frame Pointer and Arg Pointer **/
mgl@1371
  9677
+
mgl@1371
  9678
+/*
mgl@1371
  9679
+A C expression which is nonzero if a function must have and use a frame
mgl@1371
  9680
+pointer.  This expression is evaluated  in the reload pass.  If its value is
mgl@1371
  9681
+nonzero the function will have a frame pointer.
mgl@1371
  9682
+
mgl@1371
  9683
+The expression can in principle examine the current function and decide
mgl@1371
  9684
+according to the facts, but on most machines the constant 0 or the
mgl@1371
  9685
+constant 1 suffices.  Use 0 when the machine allows code to be generated
mgl@1371
  9686
+with no frame pointer, and doing so saves some time or space.  Use 1
mgl@1371
  9687
+when there is no possible advantage to avoiding a frame pointer.
mgl@1371
  9688
+
mgl@1371
  9689
+In certain cases, the compiler does not know how to produce valid code
mgl@1371
  9690
+without a frame pointer.  The compiler recognizes those cases and
mgl@1371
  9691
+automatically gives the function a frame pointer regardless of what
mgl@1371
  9692
+FRAME_POINTER_REQUIRED says.  You don't need to worry about
mgl@1371
  9693
+them.
mgl@1371
  9694
+
mgl@1371
  9695
+In a function that does not require a frame pointer, the frame pointer
mgl@1371
  9696
+register can be allocated for ordinary usage, unless you mark it as a
mgl@1371
  9697
+fixed register.  See FIXED_REGISTERS for more information.
mgl@1371
  9698
+*/
mgl@1371
  9699
+/* We need the frame pointer when compiling for profiling */
mgl@1371
  9700
+#define FRAME_POINTER_REQUIRED (current_function_profile)
mgl@1371
  9701
+
mgl@1371
  9702
+/*
mgl@1371
  9703
+A C statement to store in the variable DEPTH_VAR the difference
mgl@1371
  9704
+between the frame pointer and the stack pointer values immediately after
mgl@1371
  9705
+the function prologue.  The value would be computed from information
mgl@1371
  9706
+such as the result of get_frame_size () and the tables of
mgl@1371
  9707
+registers regs_ever_live and call_used_regs.
mgl@1371
  9708
+
mgl@1371
  9709
+If ELIMINABLE_REGS is defined, this macro will be not be used and
mgl@1371
  9710
+need not be defined.  Otherwise, it must be defined even if
mgl@1371
  9711
+FRAME_POINTER_REQUIRED is defined to always be true; in that
mgl@1371
  9712
+case, you may set DEPTH_VAR to anything.
mgl@1371
  9713
+*/
mgl@1371
  9714
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) ((DEPTH_VAR) = get_frame_size())
mgl@1371
  9715
+
mgl@1371
  9716
+/*
mgl@1371
  9717
+If defined, this macro specifies a table of register pairs used to
mgl@1371
  9718
+eliminate unneeded registers that point into the stack frame.  If it is not
mgl@1371
  9719
+defined, the only elimination attempted by the compiler is to replace
mgl@1371
  9720
+references to the frame pointer with references to the stack pointer.
mgl@1371
  9721
+
mgl@1371
  9722
+The definition of this macro is a list of structure initializations, each
mgl@1371
  9723
+of which specifies an original and replacement register.
mgl@1371
  9724
+
mgl@1371
  9725
+On some machines, the position of the argument pointer is not known until
mgl@1371
  9726
+the compilation is completed.  In such a case, a separate hard register
mgl@1371
  9727
+must be used for the argument pointer.  This register can be eliminated by
mgl@1371
  9728
+replacing it with either the frame pointer or the argument pointer,
mgl@1371
  9729
+depending on whether or not the frame pointer has been eliminated.
mgl@1371
  9730
+
mgl@1371
  9731
+In this case, you might specify:
mgl@1371
  9732
+  #define ELIMINABLE_REGS  \
mgl@1371
  9733
+  {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
mgl@1371
  9734
+   {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
mgl@1371
  9735
+   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
mgl@1371
  9736
+
mgl@1371
  9737
+Note that the elimination of the argument pointer with the stack pointer is
mgl@1371
  9738
+specified first since that is the preferred elimination.
mgl@1371
  9739
+*/
mgl@1371
  9740
+#define ELIMINABLE_REGS					\
mgl@1371
  9741
+{							\
mgl@1371
  9742
+  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },	\
mgl@1371
  9743
+  { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },		\
mgl@1371
  9744
+  { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }		\
mgl@1371
  9745
+}
mgl@1371
  9746
+
mgl@1371
  9747
+/*
mgl@1371
  9748
+A C expression that returns nonzero if the compiler is allowed to try
mgl@1371
  9749
+to replace register number FROM with register number
mgl@1371
  9750
+TO.  This macro need only be defined if ELIMINABLE_REGS
mgl@1371
  9751
+is defined, and will usually be the constant 1, since most of the cases
mgl@1371
  9752
+preventing register elimination are things that the compiler already
mgl@1371
  9753
+knows about.
mgl@1371
  9754
+*/
mgl@1371
  9755
+#define CAN_ELIMINATE(FROM, TO) 1
mgl@1371
  9756
+
mgl@1371
  9757
+/*
mgl@1371
  9758
+This macro is similar to INITIAL_FRAME_POINTER_OFFSET.  It
mgl@1371
  9759
+specifies the initial difference between the specified pair of
mgl@1371
  9760
+registers.  This macro must be defined if ELIMINABLE_REGS is
mgl@1371
  9761
+defined.
mgl@1371
  9762
+*/
mgl@1371
  9763
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)		\
mgl@1371
  9764
+  ((OFFSET) = avr32_initial_elimination_offset(FROM, TO))
mgl@1371
  9765
+
mgl@1371
  9766
+/** Passing Function Arguments on the Stack **/
mgl@1371
  9767
+
mgl@1371
  9768
+
mgl@1371
  9769
+/*
mgl@1371
  9770
+A C expression.  If nonzero, push insns will be used to pass
mgl@1371
  9771
+outgoing arguments.
mgl@1371
  9772
+If the target machine does not have a push instruction, set it to zero.
mgl@1371
  9773
+That directs GCC to use an alternate strategy: to
mgl@1371
  9774
+allocate the entire argument block and then store the arguments into
mgl@1371
  9775
+it.  When PUSH_ARGS is nonzero, PUSH_ROUNDING must be defined too.
mgl@1371
  9776
+*/
mgl@1371
  9777
+#define PUSH_ARGS 1
mgl@1371
  9778
+
mgl@1371
  9779
+
mgl@1371
  9780
+/*
mgl@1371
  9781
+A C expression that is the number of bytes actually pushed onto the
mgl@1371
  9782
+stack when an instruction attempts to push NPUSHED bytes.
mgl@1371
  9783
+
mgl@1371
  9784
+On some machines, the definition
mgl@1371
  9785
+
mgl@1371
  9786
+  #define PUSH_ROUNDING(BYTES) (BYTES)
mgl@1371
  9787
+
mgl@1371
  9788
+will suffice.  But on other machines, instructions that appear
mgl@1371
  9789
+to push one byte actually push two bytes in an attempt to maintain
mgl@1371
  9790
+alignment.  Then the definition should be
mgl@1371
  9791
+
mgl@1371
  9792
+  #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
mgl@1371
  9793
+*/
mgl@1371
  9794
+/* Push 4 bytes at the time. */
mgl@1371
  9795
+#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3)
mgl@1371
  9796
+
mgl@1371
  9797
+/*
mgl@1371
  9798
+A C expression.  If nonzero, the maximum amount of space required for
mgl@1371
  9799
+outgoing arguments will be computed and placed into the variable
mgl@1371
  9800
+current_function_outgoing_args_size.  No space will be pushed
mgl@1371
  9801
+onto the stack for each call; instead, the function prologue should
mgl@1371
  9802
+increase the stack frame size by this amount.
mgl@1371
  9803
+
mgl@1371
  9804
+Setting both PUSH_ARGS and ACCUMULATE_OUTGOING_ARGS is not proper.
mgl@1371
  9805
+*/
mgl@1371
  9806
+#define ACCUMULATE_OUTGOING_ARGS 0
mgl@1371
  9807
+
mgl@1371
  9808
+
mgl@1371
  9809
+
mgl@1371
  9810
+
mgl@1371
  9811
+/*
mgl@1371
  9812
+A C expression that should indicate the number of bytes of its own
mgl@1371
  9813
+arguments that a function pops on returning, or 0 if the
mgl@1371
  9814
+function pops no arguments and the caller must therefore pop them all
mgl@1371
  9815
+after the function returns.
mgl@1371
  9816
+
mgl@1371
  9817
+FUNDECL is a C variable whose value is a tree node that describes
mgl@1371
  9818
+the function in question.  Normally it is a node of type
mgl@1371
  9819
+FUNCTION_DECL that describes the declaration of the function.
mgl@1371
  9820
+From this you can obtain the DECL_ATTRIBUTES of the function.
mgl@1371
  9821
+
mgl@1371
  9822
+FUNTYPE is a C variable whose value is a tree node that
mgl@1371
  9823
+describes the function in question.  Normally it is a node of type
mgl@1371
  9824
+FUNCTION_TYPE that describes the data type of the function.
mgl@1371
  9825
+From this it is possible to obtain the data types of the value and
mgl@1371
  9826
+arguments (if known).
mgl@1371
  9827
+
mgl@1371
  9828
+When a call to a library function is being considered, FUNDECL
mgl@1371
  9829
+will contain an identifier node for the library function.  Thus, if
mgl@1371
  9830
+you need to distinguish among various library functions, you can do so
mgl@1371
  9831
+by their names.  Note that ``library function'' in this context means
mgl@1371
  9832
+a function used to perform arithmetic, whose name is known specially
mgl@1371
  9833
+in the compiler and was not mentioned in the C code being compiled.
mgl@1371
  9834
+
mgl@1371
  9835
+STACK_SIZE is the number of bytes of arguments passed on the
mgl@1371
  9836
+stack.  If a variable number of bytes is passed, it is zero, and
mgl@1371
  9837
+argument popping will always be the responsibility of the calling function.
mgl@1371
  9838
+
mgl@1371
  9839
+On the VAX, all functions always pop their arguments, so the definition
mgl@1371
  9840
+of this macro is STACK_SIZE.  On the 68000, using the standard
mgl@1371
  9841
+calling convention, no functions pop their arguments, so the value of
mgl@1371
  9842
+the macro is always 0 in this case.  But an alternative calling
mgl@1371
  9843
+convention is available in which functions that take a fixed number of
mgl@1371
  9844
+arguments pop them but other functions (such as printf) pop
mgl@1371
  9845
+nothing (the caller pops all).  When this convention is in use,
mgl@1371
  9846
+FUNTYPE is examined to determine whether a function takes a fixed
mgl@1371
  9847
+number of arguments.
mgl@1371
  9848
+*/
mgl@1371
  9849
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
mgl@1371
  9850
+
mgl@1371
  9851
+
mgl@1371
  9852
+/*Return true if this function can we use a single return instruction*/
mgl@1371
  9853
+#define USE_RETURN_INSN(ISCOND) avr32_use_return_insn(ISCOND)
mgl@1371
  9854
+
mgl@1371
  9855
+/*
mgl@1371
  9856
+A C expression that should indicate the number of bytes a call sequence
mgl@1371
  9857
+pops off the stack.  It is added to the value of RETURN_POPS_ARGS
mgl@1371
  9858
+when compiling a function call.
mgl@1371
  9859
+
mgl@1371
  9860
+CUM is the variable in which all arguments to the called function
mgl@1371
  9861
+have been accumulated.
mgl@1371
  9862
+
mgl@1371
  9863
+On certain architectures, such as the SH5, a call trampoline is used
mgl@1371
  9864
+that pops certain registers off the stack, depending on the arguments
mgl@1371
  9865
+that have been passed to the function.  Since this is a property of the
mgl@1371
  9866
+call site, not of the called function, RETURN_POPS_ARGS is not
mgl@1371
  9867
+appropriate.
mgl@1371
  9868
+*/
mgl@1371
  9869
+#define CALL_POPS_ARGS(CUM) 0
mgl@1371
  9870
+
mgl@1371
  9871
+/* Passing Arguments in Registers */
mgl@1371
  9872
+
mgl@1371
  9873
+/*
mgl@1371
  9874
+A C expression that controls whether a function argument is passed
mgl@1371
  9875
+in a register, and which register.
mgl@1371
  9876
+
mgl@1371
  9877
+The arguments are CUM, which summarizes all the previous
mgl@1371
  9878
+arguments; MODE, the machine mode of the argument; TYPE,
mgl@1371
  9879
+the data type of the argument as a tree node or 0 if that is not known
mgl@1371
  9880
+(which happens for C support library functions); and NAMED,
mgl@1371
  9881
+which is 1 for an ordinary argument and 0 for nameless arguments that
mgl@1371
  9882
+correspond to '...' in the called function's prototype.
mgl@1371
  9883
+TYPE can be an incomplete type if a syntax error has previously
mgl@1371
  9884
+occurred.
mgl@1371
  9885
+
mgl@1371
  9886
+The value of the expression is usually either a reg RTX for the
mgl@1371
  9887
+hard register in which to pass the argument, or zero to pass the
mgl@1371
  9888
+argument on the stack.
mgl@1371
  9889
+
mgl@1371
  9890
+For machines like the VAX and 68000, where normally all arguments are
mgl@1371
  9891
+pushed, zero suffices as a definition.
mgl@1371
  9892
+
mgl@1371
  9893
+The value of the expression can also be a parallel RTX.  This is
mgl@1371
  9894
+used when an argument is passed in multiple locations.  The mode of the
mgl@1371
  9895
+of the parallel should be the mode of the entire argument.  The
mgl@1371
  9896
+parallel holds any number of expr_list pairs; each one
mgl@1371
  9897
+describes where part of the argument is passed.  In each
mgl@1371
  9898
+expr_list the first operand must be a reg RTX for the hard
mgl@1371
  9899
+register in which to pass this part of the argument, and the mode of the
mgl@1371
  9900
+register RTX indicates how large this part of the argument is.  The
mgl@1371
  9901
+second operand of the expr_list is a const_int which gives
mgl@1371
  9902
+the offset in bytes into the entire argument of where this part starts.
mgl@1371
  9903
+As a special exception the first expr_list in the parallel
mgl@1371
  9904
+RTX may have a first operand of zero.  This indicates that the entire
mgl@1371
  9905
+argument is also stored on the stack.
mgl@1371
  9906
+
mgl@1371
  9907
+The last time this macro is called, it is called with MODE == VOIDmode,
mgl@1371
  9908
+and its result is passed to the call or call_value
mgl@1371
  9909
+pattern as operands 2 and 3 respectively.
mgl@1371
  9910
+
mgl@1371
  9911
+The usual way to make the ISO library 'stdarg.h' work on a machine
mgl@1371
  9912
+where some arguments are usually passed in registers, is to cause
mgl@1371
  9913
+nameless arguments to be passed on the stack instead.  This is done
mgl@1371
  9914
+by making FUNCTION_ARG return 0 whenever NAMED is 0.
mgl@1371
  9915
+
mgl@1371
  9916
+You may use the macro MUST_PASS_IN_STACK (MODE, TYPE)
mgl@1371
  9917
+in the definition of this macro to determine if this argument is of a
mgl@1371
  9918
+type that must be passed in the stack.  If REG_PARM_STACK_SPACE
mgl@1371
  9919
+is not defined and FUNCTION_ARG returns nonzero for such an
mgl@1371
  9920
+argument, the compiler will abort.  If REG_PARM_STACK_SPACE is
mgl@1371
  9921
+defined, the argument will be computed in the stack and then loaded into
mgl@1371
  9922
+a register.  */
mgl@1371
  9923
+
mgl@1371
  9924
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
mgl@1371
  9925
+  avr32_function_arg(&(CUM), MODE, TYPE, NAMED)
mgl@1371
  9926
+
mgl@1371
  9927
+
mgl@1371
  9928
+
mgl@1371
  9929
+
mgl@1371
  9930
+/*
mgl@1371
  9931
+A C type for declaring a variable that is used as the first argument of
mgl@1371
  9932
+FUNCTION_ARG and other related values.  For some target machines,
mgl@1371
  9933
+the type int suffices and can hold the number of bytes of
mgl@1371
  9934
+argument so far.
mgl@1371
  9935
+
mgl@1371
  9936
+There is no need to record in CUMULATIVE_ARGS anything about the
mgl@1371
  9937
+arguments that have been passed on the stack.  The compiler has other
mgl@1371
  9938
+variables to keep track of that.  For target machines on which all
mgl@1371
  9939
+arguments are passed on the stack, there is no need to store anything in
mgl@1371
  9940
+CUMULATIVE_ARGS; however, the data structure must exist and
mgl@1371
  9941
+should not be empty, so use int.
mgl@1371
  9942
+*/
mgl@1371
  9943
+typedef struct avr32_args
mgl@1371
  9944
+{
mgl@1371
  9945
+  /* Index representing the argument register the current function argument
mgl@1371
  9946
+     will occupy */
mgl@1371
  9947
+  int index;
mgl@1371
  9948
+  /* A mask with bits representing the argument registers: if a bit is set
mgl@1371
  9949
+     then this register is used for an arguemnt */
mgl@1371
  9950
+  int used_index;
mgl@1371
  9951
+  /* TRUE if this function has anonymous arguments */
mgl@1371
  9952
+  int uses_anonymous_args;
mgl@1371
  9953
+  /* The size in bytes of the named arguments pushed on the stack */
mgl@1371
  9954
+  int stack_pushed_args_size;
mgl@1371
  9955
+  /* Set to true if this function needs a Return Value Pointer */
mgl@1371
  9956
+  int use_rvp;
mgl@1371
  9957
+
mgl@1371
  9958
+} CUMULATIVE_ARGS;
mgl@1371
  9959
+
mgl@1371
  9960
+
mgl@1371
  9961
+#define FIRST_CUM_REG_INDEX 0
mgl@1371
  9962
+#define LAST_CUM_REG_INDEX 4
mgl@1371
  9963
+#define GET_REG_INDEX(CUM) ((CUM)->index)
mgl@1371
  9964
+#define SET_REG_INDEX(CUM, INDEX) ((CUM)->index = (INDEX));
mgl@1371
  9965
+#define GET_USED_INDEX(CUM, INDEX) ((CUM)->used_index & (1 << (INDEX)))
mgl@1371
  9966
+#define SET_USED_INDEX(CUM, INDEX)		\
mgl@1371
  9967
+  do						\
mgl@1371
  9968
+    {						\
mgl@1371
  9969
+      if (INDEX >= 0)				\
mgl@1371
  9970
+        (CUM)->used_index |= (1 << (INDEX));	\
mgl@1371
  9971
+    }						\
mgl@1371
  9972
+  while (0)
mgl@1371
  9973
+#define SET_INDEXES_UNUSED(CUM) ((CUM)->used_index = 0)
mgl@1371
  9974
+
mgl@1371
  9975
+
mgl@1371
  9976
+/*
mgl@1371
  9977
+   A C statement (sans semicolon) for initializing the variable cum for the
mgl@1371
  9978
+   state at the beginning of the argument list. The variable has type
mgl@1371
  9979
+   CUMULATIVE_ARGS. The value of FNTYPE is the tree node for the data type of
mgl@1371
  9980
+   the function which will receive the args, or 0 if the args are to a compiler
mgl@1371
  9981
+   support library function. For direct calls that are not libcalls, FNDECL
mgl@1371
  9982
+   contain the declaration node of the function. FNDECL is also set when
mgl@1371
  9983
+   INIT_CUMULATIVE_ARGS is used to find arguments for the function being
mgl@1371
  9984
+   compiled.  N_NAMED_ARGS is set to the number of named arguments, including a
mgl@1371
  9985
+   structure return address if it is passed as a parameter, when making a call.
mgl@1371
  9986
+   When processing incoming arguments, N_NAMED_ARGS is set to -1.
mgl@1371
  9987
+
mgl@1371
  9988
+   When processing a call to a compiler support library function, LIBNAME
mgl@1371
  9989
+   identifies which one.  It is a symbol_ref rtx which contains the name of the
mgl@1371
  9990
+   function, as a string. LIBNAME is 0 when an ordinary C function call is
mgl@1371
  9991
+   being processed. Thus, each time this macro is called, either LIBNAME or
mgl@1371
  9992
+   FNTYPE is nonzero, but never both of them at once.
mgl@1371
  9993
+*/
mgl@1371
  9994
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
mgl@1371
  9995
+  avr32_init_cumulative_args(&(CUM), FNTYPE, LIBNAME, FNDECL)
mgl@1371
  9996
+
mgl@1371
  9997
+
mgl@1371
  9998
+/*
mgl@1371
  9999
+A C statement (sans semicolon) to update the summarizer variable
mgl@1371
 10000
+CUM to advance past an argument in the argument list.  The
mgl@1371
 10001
+values MODE, TYPE and NAMED describe that argument.
mgl@1371
 10002
+Once this is done, the variable CUM is suitable for analyzing
mgl@1371
 10003
+the following argument with FUNCTION_ARG, etc.
mgl@1371
 10004
+
mgl@1371
 10005
+This macro need not do anything if the argument in question was passed
mgl@1371
 10006
+on the stack.  The compiler knows how to track the amount of stack space
mgl@1371
 10007
+used for arguments without any special help.
mgl@1371
 10008
+*/
mgl@1371
 10009
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
mgl@1371
 10010
+  avr32_function_arg_advance(&(CUM), MODE, TYPE, NAMED)
mgl@1371
 10011
+
mgl@1371
 10012
+/*
mgl@1371
 10013
+If defined, a C expression which determines whether, and in which direction,
mgl@1371
 10014
+to pad out an argument with extra space.  The value should be of type
mgl@1371
 10015
+enum direction: either 'upward' to pad above the argument,
mgl@1371
 10016
+'downward' to pad below, or 'none' to inhibit padding.
mgl@1371
 10017
+
mgl@1371
 10018
+The amount of padding is always just enough to reach the next
mgl@1371
 10019
+multiple of FUNCTION_ARG_BOUNDARY; this macro does not control
mgl@1371
 10020
+it.
mgl@1371
 10021
+
mgl@1371
 10022
+This macro has a default definition which is right for most systems.
mgl@1371
 10023
+For little-endian machines, the default is to pad upward.  For
mgl@1371
 10024
+big-endian machines, the default is to pad downward for an argument of
mgl@1371
 10025
+constant size shorter than an int, and upward otherwise.
mgl@1371
 10026
+*/
mgl@1371
 10027
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
mgl@1371
 10028
+  avr32_function_arg_padding(MODE, TYPE)
mgl@1371
 10029
+
mgl@1371
 10030
+/*
mgl@1371
 10031
+  Specify padding for the last element of a block move between registers
mgl@1371
 10032
+  and memory. First is nonzero if this is the only element. Defining
mgl@1371
 10033
+  this macro allows better control of register function parameters on
mgl@1371
 10034
+  big-endian machines, without using PARALLEL rtl. In particular,
mgl@1371
 10035
+  MUST_PASS_IN_STACK need not test padding and mode of types in registers,
mgl@1371
 10036
+  as there is no longer a "wrong" part of a register; For example, a three
mgl@1371
 10037
+  byte aggregate may be passed in the high part of a register if so required.
mgl@1371
 10038
+*/
mgl@1371
 10039
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
mgl@1371
 10040
+  avr32_function_arg_padding(MODE, TYPE)
mgl@1371
 10041
+
mgl@1371
 10042
+/*
mgl@1371
 10043
+If defined, a C expression which determines whether the default
mgl@1371
 10044
+implementation of va_arg will attempt to pad down before reading the
mgl@1371
 10045
+next argument, if that argument is smaller than its aligned space as
mgl@1371
 10046
+controlled by PARM_BOUNDARY.  If this macro is not defined, all such
mgl@1371
 10047
+arguments are padded down if BYTES_BIG_ENDIAN is true.
mgl@1371
 10048
+*/
mgl@1371
 10049
+#define PAD_VARARGS_DOWN \
mgl@1371
 10050
+  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
mgl@1371
 10051
+
mgl@1371
 10052
+
mgl@1371
 10053
+/*
mgl@1371
 10054
+A C expression that is nonzero if REGNO is the number of a hard
mgl@1371
 10055
+register in which function arguments are sometimes passed.  This does
mgl@1371
 10056
+not include implicit arguments such as the static chain and
mgl@1371
 10057
+the structure-value address.  On many machines, no registers can be
mgl@1371
 10058
+used for this purpose since all function arguments are pushed on the
mgl@1371
 10059
+stack.
mgl@1371
 10060
+*/
mgl@1371
 10061
+/*
mgl@1371
 10062
+  Use r8 - r12 for function arguments.
mgl@1371
 10063
+*/
mgl@1371
 10064
+#define FUNCTION_ARG_REGNO_P(REGNO) \
mgl@1371
 10065
+  (REGNO >= 3 && REGNO <= 7)
mgl@1371
 10066
+
mgl@1371
 10067
+/* Number of registers used for passing function arguments */
mgl@1371
 10068
+#define NUM_ARG_REGS 5
mgl@1371
 10069
+
mgl@1371
 10070
+/*
mgl@1371
 10071
+If defined, the order in which arguments are loaded into their
mgl@1371
 10072
+respective argument registers is reversed so that the last
mgl@1371
 10073
+argument is loaded first.  This macro only affects arguments
mgl@1371
 10074
+passed in registers.
mgl@1371
 10075
+*/
mgl@1371
 10076
+/* #define LOAD_ARGS_REVERSED */
mgl@1371
 10077
+
mgl@1371
 10078
+/** How Scalar Function Values Are Returned **/
mgl@1371
 10079
+
mgl@1371
 10080
+/* AVR32 is using r12 as return register. */
mgl@1371
 10081
+#define RET_REGISTER (15 - 12)
mgl@1371
 10082
+
mgl@1371
 10083
+
mgl@1371
 10084
+/*
mgl@1371
 10085
+A C expression to create an RTX representing the place where a library
mgl@1371
 10086
+function returns a value of mode MODE.  If the precise function
mgl@1371
 10087
+being called is known, FUNC is a tree node
mgl@1371
 10088
+(FUNCTION_DECL) for it; otherwise, func is a null
mgl@1371
 10089
+pointer.  This makes it possible to use a different value-returning
mgl@1371
 10090
+convention for specific functions when all their calls are
mgl@1371
 10091
+known.
mgl@1371
 10092
+
mgl@1371
 10093
+Note that "library function" in this context means a compiler
mgl@1371
 10094
+support routine, used to perform arithmetic, whose name is known
mgl@1371
 10095
+specially by the compiler and was not mentioned in the C code being
mgl@1371
 10096
+compiled.
mgl@1371
 10097
+
mgl@1371
 10098
+The definition of LIBRARY_VALUE need not be concerned aggregate
mgl@1371
 10099
+data types, because none of the library functions returns such types.
mgl@1371
 10100
+*/
mgl@1371
 10101
+#define LIBCALL_VALUE(MODE) avr32_libcall_value(MODE)
mgl@1371
 10102
+
mgl@1371
 10103
+/*
mgl@1371
 10104
+A C expression that is nonzero if REGNO is the number of a hard
mgl@1371
 10105
+register in which the values of called function may come back.
mgl@1371
 10106
+
mgl@1371
 10107
+A register whose use for returning values is limited to serving as the
mgl@1371
 10108
+second of a pair (for a value of type double, say) need not be
mgl@1371
 10109
+recognized by this macro.  So for most machines, this definition
mgl@1371
 10110
+suffices:
mgl@1371
 10111
+  #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
mgl@1371
 10112
+
mgl@1371
 10113
+If the machine has register windows, so that the caller and the called
mgl@1371
 10114
+function use different registers for the return value, this macro
mgl@1371
 10115
+should recognize only the caller's register numbers.
mgl@1371
 10116
+*/
mgl@1371
 10117
+/*
mgl@1371
 10118
+  When returning a value of mode DImode, r11:r10 is used, else r12 is used.
mgl@1371
 10119
+*/
mgl@1371
 10120
+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RET_REGISTER \
mgl@1371
 10121
+                                       || (REGNO) == INTERNAL_REGNUM(11))
mgl@1371
 10122
+
mgl@1371
 10123
+
mgl@1371
 10124
+/** How Large Values Are Returned **/
mgl@1371
 10125
+
mgl@1371
 10126
+
mgl@1371
 10127
+/*
mgl@1371
 10128
+Define this macro to be 1 if all structure and union return values must be
mgl@1371
 10129
+in memory.  Since this results in slower code, this should be defined
mgl@1371
 10130
+only if needed for compatibility with other compilers or with an ABI.
mgl@1371
 10131
+If you define this macro to be 0, then the conventions used for structure
mgl@1371
 10132
+and union return values are decided by the RETURN_IN_MEMORY macro.
mgl@1371
 10133
+
mgl@1371
 10134
+If not defined, this defaults to the value 1.
mgl@1371
 10135
+*/
mgl@1371
 10136
+#define DEFAULT_PCC_STRUCT_RETURN 0
mgl@1371
 10137
+
mgl@1371
 10138
+
mgl@1371
 10139
+
mgl@1371
 10140
+
mgl@1371
 10141
+/** Generating Code for Profiling **/
mgl@1371
 10142
+
mgl@1371
 10143
+/*
mgl@1371
 10144
+A C statement or compound statement to output to FILE some
mgl@1371
 10145
+assembler code to call the profiling subroutine mcount.
mgl@1371
 10146
+
mgl@1371
 10147
+The details of how mcount expects to be called are determined by
mgl@1371
 10148
+your operating system environment, not by GCC.  To figure them out,
mgl@1371
 10149
+compile a small program for profiling using the system's installed C
mgl@1371
 10150
+compiler and look at the assembler code that results.
mgl@1371
 10151
+
mgl@1371
 10152
+Older implementations of mcount expect the address of a counter
mgl@1371
 10153
+variable to be loaded into some register.  The name of this variable is
mgl@1371
 10154
+'LP' followed by the number LABELNO, so you would generate
mgl@1371
 10155
+the name using 'LP%d' in a fprintf.
mgl@1371
 10156
+*/
mgl@1371
 10157
+/* ToDo: fixme */
mgl@1371
 10158
+#ifndef FUNCTION_PROFILER
mgl@1371
 10159
+#define FUNCTION_PROFILER(FILE, LABELNO) \
mgl@1371
 10160
+  fprintf((FILE), "/* profiler %d */", (LABELNO))
mgl@1371
 10161
+#endif
mgl@1371
 10162
+
mgl@1371
 10163
+
mgl@1371
 10164
+/*****************************************************************************
mgl@1371
 10165
+ * Trampolines for Nested Functions                                          *
mgl@1371
 10166
+ *****************************************************************************/
mgl@1371
 10167
+
mgl@1371
 10168
+/*
mgl@1371
 10169
+A C statement to output, on the stream FILE, assembler code for a
mgl@1371
 10170
+block of data that contains the constant parts of a trampoline.  This
mgl@1371
 10171
+code should not include a label - the label is taken care of
mgl@1371
 10172
+automatically.
mgl@1371
 10173
+
mgl@1371
 10174
+If you do not define this macro, it means no template is needed
mgl@1371
 10175
+for the target.  Do not define this macro on systems where the block move
mgl@1371
 10176
+code to copy the trampoline into place would be larger than the code
mgl@1371
 10177
+to generate it on the spot.
mgl@1371
 10178
+*/
mgl@1371
 10179
+/* ToDo: correct? */
mgl@1371
 10180
+#define TRAMPOLINE_TEMPLATE(FILE) avr32_trampoline_template(FILE);
mgl@1371
 10181
+
mgl@1371
 10182
+
mgl@1371
 10183
+/*
mgl@1371
 10184
+A C expression for the size in bytes of the trampoline, as an integer.
mgl@1371
 10185
+*/
mgl@1371
 10186
+/* ToDo: fixme */
mgl@1371
 10187
+#define TRAMPOLINE_SIZE 0x0C
mgl@1371
 10188
+
mgl@1371
 10189
+/*
mgl@1371
 10190
+Alignment required for trampolines, in bits.
mgl@1371
 10191
+
mgl@1371
 10192
+If you don't define this macro, the value of BIGGEST_ALIGNMENT
mgl@1371
 10193
+is used for aligning trampolines.
mgl@1371
 10194
+*/
mgl@1371
 10195
+#define TRAMPOLINE_ALIGNMENT 16
mgl@1371
 10196
+
mgl@1371
 10197
+/*
mgl@1371
 10198
+A C statement to initialize the variable parts of a trampoline.
mgl@1371
 10199
+ADDR is an RTX for the address of the trampoline; FNADDR is
mgl@1371
 10200
+an RTX for the address of the nested function; STATIC_CHAIN is an
mgl@1371
 10201
+RTX for the static chain value that should be passed to the function
mgl@1371
 10202
+when it is called.
mgl@1371
 10203
+*/
mgl@1371
 10204
+#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \
mgl@1371
 10205
+  avr32_initialize_trampoline(ADDR, FNADDR, STATIC_CHAIN)
mgl@1371
 10206
+
mgl@1371
 10207
+
mgl@1371
 10208
+/******************************************************************************
mgl@1371
 10209
+ * Implicit Calls to Library Routines
mgl@1371
 10210
+ *****************************************************************************/
mgl@1371
 10211
+
mgl@1371
 10212
+/* Tail calling.  */
mgl@1371
 10213
+
mgl@1371
 10214
+/* A C expression that evaluates to true if it is ok to perform a sibling
mgl@1371
 10215
+   call to DECL.  */
mgl@1371
 10216
+#define FUNCTION_OK_FOR_SIBCALL(DECL) 0
mgl@1371
 10217
+
mgl@1371
 10218
+#define OVERRIDE_OPTIONS  avr32_override_options ()
mgl@1371
 10219
+
mgl@1371
 10220
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) avr32_optimization_options (LEVEL, SIZE)
mgl@1371
 10221
+
mgl@1371
 10222
+/******************************************************************************
mgl@1371
 10223
+ * Addressing Modes
mgl@1371
 10224
+ *****************************************************************************/
mgl@1371
 10225
+
mgl@1371
 10226
+/*
mgl@1371
 10227
+A C expression that is nonzero if the machine supports pre-increment,
mgl@1371
 10228
+pre-decrement, post-increment, or post-decrement addressing respectively.
mgl@1371
 10229
+*/
mgl@1371
 10230
+/*
mgl@1371
 10231
+  AVR32 supports Rp++ and --Rp
mgl@1371
 10232
+*/
mgl@1371
 10233
+#define HAVE_PRE_INCREMENT 0
mgl@1371
 10234
+#define HAVE_PRE_DECREMENT 1
mgl@1371
 10235
+#define HAVE_POST_INCREMENT 1
mgl@1371
 10236
+#define HAVE_POST_DECREMENT 0
mgl@1371
 10237
+
mgl@1371
 10238
+/*
mgl@1371
 10239
+A C expression that is nonzero if the machine supports pre- or
mgl@1371
 10240
+post-address side-effect generation involving constants other than
mgl@1371
 10241
+the size of the memory operand.
mgl@1371
 10242
+*/
mgl@1371
 10243
+#define HAVE_PRE_MODIFY_DISP 0
mgl@1371
 10244
+#define HAVE_POST_MODIFY_DISP 0
mgl@1371
 10245
+
mgl@1371
 10246
+/*
mgl@1371
 10247
+A C expression that is nonzero if the machine supports pre- or
mgl@1371
 10248
+post-address side-effect generation involving a register displacement.
mgl@1371
 10249
+*/
mgl@1371
 10250
+#define HAVE_PRE_MODIFY_REG 0
mgl@1371
 10251
+#define HAVE_POST_MODIFY_REG 0
mgl@1371
 10252
+
mgl@1371
 10253
+/*
mgl@1371
 10254
+A C expression that is 1 if the RTX X is a constant which
mgl@1371
 10255
+is a valid address.  On most machines, this can be defined as
mgl@1371
 10256
+CONSTANT_P (X), but a few machines are more restrictive
mgl@1371
 10257
+in which constant addresses are supported.
mgl@1371
 10258
+
mgl@1371
 10259
+CONSTANT_P accepts integer-values expressions whose values are
mgl@1371
 10260
+not explicitly known, such as symbol_ref, label_ref, and
mgl@1371
 10261
+high expressions and const arithmetic expressions, in
mgl@1371
 10262
+addition to const_int and const_double expressions.
mgl@1371
 10263
+*/
mgl@1371
 10264
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P(X)
mgl@1371
 10265
+
mgl@1371
 10266
+/*
mgl@1371
 10267
+A number, the maximum number of registers that can appear in a valid
mgl@1371
 10268
+memory address.  Note that it is up to you to specify a value equal to
mgl@1371
 10269
+the maximum number that GO_IF_LEGITIMATE_ADDRESS would ever
mgl@1371
 10270
+accept.
mgl@1371
 10271
+*/
mgl@1371
 10272
+#define MAX_REGS_PER_ADDRESS 2
mgl@1371
 10273
+
mgl@1371
 10274
+/*
mgl@1371
 10275
+A C compound statement with a conditional goto LABEL;
mgl@1371
 10276
+executed if X (an RTX) is a legitimate memory address on the
mgl@1371
 10277
+target machine for a memory operand of mode MODE.
mgl@1371
 10278
+
mgl@1371
 10279
+It usually pays to define several simpler macros to serve as
mgl@1371
 10280
+subroutines for this one.  Otherwise it may be too complicated to
mgl@1371
 10281
+understand.
mgl@1371
 10282
+
mgl@1371
 10283
+This macro must exist in two variants: a strict variant and a
mgl@1371
 10284
+non-strict one.  The strict variant is used in the reload pass.  It
mgl@1371
 10285
+must be defined so that any pseudo-register that has not been
mgl@1371
 10286
+allocated a hard register is considered a memory reference.  In
mgl@1371
 10287
+contexts where some kind of register is required, a pseudo-register
mgl@1371
 10288
+with no hard register must be rejected.
mgl@1371
 10289
+
mgl@1371
 10290
+The non-strict variant is used in other passes.  It must be defined to
mgl@1371
 10291
+accept all pseudo-registers in every context where some kind of
mgl@1371
 10292
+register is required.
mgl@1371
 10293
+
mgl@1371
 10294
+Compiler source files that want to use the strict variant of this
mgl@1371
 10295
+macro define the macro REG_OK_STRICT.  You should use an
mgl@1371
 10296
+#ifdef REG_OK_STRICT conditional to define the strict variant
mgl@1371
 10297
+in that case and the non-strict variant otherwise.
mgl@1371
 10298
+
mgl@1371
 10299
+Subroutines to check for acceptable registers for various purposes (one
mgl@1371
 10300
+for base registers, one for index registers, and so on) are typically
mgl@1371
 10301
+among the subroutines used to define GO_IF_LEGITIMATE_ADDRESS.
mgl@1371
 10302
+Then only these subroutine macros need have two variants; the higher
mgl@1371
 10303
+levels of macros may be the same whether strict or not.
mgl@1371
 10304
+
mgl@1371
 10305
+Normally, constant addresses which are the sum of a symbol_ref
mgl@1371
 10306
+and an integer are stored inside a const RTX to mark them as
mgl@1371
 10307
+constant.  Therefore, there is no need to recognize such sums
mgl@1371
 10308
+specifically as legitimate addresses.  Normally you would simply
mgl@1371
 10309
+recognize any const as legitimate.
mgl@1371
 10310
+
mgl@1371
 10311
+Usually PRINT_OPERAND_ADDRESS is not prepared to handle constant
mgl@1371
 10312
+sums that are not marked with  const.  It assumes that a naked
mgl@1371
 10313
+plus indicates indexing.  If so, then you must reject such
mgl@1371
 10314
+naked constant sums as illegitimate addresses, so that none of them will
mgl@1371
 10315
+be given to PRINT_OPERAND_ADDRESS.
mgl@1371
 10316
+
mgl@1371
 10317
+On some machines, whether a symbolic address is legitimate depends on
mgl@1371
 10318
+the section that the address refers to.  On these machines, define the
mgl@1371
 10319
+macro ENCODE_SECTION_INFO to store the information into the
mgl@1371
 10320
+symbol_ref, and then check for it here.  When you see a
mgl@1371
 10321
+const, you will have to look inside it to find the
mgl@1371
 10322
+symbol_ref in order to determine the section.
mgl@1371
 10323
+
mgl@1371
 10324
+The best way to modify the name string is by adding text to the
mgl@1371
 10325
+beginning, with suitable punctuation to prevent any ambiguity.  Allocate
mgl@1371
 10326
+the new name in saveable_obstack.  You will have to modify
mgl@1371
 10327
+ASM_OUTPUT_LABELREF to remove and decode the added text and
mgl@1371
 10328
+output the name accordingly, and define STRIP_NAME_ENCODING to
mgl@1371
 10329
+access the original name string.
mgl@1371
 10330
+
mgl@1371
 10331
+You can check the information stored here into the symbol_ref in
mgl@1371
 10332
+the definitions of the macros GO_IF_LEGITIMATE_ADDRESS and
mgl@1371
 10333
+PRINT_OPERAND_ADDRESS.
mgl@1371
 10334
+*/
mgl@1371
 10335
+#ifdef REG_OK_STRICT
mgl@1371
 10336
+#  define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)	\
mgl@1371
 10337
+  do							\
mgl@1371
 10338
+    {							\
mgl@1371
 10339
+      if (avr32_legitimate_address(MODE, X, 1))		\
mgl@1371
 10340
+	goto LABEL;					\
mgl@1371
 10341
+    }							\
mgl@1371
 10342
+  while (0)
mgl@1371
 10343
+#else
mgl@1371
 10344
+#  define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)	\
mgl@1371
 10345
+  do							\
mgl@1371
 10346
+    {							\
mgl@1371
 10347
+      if (avr32_legitimate_address(MODE, X, 0))		\
mgl@1371
 10348
+	goto LABEL;					\
mgl@1371
 10349
+    }							\
mgl@1371
 10350
+  while (0)
mgl@1371
 10351
+#endif
mgl@1371
 10352
+
mgl@1371
 10353
+
mgl@1371
 10354
+
mgl@1371
 10355
+/*
mgl@1371
 10356
+A C compound statement that attempts to replace X with a valid
mgl@1371
 10357
+memory address for an operand of mode MODE.  win will be a
mgl@1371
 10358
+C statement label elsewhere in the code; the macro definition may use
mgl@1371
 10359
+
mgl@1371
 10360
+  GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN);
mgl@1371
 10361
+
mgl@1371
 10362
+to avoid further processing if the address has become legitimate.
mgl@1371
 10363
+
mgl@1371
 10364
+X will always be the result of a call to break_out_memory_refs,
mgl@1371
 10365
+and OLDX will be the operand that was given to that function to produce
mgl@1371
 10366
+X.
mgl@1371
 10367
+
mgl@1371
 10368
+The code generated by this macro should not alter the substructure of
mgl@1371
 10369
+X.  If it transforms X into a more legitimate form, it
mgl@1371
 10370
+should assign X (which will always be a C variable) a new value.
mgl@1371
 10371
+
mgl@1371
 10372
+It is not necessary for this macro to come up with a legitimate
mgl@1371
 10373
+address.  The compiler has standard ways of doing so in all cases.  In
mgl@1371
 10374
+fact, it is safe for this macro to do nothing.  But often a
mgl@1371
 10375
+machine-dependent strategy can generate better code.
mgl@1371
 10376
+*/
mgl@1371
 10377
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)			\
mgl@1371
 10378
+  do								\
mgl@1371
 10379
+    {								\
mgl@1371
 10380
+      if (GET_CODE(X) == PLUS					\
mgl@1371
 10381
+	  && GET_CODE(XEXP(X, 0)) == REG			\
mgl@1371
 10382
+	  && GET_CODE(XEXP(X, 1)) == CONST_INT			\
mgl@1371
 10383
+	  && !CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(X, 1)),	\
mgl@1371
 10384
+					'K', "Ks16"))		\
mgl@1371
 10385
+	{							\
mgl@1371
 10386
+	  rtx index = force_reg(SImode, XEXP(X, 1));		\
mgl@1371
 10387
+	  X = gen_rtx_PLUS( SImode, XEXP(X, 0), index);		\
mgl@1371
 10388
+	}							\
mgl@1371
 10389
+      GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN);			\
mgl@1371
 10390
+    }								\
mgl@1371
 10391
+  while(0)
mgl@1371
 10392
+
mgl@1371
 10393
+
mgl@1371
 10394
+/*
mgl@1371
 10395
+A C statement or compound statement with a conditional
mgl@1371
 10396
+goto LABEL; executed if memory address X (an RTX) can have
mgl@1371
 10397
+different meanings depending on the machine mode of the memory
mgl@1371
 10398
+reference it is used for or if the address is valid for some modes
mgl@1371
 10399
+but not others.
mgl@1371
 10400
+
mgl@1371
 10401
+Autoincrement and autodecrement addresses typically have mode-dependent
mgl@1371
 10402
+effects because the amount of the increment or decrement is the size
mgl@1371
 10403
+of the operand being addressed.  Some machines have other mode-dependent
mgl@1371
 10404
+addresses.  Many RISC machines have no mode-dependent addresses.
mgl@1371
 10405
+
mgl@1371
 10406
+You may assume that ADDR is a valid address for the machine.
mgl@1371
 10407
+*/
mgl@1371
 10408
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)	\
mgl@1371
 10409
+  do							\
mgl@1371
 10410
+    {							\
mgl@1371
 10411
+      if (GET_CODE (ADDR) == POST_INC			\
mgl@1371
 10412
+	  || GET_CODE (ADDR) == PRE_DEC)		\
mgl@1371
 10413
+	goto LABEL;					\
mgl@1371
 10414
+    }							\
mgl@1371
 10415
+  while (0)
mgl@1371
 10416
+
mgl@1371
 10417
+/*
mgl@1371
 10418
+A C expression that is nonzero if X is a legitimate constant for
mgl@1371
 10419
+an immediate operand on the target machine.  You can assume that
mgl@1371
 10420
+X satisfies CONSTANT_P, so you need not check this.  In fact,
mgl@1371
 10421
+'1' is a suitable definition for this macro on machines where
mgl@1371
 10422
+anything CONSTANT_P is valid.
mgl@1371
 10423
+*/
mgl@1371
 10424
+#define LEGITIMATE_CONSTANT_P(X) avr32_legitimate_constant_p(X)
mgl@1371
 10425
+
mgl@1371
 10426
+
mgl@1371
 10427
+/******************************************************************************
mgl@1371
 10428
+ * Condition Code Status
mgl@1371
 10429
+ *****************************************************************************/
mgl@1371
 10430
+
mgl@1371
 10431
+/*
mgl@1371
 10432
+C code for a data type which is used for declaring the mdep
mgl@1371
 10433
+component of cc_status.  It defaults to int.
mgl@1371
 10434
+
mgl@1371
 10435
+This macro is not used on machines that do not use cc0.
mgl@1371
 10436
+*/
mgl@1371
 10437
+
mgl@1371
 10438
+typedef struct
mgl@1371
 10439
+{
mgl@1371
 10440
+  int flags;
mgl@1371
 10441
+  rtx value;
mgl@1371
 10442
+  int fpflags;
mgl@1371
 10443
+  rtx fpvalue;
mgl@1371
 10444
+  int cond_exec_cmp_clobbered;
mgl@1371
 10445
+} avr32_status_reg;
mgl@1371
 10446
+
mgl@1371
 10447
+
mgl@1371
 10448
+#define CC_STATUS_MDEP avr32_status_reg
mgl@1371
 10449
+
mgl@1371
 10450
+/*
mgl@1371
 10451
+A C expression to initialize the mdep field to "empty".
mgl@1371
 10452
+The default definition does nothing, since most machines don't use
mgl@1371
 10453
+the field anyway.  If you want to use the field, you should probably
mgl@1371
 10454
+define this macro to initialize it.
mgl@1371
 10455
+
mgl@1371
 10456
+This macro is not used on machines that do not use cc0.
mgl@1371
 10457
+*/
mgl@1371
 10458
+
mgl@1371
 10459
+#define CC_STATUS_MDEP_INIT  \
mgl@1371
 10460
+   (cc_status.mdep.flags = CC_NONE , cc_status.mdep.cond_exec_cmp_clobbered = 0, cc_status.mdep.value = 0)
mgl@1371
 10461
+
mgl@1371
 10462
+#define FPCC_STATUS_INIT \
mgl@1371
 10463
+   (cc_status.mdep.fpflags = CC_NONE , cc_status.mdep.fpvalue = 0)
mgl@1371
 10464
+
mgl@1371
 10465
+/*
mgl@1371
 10466
+A C compound statement to set the components of cc_status
mgl@1371
 10467
+appropriately for an insn INSN whose body is EXP.  It is
mgl@1371
 10468
+this macro's responsibility to recognize insns that set the condition
mgl@1371
 10469
+code as a byproduct of other activity as well as those that explicitly
mgl@1371
 10470
+set (cc0).
mgl@1371
 10471
+
mgl@1371
 10472
+This macro is not used on machines that do not use cc0.
mgl@1371
 10473
+
mgl@1371
 10474
+If there are insns that do not set the condition code but do alter
mgl@1371
 10475
+other machine registers, this macro must check to see whether they
mgl@1371
 10476
+invalidate the expressions that the condition code is recorded as
mgl@1371
 10477
+reflecting.  For example, on the 68000, insns that store in address
mgl@1371
 10478
+registers do not set the condition code, which means that usually
mgl@1371
 10479
+NOTICE_UPDATE_CC can leave cc_status unaltered for such
mgl@1371
 10480
+insns.  But suppose that the previous insn set the condition code
mgl@1371
 10481
+based on location 'a4@@(102)' and the current insn stores a new
mgl@1371
 10482
+value in 'a4'.  Although the condition code is not changed by
mgl@1371
 10483
+this, it will no longer be true that it reflects the contents of
mgl@1371
 10484
+'a4@@(102)'.  Therefore, NOTICE_UPDATE_CC must alter
mgl@1371
 10485
+cc_status in this case to say that nothing is known about the
mgl@1371
 10486
+condition code value.
mgl@1371
 10487
+
mgl@1371
 10488
+The definition of NOTICE_UPDATE_CC must be prepared to deal
mgl@1371
 10489
+with the results of peephole optimization: insns whose patterns are
mgl@1371
 10490
+parallel RTXs containing various reg, mem or
mgl@1371
 10491
+constants which are just the operands.  The RTL structure of these
mgl@1371
 10492
+insns is not sufficient to indicate what the insns actually do.  What
mgl@1371
 10493
+NOTICE_UPDATE_CC should do when it sees one is just to run
mgl@1371
 10494
+CC_STATUS_INIT.
mgl@1371
 10495
+
mgl@1371
 10496
+A possible definition of NOTICE_UPDATE_CC is to call a function
mgl@1371
 10497
+that looks at an attribute (see Insn Attributes) named, for example,
mgl@1371
 10498
+'cc'.  This avoids having detailed information about patterns in
mgl@1371
 10499
+two places, the 'md' file and in NOTICE_UPDATE_CC.
mgl@1371
 10500
+*/
mgl@1371
 10501
+
mgl@1371
 10502
+#define NOTICE_UPDATE_CC(EXP, INSN) avr32_notice_update_cc(EXP, INSN)
mgl@1371
 10503
+
mgl@1371
 10504
+
mgl@1371
 10505
+
mgl@1371
 10506
+
mgl@1371
 10507
+/******************************************************************************
mgl@1371
 10508
+ * Describing Relative Costs of Operations
mgl@1371
 10509
+ *****************************************************************************/
mgl@1371
 10510
+
mgl@1371
 10511
+
mgl@1371
 10512
+
mgl@1371
 10513
+/*
mgl@1371
 10514
+A C expression for the cost of moving data of mode MODE from a
mgl@1371
 10515
+register in class FROM to one in class TO.  The classes are
mgl@1371
 10516
+expressed using the enumeration values such as GENERAL_REGS.  A
mgl@1371
 10517
+value of 2 is the default; other values are interpreted relative to
mgl@1371
 10518
+that.
mgl@1371
 10519
+
mgl@1371
 10520
+It is not required that the cost always equal 2 when FROM is the
mgl@1371
 10521
+same as TO; on some machines it is expensive to move between
mgl@1371
 10522
+registers if they are not general registers.
mgl@1371
 10523
+
mgl@1371
 10524
+If reload sees an insn consisting of a single set between two
mgl@1371
 10525
+hard registers, and if REGISTER_MOVE_COST applied to their
mgl@1371
 10526
+classes returns a value of 2, reload does not check to ensure that the
mgl@1371
 10527
+constraints of the insn are met.  Setting a cost of other than 2 will
mgl@1371
 10528
+allow reload to verify that the constraints are met.  You should do this
mgl@1371
 10529
+if the movm pattern's constraints do not allow such copying.
mgl@1371
 10530
+*/
mgl@1371
 10531
+#define REGISTER_MOVE_COST(MODE, FROM, TO) \
mgl@1371
 10532
+  ((GET_MODE_SIZE(MODE) <= 4) ? 2:         \
mgl@1371
 10533
+   (GET_MODE_SIZE(MODE) <= 8) ? 3:         \
mgl@1371
 10534
+   4)
mgl@1371
 10535
+
mgl@1371
 10536
+/*
mgl@1371
 10537
+A C expression for the cost of moving data of mode MODE between a
mgl@1371
 10538
+register of class CLASS and memory; IN is zero if the value
mgl@1371
 10539
+is to be written to memory, nonzero if it is to be read in.  This cost
mgl@1371
 10540
+is relative to those in REGISTER_MOVE_COST.  If moving between
mgl@1371
 10541
+registers and memory is more expensive than between two registers, you
mgl@1371
 10542
+should define this macro to express the relative cost.
mgl@1371
 10543
+
mgl@1371
 10544
+If you do not define this macro, GCC uses a default cost of 4 plus
mgl@1371
 10545
+the cost of copying via a secondary reload register, if one is
mgl@1371
 10546
+needed.  If your machine requires a secondary reload register to copy
mgl@1371
 10547
+between memory and a register of CLASS but the reload mechanism is
mgl@1371
 10548
+more complex than copying via an intermediate, define this macro to
mgl@1371
 10549
+reflect the actual cost of the move.
mgl@1371
 10550
+
mgl@1371
 10551
+GCC defines the function memory_move_secondary_cost if
mgl@1371
 10552
+secondary reloads are needed.  It computes the costs due to copying via
mgl@1371
 10553
+a secondary register.  If your machine copies from memory using a
mgl@1371
 10554
+secondary register in the conventional way but the default base value of
mgl@1371
 10555
+4 is not correct for your machine, define this macro to add some other
mgl@1371
 10556
+value to the result of that function.  The arguments to that function
mgl@1371
 10557
+are the same as to this macro.
mgl@1371
 10558
+*/
mgl@1371
 10559
+/*
mgl@1371
 10560
+  Memory moves are costly
mgl@1371
 10561
+*/
mgl@1371
 10562
+#define MEMORY_MOVE_COST(MODE, CLASS, IN)            \
mgl@1371
 10563
+  (((IN) ? ((GET_MODE_SIZE(MODE) < 4) ? 4 :          \
mgl@1371
 10564
+            (GET_MODE_SIZE(MODE) > 8) ? 6 :          \
mgl@1371
 10565
+            3)                                       \
mgl@1371
 10566
+    : ((GET_MODE_SIZE(MODE) > 8) ? 6 : 3)))
mgl@1371
 10567
+
mgl@1371
 10568
+/*
mgl@1371
 10569
+A C expression for the cost of a branch instruction.  A value of 1 is
mgl@1371
 10570
+the default; other values are interpreted relative to that.
mgl@1371
 10571
+*/
mgl@1371
 10572
+  /* Try to use conditionals as much as possible */
mgl@1371
 10573
+#define BRANCH_COST (TARGET_BRANCH_PRED ? 3 : 4)
mgl@1371
 10574
+
mgl@1371
 10575
+/*A C expression for the maximum number of instructions to execute via conditional
mgl@1371
 10576
+  execution instructions instead of a branch. A value of BRANCH_COST+1 is the default
mgl@1371
 10577
+  if the machine does not use cc0, and 1 if it does use cc0.*/
mgl@1371
 10578
+#define MAX_CONDITIONAL_EXECUTE 4
mgl@1371
 10579
+
mgl@1371
 10580
+/*
mgl@1371
 10581
+Define this macro as a C expression which is nonzero if accessing less
mgl@1371
 10582
+than a word of memory (i.e.: a char or a short) is no
mgl@1371
 10583
+faster than accessing a word of memory, i.e., if such access
mgl@1371
 10584
+require more than one instruction or if there is no difference in cost
mgl@1371
 10585
+between byte and (aligned) word loads.
mgl@1371
 10586
+
mgl@1371
 10587
+When this macro is not defined, the compiler will access a field by
mgl@1371
 10588
+finding the smallest containing object; when it is defined, a fullword
mgl@1371
 10589
+load will be used if alignment permits.  Unless bytes accesses are
mgl@1371
 10590
+faster than word accesses, using word accesses is preferable since it
mgl@1371
 10591
+may eliminate subsequent memory access if subsequent accesses occur to
mgl@1371
 10592
+other fields in the same word of the structure, but to different bytes.
mgl@1371
 10593
+*/
mgl@1371
 10594
+#define SLOW_BYTE_ACCESS 1
mgl@1371
 10595
+
mgl@1371
 10596
+
mgl@1371
 10597
+/*
mgl@1371
 10598
+Define this macro if it is as good or better to call a constant
mgl@1371
 10599
+function address than to call an address kept in a register.
mgl@1371
 10600
+*/
mgl@1371
 10601
+#define NO_FUNCTION_CSE
mgl@1371
 10602
+
mgl@1371
 10603
+
mgl@1371
 10604
+/******************************************************************************
mgl@1371
 10605
+ * Adjusting the Instruction Scheduler
mgl@1371
 10606
+ *****************************************************************************/
mgl@1371
 10607
+
mgl@1371
 10608
+/*****************************************************************************
mgl@1371
 10609
+ * Dividing the Output into Sections (Texts, Data, ...)                      *
mgl@1371
 10610
+ *****************************************************************************/
mgl@1371
 10611
+
mgl@1371
 10612
+/*
mgl@1371
 10613
+A C expression whose value is a string, including spacing, containing the
mgl@1371
 10614
+assembler operation that should precede instructions and read-only data.
mgl@1371
 10615
+Normally "\t.text" is right.
mgl@1371
 10616
+*/
mgl@1371
 10617
+#define TEXT_SECTION_ASM_OP "\t.text"
mgl@1371
 10618
+/*
mgl@1371
 10619
+A C statement that switches to the default section containing instructions.
mgl@1371
 10620
+Normally this is not needed, as simply defining TEXT_SECTION_ASM_OP
mgl@1371
 10621
+is enough.  The MIPS port uses this to sort all functions after all data
mgl@1371
 10622
+declarations.
mgl@1371
 10623
+*/
mgl@1371
 10624
+/* #define TEXT_SECTION */
mgl@1371
 10625
+
mgl@1371
 10626
+/*
mgl@1371
 10627
+A C expression whose value is a string, including spacing, containing the
mgl@1371
 10628
+assembler operation to identify the following data as writable initialized
mgl@1371
 10629
+data.  Normally "\t.data" is right.
mgl@1371
 10630
+*/
mgl@1371
 10631
+#define DATA_SECTION_ASM_OP "\t.data"
mgl@1371
 10632
+
mgl@1371
 10633
+/*
mgl@1371
 10634
+If defined, a C expression whose value is a string, including spacing,
mgl@1371
 10635
+containing the assembler operation to identify the following data as
mgl@1371
 10636
+shared data.  If not defined, DATA_SECTION_ASM_OP will be used.
mgl@1371
 10637
+*/
mgl@1371
 10638
+
mgl@1371
 10639
+/*
mgl@1371
 10640
+A C expression whose value is a string, including spacing, containing
mgl@1371
 10641
+the assembler operation to identify the following data as read-only
mgl@1371
 10642
+initialized data.
mgl@1371
 10643
+*/
mgl@1371
 10644
+#undef READONLY_DATA_SECTION_ASM_OP
mgl@1371
 10645
+#define READONLY_DATA_SECTION_ASM_OP \
mgl@1371
 10646
+  ((TARGET_USE_RODATA_SECTION) ?  \
mgl@1371
 10647
+   "\t.section\t.rodata" :                \
mgl@1371
 10648
+   TEXT_SECTION_ASM_OP )
mgl@1371
 10649
+
mgl@1371
 10650
+
mgl@1371
 10651
+/*
mgl@1371
 10652
+If defined, a C expression whose value is a string, including spacing,
mgl@1371
 10653
+containing the assembler operation to identify the following data as
mgl@1371
 10654
+uninitialized global data.  If not defined, and neither
mgl@1371
 10655
+ASM_OUTPUT_BSS nor ASM_OUTPUT_ALIGNED_BSS are defined,
mgl@1371
 10656
+uninitialized global data will be output in the data section if
mgl@1371
 10657
+-fno-common is passed, otherwise ASM_OUTPUT_COMMON will be
mgl@1371
 10658
+used.
mgl@1371
 10659
+*/
mgl@1371
 10660
+#define BSS_SECTION_ASM_OP	"\t.section\t.bss"
mgl@1371
 10661
+
mgl@1371
 10662
+/*
mgl@1371
 10663
+If defined, a C expression whose value is a string, including spacing,
mgl@1371
 10664
+containing the assembler operation to identify the following data as
mgl@1371
 10665
+uninitialized global shared data.  If not defined, and
mgl@1371
 10666
+BSS_SECTION_ASM_OP is, the latter will be used.
mgl@1371
 10667
+*/
mgl@1371
 10668
+/*#define SHARED_BSS_SECTION_ASM_OP "\trseg\tshared_bbs_section:data:noroot(0)\n"*/
mgl@1371
 10669
+/*
mgl@1371
 10670
+If defined, a C expression whose value is a string, including spacing,
mgl@1371
 10671
+containing the assembler operation to identify the following data as
mgl@1371
 10672
+initialization code.  If not defined, GCC will assume such a section does
mgl@1371
 10673
+not exist.
mgl@1371
 10674
+*/
mgl@1371
 10675
+#undef  INIT_SECTION_ASM_OP
mgl@1371
 10676
+#define INIT_SECTION_ASM_OP "\t.section\t.init"
mgl@1371
 10677
+
mgl@1371
 10678
+/*
mgl@1371
 10679
+If defined, a C expression whose value is a string, including spacing,
mgl@1371
 10680
+containing the assembler operation to identify the following data as
mgl@1371
 10681
+finalization code.  If not defined, GCC will assume such a section does
mgl@1371
 10682
+not exist.
mgl@1371
 10683
+*/
mgl@1371
 10684
+#undef  FINI_SECTION_ASM_OP
mgl@1371
 10685
+#define FINI_SECTION_ASM_OP "\t.section\t.fini"
mgl@1371
 10686
+
mgl@1371
 10687
+/*
mgl@1371
 10688
+If defined, an ASM statement that switches to a different section
mgl@1371
 10689
+via SECTION_OP, calls FUNCTION, and switches back to
mgl@1371
 10690
+the text section.  This is used in crtstuff.c if
mgl@1371
 10691
+INIT_SECTION_ASM_OP or FINI_SECTION_ASM_OP to calls
mgl@1371
 10692
+to initialization and finalization functions from the init and fini
mgl@1371
 10693
+sections.  By default, this macro uses a simple function call.  Some
mgl@1371
 10694
+ports need hand-crafted assembly code to avoid dependencies on
mgl@1371
 10695
+registers initialized in the function prologue or to ensure that
mgl@1371
 10696
+constant pools don't end up too far way in the text section.
mgl@1371
 10697
+*/
mgl@1371
 10698
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)      \
mgl@1371
 10699
+   asm ( SECTION_OP "\n" \
mgl@1371
 10700
+         "mcall   r6[" USER_LABEL_PREFIX #FUNC "@got]\n" \
mgl@1371
 10701
+         TEXT_SECTION_ASM_OP);
mgl@1371
 10702
+
mgl@1371
 10703
+
mgl@1371
 10704
+/*
mgl@1371
 10705
+Define this macro to be an expression with a nonzero value if jump
mgl@1371
 10706
+tables (for tablejump insns) should be output in the text
mgl@1371
 10707
+section, along with the assembler instructions.  Otherwise, the
mgl@1371
 10708
+readonly data section is used.
mgl@1371
 10709
+
mgl@1371
 10710
+This macro is irrelevant if there is no separate readonly data section.
mgl@1371
 10711
+*/
mgl@1371
 10712
+/* Put jump tables in text section if we have caches. Otherwise assume that
mgl@1371
 10713
+   loading data from code memory is slow. */
mgl@1371
 10714
+#define JUMP_TABLES_IN_TEXT_SECTION    \
mgl@1371
 10715
+    (TARGET_CACHES ? 1 : 0)
mgl@1371
 10716
+
mgl@1371
 10717
+
mgl@1371
 10718
+/******************************************************************************
mgl@1371
 10719
+ * Position Independent Code (PIC)
mgl@1371
 10720
+ *****************************************************************************/
mgl@1371
 10721
+
mgl@1371
 10722
+#ifndef AVR32_ALWAYS_PIC
mgl@1371
 10723
+#define AVR32_ALWAYS_PIC 0
mgl@1371
 10724
+#endif
mgl@1371
 10725
+
mgl@1371
 10726
+/* GOT is set to r6 */
mgl@1371
 10727
+#define PIC_OFFSET_TABLE_REGNUM INTERNAL_REGNUM(6)
mgl@1371
 10728
+
mgl@1371
 10729
+/*
mgl@1371
 10730
+A C expression that is nonzero if X is a legitimate immediate
mgl@1371
 10731
+operand on the target machine when generating position independent code.
mgl@1371
 10732
+You can assume that X satisfies CONSTANT_P, so you need not
mgl@1371
 10733
+check this.  You can also assume flag_pic is true, so you need not
mgl@1371
 10734
+check it either.  You need not define this macro if all constants
mgl@1371
 10735
+(including SYMBOL_REF) can be immediate operands when generating
mgl@1371
 10736
+position independent code.
mgl@1371
 10737
+*/
mgl@1371
 10738
+/* We can't directly access anything that contains a symbol,
mgl@1371
 10739
+   nor can we indirect via the constant pool.  */
mgl@1371
 10740
+#define LEGITIMATE_PIC_OPERAND_P(X) avr32_legitimate_pic_operand_p(X)
mgl@1371
 10741
+
mgl@1371
 10742
+
mgl@1371
 10743
+/* We need to know when we are making a constant pool; this determines
mgl@1371
 10744
+   whether data needs to be in the GOT or can be referenced via a GOT
mgl@1371
 10745
+   offset.  */
mgl@1371
 10746
+extern int making_const_table;
mgl@1371
 10747
+
mgl@1371
 10748
+/******************************************************************************
mgl@1371
 10749
+ * Defining the Output Assembler Language
mgl@1371
 10750
+ *****************************************************************************/
mgl@1371
 10751
+
mgl@1371
 10752
+
mgl@1371
 10753
+/*
mgl@1371
 10754
+A C string constant describing how to begin a comment in the target
mgl@1371
 10755
+assembler language.  The compiler assumes that the comment will end at
mgl@1371
 10756
+the end of the line.
mgl@1371
 10757
+*/
mgl@1371
 10758
+#define ASM_COMMENT_START "# "
mgl@1371
 10759
+
mgl@1371
 10760
+/*
mgl@1371
 10761
+A C string constant for text to be output before each asm
mgl@1371
 10762
+statement or group of consecutive ones.  Normally this is
mgl@1371
 10763
+"#APP", which is a comment that has no effect on most
mgl@1371
 10764
+assemblers but tells the GNU assembler that it must check the lines
mgl@1371
 10765
+that follow for all valid assembler constructs.
mgl@1371
 10766
+*/
mgl@1371
 10767
+#undef ASM_APP_ON
mgl@1371
 10768
+#define ASM_APP_ON "#APP\n"
mgl@1371
 10769
+
mgl@1371
 10770
+/*
mgl@1371
 10771
+A C string constant for text to be output after each asm
mgl@1371
 10772
+statement or group of consecutive ones.  Normally this is
mgl@1371
 10773
+"#NO_APP", which tells the GNU assembler to resume making the
mgl@1371
 10774
+time-saving assumptions that are valid for ordinary compiler output.
mgl@1371
 10775
+*/
mgl@1371
 10776
+#undef ASM_APP_OFF
mgl@1371
 10777
+#define ASM_APP_OFF "#NO_APP\n"
mgl@1371
 10778
+
mgl@1371
 10779
+
mgl@1371
 10780
+
mgl@1371
 10781
+#define FILE_ASM_OP 		"\t.file\n"
mgl@1371
 10782
+#define IDENT_ASM_OP 		"\t.ident\t"
mgl@1371
 10783
+#define SET_ASM_OP		"\t.set\t"
mgl@1371
 10784
+
mgl@1371
 10785
+
mgl@1371
 10786
+/*
mgl@1371
 10787
+ * Output assembly directives to switch to section name. The section
mgl@1371
 10788
+ * should have attributes as specified by flags, which is a bit mask
mgl@1371
 10789
+ * of the SECTION_* flags defined in 'output.h'. If align is nonzero,
mgl@1371
 10790
+ * it contains an alignment in bytes to be used for the section,
mgl@1371
 10791
+ * otherwise some target default should be used. Only targets that
mgl@1371
 10792
+ * must specify an alignment within the section directive need pay
mgl@1371
 10793
+ * attention to align -- we will still use ASM_OUTPUT_ALIGN.
mgl@1371
 10794
+ *
mgl@1371
 10795
+ * NOTE: This one must not be moved to avr32.c
mgl@1371
 10796
+ */
mgl@1371
 10797
+#undef TARGET_ASM_NAMED_SECTION
mgl@1371
 10798
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
mgl@1371
 10799
+
mgl@1371
 10800
+
mgl@1371
 10801
+/*
mgl@1371
 10802
+You may define this macro as a C expression.  You should define the
mgl@1371
 10803
+expression to have a nonzero value if GCC should output the constant
mgl@1371
 10804
+pool for a function before the code for the function, or a zero value if
mgl@1371
 10805
+GCC should output the constant pool after the function.  If you do
mgl@1371
 10806
+not define this macro, the usual case, GCC will output the constant
mgl@1371
 10807
+pool before the function.
mgl@1371
 10808
+*/
mgl@1371
 10809
+#define CONSTANT_POOL_BEFORE_FUNCTION 0
mgl@1371
 10810
+
mgl@1371
 10811
+
mgl@1371
 10812
+/*
mgl@1371
 10813
+Define this macro as a C expression which is nonzero if the constant
mgl@1371
 10814
+EXP, of type tree, should be output after the code for a
mgl@1371
 10815
+function.  The compiler will normally output all constants before the
mgl@1371
 10816
+function; you need not define this macro if this is OK.
mgl@1371
 10817
+*/
mgl@1371
 10818
+#define CONSTANT_AFTER_FUNCTION_P(EXP) 1
mgl@1371
 10819
+
mgl@1371
 10820
+
mgl@1371
 10821
+/*
mgl@1371
 10822
+Define this macro as a C expression which is nonzero if C is
mgl@1371
 10823
+used as a logical line separator by the assembler.
mgl@1371
 10824
+
mgl@1371
 10825
+If you do not define this macro, the default is that only
mgl@1371
 10826
+the character ';' is treated as a logical line separator.
mgl@1371
 10827
+*/
mgl@1371
 10828
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
mgl@1371
 10829
+
mgl@1371
 10830
+
mgl@1371
 10831
+/** Output of Uninitialized Variables **/
mgl@1371
 10832
+
mgl@1371
 10833
+/*
mgl@1371
 10834
+A C statement (sans semicolon) to output to the stdio stream
mgl@1371
 10835
+STREAM the assembler definition of a common-label named
mgl@1371
 10836
+NAME whose size is SIZE bytes.  The variable ROUNDED
mgl@1371
 10837
+is the size rounded up to whatever alignment the caller wants.
mgl@1371
 10838
+
mgl@1371
 10839
+Use the expression assemble_name(STREAM, NAME) to
mgl@1371
 10840
+output the name itself; before and after that, output the additional
mgl@1371
 10841
+assembler syntax for defining the name, and a newline.
mgl@1371
 10842
+
mgl@1371
 10843
+This macro controls how the assembler definitions of uninitialized
mgl@1371
 10844
+common global variables are output.
mgl@1371
 10845
+*/
mgl@1371
 10846
+/*
mgl@1371
 10847
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
mgl@1371
 10848
+  avr32_asm_output_common(STREAM, NAME, SIZE, ROUNDED)
mgl@1371
 10849
+*/
mgl@1371
 10850
+
mgl@1371
 10851
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)	\
mgl@1371
 10852
+  do							\
mgl@1371
 10853
+    {							\
mgl@1371
 10854
+      fputs ("\t.comm ", (FILE));			\
mgl@1371
 10855
+      assemble_name ((FILE), (NAME));			\
mgl@1371
 10856
+      fprintf ((FILE), ",%d\n", (SIZE));		\
mgl@1371
 10857
+    }							\
mgl@1371
 10858
+  while (0)
mgl@1371
 10859
+
mgl@1371
 10860
+/*
mgl@1371
 10861
+ * Like ASM_OUTPUT_BSS except takes the required alignment as a
mgl@1371
 10862
+ * separate, explicit argument.  If you define this macro, it is used
mgl@1371
 10863
+ * in place of ASM_OUTPUT_BSS, and gives you more flexibility in
mgl@1371
 10864
+ * handling the required alignment of the variable.  The alignment is
mgl@1371
 10865
+ * specified as the number of bits.
mgl@1371
 10866
+ *
mgl@1371
 10867
+ * Try to use function asm_output_aligned_bss defined in file varasm.c
mgl@1371
 10868
+ * when defining this macro.
mgl@1371
 10869
+ */
mgl@1371
 10870
+#define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
mgl@1371
 10871
+  asm_output_aligned_bss (STREAM, DECL, NAME, SIZE, ALIGNMENT)
mgl@1371
 10872
+
mgl@1371
 10873
+/*
mgl@1371
 10874
+A C statement (sans semicolon) to output to the stdio stream
mgl@1371
 10875
+STREAM the assembler definition of a local-common-label named
mgl@1371
 10876
+NAME whose size is SIZE bytes.  The variable ROUNDED
mgl@1371
 10877
+is the size rounded up to whatever alignment the caller wants.
mgl@1371
 10878
+
mgl@1371
 10879
+Use the expression assemble_name(STREAM, NAME) to
mgl@1371
 10880
+output the name itself; before and after that, output the additional
mgl@1371
 10881
+assembler syntax for defining the name, and a newline.
mgl@1371
 10882
+
mgl@1371
 10883
+This macro controls how the assembler definitions of uninitialized
mgl@1371
 10884
+static variables are output.
mgl@1371
 10885
+*/
mgl@1371
 10886
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)	\
mgl@1371
 10887
+  do							\
mgl@1371
 10888
+    {							\
mgl@1371
 10889
+      fputs ("\t.lcomm ", (FILE));			\
mgl@1371
 10890
+      assemble_name ((FILE), (NAME));			\
mgl@1371
 10891
+      fprintf ((FILE), ",%d, %d\n", (SIZE), 2);		\
mgl@1371
 10892
+    }							\
mgl@1371
 10893
+  while (0)
mgl@1371
 10894
+
mgl@1371
 10895
+
mgl@1371
 10896
+/*
mgl@1371
 10897
+A C statement (sans semicolon) to output to the stdio stream
mgl@1371
 10898
+STREAM the assembler definition of a label named NAME.
mgl@1371
 10899
+Use the expression assemble_name(STREAM, NAME) to
mgl@1371
 10900
+output the name itself; before and after that, output the additional
mgl@1371
 10901
+assembler syntax for defining the name, and a newline.
mgl@1371
 10902
+*/
mgl@1371
 10903
+#define ASM_OUTPUT_LABEL(STREAM, NAME) avr32_asm_output_label(STREAM, NAME)
mgl@1371
 10904
+
mgl@1371
 10905
+/* A C string containing the appropriate assembler directive to
mgl@1371
 10906
+ * specify the size of a symbol, without any arguments. On systems
mgl@1371
 10907
+ * that use ELF, the default (in 'config/elfos.h') is '"\t.size\t"';
mgl@1371
 10908
+ * on other systems, the default is not to define this macro.
mgl@1371
 10909
+ *
mgl@1371
 10910
+ * Define this macro only if it is correct to use the default
mgl@1371
 10911
+ * definitions of ASM_ OUTPUT_SIZE_DIRECTIVE and
mgl@1371
 10912
+ * ASM_OUTPUT_MEASURED_SIZE for your system. If you need your own
mgl@1371
 10913
+ * custom definitions of those macros, or if you do not need explicit
mgl@1371
 10914
+ * symbol sizes at all, do not define this macro.
mgl@1371
 10915
+ */
mgl@1371
 10916
+#define SIZE_ASM_OP "\t.size\t"
mgl@1371
 10917
+
mgl@1371
 10918
+
mgl@1371
 10919
+/*
mgl@1371
 10920
+A C statement (sans semicolon) to output to the stdio stream
mgl@1371
 10921
+STREAM some commands that will make the label NAME global;
mgl@1371
 10922
+that is, available for reference from other files.  Use the expression
mgl@1371
 10923
+assemble_name(STREAM, NAME) to output the name
mgl@1371
 10924
+itself; before and after that, output the additional assembler syntax
mgl@1371
 10925
+for making that name global, and a newline.
mgl@1371
 10926
+*/
mgl@1371
 10927
+#define GLOBAL_ASM_OP "\t.globl\t"
mgl@1371
 10928
+
mgl@1371
 10929
+
mgl@1371
 10930
+
mgl@1371
 10931
+/*
mgl@1371
 10932
+A C expression which evaluates to true if the target supports weak symbols.
mgl@1371
 10933
+
mgl@1371
 10934
+If you don't define this macro, defaults.h provides a default
mgl@1371
 10935
+definition.  If either ASM_WEAKEN_LABEL or ASM_WEAKEN_DECL
mgl@1371
 10936
+is defined, the default definition is '1'; otherwise, it is
mgl@1371
 10937
+'0'.  Define this macro if you want to control weak symbol support
mgl@1371
 10938
+with a compiler flag such as -melf.
mgl@1371
 10939
+*/
mgl@1371
 10940
+#define SUPPORTS_WEAK 1
mgl@1371
 10941
+
mgl@1371
 10942
+/*
mgl@1371
 10943
+A C statement (sans semicolon) to output to the stdio stream
mgl@1371
 10944
+STREAM a reference in assembler syntax to a label named
mgl@1371
 10945
+NAME.  This should add '_' to the front of the name, if that
mgl@1371
 10946
+is customary on your operating system, as it is in most Berkeley Unix
mgl@1371
 10947
+systems.  This macro is used in assemble_name.
mgl@1371
 10948
+*/
mgl@1371
 10949
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
mgl@1371
 10950
+  avr32_asm_output_labelref(STREAM, NAME)
mgl@1371
 10951
+
mgl@1371
 10952
+
mgl@1371
 10953
+
mgl@1371
 10954
+/*
mgl@1371
 10955
+A C expression to assign to OUTVAR (which is a variable of type
mgl@1371
 10956
+char *) a newly allocated string made from the string
mgl@1371
 10957
+NAME and the number NUMBER, with some suitable punctuation
mgl@1371
 10958
+added.  Use alloca to get space for the string.
mgl@1371
 10959
+
mgl@1371
 10960
+The string will be used as an argument to ASM_OUTPUT_LABELREF to
mgl@1371
 10961
+produce an assembler label for an internal static variable whose name is
mgl@1371
 10962
+NAME.  Therefore, the string must be such as to result in valid
mgl@1371
 10963
+assembler code.  The argument NUMBER is different each time this
mgl@1371
 10964
+macro is executed; it prevents conflicts between similarly-named
mgl@1371
 10965
+internal static variables in different scopes.
mgl@1371
 10966
+
mgl@1371
 10967
+Ideally this string should not be a valid C identifier, to prevent any
mgl@1371
 10968
+conflict with the user's own symbols.  Most assemblers allow periods
mgl@1371
 10969
+or percent signs in assembler symbols; putting at least one of these
mgl@1371
 10970
+between the name and the number will suffice.
mgl@1371
 10971
+*/
mgl@1371
 10972
+#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER)		\
mgl@1371
 10973
+  do								\
mgl@1371
 10974
+    {								\
mgl@1371
 10975
+      (OUTVAR) = (char *) alloca (strlen ((NAME)) + 10);	\
mgl@1371
 10976
+      sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER));		\
mgl@1371
 10977
+    }								\
mgl@1371
 10978
+  while (0)
mgl@1371
 10979
+
mgl@1371
 10980
+
mgl@1371
 10981
+/** Macros Controlling Initialization Routines **/
mgl@1371
 10982
+
mgl@1371
 10983
+
mgl@1371
 10984
+/*
mgl@1371
 10985
+If defined, main will not call __main as described above.
mgl@1371
 10986
+This macro should be defined for systems that control start-up code
mgl@1371
 10987
+on a symbol-by-symbol basis, such as OSF/1, and should not
mgl@1371
 10988
+be defined explicitly for systems that support INIT_SECTION_ASM_OP.
mgl@1371
 10989
+*/
mgl@1371
 10990
+/*
mgl@1371
 10991
+  __main is not defined when debugging.
mgl@1371
 10992
+*/
mgl@1371
 10993
+#define HAS_INIT_SECTION
mgl@1371
 10994
+
mgl@1371
 10995
+
mgl@1371
 10996
+/** Output of Assembler Instructions **/
mgl@1371
 10997
+
mgl@1371
 10998
+/*
mgl@1371
 10999
+A C initializer containing the assembler's names for the machine
mgl@1371
 11000
+registers, each one as a C string constant.  This is what translates
mgl@1371
 11001
+register numbers in the compiler into assembler language.
mgl@1371
 11002
+*/
mgl@1371
 11003
+
mgl@1371
 11004
+#define REGISTER_NAMES	\
mgl@1371
 11005
+{			\
mgl@1371
 11006
+  "pc",  "lr",		\
mgl@1371
 11007
+  "sp",  "r12",		\
mgl@1371
 11008
+  "r11", "r10",		\
mgl@1371
 11009
+  "r9",  "r8",		\
mgl@1371
 11010
+  "r7",  "r6",		\
mgl@1371
 11011
+  "r5",  "r4",		\
mgl@1371
 11012
+  "r3",  "r2",		\
mgl@1371
 11013
+  "r1",  "r0",		\
mgl@1371
 11014
+  "f15","f14",		\
mgl@1371
 11015
+  "f13","f12",		\
mgl@1371
 11016
+  "f11","f10",		\
mgl@1371
 11017
+  "f9", "f8",		\
mgl@1371
 11018
+  "f7", "f6",		\
mgl@1371
 11019
+  "f5", "f4",		\
mgl@1371
 11020
+  "f3", "f2",		\
mgl@1371
 11021
+  "f1", "f0"		\
mgl@1371
 11022
+}
mgl@1371
 11023
+
mgl@1371
 11024
+/*
mgl@1371
 11025
+A C compound statement to output to stdio stream STREAM the
mgl@1371
 11026
+assembler syntax for an instruction operand X.  X is an
mgl@1371
 11027
+RTL expression.
mgl@1371
 11028
+
mgl@1371
 11029
+CODE is a value that can be used to specify one of several ways
mgl@1371
 11030
+of printing the operand.  It is used when identical operands must be
mgl@1371
 11031
+printed differently depending on the context.  CODE comes from
mgl@1371
 11032
+the '%' specification that was used to request printing of the
mgl@1371
 11033
+operand.  If the specification was just '%digit' then
mgl@1371
 11034
+CODE is 0; if the specification was '%ltr digit'
mgl@1371
 11035
+then CODE is the ASCII code for ltr.
mgl@1371
 11036
+
mgl@1371
 11037
+If X is a register, this macro should print the register's name.
mgl@1371
 11038
+The names can be found in an array reg_names whose type is
mgl@1371
 11039
+char *[].  reg_names is initialized from REGISTER_NAMES.
mgl@1371
 11040
+
mgl@1371
 11041
+When the machine description has a specification '%punct'
mgl@1371
 11042
+(a '%' followed by a punctuation character), this macro is called
mgl@1371
 11043
+with a null pointer for X and the punctuation character for
mgl@1371
 11044
+CODE.
mgl@1371
 11045
+*/
mgl@1371
 11046
+#define PRINT_OPERAND(STREAM, X, CODE) avr32_print_operand(STREAM, X, CODE)
mgl@1371
 11047
+
mgl@1371
 11048
+/* A C statement to be executed just prior to the output of
mgl@1371
 11049
+   assembler code for INSN, to modify the extracted operands so
mgl@1371
 11050
+   they will be output differently.
mgl@1371
 11051
+
mgl@1371
 11052
+   Here the argument OPVEC is the vector containing the operands
mgl@1371
 11053
+   extracted from INSN, and NOPERANDS is the number of elements of
mgl@1371
 11054
+   the vector which contain meaningful data for this insn.
mgl@1371
 11055
+   The contents of this vector are what will be used to convert the insn
mgl@1371
 11056
+   template into assembler code, so you can change the assembler output
mgl@1371
 11057
+   by changing the contents of the vector.  */
mgl@1371
 11058
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
mgl@1371
 11059
+  avr32_final_prescan_insn ((INSN), (OPVEC), (NOPERANDS))
mgl@1371
 11060
+
mgl@1371
 11061
+/*
mgl@1371
 11062
+A C expression which evaluates to true if CODE is a valid
mgl@1371
 11063
+punctuation character for use in the PRINT_OPERAND macro.  If
mgl@1371
 11064
+PRINT_OPERAND_PUNCT_VALID_P is not defined, it means that no
mgl@1371
 11065
+punctuation characters (except for the standard one, '%') are used
mgl@1371
 11066
+in this way.
mgl@1371
 11067
+*/
mgl@1371
 11068
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)                          \
mgl@1371
 11069
+  (((CODE) == '?')                                                 \
mgl@1371
 11070
+   || ((CODE) == '!'))
mgl@1371
 11071
+
mgl@1371
 11072
+/*
mgl@1371
 11073
+A C compound statement to output to stdio stream STREAM the
mgl@1371
 11074
+assembler syntax for an instruction operand that is a memory reference
mgl@1371
 11075
+whose address is X.  X is an RTL expression.
mgl@1371
 11076
+
mgl@1371
 11077
+On some machines, the syntax for a symbolic address depends on the
mgl@1371
 11078
+section that the address refers to.  On these machines, define the macro
mgl@1371
 11079
+ENCODE_SECTION_INFO to store the information into the
mgl@1371
 11080
+symbol_ref, and then check for it here.  (see Assembler Format.)
mgl@1371
 11081
+*/
mgl@1371
 11082
+#define PRINT_OPERAND_ADDRESS(STREAM, X) avr32_print_operand_address(STREAM, X)
mgl@1371
 11083
+
mgl@1371
 11084
+
mgl@1371
 11085
+/** Output of Dispatch Tables **/
mgl@1371
 11086
+
mgl@1371
 11087
+/*
mgl@1371
 11088
+ * A C statement to output to the stdio stream stream an assembler
mgl@1371
 11089
+ * pseudo-instruction to generate a difference between two
mgl@1371
 11090
+ * labels. value and rel are the numbers of two internal labels. The
mgl@1371
 11091
+ * definitions of these labels are output using
mgl@1371
 11092
+ * (*targetm.asm_out.internal_label), and they must be printed in the
mgl@1371
 11093
+ * same way here. For example,
mgl@1371
 11094
+ *
mgl@1371
 11095
+ *         fprintf (stream, "\t.word L%d-L%d\n",
mgl@1371
 11096
+ *                  value, rel)
mgl@1371
 11097
+ *
mgl@1371
 11098
+ * You must provide this macro on machines where the addresses in a
mgl@1371
 11099
+ * dispatch table are relative to the table's own address. If defined,
mgl@1371
 11100
+ * GCC will also use this macro on all machines when producing
mgl@1371
 11101
+ * PIC. body is the body of the ADDR_DIFF_VEC; it is provided so that
mgl@1371
 11102
+ * the mode and flags can be read.
mgl@1371
 11103
+ */
mgl@1371
 11104
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)	    \
mgl@1371
 11105
+    fprintf(STREAM, "\tbral\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
mgl@1371
 11106
+
mgl@1371
 11107
+/*
mgl@1371
 11108
+This macro should be provided on machines where the addresses
mgl@1371
 11109
+in a dispatch table are absolute.
mgl@1371
 11110
+
mgl@1371
 11111
+The definition should be a C statement to output to the stdio stream
mgl@1371
 11112
+STREAM an assembler pseudo-instruction to generate a reference to
mgl@1371
 11113
+a label.  VALUE is the number of an internal label whose
mgl@1371
 11114
+definition is output using ASM_OUTPUT_INTERNAL_LABEL.
mgl@1371
 11115
+For example,
mgl@1371
 11116
+
mgl@1371
 11117
+fprintf(STREAM, "\t.word L%d\n", VALUE)
mgl@1371
 11118
+*/
mgl@1371
 11119
+
mgl@1371
 11120
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE)  \
mgl@1371
 11121
+  fprintf(STREAM, "\t.long %sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
mgl@1371
 11122
+
mgl@1371
 11123
+/** Assembler Commands for Exception Regions */
mgl@1371
 11124
+
mgl@1371
 11125
+/* ToDo: All of this subsection */
mgl@1371
 11126
+
mgl@1371
 11127
+/** Assembler Commands for Alignment */
mgl@1371
 11128
+
mgl@1371
 11129
+
mgl@1371
 11130
+/*
mgl@1371
 11131
+A C statement to output to the stdio stream STREAM an assembler
mgl@1371
 11132
+command to advance the location counter to a multiple of 2 to the
mgl@1371
 11133
+POWER bytes.  POWER will be a C expression of type int.
mgl@1371
 11134
+*/
mgl@1371
 11135
+#define ASM_OUTPUT_ALIGN(STREAM, POWER)			\
mgl@1371
 11136
+  do							\
mgl@1371
 11137
+    {							\
mgl@1371
 11138
+      if ((POWER) != 0)					\
mgl@1371
 11139
+	fprintf(STREAM, "\t.align\t%d\n", POWER);	\
mgl@1371
 11140
+    }							\
mgl@1371
 11141
+  while (0)
mgl@1371
 11142
+
mgl@1371
 11143
+/*
mgl@1371
 11144
+Like ASM_OUTPUT_ALIGN, except that the \nop" instruction is used for padding, if
mgl@1371
 11145
+necessary.
mgl@1371
 11146
+*/
mgl@1371
 11147
+#define ASM_OUTPUT_ALIGN_WITH_NOP(STREAM, POWER) \
mgl@1371
 11148
+ fprintf(STREAM, "\t.balignw\t%d, 0xd703\n", (1 << POWER))
mgl@1371
 11149
+
mgl@1371
 11150
+
mgl@1371
 11151
+
mgl@1371
 11152
+/******************************************************************************
mgl@1371
 11153
+ * Controlling Debugging Information Format
mgl@1371
 11154
+ *****************************************************************************/
mgl@1371
 11155
+
mgl@1371
 11156
+/* How to renumber registers for dbx and gdb.  */
mgl@1371
 11157
+#define DBX_REGISTER_NUMBER(REGNO) ASM_REGNUM (REGNO)
mgl@1371
 11158
+
mgl@1371
 11159
+/* The DWARF 2 CFA column which tracks the return address.  */
mgl@1371
 11160
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM(LR_REGNUM)
mgl@1371
 11161
+
mgl@1371
 11162
+/*
mgl@1371
 11163
+Define this macro if GCC should produce dwarf version 2 format
mgl@1371
 11164
+debugging output in response to the -g option.
mgl@1371
 11165
+
mgl@1371
 11166
+To support optional call frame debugging information, you must also
mgl@1371
 11167
+define INCOMING_RETURN_ADDR_RTX and either set
mgl@1371
 11168
+RTX_FRAME_RELATED_P on the prologue insns if you use RTL for the
mgl@1371
 11169
+prologue, or call dwarf2out_def_cfa and dwarf2out_reg_save
mgl@1371
 11170
+as appropriate from TARGET_ASM_FUNCTION_PROLOGUE if you don't.
mgl@1371
 11171
+*/
mgl@1371
 11172
+#define DWARF2_DEBUGGING_INFO 1
mgl@1371
 11173
+
mgl@1371
 11174
+
mgl@1371
 11175
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
mgl@1371
 11176
+#define DWARF2_FRAME_INFO 1
mgl@1371
 11177
+
mgl@1371
 11178
+
mgl@1371
 11179
+/******************************************************************************
mgl@1371
 11180
+ * Miscellaneous Parameters
mgl@1371
 11181
+ *****************************************************************************/
mgl@1371
 11182
+
mgl@1371
 11183
+/* ToDo: a lot */
mgl@1371
 11184
+
mgl@1371
 11185
+/*
mgl@1371
 11186
+An alias for a machine mode name.  This is the machine mode that
mgl@1371
 11187
+elements of a jump-table should have.
mgl@1371
 11188
+*/
mgl@1371
 11189
+#define CASE_VECTOR_MODE SImode
mgl@1371
 11190
+
mgl@1371
 11191
+/*
mgl@1371
 11192
+Define this macro to be a C expression to indicate when jump-tables
mgl@1371
 11193
+should contain relative addresses.  If jump-tables never contain
mgl@1371
 11194
+relative addresses, then you need not define this macro.
mgl@1371
 11195
+*/
mgl@1371
 11196
+#define CASE_VECTOR_PC_RELATIVE 0
mgl@1371
 11197
+
mgl@1371
 11198
+/* Increase the threshold for using table jumps on the UC arch. */
mgl@1371
 11199
+#define CASE_VALUES_THRESHOLD  (TARGET_BRANCH_PRED ? 4 : 7)
mgl@1371
 11200
+
mgl@1371
 11201
+/*
mgl@1371
 11202
+The maximum number of bytes that a single instruction can move quickly
mgl@1371
 11203
+between memory and registers or between two memory locations.
mgl@1371
 11204
+*/
mgl@1371
 11205
+#define MOVE_MAX (2*UNITS_PER_WORD)
mgl@1371
 11206
+
mgl@1371
 11207
+
mgl@1371
 11208
+/* A C expression that is nonzero if on this machine the number of bits actually used
mgl@1371
 11209
+   for the count of a shift operation is equal to the number of bits needed to represent
mgl@1371
 11210
+   the size of the object being shifted. When this macro is nonzero, the compiler will
mgl@1371
 11211
+   assume that it is safe to omit a sign-extend, zero-extend, and certain bitwise 'and'
mgl@1371
 11212
+   instructions that truncates the count of a shift operation. On machines that have
mgl@1371
 11213
+   instructions that act on bit-fields at variable positions, which may include 'bit test'
mgl@1371
 11214
+   378 GNU Compiler Collection (GCC) Internals
mgl@1371
 11215
+   instructions, a nonzero SHIFT_COUNT_TRUNCATED also enables deletion of truncations
mgl@1371
 11216
+   of the values that serve as arguments to bit-field instructions.
mgl@1371
 11217
+   If both types of instructions truncate the count (for shifts) and position (for bit-field
mgl@1371
 11218
+   operations), or if no variable-position bit-field instructions exist, you should define
mgl@1371
 11219
+   this macro.
mgl@1371
 11220
+   However, on some machines, such as the 80386 and the 680x0, truncation only applies
mgl@1371
 11221
+   to shift operations and not the (real or pretended) bit-field operations. Define SHIFT_
mgl@1371
 11222
+   COUNT_TRUNCATED to be zero on such machines. Instead, add patterns to the 'md' file
mgl@1371
 11223
+   that include the implied truncation of the shift instructions.
mgl@1371
 11224
+   You need not dene this macro if it would always have the value of zero. */
mgl@1371
 11225
+#define SHIFT_COUNT_TRUNCATED 1
mgl@1371
 11226
+
mgl@1371
 11227
+/*
mgl@1371
 11228
+A C expression which is nonzero if on this machine it is safe to
mgl@1371
 11229
+convert an integer of INPREC bits to one of OUTPREC
mgl@1371
 11230
+bits (where OUTPREC is smaller than INPREC) by merely
mgl@1371
 11231
+operating on it as if it had only OUTPREC bits.
mgl@1371
 11232
+
mgl@1371
 11233
+On many machines, this expression can be 1.
mgl@1371
 11234
+
mgl@1371
 11235
+When TRULY_NOOP_TRUNCATION returns 1 for a pair of sizes for
mgl@1371
 11236
+modes for which MODES_TIEABLE_P is 0, suboptimal code can result.
mgl@1371
 11237
+If this is the case, making TRULY_NOOP_TRUNCATION return 0 in
mgl@1371
 11238
+such cases may improve things.
mgl@1371
 11239
+*/
mgl@1371
 11240
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
mgl@1371
 11241
+
mgl@1371
 11242
+/*
mgl@1371
 11243
+An alias for the machine mode for pointers.  On most machines, define
mgl@1371
 11244
+this to be the integer mode corresponding to the width of a hardware
mgl@1371
 11245
+pointer; SImode on 32-bit machine or DImode on 64-bit machines.
mgl@1371
 11246
+On some machines you must define this to be one of the partial integer
mgl@1371
 11247
+modes, such as PSImode.
mgl@1371
 11248
+
mgl@1371
 11249
+The width of Pmode must be at least as large as the value of
mgl@1371
 11250
+POINTER_SIZE.  If it is not equal, you must define the macro
mgl@1371
 11251
+POINTERS_EXTEND_UNSIGNED to specify how pointers are extended
mgl@1371
 11252
+to Pmode.
mgl@1371
 11253
+*/
mgl@1371
 11254
+#define Pmode SImode
mgl@1371
 11255
+
mgl@1371
 11256
+/*
mgl@1371
 11257
+An alias for the machine mode used for memory references to functions
mgl@1371
 11258
+being called, in call RTL expressions.  On most machines this
mgl@1371
 11259
+should be QImode.
mgl@1371
 11260
+*/
mgl@1371
 11261
+#define FUNCTION_MODE SImode
mgl@1371
 11262
+
mgl@1371
 11263
+
mgl@1371
 11264
+#define REG_S_P(x) \
mgl@1371
 11265
+ (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (XEXP (x, 0))))
mgl@1371
 11266
+
mgl@1371
 11267
+
mgl@1371
 11268
+/* If defined, modifies the length assigned to instruction INSN as a
mgl@1371
 11269
+   function of the context in which it is used.  LENGTH is an lvalue
mgl@1371
 11270
+   that contains the initially computed length of the insn and should
mgl@1371
 11271
+   be updated with the correct length of the insn.  */
mgl@1371
 11272
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
mgl@1371
 11273
+  ((LENGTH) = avr32_adjust_insn_length ((INSN), (LENGTH)))
mgl@1371
 11274
+
mgl@1371
 11275
+
mgl@1371
 11276
+#define CLZ_DEFINED_VALUE_AT_ZERO(mode, value) \
mgl@1371
 11277
+  (value = 32, (mode == SImode))
mgl@1371
 11278
+
mgl@1371
 11279
+#define CTZ_DEFINED_VALUE_AT_ZERO(mode, value) \
mgl@1371
 11280
+  (value = 32, (mode == SImode))
mgl@1371
 11281
+
mgl@1371
 11282
+#define UNITS_PER_SIMD_WORD UNITS_PER_WORD
mgl@1371
 11283
+
mgl@1371
 11284
+#define STORE_FLAG_VALUE 1
mgl@1371
 11285
+
mgl@1371
 11286
+
mgl@1371
 11287
+/* IF-conversion macros. */
mgl@1371
 11288
+#define IFCVT_MODIFY_INSN( CE_INFO, PATTERN, INSN )                     \
mgl@1371
 11289
+  {                                                                     \
mgl@1371
 11290
+    (PATTERN) = avr32_ifcvt_modify_insn (CE_INFO, PATTERN, INSN, &num_true_changes); \
mgl@1371
 11291
+  }
mgl@1371
 11292
+
mgl@1371
 11293
+#define IFCVT_EXTRA_FIELDS                              \
mgl@1371
 11294
+  int num_cond_clobber_insns;                           \
mgl@1371
 11295
+  int num_extra_move_insns;                             \
mgl@1371
 11296
+  rtx extra_move_insns[MAX_CONDITIONAL_EXECUTE];        \
mgl@1371
 11297
+  rtx moved_insns[MAX_CONDITIONAL_EXECUTE];
mgl@1371
 11298
+
mgl@1371
 11299
+#define IFCVT_INIT_EXTRA_FIELDS( CE_INFO )       \
mgl@1371
 11300
+  {                                              \
mgl@1371
 11301
+    (CE_INFO)->num_cond_clobber_insns = 0;       \
mgl@1371
 11302
+    (CE_INFO)->num_extra_move_insns = 0;         \
mgl@1371
 11303
+  }
mgl@1371
 11304
+
mgl@1371
 11305
+
mgl@1371
 11306
+#define IFCVT_MODIFY_CANCEL( CE_INFO )  avr32_ifcvt_modify_cancel (CE_INFO, &num_true_changes)
mgl@1371
 11307
+
mgl@1371
 11308
+#define IFCVT_ALLOW_MODIFY_TEST_IN_INSN 1
mgl@1371
 11309
+#define IFCVT_COND_EXEC_BEFORE_RELOAD (TARGET_COND_EXEC_BEFORE_RELOAD)
mgl@1371
 11310
+
mgl@1371
 11311
+enum avr32_builtins
mgl@1371
 11312
+{
mgl@1371
 11313
+  AVR32_BUILTIN_MTSR,
mgl@1371
 11314
+  AVR32_BUILTIN_MFSR,
mgl@1371
 11315
+  AVR32_BUILTIN_MTDR,
mgl@1371
 11316
+  AVR32_BUILTIN_MFDR,
mgl@1371
 11317
+  AVR32_BUILTIN_CACHE,
mgl@1371
 11318
+  AVR32_BUILTIN_SYNC,
mgl@1371
 11319
+  AVR32_BUILTIN_SSRF,
mgl@1371
 11320
+  AVR32_BUILTIN_CSRF,
mgl@1371
 11321
+  AVR32_BUILTIN_TLBR,
mgl@1371
 11322
+  AVR32_BUILTIN_TLBS,
mgl@1371
 11323
+  AVR32_BUILTIN_TLBW,
mgl@1371
 11324
+  AVR32_BUILTIN_BREAKPOINT,
mgl@1371
 11325
+  AVR32_BUILTIN_XCHG,
mgl@1371
 11326
+  AVR32_BUILTIN_LDXI,
mgl@1371
 11327
+  AVR32_BUILTIN_BSWAP16,
mgl@1371
 11328
+  AVR32_BUILTIN_BSWAP32,
mgl@1371
 11329
+  AVR32_BUILTIN_COP,
mgl@1371
 11330
+  AVR32_BUILTIN_MVCR_W,
mgl@1371
 11331
+  AVR32_BUILTIN_MVRC_W,
mgl@1371
 11332
+  AVR32_BUILTIN_MVCR_D,
mgl@1371
 11333
+  AVR32_BUILTIN_MVRC_D,
mgl@1371
 11334
+  AVR32_BUILTIN_MULSATHH_H,
mgl@1371
 11335
+  AVR32_BUILTIN_MULSATHH_W,
mgl@1371
 11336
+  AVR32_BUILTIN_MULSATRNDHH_H,
mgl@1371
 11337
+  AVR32_BUILTIN_MULSATRNDWH_W,
mgl@1371
 11338
+  AVR32_BUILTIN_MULSATWH_W,
mgl@1371
 11339
+  AVR32_BUILTIN_MACSATHH_W,
mgl@1371
 11340
+  AVR32_BUILTIN_SATADD_H,
mgl@1371
 11341
+  AVR32_BUILTIN_SATSUB_H,
mgl@1371
 11342
+  AVR32_BUILTIN_SATADD_W,
mgl@1371
 11343
+  AVR32_BUILTIN_SATSUB_W,
mgl@1371
 11344
+  AVR32_BUILTIN_MULWH_D,
mgl@1371
 11345
+  AVR32_BUILTIN_MULNWH_D,
mgl@1371
 11346
+  AVR32_BUILTIN_MACWH_D,
mgl@1371
 11347
+  AVR32_BUILTIN_MACHH_D,
mgl@1371
 11348
+  AVR32_BUILTIN_MUSFR,
mgl@1371
 11349
+  AVR32_BUILTIN_MUSTR,
mgl@1371
 11350
+  AVR32_BUILTIN_SATS,
mgl@1371
 11351
+  AVR32_BUILTIN_SATU,
mgl@1371
 11352
+  AVR32_BUILTIN_SATRNDS,
mgl@1371
 11353
+  AVR32_BUILTIN_SATRNDU,
mgl@1371
 11354
+  AVR32_BUILTIN_MEMS,
mgl@1371
 11355
+  AVR32_BUILTIN_MEMC,
mgl@1371
 11356
+  AVR32_BUILTIN_MEMT
mgl@1371
 11357
+};
mgl@1371
 11358
+
mgl@1371
 11359
+
mgl@1371
 11360
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) \
mgl@1371
 11361
+  ((MODE == SFmode) || (MODE == DFmode))
mgl@1371
 11362
+
mgl@1371
 11363
+#define RENAME_LIBRARY_SET ".set"
mgl@1371
 11364
+
mgl@1371
 11365
+/* Make ABI_NAME an alias for __GCC_NAME.  */
mgl@1371
 11366
+#define RENAME_LIBRARY(GCC_NAME, ABI_NAME)		\
mgl@1371
 11367
+  __asm__ (".globl\t__avr32_" #ABI_NAME "\n"		\
mgl@1371
 11368
+	   ".set\t__avr32_" #ABI_NAME 	\
mgl@1371
 11369
+	     ", __" #GCC_NAME "\n");
mgl@1371
 11370
+
mgl@1371
 11371
+/* Give libgcc functions avr32 ABI name.  */
mgl@1371
 11372
+#ifdef L_muldi3
mgl@1371
 11373
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, mul64)
mgl@1371
 11374
+#endif
mgl@1371
 11375
+#ifdef L_divdi3
mgl@1371
 11376
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (divdi3, sdiv64)
mgl@1371
 11377
+#endif
mgl@1371
 11378
+#ifdef L_udivdi3
mgl@1371
 11379
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (udivdi3, udiv64)
mgl@1371
 11380
+#endif
mgl@1371
 11381
+#ifdef L_moddi3
mgl@1371
 11382
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (moddi3, smod64)
mgl@1371
 11383
+#endif
mgl@1371
 11384
+#ifdef L_umoddi3
mgl@1371
 11385
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (umoddi3, umod64)
mgl@1371
 11386
+#endif
mgl@1371
 11387
+#ifdef L_ashldi3
mgl@1371
 11388
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashldi3, lsl64)
mgl@1371
 11389
+#endif
mgl@1371
 11390
+#ifdef L_lshrdi3
mgl@1371
 11391
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (lshrdi3, lsr64)
mgl@1371
 11392
+#endif
mgl@1371
 11393
+#ifdef L_ashrdi3
mgl@1371
 11394
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashrdi3, asr64)
mgl@1371
 11395
+#endif
mgl@1371
 11396
+
mgl@1371
 11397
+#ifdef L_fixsfdi
mgl@1371
 11398
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f32_to_s64)
mgl@1371
 11399
+#endif
mgl@1371
 11400
+#ifdef L_fixunssfdi
mgl@1371
 11401
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f32_to_u64)
mgl@1371
 11402
+#endif
mgl@1371
 11403
+#ifdef L_floatdidf
mgl@1371
 11404
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, s64_to_f64)
mgl@1371
 11405
+#endif
mgl@1371
 11406
+#ifdef L_floatdisf
mgl@1371
 11407
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, s64_to_f32)
mgl@1371
 11408
+#endif
mgl@1371
 11409
+
mgl@1371
 11410
+#endif
mgl@1371
 11411
--- /dev/null
mgl@1371
 11412
+++ b/gcc/config/avr32/avr32.md
mgl@1371
 11413
@@ -0,0 +1,4893 @@
mgl@1371
 11414
+;;   AVR32 machine description file.
mgl@1371
 11415
+;;   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 11416
+;;
mgl@1371
 11417
+;;   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 11418
+;;
mgl@1371
 11419
+;;   This file is part of GCC.
mgl@1371
 11420
+;;
mgl@1371
 11421
+;;   This program is free software; you can redistribute it and/or modify
mgl@1371
 11422
+;;   it under the terms of the GNU General Public License as published by
mgl@1371
 11423
+;;   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 11424
+;;   (at your option) any later version.
mgl@1371
 11425
+;;
mgl@1371
 11426
+;;   This program is distributed in the hope that it will be useful,
mgl@1371
 11427
+;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 11428
+;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 11429
+;;   GNU General Public License for more details.
mgl@1371
 11430
+;;
mgl@1371
 11431
+;;   You should have received a copy of the GNU General Public License
mgl@1371
 11432
+;;   along with this program; if not, write to the Free Software
mgl@1371
 11433
+;;   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
mgl@1371
 11434
+
mgl@1371
 11435
+;; -*- Mode: Scheme -*-
mgl@1371
 11436
+
mgl@1371
 11437
+(define_attr "type" "alu,alu2,alu_sat,mulhh,mulwh,mulww_w,mulww_d,div,machh_w,macww_w,macww_d,branch,call,load,load_rm,store,load2,load4,store2,store4,fmul,fcmps,fcmpd,fcast,fmv,fmvcpu,fldd,fstd,flds,fsts,fstm"
mgl@1371
 11438
+  (const_string "alu"))
mgl@1371
 11439
+
mgl@1371
 11440
+
mgl@1371
 11441
+(define_attr "cc" "none,set_vncz,set_ncz,set_cz,set_z,set_z_if_not_v2,bld,compare,cmp_cond_insn,clobber,call_set,fpcompare,from_fpcc"
mgl@1371
 11442
+  (const_string "none"))
mgl@1371
 11443
+
mgl@1371
 11444
+
mgl@1371
 11445
+; NB! Keep this in sync with enum architecture_type in avr32.h
mgl@1371
 11446
+(define_attr "pipeline" "ap,ucr1,ucr2,ucr2nomul"
mgl@1371
 11447
+  (const (symbol_ref "avr32_arch->arch_type")))
mgl@1371
 11448
+
mgl@1371
 11449
+; Insn length in bytes
mgl@1371
 11450
+(define_attr "length" ""
mgl@1371
 11451
+  (const_int 4))
mgl@1371
 11452
+
mgl@1371
 11453
+; Signal if an insn is predicable and hence can be conditionally executed.
mgl@1371
 11454
+(define_attr "predicable" "no,yes" (const_string "no"))
mgl@1371
 11455
+
mgl@1371
 11456
+;; Uses of UNSPEC in this file:
mgl@1371
 11457
+(define_constants
mgl@1371
 11458
+  [(UNSPEC_PUSHM                0)
mgl@1371
 11459
+   (UNSPEC_POPM                 1)
mgl@1371
 11460
+   (UNSPEC_UDIVMODSI4_INTERNAL	2)
mgl@1371
 11461
+   (UNSPEC_DIVMODSI4_INTERNAL   3)
mgl@1371
 11462
+   (UNSPEC_STM                  4)
mgl@1371
 11463
+   (UNSPEC_LDM                  5)
mgl@1371
 11464
+   (UNSPEC_MOVSICC              6)
mgl@1371
 11465
+   (UNSPEC_ADDSICC              7)
mgl@1371
 11466
+   (UNSPEC_COND_MI              8)
mgl@1371
 11467
+   (UNSPEC_COND_PL              9)
mgl@1371
 11468
+   (UNSPEC_PIC_SYM              10)
mgl@1371
 11469
+   (UNSPEC_PIC_BASE             11)
mgl@1371
 11470
+   (UNSPEC_STORE_MULTIPLE       12)
mgl@1371
 11471
+   (UNSPEC_STMFP                13)
mgl@1371
 11472
+   (UNSPEC_FPCC_TO_REG          14)
mgl@1371
 11473
+   (UNSPEC_REG_TO_CC            15)
mgl@1371
 11474
+   (UNSPEC_FORCE_MINIPOOL       16)
mgl@1371
 11475
+   (UNSPEC_SATS                 17)
mgl@1371
 11476
+   (UNSPEC_SATU                 18)
mgl@1371
 11477
+   (UNSPEC_SATRNDS              19)
mgl@1371
 11478
+   (UNSPEC_SATRNDU              20)
mgl@1371
 11479
+  ])
mgl@1371
 11480
+
mgl@1371
 11481
+(define_constants
mgl@1371
 11482
+  [(VUNSPEC_EPILOGUE                  0)
mgl@1371
 11483
+   (VUNSPEC_CACHE                     1)
mgl@1371
 11484
+   (VUNSPEC_MTSR                      2)
mgl@1371
 11485
+   (VUNSPEC_MFSR                      3)
mgl@1371
 11486
+   (VUNSPEC_BLOCKAGE                  4)
mgl@1371
 11487
+   (VUNSPEC_SYNC                      5)
mgl@1371
 11488
+   (VUNSPEC_TLBR                      6)
mgl@1371
 11489
+   (VUNSPEC_TLBW                      7)
mgl@1371
 11490
+   (VUNSPEC_TLBS                      8)
mgl@1371
 11491
+   (VUNSPEC_BREAKPOINT                9)
mgl@1371
 11492
+   (VUNSPEC_MTDR                      10)
mgl@1371
 11493
+   (VUNSPEC_MFDR                      11)
mgl@1371
 11494
+   (VUNSPEC_MVCR                      12)
mgl@1371
 11495
+   (VUNSPEC_MVRC                      13)
mgl@1371
 11496
+   (VUNSPEC_COP                       14)
mgl@1371
 11497
+   (VUNSPEC_ALIGN                     15)
mgl@1371
 11498
+   (VUNSPEC_POOL_START                16)
mgl@1371
 11499
+   (VUNSPEC_POOL_END                  17)
mgl@1371
 11500
+   (VUNSPEC_POOL_4                    18)
mgl@1371
 11501
+   (VUNSPEC_POOL_8                    19)
mgl@1371
 11502
+   (VUNSPEC_POOL_16                   20)
mgl@1371
 11503
+   (VUNSPEC_MUSFR                     21)
mgl@1371
 11504
+   (VUNSPEC_MUSTR                     22)
mgl@1371
 11505
+   (VUNSPEC_SYNC_CMPXCHG              23)
mgl@1371
 11506
+   (VUNSPEC_SYNC_SET_LOCK_AND_LOAD    24)
mgl@1371
 11507
+   (VUNSPEC_SYNC_STORE_IF_LOCK        25)
mgl@1371
 11508
+   (VUNSPEC_EH_RETURN                 26)
mgl@1371
 11509
+   (VUNSPEC_FRS                       27)
mgl@1371
 11510
+   (VUNSPEC_CSRF                      28)
mgl@1371
 11511
+   (VUNSPEC_SSRF                      29)
mgl@1371
 11512
+   ])
mgl@1371
 11513
+
mgl@1371
 11514
+(define_constants
mgl@1371
 11515
+  [
mgl@1371
 11516
+   ;; R7 = 15-7 = 8
mgl@1371
 11517
+   (FP_REGNUM   8)
mgl@1371
 11518
+   ;; Return Register = R12 = 15 - 12 = 3
mgl@1371
 11519
+   (RETVAL_REGNUM   3)
mgl@1371
 11520
+   ;; SP = R13 = 15 - 13 = 2
mgl@1371
 11521
+   (SP_REGNUM   2)
mgl@1371
 11522
+   ;; LR = R14 = 15 - 14 = 1
mgl@1371
 11523
+   (LR_REGNUM   1)
mgl@1371
 11524
+   ;; PC = R15 = 15 - 15 = 0
mgl@1371
 11525
+   (PC_REGNUM   0)
mgl@1371
 11526
+   ;; FPSR = GENERAL_REGS + 1 = 17
mgl@1371
 11527
+   (FPCC_REGNUM 17)
mgl@1371
 11528
+   ])
mgl@1371
 11529
+
mgl@1371
 11530
+
mgl@1371
 11531
+
mgl@1371
 11532
+
mgl@1371
 11533
+;;******************************************************************************
mgl@1371
 11534
+;; Macros
mgl@1371
 11535
+;;******************************************************************************
mgl@1371
 11536
+
mgl@1371
 11537
+;; Integer Modes for basic alu insns
mgl@1371
 11538
+(define_mode_macro INTM [SI HI QI])
mgl@1371
 11539
+(define_mode_attr  alu_cc_attr [(SI "set_vncz") (HI "clobber") (QI "clobber")])
mgl@1371
 11540
+
mgl@1371
 11541
+;; Move word modes
mgl@1371
 11542
+(define_mode_macro MOVM [SI V2HI V4QI])
mgl@1371
 11543
+
mgl@1371
 11544
+;; For mov/addcc insns
mgl@1371
 11545
+(define_mode_macro ADDCC [SI HI QI])
mgl@1371
 11546
+(define_mode_macro MOVCC [SF SI HI QI])
mgl@1371
 11547
+(define_mode_macro CMP [DI SI HI QI])
mgl@1371
 11548
+(define_mode_attr  store_postfix [(SF ".w") (SI ".w") (HI ".h") (QI ".b")])
mgl@1371
 11549
+(define_mode_attr  load_postfix [(SF ".w") (SI ".w") (HI ".sh") (QI ".ub")])
mgl@1371
 11550
+(define_mode_attr  load_postfix_s [(SI ".w") (HI ".sh") (QI ".sb")])
mgl@1371
 11551
+(define_mode_attr  load_postfix_u [(SI ".w") (HI ".uh") (QI ".ub")])
mgl@1371
 11552
+(define_mode_attr  pred_mem_constraint [(SF "RKu11") (SI "RKu11") (HI "RKu10") (QI "RKu09")])
mgl@1371
 11553
+(define_mode_attr  cmp_constraint [(DI "rKu20") (SI "rKs21") (HI "r") (QI "r")])
mgl@1371
 11554
+(define_mode_attr  cmp_predicate [(DI "register_immediate_operand")
mgl@1371
 11555
+                                  (SI "register_const_int_operand")
mgl@1371
 11556
+                                  (HI "register_operand")
mgl@1371
 11557
+                                  (QI "register_operand")])
mgl@1371
 11558
+(define_mode_attr  cmp_length [(DI "6")
mgl@1371
 11559
+                               (SI "4")
mgl@1371
 11560
+                               (HI "4")
mgl@1371
 11561
+                               (QI "4")])
mgl@1371
 11562
+
mgl@1371
 11563
+;; For all conditional insns
mgl@1371
 11564
+(define_code_macro any_cond [eq ne gt ge lt le gtu geu ltu leu])
mgl@1371
 11565
+(define_code_attr cond [(eq "eq") (ne "ne") (gt "gt") (ge "ge") (lt "lt") (le "le")
mgl@1371
 11566
+                        (gtu "hi") (geu "hs") (ltu "lo") (leu "ls")])
mgl@1371
 11567
+(define_code_attr invcond [(eq "ne") (ne "eq") (gt "le") (ge "lt") (lt "ge") (le "gt")
mgl@1371
 11568
+                           (gtu "ls") (geu "lo") (ltu "hs") (leu "hi")])
mgl@1371
 11569
+
mgl@1371
 11570
+;; For logical operations
mgl@1371
 11571
+(define_code_macro logical [and ior xor])
mgl@1371
 11572
+(define_code_attr logical_insn [(and "and") (ior "or") (xor "eor")])
mgl@1371
 11573
+
mgl@1371
 11574
+;; Predicable operations with three register operands 
mgl@1371
 11575
+(define_code_macro predicable_op3 [and ior xor plus minus])
mgl@1371
 11576
+(define_code_attr predicable_insn3 [(and "and") (ior "or") (xor "eor") (plus "add") (minus "sub")])
mgl@1371
 11577
+(define_code_attr predicable_commutative3 [(and "%") (ior "%") (xor "%") (plus "%") (minus "")])
mgl@1371
 11578
+
mgl@1371
 11579
+;; Load the predicates
mgl@1371
 11580
+(include "predicates.md")
mgl@1371
 11581
+
mgl@1371
 11582
+
mgl@1371
 11583
+;;******************************************************************************
mgl@1371
 11584
+;; Automaton pipeline description for avr32
mgl@1371
 11585
+;;******************************************************************************
mgl@1371
 11586
+
mgl@1371
 11587
+(define_automaton "avr32_ap")
mgl@1371
 11588
+
mgl@1371
 11589
+
mgl@1371
 11590
+(define_cpu_unit "is" "avr32_ap")
mgl@1371
 11591
+(define_cpu_unit "a1,m1,da" "avr32_ap")
mgl@1371
 11592
+(define_cpu_unit "a2,m2,d" "avr32_ap")
mgl@1371
 11593
+
mgl@1371
 11594
+;;Alu instructions
mgl@1371
 11595
+(define_insn_reservation "alu_op" 1
mgl@1371
 11596
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11597
+       (eq_attr "type" "alu"))
mgl@1371
 11598
+  "is,a1,a2")
mgl@1371
 11599
+
mgl@1371
 11600
+(define_insn_reservation "alu2_op" 2
mgl@1371
 11601
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11602
+       (eq_attr "type" "alu2"))
mgl@1371
 11603
+  "is,is+a1,a1+a2,a2")
mgl@1371
 11604
+
mgl@1371
 11605
+(define_insn_reservation "alu_sat_op" 2
mgl@1371
 11606
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11607
+       (eq_attr "type" "alu_sat"))
mgl@1371
 11608
+  "is,a1,a2")
mgl@1371
 11609
+
mgl@1371
 11610
+
mgl@1371
 11611
+;;Mul instructions
mgl@1371
 11612
+(define_insn_reservation "mulhh_op" 2
mgl@1371
 11613
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11614
+       (eq_attr "type" "mulhh,mulwh"))
mgl@1371
 11615
+  "is,m1,m2")
mgl@1371
 11616
+
mgl@1371
 11617
+(define_insn_reservation "mulww_w_op" 3
mgl@1371
 11618
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11619
+       (eq_attr "type" "mulww_w"))
mgl@1371
 11620
+  "is,m1,m1+m2,m2")
mgl@1371
 11621
+
mgl@1371
 11622
+(define_insn_reservation "mulww_d_op" 5
mgl@1371
 11623
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11624
+       (eq_attr "type" "mulww_d"))
mgl@1371
 11625
+  "is,m1,m1+m2,m1+m2,m2,m2")
mgl@1371
 11626
+
mgl@1371
 11627
+(define_insn_reservation "div_op" 33
mgl@1371
 11628
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11629
+       (eq_attr "type" "div"))
mgl@1371
 11630
+  "is,m1,m1*31 + m2*31,m2")
mgl@1371
 11631
+
mgl@1371
 11632
+(define_insn_reservation "machh_w_op" 3
mgl@1371
 11633
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11634
+       (eq_attr "type" "machh_w"))
mgl@1371
 11635
+  "is*2,m1,m2")
mgl@1371
 11636
+
mgl@1371
 11637
+
mgl@1371
 11638
+(define_insn_reservation "macww_w_op" 4
mgl@1371
 11639
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11640
+       (eq_attr "type" "macww_w"))
mgl@1371
 11641
+  "is*2,m1,m1,m2")
mgl@1371
 11642
+
mgl@1371
 11643
+
mgl@1371
 11644
+(define_insn_reservation "macww_d_op" 6
mgl@1371
 11645
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11646
+       (eq_attr "type" "macww_d"))
mgl@1371
 11647
+  "is*2,m1,m1+m2,m1+m2,m2")
mgl@1371
 11648
+
mgl@1371
 11649
+;;Bypasses for Mac instructions, because of accumulator cache.
mgl@1371
 11650
+;;Set latency as low as possible in order to let the compiler let
mgl@1371
 11651
+;;mul -> mac and mac -> mac combinations which use the same
mgl@1371
 11652
+;;accumulator cache be placed close together to avoid any
mgl@1371
 11653
+;;instructions which can ruin the accumulator cache come inbetween.
mgl@1371
 11654
+(define_bypass 4 "machh_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11655
+(define_bypass 5 "macww_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11656
+(define_bypass 7 "macww_d_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11657
+
mgl@1371
 11658
+(define_bypass 3 "mulhh_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11659
+(define_bypass 4 "mulww_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11660
+(define_bypass 6 "mulww_d_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
mgl@1371
 11661
+
mgl@1371
 11662
+
mgl@1371
 11663
+;;Bypasses for all mul/mac instructions followed by an instruction
mgl@1371
 11664
+;;which reads the output AND writes the result to the same register.
mgl@1371
 11665
+;;This will generate an Write After Write hazard which gives an
mgl@1371
 11666
+;;extra cycle before the result is ready.
mgl@1371
 11667
+(define_bypass 0 "machh_w_op" "machh_w_op" "avr32_valid_macmac_bypass")
mgl@1371
 11668
+(define_bypass 0 "macww_w_op" "macww_w_op" "avr32_valid_macmac_bypass")
mgl@1371
 11669
+(define_bypass 0 "macww_d_op" "macww_d_op" "avr32_valid_macmac_bypass")
mgl@1371
 11670
+
mgl@1371
 11671
+(define_bypass 0 "mulhh_op" "machh_w_op" "avr32_valid_mulmac_bypass")
mgl@1371
 11672
+(define_bypass 0 "mulww_w_op" "macww_w_op" "avr32_valid_mulmac_bypass")
mgl@1371
 11673
+(define_bypass 0 "mulww_d_op" "macww_d_op" "avr32_valid_mulmac_bypass")
mgl@1371
 11674
+
mgl@1371
 11675
+;;Branch and call instructions
mgl@1371
 11676
+;;We assume that all branches and rcalls are predicted correctly :-)
mgl@1371
 11677
+;;while calls use a lot of cycles.
mgl@1371
 11678
+(define_insn_reservation "branch_op" 0
mgl@1371
 11679
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11680
+       (eq_attr "type" "branch"))
mgl@1371
 11681
+  "nothing")
mgl@1371
 11682
+
mgl@1371
 11683
+(define_insn_reservation "call_op" 10
mgl@1371
 11684
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11685
+       (eq_attr "type" "call"))
mgl@1371
 11686
+  "nothing")
mgl@1371
 11687
+
mgl@1371
 11688
+
mgl@1371
 11689
+;;Load store instructions
mgl@1371
 11690
+(define_insn_reservation "load_op" 2
mgl@1371
 11691
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11692
+       (eq_attr "type" "load"))
mgl@1371
 11693
+  "is,da,d")
mgl@1371
 11694
+
mgl@1371
 11695
+(define_insn_reservation "load_rm_op" 3
mgl@1371
 11696
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11697
+       (eq_attr "type" "load_rm"))
mgl@1371
 11698
+  "is,da,d")
mgl@1371
 11699
+
mgl@1371
 11700
+
mgl@1371
 11701
+(define_insn_reservation "store_op" 0
mgl@1371
 11702
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11703
+       (eq_attr "type" "store"))
mgl@1371
 11704
+  "is,da,d")
mgl@1371
 11705
+
mgl@1371
 11706
+
mgl@1371
 11707
+(define_insn_reservation "load_double_op" 3
mgl@1371
 11708
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11709
+       (eq_attr "type" "load2"))
mgl@1371
 11710
+  "is,da,da+d,d")
mgl@1371
 11711
+
mgl@1371
 11712
+(define_insn_reservation "load_quad_op" 4
mgl@1371
 11713
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11714
+       (eq_attr "type" "load4"))
mgl@1371
 11715
+  "is,da,da+d,da+d,d")
mgl@1371
 11716
+
mgl@1371
 11717
+(define_insn_reservation "store_double_op" 0
mgl@1371
 11718
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11719
+       (eq_attr "type" "store2"))
mgl@1371
 11720
+  "is,da,da+d,d")
mgl@1371
 11721
+
mgl@1371
 11722
+
mgl@1371
 11723
+(define_insn_reservation "store_quad_op" 0
mgl@1371
 11724
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 11725
+       (eq_attr "type" "store4"))
mgl@1371
 11726
+  "is,da,da+d,da+d,d")
mgl@1371
 11727
+
mgl@1371
 11728
+;;For store the operand to write to memory is read in d and
mgl@1371
 11729
+;;the real latency between any instruction and a store is therefore
mgl@1371
 11730
+;;one less than for the instructions which reads the operands in the first
mgl@1371
 11731
+;;excecution stage
mgl@1371
 11732
+(define_bypass 2 "load_double_op" "store_double_op" "avr32_store_bypass")
mgl@1371
 11733
+(define_bypass 3 "load_quad_op" "store_quad_op" "avr32_store_bypass")
mgl@1371
 11734
+(define_bypass 1 "load_op" "store_op" "avr32_store_bypass")
mgl@1371
 11735
+(define_bypass 2 "load_rm_op" "store_op" "avr32_store_bypass")
mgl@1371
 11736
+(define_bypass 1 "alu_sat_op" "store_op" "avr32_store_bypass")
mgl@1371
 11737
+(define_bypass 1 "alu2_op" "store_op" "avr32_store_bypass")
mgl@1371
 11738
+(define_bypass 1 "mulhh_op" "store_op" "avr32_store_bypass")
mgl@1371
 11739
+(define_bypass 2 "mulww_w_op" "store_op" "avr32_store_bypass")
mgl@1371
 11740
+(define_bypass 4 "mulww_d_op" "store_op" "avr32_store_bypass" )
mgl@1371
 11741
+(define_bypass 2 "machh_w_op" "store_op" "avr32_store_bypass")
mgl@1371
 11742
+(define_bypass 3 "macww_w_op" "store_op" "avr32_store_bypass")
mgl@1371
 11743
+(define_bypass 5 "macww_d_op" "store_op" "avr32_store_bypass")
mgl@1371
 11744
+
mgl@1371
 11745
+
mgl@1371
 11746
+; Bypass for load double operation. If only the first loaded word is needed
mgl@1371
 11747
+; then the latency is 2
mgl@1371
 11748
+(define_bypass 2 "load_double_op"
mgl@1371
 11749
+                 "load_op,load_rm_op,alu_sat_op, alu2_op, alu_op, mulhh_op, mulww_w_op,
mgl@1371
 11750
+                  mulww_d_op, machh_w_op, macww_w_op, macww_d_op"
mgl@1371
 11751
+                 "avr32_valid_load_double_bypass")
mgl@1371
 11752
+
mgl@1371
 11753
+; Bypass for load quad operation. If only the first or second loaded word is needed
mgl@1371
 11754
+; we set the latency to 2
mgl@1371
 11755
+(define_bypass 2 "load_quad_op"
mgl@1371
 11756
+                 "load_op,load_rm_op,alu_sat_op, alu2_op, alu_op, mulhh_op, mulww_w_op,
mgl@1371
 11757
+                  mulww_d_op, machh_w_op, macww_w_op, macww_d_op"
mgl@1371
 11758
+                 "avr32_valid_load_quad_bypass")
mgl@1371
 11759
+
mgl@1371
 11760
+
mgl@1371
 11761
+;;******************************************************************************
mgl@1371
 11762
+;; End of Automaton pipeline description for avr32
mgl@1371
 11763
+;;******************************************************************************
mgl@1371
 11764
+
mgl@1371
 11765
+(define_cond_exec
mgl@1371
 11766
+  [(match_operator 0 "avr32_comparison_operator"
mgl@1371
 11767
+    [(match_operand:CMP 1 "register_operand" "r")         
mgl@1371
 11768
+     (match_operand:CMP 2 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])]
mgl@1371
 11769
+  "TARGET_V2_INSNS" 
mgl@1371
 11770
+  "%!"
mgl@1371
 11771
+)
mgl@1371
 11772
+
mgl@1371
 11773
+(define_cond_exec
mgl@1371
 11774
+  [(match_operator 0 "avr32_comparison_operator"
mgl@1371
 11775
+     [(and:SI (match_operand:SI 1 "register_operand" "r")         
mgl@1371
 11776
+              (match_operand:SI 2 "one_bit_set_operand" "i"))
mgl@1371
 11777
+      (const_int 0)])]
mgl@1371
 11778
+  "TARGET_V2_INSNS" 
mgl@1371
 11779
+  "%!"
mgl@1371
 11780
+  )
mgl@1371
 11781
+
mgl@1371
 11782
+;;=============================================================================
mgl@1371
 11783
+;; move
mgl@1371
 11784
+;;-----------------------------------------------------------------------------
mgl@1371
 11785
+
mgl@1371
 11786
+
mgl@1371
 11787
+;;== char - 8 bits ============================================================
mgl@1371
 11788
+(define_expand "movqi"
mgl@1371
 11789
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
mgl@1371
 11790
+	(match_operand:QI 1 "general_operand" ""))]
mgl@1371
 11791
+  ""
mgl@1371
 11792
+  {
mgl@1371
 11793
+   if ( !no_new_pseudos ){
mgl@1371
 11794
+     if (GET_CODE (operands[1]) == MEM && optimize){
mgl@1371
 11795
+         rtx reg = gen_reg_rtx (SImode);
mgl@1371
 11796
+
mgl@1371
 11797
+         emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
mgl@1371
 11798
+         operands[1] = gen_lowpart (QImode, reg);
mgl@1371
 11799
+     }
mgl@1371
 11800
+
mgl@1371
 11801
+     /* One of the ops has to be in a register.  */
mgl@1371
 11802
+     if (GET_CODE (operands[0]) == MEM)
mgl@1371
 11803
+       operands[1] = force_reg (QImode, operands[1]);
mgl@1371
 11804
+   }
mgl@1371
 11805
+
mgl@1371
 11806
+  })
mgl@1371
 11807
+
mgl@1371
 11808
+(define_insn "*movqi_internal"
mgl@1371
 11809
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r")
mgl@1371
 11810
+	(match_operand:QI 1 "general_operand"  "rKs08,m,r,i"))]
mgl@1371
 11811
+  "register_operand (operands[0], QImode)
mgl@1371
 11812
+   || register_operand (operands[1], QImode)"
mgl@1371
 11813
+  "@
mgl@1371
 11814
+   mov\t%0, %1
mgl@1371
 11815
+   ld.ub\t%0, %1
mgl@1371
 11816
+   st.b\t%0, %1
mgl@1371
 11817
+   mov\t%0, %1"
mgl@1371
 11818
+  [(set_attr "length" "2,4,4,4")
mgl@1371
 11819
+   (set_attr "type" "alu,load_rm,store,alu")])
mgl@1371
 11820
+
mgl@1371
 11821
+
mgl@1371
 11822
+
mgl@1371
 11823
+;;== short - 16 bits ==========================================================
mgl@1371
 11824
+(define_expand "movhi"
mgl@1371
 11825
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
mgl@1371
 11826
+	(match_operand:HI 1 "general_operand" ""))]
mgl@1371
 11827
+  ""
mgl@1371
 11828
+  {
mgl@1371
 11829
+   if ( !no_new_pseudos ){
mgl@1371
 11830
+     if (GET_CODE (operands[1]) == MEM && optimize){
mgl@1371
 11831
+         rtx reg = gen_reg_rtx (SImode);
mgl@1371
 11832
+
mgl@1371
 11833
+         emit_insn (gen_extendhisi2 (reg, operands[1]));
mgl@1371
 11834
+         operands[1] = gen_lowpart (HImode, reg);
mgl@1371
 11835
+     }
mgl@1371
 11836
+
mgl@1371
 11837
+     /* One of the ops has to be in a register.  */
mgl@1371
 11838
+     if (GET_CODE (operands[0]) == MEM)
mgl@1371
 11839
+       operands[1] = force_reg (HImode, operands[1]);
mgl@1371
 11840
+   }
mgl@1371
 11841
+
mgl@1371
 11842
+  })
mgl@1371
 11843
+
mgl@1371
 11844
+
mgl@1371
 11845
+(define_insn "*movhi_internal"
mgl@1371
 11846
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
mgl@1371
 11847
+	(match_operand:HI 1 "general_operand"  "rKs08,m,r,i"))]
mgl@1371
 11848
+  "register_operand (operands[0], HImode)
mgl@1371
 11849
+   || register_operand (operands[1], HImode)"
mgl@1371
 11850
+  "@
mgl@1371
 11851
+   mov\t%0, %1
mgl@1371
 11852
+   ld.sh\t%0, %1
mgl@1371
 11853
+   st.h\t%0, %1
mgl@1371
 11854
+   mov\t%0, %1"
mgl@1371
 11855
+  [(set_attr "length" "2,4,4,4")
mgl@1371
 11856
+   (set_attr "type" "alu,load_rm,store,alu")])
mgl@1371
 11857
+
mgl@1371
 11858
+
mgl@1371
 11859
+;;== int - 32 bits ============================================================
mgl@1371
 11860
+
mgl@1371
 11861
+(define_expand "movmisalignsi"
mgl@1371
 11862
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
mgl@1371
 11863
+	(match_operand:SI 1 "nonimmediate_operand" ""))]
mgl@1371
 11864
+  "TARGET_UNALIGNED_WORD"
mgl@1371
 11865
+  {
mgl@1371
 11866
+  }
mgl@1371
 11867
+)
mgl@1371
 11868
+
mgl@1371
 11869
+
mgl@1371
 11870
+(define_expand "mov<mode>"
mgl@1371
 11871
+  [(set (match_operand:MOVM 0 "avr32_non_rmw_nonimmediate_operand" "")
mgl@1371
 11872
+	(match_operand:MOVM 1 "avr32_non_rmw_general_operand" ""))]
mgl@1371
 11873
+  ""
mgl@1371
 11874
+  {
mgl@1371
 11875
+
mgl@1371
 11876
+    /* One of the ops has to be in a register.  */
mgl@1371
 11877
+    if (GET_CODE (operands[0]) == MEM)
mgl@1371
 11878
+      operands[1] = force_reg (<MODE>mode, operands[1]);
mgl@1371
 11879
+
mgl@1371
 11880
+
mgl@1371
 11881
+    /* Check for out of range immediate constants as these may
mgl@1371
 11882
+       occur during reloading, since it seems like reload does
mgl@1371
 11883
+       not check if the immediate is legitimate. Don't know if
mgl@1371
 11884
+       this is a bug? */
mgl@1371
 11885
+    if ( reload_in_progress
mgl@1371
 11886
+         && avr32_imm_in_const_pool
mgl@1371
 11887
+         && GET_CODE(operands[1]) == CONST_INT
mgl@1371
 11888
+         && !avr32_const_ok_for_constraint_p(INTVAL(operands[1]), 'K', "Ks21") ){
mgl@1371
 11889
+        operands[1] = force_const_mem(SImode, operands[1]);
mgl@1371
 11890
+    }
mgl@1371
 11891
+
mgl@1371
 11892
+    /* Check for RMW memory operands. They are not allowed for mov operations
mgl@1371
 11893
+       only the atomic memc/s/t operations */
mgl@1371
 11894
+    if ( !reload_in_progress
mgl@1371
 11895
+         && avr32_rmw_memory_operand (operands[0], <MODE>mode) ){
mgl@1371
 11896
+       operands[0] = copy_rtx (operands[0]);                                                              
mgl@1371
 11897
+       XEXP(operands[0], 0) = force_reg (<MODE>mode, XEXP(operands[0], 0));
mgl@1371
 11898
+    }
mgl@1371
 11899
+
mgl@1371
 11900
+    if ( !reload_in_progress
mgl@1371
 11901
+         && avr32_rmw_memory_operand (operands[1], <MODE>mode) ){
mgl@1371
 11902
+       operands[1] = copy_rtx (operands[1]);                                                              
mgl@1371
 11903
+       XEXP(operands[1], 0) = force_reg (<MODE>mode, XEXP(operands[1], 0));
mgl@1371
 11904
+    }
mgl@1371
 11905
+
mgl@1371
 11906
+    if ( (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS)
mgl@1371
 11907
+         && !avr32_legitimate_pic_operand_p(operands[1]) )
mgl@1371
 11908
+      operands[1] = legitimize_pic_address (operands[1], <MODE>mode,
mgl@1371
 11909
+                                            (no_new_pseudos ? operands[0] : 0));
mgl@1371
 11910
+    else if ( flag_pic && avr32_address_operand(operands[1], GET_MODE(operands[1])) )
mgl@1371
 11911
+      /* If we have an address operand then this function uses the pic register. */
mgl@1371
 11912
+      current_function_uses_pic_offset_table = 1;
mgl@1371
 11913
+  })
mgl@1371
 11914
+
mgl@1371
 11915
+
mgl@1371
 11916
+
mgl@1371
 11917
+(define_insn "mov<mode>_internal"
mgl@1371
 11918
+  [(set (match_operand:MOVM 0 "avr32_non_rmw_nonimmediate_operand" "=r,   r,   r,r,r,Q,r")
mgl@1371
 11919
+	(match_operand:MOVM 1 "avr32_non_rmw_general_operand"      "rKs08,Ks21,J,n,Q,r,W"))]
mgl@1371
 11920
+  "(register_operand (operands[0], <MODE>mode)
mgl@1371
 11921
+    || register_operand (operands[1], <MODE>mode))
mgl@1371
 11922
+   && !avr32_rmw_memory_operand (operands[0], <MODE>mode) 
mgl@1371
 11923
+   && !avr32_rmw_memory_operand (operands[1], <MODE>mode)"
mgl@1371
 11924
+  {
mgl@1371
 11925
+    switch (which_alternative) {
mgl@1371
 11926
+      case 0:
mgl@1371
 11927
+      case 1: return "mov\t%0, %1";
mgl@1371
 11928
+      case 2:
mgl@1371
 11929
+        if ( TARGET_V2_INSNS )
mgl@1371
 11930
+           return "movh\t%0, hi(%1)";
mgl@1371
 11931
+        /* Fallthrough */
mgl@1371
 11932
+      case 3: return "mov\t%0, lo(%1)\;orh\t%0,hi(%1)";
mgl@1371
 11933
+      case 4:
mgl@1371
 11934
+        if ( (REG_P(XEXP(operands[1], 0))
mgl@1371
 11935
+              && REGNO(XEXP(operands[1], 0)) == SP_REGNUM)
mgl@1371
 11936
+             || (GET_CODE(XEXP(operands[1], 0)) == PLUS
mgl@1371
 11937
+                 && REGNO(XEXP(XEXP(operands[1], 0), 0)) == SP_REGNUM
mgl@1371
 11938
+	         && GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT
mgl@1371
 11939
+	         && INTVAL(XEXP(XEXP(operands[1], 0), 1)) % 4 == 0
mgl@1371
 11940
+	         && INTVAL(XEXP(XEXP(operands[1], 0), 1)) <= 0x1FC) )
mgl@1371
 11941
+          return "lddsp\t%0, %1";
mgl@1371
 11942
+	else if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])) )
mgl@1371
 11943
+          return "lddpc\t%0, %1";
mgl@1371
 11944
+        else
mgl@1371
 11945
+          return "ld.w\t%0, %1";
mgl@1371
 11946
+      case 5:
mgl@1371
 11947
+        if ( (REG_P(XEXP(operands[0], 0))
mgl@1371
 11948
+              && REGNO(XEXP(operands[0], 0)) == SP_REGNUM)
mgl@1371
 11949
+             || (GET_CODE(XEXP(operands[0], 0)) == PLUS
mgl@1371
 11950
+                 && REGNO(XEXP(XEXP(operands[0], 0), 0)) == SP_REGNUM
mgl@1371
 11951
+	         && GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT
mgl@1371
 11952
+	         && INTVAL(XEXP(XEXP(operands[0], 0), 1)) % 4 == 0
mgl@1371
 11953
+	         && INTVAL(XEXP(XEXP(operands[0], 0), 1)) <= 0x1FC) )
mgl@1371
 11954
+          return "stdsp\t%0, %1";
mgl@1371
 11955
+	else
mgl@1371
 11956
+          return "st.w\t%0, %1";
mgl@1371
 11957
+      case 6:
mgl@1371
 11958
+        if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
mgl@1371
 11959
+          return "lda.w\t%0, %1";
mgl@1371
 11960
+        else
mgl@1371
 11961
+          return "ld.w\t%0, r6[%1@got]";
mgl@1371
 11962
+      default:
mgl@1371
 11963
+	abort();
mgl@1371
 11964
+    }
mgl@1371
 11965
+  }
mgl@1371
 11966
+  
mgl@1371
 11967
+  [(set_attr "length" "2,4,4,8,4,4,8")
mgl@1371
 11968
+   (set_attr "type" "alu,alu,alu,alu2,load,store,load")
mgl@1371
 11969
+   (set_attr "cc" "none,none,set_z_if_not_v2,set_z,none,none,clobber")])
mgl@1371
 11970
+
mgl@1371
 11971
+
mgl@1371
 11972
+(define_expand "reload_out_rmw_memory_operand"
mgl@1371
 11973
+  [(set (match_operand:SI 2 "register_operand" "=r")
mgl@1371
 11974
+        (match_operand:SI 0 "address_operand" ""))
mgl@1371
 11975
+   (set (mem:SI (match_dup 2))
mgl@1371
 11976
+        (match_operand:SI 1 "register_operand" ""))]
mgl@1371
 11977
+  ""
mgl@1371
 11978
+  {
mgl@1371
 11979
+   operands[0] = XEXP(operands[0], 0);
mgl@1371
 11980
+  }
mgl@1371
 11981
+)
mgl@1371
 11982
+
mgl@1371
 11983
+(define_expand "reload_in_rmw_memory_operand"
mgl@1371
 11984
+  [(set (match_operand:SI 2 "register_operand" "=r")
mgl@1371
 11985
+        (match_operand:SI 1 "address_operand" ""))
mgl@1371
 11986
+   (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 11987
+        (mem:SI (match_dup 2)))]
mgl@1371
 11988
+  ""
mgl@1371
 11989
+  {
mgl@1371
 11990
+   operands[1] = XEXP(operands[1], 0);
mgl@1371
 11991
+  }
mgl@1371
 11992
+)
mgl@1371
 11993
+
mgl@1371
 11994
+
mgl@1371
 11995
+;; These instructions are for loading constants which cannot be loaded
mgl@1371
 11996
+;; directly from the constant pool because the offset is too large
mgl@1371
 11997
+;; high and lo_sum are used even tough for our case it should be
mgl@1371
 11998
+;; low and high sum :-)
mgl@1371
 11999
+(define_insn "mov_symbol_lo"
mgl@1371
 12000
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12001
+	(high:SI (match_operand:SI 1 "immediate_operand" "i" )))]
mgl@1371
 12002
+  ""
mgl@1371
 12003
+  "mov\t%0, lo(%1)"
mgl@1371
 12004
+  [(set_attr "type" "alu")
mgl@1371
 12005
+   (set_attr "length" "4")]
mgl@1371
 12006
+)
mgl@1371
 12007
+
mgl@1371
 12008
+(define_insn "add_symbol_hi"
mgl@1371
 12009
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12010
+	(lo_sum:SI (match_dup 0)
mgl@1371
 12011
+                   (match_operand:SI 1 "immediate_operand" "i" )))]
mgl@1371
 12012
+  ""
mgl@1371
 12013
+  "orh\t%0, hi(%1)"
mgl@1371
 12014
+  [(set_attr "type" "alu")
mgl@1371
 12015
+   (set_attr "length" "4")]
mgl@1371
 12016
+)
mgl@1371
 12017
+
mgl@1371
 12018
+
mgl@1371
 12019
+
mgl@1371
 12020
+;; When generating pic, we need to load the symbol offset into a register.
mgl@1371
 12021
+;; So that the optimizer does not confuse this with a normal symbol load
mgl@1371
 12022
+;; we use an unspec.  The offset will be loaded from a constant pool entry,
mgl@1371
 12023
+;; since that is the only type of relocation we can use.
mgl@1371
 12024
+(define_insn "pic_load_addr"
mgl@1371
 12025
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12026
+	(unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYM))]
mgl@1371
 12027
+  "flag_pic && CONSTANT_POOL_ADDRESS_P(XEXP(operands[1], 0))"
mgl@1371
 12028
+  "lddpc\t%0, %1"
mgl@1371
 12029
+  [(set_attr "type" "load")
mgl@1371
 12030
+   (set_attr "length" "4")]
mgl@1371
 12031
+)
mgl@1371
 12032
+
mgl@1371
 12033
+(define_insn "pic_compute_got_from_pc"
mgl@1371
 12034
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 12035
+	(unspec:SI [(minus:SI (pc)
mgl@1371
 12036
+                              (match_dup 0))] UNSPEC_PIC_BASE))
mgl@1371
 12037
+   (use (label_ref (match_operand 1 "" "")))]
mgl@1371
 12038
+  "flag_pic"
mgl@1371
 12039
+  {
mgl@1371
 12040
+   (*targetm.asm_out.internal_label) (asm_out_file, "L",
mgl@1371
 12041
+	 		     CODE_LABEL_NUMBER (operands[1]));
mgl@1371
 12042
+   return \"rsub\t%0, pc\";
mgl@1371
 12043
+  }
mgl@1371
 12044
+  [(set_attr "cc" "clobber")
mgl@1371
 12045
+   (set_attr "length" "2")]
mgl@1371
 12046
+)
mgl@1371
 12047
+
mgl@1371
 12048
+;;== long long int - 64 bits ==================================================
mgl@1371
 12049
+
mgl@1371
 12050
+(define_expand "movdi"
mgl@1371
 12051
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
mgl@1371
 12052
+	(match_operand:DI 1 "general_operand" ""))]
mgl@1371
 12053
+  ""
mgl@1371
 12054
+  {
mgl@1371
 12055
+
mgl@1371
 12056
+    /* One of the ops has to be in a register.  */
mgl@1371
 12057
+    if (GET_CODE (operands[0]) != REG)
mgl@1371
 12058
+      operands[1] = force_reg (DImode, operands[1]);
mgl@1371
 12059
+
mgl@1371
 12060
+  })
mgl@1371
 12061
+
mgl@1371
 12062
+
mgl@1371
 12063
+(define_insn_and_split "*movdi_internal"
mgl@1371
 12064
+  [(set (match_operand:DI 0 "nonimmediate_operand"     "=r,r,   r,   r,r,r,m")
mgl@1371
 12065
+	(match_operand:DI 1 "general_operand"          "r, Ks08,Ks21,G,n,m,r"))]
mgl@1371
 12066
+  "register_operand (operands[0], DImode)
mgl@1371
 12067
+   || register_operand (operands[1], DImode)"
mgl@1371
 12068
+  {
mgl@1371
 12069
+    switch (which_alternative ){
mgl@1371
 12070
+    case 0:
mgl@1371
 12071
+    case 1:
mgl@1371
 12072
+    case 2:
mgl@1371
 12073
+    case 3:
mgl@1371
 12074
+    case 4:
mgl@1371
 12075
+        return "#";
mgl@1371
 12076
+    case 5:
mgl@1371
 12077
+      if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])))
mgl@1371
 12078
+        return "ld.d\t%0, pc[%1 - .]";
mgl@1371
 12079
+      else
mgl@1371
 12080
+        return "ld.d\t%0, %1";
mgl@1371
 12081
+    case 6:
mgl@1371
 12082
+      return "st.d\t%0, %1";
mgl@1371
 12083
+    default:
mgl@1371
 12084
+      abort();
mgl@1371
 12085
+    }
mgl@1371
 12086
+  }
mgl@1371
 12087
+;; Lets split all reg->reg or imm->reg transfers into two SImode transfers 
mgl@1371
 12088
+  "reload_completed &&
mgl@1371
 12089
+   (REG_P (operands[0]) &&
mgl@1371
 12090
+   (REG_P (operands[1]) 
mgl@1371
 12091
+    || GET_CODE (operands[1]) == CONST_INT
mgl@1371
 12092
+    || GET_CODE (operands[1]) == CONST_DOUBLE))"
mgl@1371
 12093
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 12094
+   (set (match_dup 2) (match_dup 3))]
mgl@1371
 12095
+  {
mgl@1371
 12096
+    operands[2] = gen_highpart (SImode, operands[0]);
mgl@1371
 12097
+    operands[0] = gen_lowpart (SImode, operands[0]);
mgl@1371
 12098
+    if ( REG_P(operands[1]) ){
mgl@1371
 12099
+      operands[3] = gen_highpart(SImode, operands[1]);
mgl@1371
 12100
+      operands[1] = gen_lowpart(SImode, operands[1]);
mgl@1371
 12101
+    } else if ( GET_CODE(operands[1]) == CONST_DOUBLE 
mgl@1371
 12102
+                || GET_CODE(operands[1]) == CONST_INT ){
mgl@1371
 12103
+      rtx split_const[2];
mgl@1371
 12104
+      avr32_split_const_expr (DImode, SImode, operands[1], split_const);
mgl@1371
 12105
+      operands[3] = split_const[1];
mgl@1371
 12106
+      operands[1] = split_const[0];
mgl@1371
 12107
+    } else {
mgl@1371
 12108
+      internal_error("Illegal operand[1] for movdi split!");
mgl@1371
 12109
+    }
mgl@1371
 12110
+  }
mgl@1371
 12111
+
mgl@1371
 12112
+  [(set_attr "length" "*,*,*,*,*,4,4")
mgl@1371
 12113
+   (set_attr "type" "*,*,*,*,*,load2,store2")
mgl@1371
 12114
+   (set_attr "cc" "*,*,*,*,*,none,none")])
mgl@1371
 12115
+
mgl@1371
 12116
+
mgl@1371
 12117
+;;== 128 bits ==================================================
mgl@1371
 12118
+(define_expand "movti"
mgl@1371
 12119
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
mgl@1371
 12120
+	(match_operand:TI 1 "nonimmediate_operand" ""))]
mgl@1371
 12121
+  "TARGET_ARCH_AP"    
mgl@1371
 12122
+  {     
mgl@1371
 12123
+        
mgl@1371
 12124
+    /* One of the ops has to be in a register.  */
mgl@1371
 12125
+    if (GET_CODE (operands[0]) != REG)
mgl@1371
 12126
+      operands[1] = force_reg (TImode, operands[1]);
mgl@1371
 12127
+
mgl@1371
 12128
+    /* We must fix any pre_dec for loads and post_inc stores */
mgl@1371
 12129
+    if ( GET_CODE (operands[0]) == MEM
mgl@1371
 12130
+         && GET_CODE (XEXP(operands[0],0)) == POST_INC ){
mgl@1371
 12131
+       emit_move_insn(gen_rtx_MEM(TImode, XEXP(XEXP(operands[0],0),0)), operands[1]);
mgl@1371
 12132
+       emit_insn(gen_addsi3(XEXP(XEXP(operands[0],0),0), XEXP(XEXP(operands[0],0),0), GEN_INT(GET_MODE_SIZE(TImode))));
mgl@1371
 12133
+       DONE;
mgl@1371
 12134
+    }
mgl@1371
 12135
+
mgl@1371
 12136
+    if ( GET_CODE (operands[1]) == MEM
mgl@1371
 12137
+         && GET_CODE (XEXP(operands[1],0)) == PRE_DEC ){
mgl@1371
 12138
+       emit_insn(gen_addsi3(XEXP(XEXP(operands[1],0),0), XEXP(XEXP(operands[1],0),0), GEN_INT(-GET_MODE_SIZE(TImode))));
mgl@1371
 12139
+       emit_move_insn(operands[0], gen_rtx_MEM(TImode, XEXP(XEXP(operands[1],0),0)));
mgl@1371
 12140
+       DONE;
mgl@1371
 12141
+    }
mgl@1371
 12142
+  })
mgl@1371
 12143
+
mgl@1371
 12144
+
mgl@1371
 12145
+(define_insn_and_split "*movti_internal"
mgl@1371
 12146
+  [(set (match_operand:TI 0 "avr32_movti_dst_operand"  "=r,&r,    r,    <RKu00,r,r")
mgl@1371
 12147
+	(match_operand:TI 1 "avr32_movti_src_operand"  " r,RKu00>,RKu00,r,     n,T"))]
mgl@1371
 12148
+  "(register_operand (operands[0], TImode)
mgl@1371
 12149
+    || register_operand (operands[1], TImode))"
mgl@1371
 12150
+  {
mgl@1371
 12151
+    switch (which_alternative ){
mgl@1371
 12152
+    case 0:
mgl@1371
 12153
+    case 2:
mgl@1371
 12154
+    case 4:
mgl@1371
 12155
+        return "#";
mgl@1371
 12156
+    case 1:
mgl@1371
 12157
+        return "ldm\t%p1, %0";
mgl@1371
 12158
+    case 3:
mgl@1371
 12159
+        return "stm\t%p0, %1";
mgl@1371
 12160
+    case 5:
mgl@1371
 12161
+        return "ld.d\t%U0, pc[%1 - .]\;ld.d\t%B0, pc[%1 - . + 8]";
mgl@1371
 12162
+    }
mgl@1371
 12163
+  }
mgl@1371
 12164
+
mgl@1371
 12165
+  "reload_completed &&
mgl@1371
 12166
+   (REG_P (operands[0]) &&
mgl@1371
 12167
+   (REG_P (operands[1]) 
mgl@1371
 12168
+    /* If this is a load from the constant pool we split it into
mgl@1371
 12169
+       two double loads. */
mgl@1371
 12170
+    || (GET_CODE (operands[1]) == MEM
mgl@1371
 12171
+        && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
mgl@1371
 12172
+        && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))               
mgl@1371
 12173
+    /* If this is a load where the pointer register is a part
mgl@1371
 12174
+       of the register list, we must split it into two double
mgl@1371
 12175
+       loads in order for it to be exception safe. */
mgl@1371
 12176
+    || (GET_CODE (operands[1]) == MEM
mgl@1371
 12177
+        && register_operand (XEXP (operands[1], 0), SImode)
mgl@1371
 12178
+        && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))               
mgl@1371
 12179
+    || GET_CODE (operands[1]) == CONST_INT
mgl@1371
 12180
+    || GET_CODE (operands[1]) == CONST_DOUBLE))"
mgl@1371
 12181
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 12182
+   (set (match_dup 2) (match_dup 3))]
mgl@1371
 12183
+  {
mgl@1371
 12184
+    operands[2] = simplify_gen_subreg ( DImode, operands[0], 
mgl@1371
 12185
+                                        TImode, 0 );
mgl@1371
 12186
+    operands[0] = simplify_gen_subreg ( DImode, operands[0], 
mgl@1371
 12187
+                                        TImode, 8 );
mgl@1371
 12188
+    if ( REG_P(operands[1]) ){
mgl@1371
 12189
+      operands[3] = simplify_gen_subreg ( DImode, operands[1], 
mgl@1371
 12190
+                                          TImode, 0 );
mgl@1371
 12191
+      operands[1] = simplify_gen_subreg ( DImode, operands[1], 
mgl@1371
 12192
+                                          TImode, 8 );
mgl@1371
 12193
+    } else if ( GET_CODE(operands[1]) == CONST_DOUBLE 
mgl@1371
 12194
+                || GET_CODE(operands[1]) == CONST_INT ){
mgl@1371
 12195
+      rtx split_const[2];
mgl@1371
 12196
+      avr32_split_const_expr (TImode, DImode, operands[1], split_const);
mgl@1371
 12197
+      operands[3] = split_const[1];
mgl@1371
 12198
+      operands[1] = split_const[0];
mgl@1371
 12199
+    } else if (avr32_const_pool_ref_operand (operands[1], GET_MODE(operands[1]))){
mgl@1371
 12200
+      rtx split_const[2];
mgl@1371
 12201
+      rtx cop = avoid_constant_pool_reference (operands[1]);
mgl@1371
 12202
+      if (operands[1] == cop)
mgl@1371
 12203
+        cop = get_pool_constant (XEXP (operands[1], 0));
mgl@1371
 12204
+      avr32_split_const_expr (TImode, DImode, cop, split_const);
mgl@1371
 12205
+      operands[3] = force_const_mem (DImode, split_const[1]); 
mgl@1371
 12206
+      operands[1] = force_const_mem (DImode, split_const[0]); 
mgl@1371
 12207
+   } else {
mgl@1371
 12208
+      rtx ptr_reg = XEXP (operands[1], 0);
mgl@1371
 12209
+      operands[1] = gen_rtx_MEM (DImode, 
mgl@1371
 12210
+                                 gen_rtx_PLUS ( SImode,
mgl@1371
 12211
+                                                ptr_reg,
mgl@1371
 12212
+                                                GEN_INT (8) ));
mgl@1371
 12213
+      operands[3] = gen_rtx_MEM (DImode,
mgl@1371
 12214
+                                 ptr_reg);
mgl@1371
 12215
+              
mgl@1371
 12216
+      /* Check if the first load will clobber the pointer.
mgl@1371
 12217
+         If so, we must switch the order of the operations. */
mgl@1371
 12218
+      if ( reg_overlap_mentioned_p (operands[0], ptr_reg) )
mgl@1371
 12219
+        {
mgl@1371
 12220
+          /* We need to switch the order of the operations
mgl@1371
 12221
+             so that the pointer register does not get clobbered
mgl@1371
 12222
+             after the first double word load. */
mgl@1371
 12223
+          rtx tmp;
mgl@1371
 12224
+          tmp = operands[0];
mgl@1371
 12225
+          operands[0] = operands[2];
mgl@1371
 12226
+          operands[2] = tmp;
mgl@1371
 12227
+          tmp = operands[1];
mgl@1371
 12228
+          operands[1] = operands[3];
mgl@1371
 12229
+          operands[3] = tmp;
mgl@1371
 12230
+        }
mgl@1371
 12231
+
mgl@1371
 12232
+
mgl@1371
 12233
+   }
mgl@1371
 12234
+  }
mgl@1371
 12235
+  [(set_attr "length" "*,*,4,4,*,8")
mgl@1371
 12236
+   (set_attr "type" "*,*,load4,store4,*,load4")])
mgl@1371
 12237
+
mgl@1371
 12238
+
mgl@1371
 12239
+;;== float - 32 bits ==========================================================
mgl@1371
 12240
+(define_expand "movsf"
mgl@1371
 12241
+  [(set (match_operand:SF 0 "nonimmediate_operand" "")
mgl@1371
 12242
+	(match_operand:SF 1 "general_operand" ""))]
mgl@1371
 12243
+  ""
mgl@1371
 12244
+  {
mgl@1371
 12245
+
mgl@1371
 12246
+
mgl@1371
 12247
+    /* One of the ops has to be in a register.  */
mgl@1371
 12248
+    if (GET_CODE (operands[0]) != REG)
mgl@1371
 12249
+      operands[1] = force_reg (SFmode, operands[1]);
mgl@1371
 12250
+
mgl@1371
 12251
+  })
mgl@1371
 12252
+
mgl@1371
 12253
+(define_insn "*movsf_internal"
mgl@1371
 12254
+  [(set (match_operand:SF 0 "nonimmediate_operand"     "=r,r,r,r,m")
mgl@1371
 12255
+	(match_operand:SF 1 "general_operand"          "r, G,F,m,r"))]
mgl@1371
 12256
+  "(register_operand (operands[0], SFmode)
mgl@1371
 12257
+    || register_operand (operands[1], SFmode))"
mgl@1371
 12258
+  {
mgl@1371
 12259
+    switch (which_alternative) {
mgl@1371
 12260
+      case 0:
mgl@1371
 12261
+      case 1: return "mov\t%0, %1";
mgl@1371
 12262
+      case 2: 
mgl@1371
 12263
+       {
mgl@1371
 12264
+        HOST_WIDE_INT target_float[2];
mgl@1371
 12265
+        real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
mgl@1371
 12266
+        if ( TARGET_V2_INSNS 
mgl@1371
 12267
+             && avr32_hi16_immediate_operand (GEN_INT (target_float[0]), VOIDmode) )
mgl@1371
 12268
+           return "movh\t%0, hi(%1)";
mgl@1371
 12269
+        else
mgl@1371
 12270
+           return "mov\t%0, lo(%1)\;orh\t%0, hi(%1)";
mgl@1371
 12271
+       }
mgl@1371
 12272
+      case 3:
mgl@1371
 12273
+        if ( (REG_P(XEXP(operands[1], 0))
mgl@1371
 12274
+              && REGNO(XEXP(operands[1], 0)) == SP_REGNUM)
mgl@1371
 12275
+             || (GET_CODE(XEXP(operands[1], 0)) == PLUS
mgl@1371
 12276
+                 && REGNO(XEXP(XEXP(operands[1], 0), 0)) == SP_REGNUM
mgl@1371
 12277
+	         && GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT
mgl@1371
 12278
+	         && INTVAL(XEXP(XEXP(operands[1], 0), 1)) % 4 == 0
mgl@1371
 12279
+	         && INTVAL(XEXP(XEXP(operands[1], 0), 1)) <= 0x1FC) )
mgl@1371
 12280
+          return "lddsp\t%0, %1";
mgl@1371
 12281
+          else if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])) )
mgl@1371
 12282
+          return "lddpc\t%0, %1";
mgl@1371
 12283
+        else
mgl@1371
 12284
+          return "ld.w\t%0, %1";
mgl@1371
 12285
+      case 4:
mgl@1371
 12286
+        if ( (REG_P(XEXP(operands[0], 0))
mgl@1371
 12287
+              && REGNO(XEXP(operands[0], 0)) == SP_REGNUM)
mgl@1371
 12288
+             || (GET_CODE(XEXP(operands[0], 0)) == PLUS
mgl@1371
 12289
+                 && REGNO(XEXP(XEXP(operands[0], 0), 0)) == SP_REGNUM
mgl@1371
 12290
+	         && GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT
mgl@1371
 12291
+	         && INTVAL(XEXP(XEXP(operands[0], 0), 1)) % 4 == 0
mgl@1371
 12292
+	         && INTVAL(XEXP(XEXP(operands[0], 0), 1)) <= 0x1FC) )
mgl@1371
 12293
+          return "stdsp\t%0, %1";
mgl@1371
 12294
+	else
mgl@1371
 12295
+          return "st.w\t%0, %1";
mgl@1371
 12296
+      default:
mgl@1371
 12297
+	abort();
mgl@1371
 12298
+    }
mgl@1371
 12299
+  }
mgl@1371
 12300
+
mgl@1371
 12301
+  [(set_attr "length" "2,4,8,4,4")
mgl@1371
 12302
+   (set_attr "type" "alu,alu,alu2,load,store")
mgl@1371
 12303
+   (set_attr "cc" "none,none,clobber,none,none")])
mgl@1371
 12304
+
mgl@1371
 12305
+
mgl@1371
 12306
+
mgl@1371
 12307
+;;== double - 64 bits =========================================================
mgl@1371
 12308
+(define_expand "movdf"
mgl@1371
 12309
+  [(set (match_operand:DF 0 "nonimmediate_operand" "")
mgl@1371
 12310
+	(match_operand:DF 1 "general_operand" ""))]
mgl@1371
 12311
+  ""
mgl@1371
 12312
+  {
mgl@1371
 12313
+    /* One of the ops has to be in a register.  */
mgl@1371
 12314
+    if (GET_CODE (operands[0]) != REG){
mgl@1371
 12315
+      operands[1] = force_reg (DFmode, operands[1]);
mgl@1371
 12316
+    }
mgl@1371
 12317
+  })
mgl@1371
 12318
+
mgl@1371
 12319
+
mgl@1371
 12320
+(define_insn_and_split "*movdf_internal"
mgl@1371
 12321
+  [(set (match_operand:DF 0 "nonimmediate_operand"     "=r,r,r,r,m")
mgl@1371
 12322
+	(match_operand:DF 1 "general_operand"          " r,G,F,m,r"))]
mgl@1371
 12323
+  "TARGET_SOFT_FLOAT
mgl@1371
 12324
+   && (register_operand (operands[0], DFmode)
mgl@1371
 12325
+       || register_operand (operands[1], DFmode))"
mgl@1371
 12326
+  {
mgl@1371
 12327
+    switch (which_alternative ){
mgl@1371
 12328
+    case 0:
mgl@1371
 12329
+    case 1:
mgl@1371
 12330
+    case 2: 
mgl@1371
 12331
+        return "#";
mgl@1371
 12332
+    case 3:
mgl@1371
 12333
+      if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])))
mgl@1371
 12334
+        return "ld.d\t%0, pc[%1 - .]";
mgl@1371
 12335
+      else
mgl@1371
 12336
+        return "ld.d\t%0, %1";
mgl@1371
 12337
+    case 4:
mgl@1371
 12338
+      return "st.d\t%0, %1";
mgl@1371
 12339
+    default:
mgl@1371
 12340
+      abort();
mgl@1371
 12341
+    }
mgl@1371
 12342
+  }
mgl@1371
 12343
+  "TARGET_SOFT_FLOAT
mgl@1371
 12344
+   && reload_completed
mgl@1371
 12345
+   && (REG_P (operands[0]) 
mgl@1371
 12346
+        && (REG_P (operands[1])
mgl@1371
 12347
+            || GET_CODE (operands[1]) == CONST_DOUBLE))"
mgl@1371
 12348
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 12349
+   (set (match_dup 2) (match_dup 3))]
mgl@1371
 12350
+  "
mgl@1371
 12351
+   {
mgl@1371
 12352
+    operands[2] = gen_highpart (SImode, operands[0]);
mgl@1371
 12353
+    operands[0] = gen_lowpart (SImode, operands[0]);
mgl@1371
 12354
+    operands[3] = gen_highpart(SImode, operands[1]);
mgl@1371
 12355
+    operands[1] = gen_lowpart(SImode, operands[1]);
mgl@1371
 12356
+   }
mgl@1371
 12357
+  "
mgl@1371
 12358
+
mgl@1371
 12359
+  [(set_attr "length" "*,*,*,4,4")
mgl@1371
 12360
+   (set_attr "type" "*,*,*,load2,store2")
mgl@1371
 12361
+   (set_attr "cc" "*,*,*,none,none")])
mgl@1371
 12362
+
mgl@1371
 12363
+
mgl@1371
 12364
+;;=============================================================================
mgl@1371
 12365
+;; Conditional Moves
mgl@1371
 12366
+;;=============================================================================
mgl@1371
 12367
+(define_insn "ld<mode>_predicable"
mgl@1371
 12368
+  [(set (match_operand:MOVCC 0 "register_operand" "=r")
mgl@1371
 12369
+	(match_operand:MOVCC 1 "avr32_non_rmw_memory_operand" "<MOVCC:pred_mem_constraint>"))]
mgl@1371
 12370
+  "TARGET_V2_INSNS"
mgl@1371
 12371
+  "ld<MOVCC:load_postfix>%?\t%0, %1"
mgl@1371
 12372
+  [(set_attr "length" "4")
mgl@1371
 12373
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12374
+   (set_attr "type" "load")
mgl@1371
 12375
+   (set_attr "predicable" "yes")]
mgl@1371
 12376
+)
mgl@1371
 12377
+
mgl@1371
 12378
+
mgl@1371
 12379
+(define_insn "st<mode>_predicable"
mgl@1371
 12380
+  [(set (match_operand:MOVCC 0 "avr32_non_rmw_memory_operand" "=<MOVCC:pred_mem_constraint>")
mgl@1371
 12381
+	(match_operand:MOVCC 1 "register_operand" "r"))]
mgl@1371
 12382
+  "TARGET_V2_INSNS"
mgl@1371
 12383
+  "st<MOVCC:store_postfix>%?\t%0, %1"
mgl@1371
 12384
+  [(set_attr "length" "4")
mgl@1371
 12385
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12386
+   (set_attr "type" "store")
mgl@1371
 12387
+   (set_attr "predicable" "yes")]
mgl@1371
 12388
+)
mgl@1371
 12389
+
mgl@1371
 12390
+(define_insn "mov<mode>_predicable"
mgl@1371
 12391
+  [(set (match_operand:MOVCC 0 "register_operand" "=r")
mgl@1371
 12392
+	(match_operand:MOVCC 1 "avr32_cond_register_immediate_operand" "rKs08"))]
mgl@1371
 12393
+  ""
mgl@1371
 12394
+  "mov%?\t%0, %1"
mgl@1371
 12395
+  [(set_attr "length" "4")
mgl@1371
 12396
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12397
+   (set_attr "type" "alu")
mgl@1371
 12398
+   (set_attr "predicable" "yes")]
mgl@1371
 12399
+)
mgl@1371
 12400
+
mgl@1371
 12401
+
mgl@1371
 12402
+;;=============================================================================
mgl@1371
 12403
+;; Move chunks of memory
mgl@1371
 12404
+;;=============================================================================
mgl@1371
 12405
+
mgl@1371
 12406
+(define_expand "movmemsi"
mgl@1371
 12407
+  [(match_operand:BLK 0 "general_operand" "")
mgl@1371
 12408
+   (match_operand:BLK 1 "general_operand" "")
mgl@1371
 12409
+   (match_operand:SI 2 "const_int_operand" "")
mgl@1371
 12410
+   (match_operand:SI 3 "const_int_operand" "")]
mgl@1371
 12411
+  ""
mgl@1371
 12412
+  "
mgl@1371
 12413
+   if (avr32_gen_movmemsi (operands))
mgl@1371
 12414
+     DONE;
mgl@1371
 12415
+   FAIL;
mgl@1371
 12416
+  "
mgl@1371
 12417
+  )
mgl@1371
 12418
+
mgl@1371
 12419
+
mgl@1371
 12420
+
mgl@1371
 12421
+
mgl@1371
 12422
+;;=============================================================================
mgl@1371
 12423
+;; Bit field instructions
mgl@1371
 12424
+;;-----------------------------------------------------------------------------
mgl@1371
 12425
+;; Instructions to insert or extract bit-fields
mgl@1371
 12426
+;;=============================================================================
mgl@1371
 12427
+
mgl@1371
 12428
+(define_insn "insv"
mgl@1371
 12429
+  [ (set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 12430
+                          (match_operand:SI 1 "immediate_operand" "Ku05")
mgl@1371
 12431
+                          (match_operand:SI 2 "immediate_operand" "Ku05"))
mgl@1371
 12432
+         (match_operand 3 "register_operand" "r"))]
mgl@1371
 12433
+  ""
mgl@1371
 12434
+  "bfins\t%0, %3, %2, %1"
mgl@1371
 12435
+  [(set_attr "type" "alu")
mgl@1371
 12436
+   (set_attr "length" "4")
mgl@1371
 12437
+   (set_attr "cc" "set_ncz")])
mgl@1371
 12438
+
mgl@1371
 12439
+
mgl@1371
 12440
+
mgl@1371
 12441
+(define_expand "extv"
mgl@1371
 12442
+  [ (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12443
+         (sign_extract:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 12444
+                          (match_operand:SI 2 "immediate_operand" "")
mgl@1371
 12445
+                          (match_operand:SI 3 "immediate_operand" "")))]
mgl@1371
 12446
+  ""
mgl@1371
 12447
+  {
mgl@1371
 12448
+   if ( INTVAL(operands[2]) >= 32 )
mgl@1371
 12449
+      FAIL;
mgl@1371
 12450
+  }
mgl@1371
 12451
+)
mgl@1371
 12452
+
mgl@1371
 12453
+(define_expand "extzv"
mgl@1371
 12454
+  [ (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12455
+         (zero_extract:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 12456
+                          (match_operand:SI 2 "immediate_operand" "")
mgl@1371
 12457
+                          (match_operand:SI 3 "immediate_operand" "")))]
mgl@1371
 12458
+  ""
mgl@1371
 12459
+  {
mgl@1371
 12460
+   if ( INTVAL(operands[2]) >= 32 )
mgl@1371
 12461
+      FAIL;
mgl@1371
 12462
+  }
mgl@1371
 12463
+)
mgl@1371
 12464
+
mgl@1371
 12465
+(define_insn "extv_internal"
mgl@1371
 12466
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12467
+         (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 12468
+                          (match_operand:SI 2 "immediate_operand" "Ku05")
mgl@1371
 12469
+                          (match_operand:SI 3 "immediate_operand" "Ku05")))]
mgl@1371
 12470
+  "INTVAL(operands[2]) < 32"
mgl@1371
 12471
+  "bfexts\t%0, %1, %3, %2"
mgl@1371
 12472
+  [(set_attr "type" "alu")
mgl@1371
 12473
+   (set_attr "length" "4")
mgl@1371
 12474
+   (set_attr "cc" "set_ncz")])
mgl@1371
 12475
+
mgl@1371
 12476
+
mgl@1371
 12477
+(define_insn "extzv_internal"
mgl@1371
 12478
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12479
+         (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 12480
+                          (match_operand:SI 2 "immediate_operand" "Ku05")
mgl@1371
 12481
+                          (match_operand:SI 3 "immediate_operand" "Ku05")))]
mgl@1371
 12482
+  "INTVAL(operands[2]) < 32"
mgl@1371
 12483
+  "bfextu\t%0, %1, %3, %2"
mgl@1371
 12484
+  [(set_attr "type" "alu")
mgl@1371
 12485
+   (set_attr "length" "4")
mgl@1371
 12486
+   (set_attr "cc" "set_ncz")])
mgl@1371
 12487
+
mgl@1371
 12488
+
mgl@1371
 12489
+
mgl@1371
 12490
+;;=============================================================================
mgl@1371
 12491
+;; Some peepholes for avoiding unnecessary cast instructions
mgl@1371
 12492
+;; followed by bfins.
mgl@1371
 12493
+;;-----------------------------------------------------------------------------
mgl@1371
 12494
+
mgl@1371
 12495
+(define_peephole2
mgl@1371
 12496
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12497
+        (zero_extend:SI (match_operand:QI 1 "register_operand" "")))
mgl@1371
 12498
+   (set (zero_extract:SI (match_operand 2 "register_operand" "")
mgl@1371
 12499
+                         (match_operand:SI 3 "immediate_operand" "")
mgl@1371
 12500
+                         (match_operand:SI 4 "immediate_operand" ""))
mgl@1371
 12501
+        (match_dup 0))]
mgl@1371
 12502
+  "((peep2_reg_dead_p(2, operands[0]) &&
mgl@1371
 12503
+    (INTVAL(operands[3]) <= 8)))"
mgl@1371
 12504
+  [(set (zero_extract:SI (match_dup 2)
mgl@1371
 12505
+                         (match_dup 3)
mgl@1371
 12506
+                         (match_dup 4))
mgl@1371
 12507
+        (match_dup 1))]
mgl@1371
 12508
+  )
mgl@1371
 12509
+
mgl@1371
 12510
+(define_peephole2
mgl@1371
 12511
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12512
+        (zero_extend:SI (match_operand:HI 1 "register_operand" "")))
mgl@1371
 12513
+   (set (zero_extract:SI (match_operand 2 "register_operand" "")
mgl@1371
 12514
+                         (match_operand:SI 3 "immediate_operand" "")
mgl@1371
 12515
+                         (match_operand:SI 4 "immediate_operand" ""))
mgl@1371
 12516
+        (match_dup 0))]
mgl@1371
 12517
+  "((peep2_reg_dead_p(2, operands[0]) &&
mgl@1371
 12518
+    (INTVAL(operands[3]) <= 16)))"
mgl@1371
 12519
+  [(set (zero_extract:SI (match_dup 2)
mgl@1371
 12520
+                         (match_dup 3)
mgl@1371
 12521
+                         (match_dup 4))
mgl@1371
 12522
+        (match_dup 1))]
mgl@1371
 12523
+  )
mgl@1371
 12524
+
mgl@1371
 12525
+;;=============================================================================
mgl@1371
 12526
+;; push bytes
mgl@1371
 12527
+;;-----------------------------------------------------------------------------
mgl@1371
 12528
+;; Implements the push instruction
mgl@1371
 12529
+;;=============================================================================
mgl@1371
 12530
+(define_insn "pushm"
mgl@1371
 12531
+  [(set (mem:BLK (pre_dec:BLK (reg:SI SP_REGNUM)))
mgl@1371
 12532
+        (unspec:BLK [(match_operand 0 "const_int_operand" "")]
mgl@1371
 12533
+                    UNSPEC_PUSHM))]
mgl@1371
 12534
+  ""
mgl@1371
 12535
+  {
mgl@1371
 12536
+    if (INTVAL(operands[0])) {
mgl@1371
 12537
+      return "pushm\t%r0";
mgl@1371
 12538
+    } else {
mgl@1371
 12539
+      return "";
mgl@1371
 12540
+    }
mgl@1371
 12541
+  }
mgl@1371
 12542
+  [(set_attr "type" "store")
mgl@1371
 12543
+   (set_attr "length" "2")
mgl@1371
 12544
+   (set_attr "cc" "none")])
mgl@1371
 12545
+
mgl@1371
 12546
+(define_insn "stm"
mgl@1371
 12547
+  [(unspec [(match_operand 0 "register_operand" "r")
mgl@1371
 12548
+            (match_operand 1 "const_int_operand" "")
mgl@1371
 12549
+            (match_operand 2 "const_int_operand" "")]
mgl@1371
 12550
+	   UNSPEC_STM)]
mgl@1371
 12551
+  ""
mgl@1371
 12552
+  {
mgl@1371
 12553
+    if (INTVAL(operands[1])) {
mgl@1371
 12554
+      if (INTVAL(operands[2]) != 0)
mgl@1371
 12555
+         return "stm\t--%0, %s1";
mgl@1371
 12556
+      else
mgl@1371
 12557
+         return "stm\t%0, %s1";
mgl@1371
 12558
+    } else {
mgl@1371
 12559
+      return "";
mgl@1371
 12560
+    }
mgl@1371
 12561
+  }
mgl@1371
 12562
+  [(set_attr "type" "store")
mgl@1371
 12563
+   (set_attr "length" "4")
mgl@1371
 12564
+   (set_attr "cc" "none")])
mgl@1371
 12565
+
mgl@1371
 12566
+
mgl@1371
 12567
+
mgl@1371
 12568
+(define_insn "popm"
mgl@1371
 12569
+  [(unspec [(match_operand 0 "const_int_operand" "")]
mgl@1371
 12570
+	   UNSPEC_POPM)]
mgl@1371
 12571
+  ""
mgl@1371
 12572
+  {
mgl@1371
 12573
+    if (INTVAL(operands[0])) {
mgl@1371
 12574
+      return "popm   %r0";
mgl@1371
 12575
+    } else {
mgl@1371
 12576
+      return "";
mgl@1371
 12577
+    }
mgl@1371
 12578
+  }
mgl@1371
 12579
+  [(set_attr "type" "load")
mgl@1371
 12580
+   (set_attr "length" "2")])
mgl@1371
 12581
+
mgl@1371
 12582
+
mgl@1371
 12583
+
mgl@1371
 12584
+;;=============================================================================
mgl@1371
 12585
+;; add
mgl@1371
 12586
+;;-----------------------------------------------------------------------------
mgl@1371
 12587
+;; Adds reg1 with reg2 and puts the result in reg0.
mgl@1371
 12588
+;;=============================================================================
mgl@1371
 12589
+(define_insn "add<mode>3"
mgl@1371
 12590
+  [(set (match_operand:INTM 0 "register_operand" "=r,r,r,r,r")
mgl@1371
 12591
+	(plus:INTM (match_operand:INTM 1 "register_operand" "%0,r,0,r,0")
mgl@1371
 12592
+                   (match_operand:INTM 2 "avr32_add_operand" "r,r,Is08,Is16,Is21")))]
mgl@1371
 12593
+  ""
mgl@1371
 12594
+  "@
mgl@1371
 12595
+   add     %0, %2
mgl@1371
 12596
+   add     %0, %1, %2
mgl@1371
 12597
+   sub     %0, %n2
mgl@1371
 12598
+   sub     %0, %1, %n2
mgl@1371
 12599
+   sub     %0, %n2"
mgl@1371
 12600
+
mgl@1371
 12601
+  [(set_attr "length" "2,4,2,4,4")
mgl@1371
 12602
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12603
+
mgl@1371
 12604
+(define_insn "add<mode>3_lsl"
mgl@1371
 12605
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12606
+	(plus:INTM (ashift:INTM (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12607
+                                (match_operand:INTM 3 "avr32_add_shift_immediate_operand" "Ku02"))
mgl@1371
 12608
+                   (match_operand:INTM 2 "register_operand" "r")))]
mgl@1371
 12609
+  ""
mgl@1371
 12610
+  "add     %0, %2, %1 << %3"
mgl@1371
 12611
+  [(set_attr "length" "4")
mgl@1371
 12612
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12613
+
mgl@1371
 12614
+(define_insn "add<mode>3_lsl2"
mgl@1371
 12615
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12616
+	(plus:INTM (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12617
+                   (ashift:INTM (match_operand:INTM 2 "register_operand" "r")
mgl@1371
 12618
+                                (match_operand:INTM 3 "avr32_add_shift_immediate_operand" "Ku02"))))]
mgl@1371
 12619
+  ""
mgl@1371
 12620
+  "add     %0, %1, %2 << %3"
mgl@1371
 12621
+  [(set_attr "length" "4")
mgl@1371
 12622
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12623
+
mgl@1371
 12624
+
mgl@1371
 12625
+(define_insn "add<mode>3_mul"
mgl@1371
 12626
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12627
+	(plus:INTM (mult:INTM (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12628
+                              (match_operand:INTM 3 "immediate_operand" "Ku04" ))
mgl@1371
 12629
+                   (match_operand:INTM 2 "register_operand" "r")))]
mgl@1371
 12630
+  "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
mgl@1371
 12631
+   (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
mgl@1371
 12632
+  "add     %0, %2, %1 << %p3"
mgl@1371
 12633
+  [(set_attr "length" "4")
mgl@1371
 12634
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12635
+
mgl@1371
 12636
+(define_insn "add<mode>3_mul2"
mgl@1371
 12637
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12638
+	(plus:INTM (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12639
+                   (mult:INTM (match_operand:INTM 2 "register_operand" "r")
mgl@1371
 12640
+                              (match_operand:INTM 3 "immediate_operand" "Ku04" ))))]
mgl@1371
 12641
+  "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
mgl@1371
 12642
+   (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
mgl@1371
 12643
+  "add     %0, %1, %2 << %p3"
mgl@1371
 12644
+  [(set_attr "length" "4")
mgl@1371
 12645
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12646
+
mgl@1371
 12647
+
mgl@1371
 12648
+(define_peephole2
mgl@1371
 12649
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12650
+        (ashift:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 12651
+                   (match_operand:SI 2 "immediate_operand" "")))
mgl@1371
 12652
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 12653
+	(plus:SI (match_dup 0)
mgl@1371
 12654
+                 (match_operand:SI 4 "register_operand" "")))]
mgl@1371
 12655
+  "(peep2_reg_dead_p(2, operands[0]) &&
mgl@1371
 12656
+    (INTVAL(operands[2]) < 4 && INTVAL(operands[2]) > 0))"
mgl@1371
 12657
+  [(set (match_dup 3)
mgl@1371
 12658
+	(plus:SI (ashift:SI (match_dup 1)
mgl@1371
 12659
+                            (match_dup 2))
mgl@1371
 12660
+                 (match_dup 4)))]
mgl@1371
 12661
+  )
mgl@1371
 12662
+
mgl@1371
 12663
+(define_peephole2
mgl@1371
 12664
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12665
+        (ashift:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 12666
+                   (match_operand:SI 2 "immediate_operand" "")))
mgl@1371
 12667
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 12668
+	(plus:SI (match_operand:SI 4 "register_operand" "")
mgl@1371
 12669
+                 (match_dup 0)))]
mgl@1371
 12670
+  "(peep2_reg_dead_p(2, operands[0]) &&
mgl@1371
 12671
+    (INTVAL(operands[2]) < 4 && INTVAL(operands[2]) > 0))"
mgl@1371
 12672
+  [(set (match_dup 3)
mgl@1371
 12673
+	(plus:SI (ashift:SI (match_dup 1)
mgl@1371
 12674
+                            (match_dup 2))
mgl@1371
 12675
+                 (match_dup 4)))]
mgl@1371
 12676
+  )
mgl@1371
 12677
+
mgl@1371
 12678
+(define_insn "adddi3"
mgl@1371
 12679
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
mgl@1371
 12680
+	(plus:DI (match_operand:DI 1 "register_operand" "%0,r")
mgl@1371
 12681
+		 (match_operand:DI 2 "register_operand" "r,r")))]
mgl@1371
 12682
+  ""
mgl@1371
 12683
+  "@
mgl@1371
 12684
+   add     %0, %2\;adc    %m0, %m0, %m2
mgl@1371
 12685
+   add     %0, %1, %2\;adc    %m0, %m1, %m2"
mgl@1371
 12686
+  [(set_attr "length" "6,8")
mgl@1371
 12687
+   (set_attr "type" "alu2")
mgl@1371
 12688
+   (set_attr "cc" "set_vncz")])
mgl@1371
 12689
+
mgl@1371
 12690
+
mgl@1371
 12691
+(define_insn "add<mode>_imm_predicable"
mgl@1371
 12692
+  [(set (match_operand:INTM 0 "register_operand" "+r")
mgl@1371
 12693
+	(plus:INTM (match_dup 0)
mgl@1371
 12694
+                   (match_operand:INTM 1 "avr32_cond_immediate_operand" "%Is08")))]
mgl@1371
 12695
+  ""
mgl@1371
 12696
+  "sub%?\t%0, -%1"
mgl@1371
 12697
+  [(set_attr "length" "4")
mgl@1371
 12698
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12699
+   (set_attr "predicable" "yes")]
mgl@1371
 12700
+)
mgl@1371
 12701
+
mgl@1371
 12702
+;;=============================================================================
mgl@1371
 12703
+;; subtract
mgl@1371
 12704
+;;-----------------------------------------------------------------------------
mgl@1371
 12705
+;; Subtract reg2 or immediate value from reg0 and puts the result in reg0.
mgl@1371
 12706
+;;=============================================================================
mgl@1371
 12707
+
mgl@1371
 12708
+(define_insn "sub<mode>3"
mgl@1371
 12709
+  [(set (match_operand:INTM 0 "general_operand" "=r,r,r,r,r,r,r")
mgl@1371
 12710
+	(minus:INTM (match_operand:INTM 1 "nonmemory_operand" "0,r,0,r,0,r,Ks08")
mgl@1371
 12711
+		  (match_operand:INTM 2 "nonmemory_operand" "r,r,Ks08,Ks16,Ks21,0,r")))]
mgl@1371
 12712
+  ""
mgl@1371
 12713
+  "@
mgl@1371
 12714
+   sub     %0, %2
mgl@1371
 12715
+   sub     %0, %1, %2
mgl@1371
 12716
+   sub     %0, %2
mgl@1371
 12717
+   sub     %0, %1, %2
mgl@1371
 12718
+   sub     %0, %2
mgl@1371
 12719
+   rsub    %0, %1
mgl@1371
 12720
+   rsub    %0, %2, %1"
mgl@1371
 12721
+  [(set_attr "length" "2,4,2,4,4,2,4")
mgl@1371
 12722
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12723
+
mgl@1371
 12724
+(define_insn "*sub<mode>3_mul"
mgl@1371
 12725
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12726
+	(minus:INTM (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12727
+                    (mult:INTM (match_operand:INTM 2 "register_operand" "r")
mgl@1371
 12728
+                               (match_operand:SI 3 "immediate_operand" "Ku04" ))))]
mgl@1371
 12729
+  "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
mgl@1371
 12730
+   (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
mgl@1371
 12731
+  "sub     %0, %1, %2 << %p3"
mgl@1371
 12732
+  [(set_attr "length" "4")
mgl@1371
 12733
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12734
+
mgl@1371
 12735
+(define_insn "*sub<mode>3_lsl"
mgl@1371
 12736
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 12737
+	(minus:INTM  (match_operand:INTM 1 "register_operand" "r")
mgl@1371
 12738
+                     (ashift:INTM (match_operand:INTM 2 "register_operand" "r")
mgl@1371
 12739
+                                  (match_operand:SI 3 "avr32_add_shift_immediate_operand" "Ku02"))))]
mgl@1371
 12740
+  ""
mgl@1371
 12741
+  "sub     %0, %1, %2 << %3"
mgl@1371
 12742
+  [(set_attr "length" "4")
mgl@1371
 12743
+   (set_attr "cc" "<INTM:alu_cc_attr>")])
mgl@1371
 12744
+
mgl@1371
 12745
+
mgl@1371
 12746
+(define_insn "subdi3"
mgl@1371
 12747
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
mgl@1371
 12748
+	(minus:DI (match_operand:DI 1 "register_operand" "%0,r")
mgl@1371
 12749
+		 (match_operand:DI 2 "register_operand" "r,r")))]
mgl@1371
 12750
+  ""
mgl@1371
 12751
+  "@
mgl@1371
 12752
+   sub     %0, %2\;sbc    %m0, %m0, %m2
mgl@1371
 12753
+   sub     %0, %1, %2\;sbc    %m0, %m1, %m2"
mgl@1371
 12754
+  [(set_attr "length" "6,8")
mgl@1371
 12755
+   (set_attr "type" "alu2")
mgl@1371
 12756
+   (set_attr "cc" "set_vncz")])
mgl@1371
 12757
+
mgl@1371
 12758
+
mgl@1371
 12759
+(define_insn "sub<mode>_imm_predicable"
mgl@1371
 12760
+  [(set (match_operand:INTM 0 "register_operand" "+r")
mgl@1371
 12761
+	(minus:INTM (match_dup 0)
mgl@1371
 12762
+                    (match_operand:INTM 1 "avr32_cond_immediate_operand" "Ks08")))]
mgl@1371
 12763
+  ""
mgl@1371
 12764
+  "sub%?\t%0, %1"
mgl@1371
 12765
+  [(set_attr "length" "4")
mgl@1371
 12766
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12767
+   (set_attr "predicable" "yes")])
mgl@1371
 12768
+
mgl@1371
 12769
+(define_insn "rsub<mode>_imm_predicable"
mgl@1371
 12770
+  [(set (match_operand:INTM 0 "register_operand" "+r")
mgl@1371
 12771
+	(minus:INTM (match_operand:INTM 1 "avr32_cond_immediate_operand"  "Ks08")
mgl@1371
 12772
+                    (match_dup 0)))]
mgl@1371
 12773
+  ""
mgl@1371
 12774
+  "rsub%?\t%0, %1"
mgl@1371
 12775
+  [(set_attr "length" "4")
mgl@1371
 12776
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 12777
+   (set_attr "predicable" "yes")])
mgl@1371
 12778
+
mgl@1371
 12779
+;;=============================================================================
mgl@1371
 12780
+;; multiply
mgl@1371
 12781
+;;-----------------------------------------------------------------------------
mgl@1371
 12782
+;; Multiply op1 and op2 and put the value in op0.
mgl@1371
 12783
+;;=============================================================================
mgl@1371
 12784
+
mgl@1371
 12785
+
mgl@1371
 12786
+(define_insn "mulqi3"
mgl@1371
 12787
+  [(set (match_operand:QI 0 "register_operand"         "=r,r,r")
mgl@1371
 12788
+	(mult:QI (match_operand:QI 1 "register_operand" "%0,r,r")
mgl@1371
 12789
+		 (match_operand:QI 2 "avr32_mul_operand" "r,r,Ks08")))]
mgl@1371
 12790
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12791
+  {
mgl@1371
 12792
+   switch (which_alternative){
mgl@1371
 12793
+    case 0:
mgl@1371
 12794
+      return "mul     %0, %2";
mgl@1371
 12795
+    case 1:
mgl@1371
 12796
+      return "mul     %0, %1, %2";
mgl@1371
 12797
+    case 2:
mgl@1371
 12798
+      return "mul     %0, %1, %2";
mgl@1371
 12799
+    default:
mgl@1371
 12800
+      gcc_unreachable();
mgl@1371
 12801
+   }
mgl@1371
 12802
+  }
mgl@1371
 12803
+  [(set_attr "type" "mulww_w,mulww_w,mulwh")
mgl@1371
 12804
+   (set_attr "length" "2,4,4")
mgl@1371
 12805
+   (set_attr "cc" "none")])
mgl@1371
 12806
+
mgl@1371
 12807
+(define_insn "mulsi3"
mgl@1371
 12808
+  [(set (match_operand:SI 0 "register_operand"         "=r,r,r")
mgl@1371
 12809
+	(mult:SI (match_operand:SI 1 "register_operand" "%0,r,r")
mgl@1371
 12810
+		 (match_operand:SI 2 "avr32_mul_operand" "r,r,Ks08")))]
mgl@1371
 12811
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12812
+  {
mgl@1371
 12813
+   switch (which_alternative){
mgl@1371
 12814
+    case 0:
mgl@1371
 12815
+      return "mul     %0, %2";
mgl@1371
 12816
+    case 1:
mgl@1371
 12817
+      return "mul     %0, %1, %2";
mgl@1371
 12818
+    case 2:
mgl@1371
 12819
+      return "mul     %0, %1, %2";
mgl@1371
 12820
+    default:
mgl@1371
 12821
+      gcc_unreachable();
mgl@1371
 12822
+   }
mgl@1371
 12823
+  }
mgl@1371
 12824
+  [(set_attr "type" "mulww_w,mulww_w,mulwh")
mgl@1371
 12825
+   (set_attr "length" "2,4,4")
mgl@1371
 12826
+   (set_attr "cc" "none")])
mgl@1371
 12827
+
mgl@1371
 12828
+
mgl@1371
 12829
+(define_insn "mulhisi3"
mgl@1371
 12830
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12831
+	(mult:SI
mgl@1371
 12832
+	 (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 12833
+	 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
mgl@1371
 12834
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 12835
+  "mulhh.w %0, %1:b, %2:b"
mgl@1371
 12836
+  [(set_attr "type" "mulhh")
mgl@1371
 12837
+   (set_attr "length" "4")
mgl@1371
 12838
+   (set_attr "cc" "none")])
mgl@1371
 12839
+
mgl@1371
 12840
+(define_peephole2
mgl@1371
 12841
+  [(match_scratch:DI 6 "r")
mgl@1371
 12842
+   (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12843
+	(mult:SI
mgl@1371
 12844
+	 (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
mgl@1371
 12845
+         (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
mgl@1371
 12846
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 12847
+        (ashiftrt:SI (match_dup 0)
mgl@1371
 12848
+                     (const_int 16)))]
mgl@1371
 12849
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP
mgl@1371
 12850
+   && (peep2_reg_dead_p(1, operands[0]) || (REGNO(operands[0]) == REGNO(operands[3])))"
mgl@1371
 12851
+  [(set (match_dup 4) (sign_extend:SI (match_dup 1)))
mgl@1371
 12852
+   (set (match_dup 6)
mgl@1371
 12853
+        (ashift:DI (mult:DI (sign_extend:DI (match_dup 4))
mgl@1371
 12854
+                            (sign_extend:DI (match_dup 2)))
mgl@1371
 12855
+                   (const_int 16)))
mgl@1371
 12856
+   (set (match_dup 3) (match_dup 5))]
mgl@1371
 12857
+
mgl@1371
 12858
+  "{
mgl@1371
 12859
+     operands[4] = gen_rtx_REG(SImode, REGNO(operands[1]));
mgl@1371
 12860
+     operands[5] = gen_highpart (SImode, operands[4]);
mgl@1371
 12861
+   }"
mgl@1371
 12862
+  )
mgl@1371
 12863
+
mgl@1371
 12864
+(define_insn "mulnhisi3"
mgl@1371
 12865
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 12866
+        (mult:SI
mgl@1371
 12867
+         (sign_extend:SI (neg:HI (match_operand:HI 1 "register_operand" "r")))
mgl@1371
 12868
+         (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
mgl@1371
 12869
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 12870
+  "mulnhh.w %0, %1:b, %2:b"
mgl@1371
 12871
+  [(set_attr "type" "mulhh")
mgl@1371
 12872
+   (set_attr "length" "4")
mgl@1371
 12873
+   (set_attr "cc" "none")])
mgl@1371
 12874
+
mgl@1371
 12875
+(define_insn "machisi3"
mgl@1371
 12876
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 12877
+	(plus:SI (mult:SI
mgl@1371
 12878
+                  (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 12879
+                  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 12880
+                 (match_dup 0)))]
mgl@1371
 12881
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 12882
+  "machh.w %0, %1:b, %2:b"
mgl@1371
 12883
+  [(set_attr "type" "machh_w")
mgl@1371
 12884
+   (set_attr "length" "4")
mgl@1371
 12885
+   (set_attr "cc" "none")])
mgl@1371
 12886
+
mgl@1371
 12887
+
mgl@1371
 12888
+
mgl@1371
 12889
+(define_insn "mulsidi3"
mgl@1371
 12890
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 12891
+	(mult:DI
mgl@1371
 12892
+	 (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
mgl@1371
 12893
+	 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
mgl@1371
 12894
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12895
+  "muls.d  %0, %1, %2"
mgl@1371
 12896
+  [(set_attr "type" "mulww_d")
mgl@1371
 12897
+   (set_attr "length" "4")
mgl@1371
 12898
+   (set_attr "cc" "none")])
mgl@1371
 12899
+
mgl@1371
 12900
+(define_insn "umulsidi3"
mgl@1371
 12901
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 12902
+	(mult:DI
mgl@1371
 12903
+	 (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
mgl@1371
 12904
+	 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
mgl@1371
 12905
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12906
+  "mulu.d  %0, %1, %2"
mgl@1371
 12907
+  [(set_attr "type" "mulww_d")
mgl@1371
 12908
+   (set_attr "length" "4")
mgl@1371
 12909
+   (set_attr "cc" "none")])
mgl@1371
 12910
+
mgl@1371
 12911
+(define_insn "*mulaccsi3"
mgl@1371
 12912
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 12913
+	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
mgl@1371
 12914
+			  (match_operand:SI 2 "register_operand" "r"))
mgl@1371
 12915
+		 (match_dup 0)))]
mgl@1371
 12916
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12917
+  "mac     %0, %1, %2"
mgl@1371
 12918
+  [(set_attr "type" "macww_w")
mgl@1371
 12919
+   (set_attr "length" "4")
mgl@1371
 12920
+   (set_attr "cc" "none")])
mgl@1371
 12921
+
mgl@1371
 12922
+(define_insn "*mulaccsidi3"
mgl@1371
 12923
+  [(set (match_operand:DI 0 "register_operand" "+r")
mgl@1371
 12924
+	(plus:DI (mult:DI
mgl@1371
 12925
+		  (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
mgl@1371
 12926
+		  (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
mgl@1371
 12927
+		 (match_dup 0)))]
mgl@1371
 12928
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12929
+  "macs.d  %0, %1, %2"
mgl@1371
 12930
+  [(set_attr "type" "macww_d")
mgl@1371
 12931
+   (set_attr "length" "4")
mgl@1371
 12932
+   (set_attr "cc" "none")])
mgl@1371
 12933
+
mgl@1371
 12934
+(define_insn "*umulaccsidi3"
mgl@1371
 12935
+  [(set (match_operand:DI 0 "register_operand" "+r")
mgl@1371
 12936
+	(plus:DI (mult:DI
mgl@1371
 12937
+		  (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
mgl@1371
 12938
+		  (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
mgl@1371
 12939
+		 (match_dup 0)))]
mgl@1371
 12940
+  "!TARGET_NO_MUL_INSNS"
mgl@1371
 12941
+  "macu.d  %0, %1, %2"
mgl@1371
 12942
+  [(set_attr "type" "macww_d")
mgl@1371
 12943
+   (set_attr "length" "4")
mgl@1371
 12944
+   (set_attr "cc" "none")])
mgl@1371
 12945
+
mgl@1371
 12946
+
mgl@1371
 12947
+
mgl@1371
 12948
+;; Try to avoid Write-After-Write hazards for mul operations
mgl@1371
 12949
+;; if it can be done
mgl@1371
 12950
+(define_peephole2
mgl@1371
 12951
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 12952
+	(mult:SI
mgl@1371
 12953
+	 (sign_extend:SI (match_operand 1 "general_operand" ""))
mgl@1371
 12954
+         (sign_extend:SI (match_operand 2 "general_operand" ""))))
mgl@1371
 12955
+   (set (match_dup 0)
mgl@1371
 12956
+	(match_operator:SI 3 "alu_operator" [(match_dup 0)
mgl@1371
 12957
+                                             (match_operand 4 "general_operand" "")]))]
mgl@1371
 12958
+  "peep2_reg_dead_p(1, operands[2])"
mgl@1371
 12959
+  [(set (match_dup 5)
mgl@1371
 12960
+        (mult:SI
mgl@1371
 12961
+         (sign_extend:SI (match_dup 1))
mgl@1371
 12962
+         (sign_extend:SI (match_dup 2))))
mgl@1371
 12963
+   (set (match_dup 0)
mgl@1371
 12964
+	(match_op_dup 3 [(match_dup 5)
mgl@1371
 12965
+                         (match_dup 4)]))]
mgl@1371
 12966
+  "{operands[5] = gen_rtx_REG(SImode, REGNO(operands[2]));}"
mgl@1371
 12967
+  )
mgl@1371
 12968
+
mgl@1371
 12969
+
mgl@1371
 12970
+
mgl@1371
 12971
+;;=============================================================================
mgl@1371
 12972
+;; DSP instructions
mgl@1371
 12973
+;;=============================================================================
mgl@1371
 12974
+(define_insn "mulsathh_h"
mgl@1371
 12975
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 12976
+        (ss_truncate:HI (ashiftrt:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 12977
+                                              (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 12978
+                                     (const_int 15))))]
mgl@1371
 12979
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 12980
+  "mulsathh.h\t%0, %1:b, %2:b"
mgl@1371
 12981
+  [(set_attr "length" "4")
mgl@1371
 12982
+   (set_attr "cc" "none")
mgl@1371
 12983
+   (set_attr "type" "mulhh")])
mgl@1371
 12984
+
mgl@1371
 12985
+(define_insn "mulsatrndhh_h"
mgl@1371
 12986
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 12987
+        (ss_truncate:HI (ashiftrt:SI
mgl@1371
 12988
+                         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 12989
+                                           (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 12990
+                                  (const_int 1073741824))
mgl@1371
 12991
+                         (const_int 15))))]
mgl@1371
 12992
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 12993
+  "mulsatrndhh.h\t%0, %1:b, %2:b"
mgl@1371
 12994
+  [(set_attr "length" "4")
mgl@1371
 12995
+   (set_attr "cc" "none")
mgl@1371
 12996
+   (set_attr "type" "mulhh")])
mgl@1371
 12997
+
mgl@1371
 12998
+(define_insn "mulsathh_w"
mgl@1371
 12999
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13000
+        (ss_truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 13001
+                                            (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13002
+                                   (const_int 1))))]
mgl@1371
 13003
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13004
+  "mulsathh.w\t%0, %1:b, %2:b"
mgl@1371
 13005
+  [(set_attr "length" "4")
mgl@1371
 13006
+   (set_attr "cc" "none")
mgl@1371
 13007
+   (set_attr "type" "mulhh")])
mgl@1371
 13008
+
mgl@1371
 13009
+(define_insn "mulsatwh_w"
mgl@1371
 13010
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13011
+        (ss_truncate:SI (ashiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
mgl@1371
 13012
+                                              (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13013
+                                     (const_int 15))))]
mgl@1371
 13014
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13015
+  "mulsatwh.w\t%0, %1, %2:b"
mgl@1371
 13016
+  [(set_attr "length" "4")
mgl@1371
 13017
+   (set_attr "cc" "none")
mgl@1371
 13018
+   (set_attr "type" "mulwh")])
mgl@1371
 13019
+
mgl@1371
 13020
+(define_insn "mulsatrndwh_w"
mgl@1371
 13021
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13022
+        (ss_truncate:SI (ashiftrt:DI (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
mgl@1371
 13023
+                                                       (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13024
+                                              (const_int 1073741824))
mgl@1371
 13025
+                                     (const_int 15))))]
mgl@1371
 13026
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13027
+  "mulsatrndwh.w\t%0, %1, %2:b"
mgl@1371
 13028
+  [(set_attr "length" "4")
mgl@1371
 13029
+   (set_attr "cc" "none")
mgl@1371
 13030
+   (set_attr "type" "mulwh")])
mgl@1371
 13031
+
mgl@1371
 13032
+(define_insn "macsathh_w"
mgl@1371
 13033
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 13034
+        (plus:SI (match_dup 0)
mgl@1371
 13035
+                 (ss_truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 13036
+                                                     (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13037
+                                            (const_int 1)))))]
mgl@1371
 13038
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13039
+  "macsathh.w\t%0, %1:b, %2:b"
mgl@1371
 13040
+  [(set_attr "length" "4")
mgl@1371
 13041
+   (set_attr "cc" "none")
mgl@1371
 13042
+   (set_attr "type" "mulhh")])
mgl@1371
 13043
+
mgl@1371
 13044
+
mgl@1371
 13045
+(define_insn "mulwh_d"
mgl@1371
 13046
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 13047
+        (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
mgl@1371
 13048
+                            (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13049
+                   (const_int 16)))]
mgl@1371
 13050
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13051
+  "mulwh.d\t%0, %1, %2:b"
mgl@1371
 13052
+  [(set_attr "length" "4")
mgl@1371
 13053
+   (set_attr "cc" "none")
mgl@1371
 13054
+   (set_attr "type" "mulwh")])
mgl@1371
 13055
+
mgl@1371
 13056
+
mgl@1371
 13057
+(define_insn "mulnwh_d"
mgl@1371
 13058
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 13059
+        (ashift:DI (mult:DI (not:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")))
mgl@1371
 13060
+                            (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13061
+                   (const_int 16)))]
mgl@1371
 13062
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13063
+  "mulnwh.d\t%0, %1, %2:b"
mgl@1371
 13064
+  [(set_attr "length" "4")
mgl@1371
 13065
+   (set_attr "cc" "none")
mgl@1371
 13066
+   (set_attr "type" "mulwh")])
mgl@1371
 13067
+
mgl@1371
 13068
+(define_insn "macwh_d"
mgl@1371
 13069
+  [(set (match_operand:DI 0 "register_operand" "+r")
mgl@1371
 13070
+        (plus:DI (match_dup 0)
mgl@1371
 13071
+                 (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
mgl@1371
 13072
+                                     (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
mgl@1371
 13073
+                            (const_int 16))))]
mgl@1371
 13074
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13075
+  "macwh.d\t%0, %1, %2:b"
mgl@1371
 13076
+  [(set_attr "length" "4")
mgl@1371
 13077
+   (set_attr "cc" "none")
mgl@1371
 13078
+   (set_attr "type" "mulwh")])
mgl@1371
 13079
+
mgl@1371
 13080
+(define_insn "machh_d"
mgl@1371
 13081
+  [(set (match_operand:DI 0 "register_operand" "+r")
mgl@1371
 13082
+        (plus:DI (match_dup 0)
mgl@1371
 13083
+                 (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
mgl@1371
 13084
+                          (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))))]
mgl@1371
 13085
+  "!TARGET_NO_MUL_INSNS && TARGET_DSP"
mgl@1371
 13086
+  "machh.d\t%0, %1:b, %2:b"
mgl@1371
 13087
+  [(set_attr "length" "4")
mgl@1371
 13088
+   (set_attr "cc" "none")
mgl@1371
 13089
+   (set_attr "type" "mulwh")])
mgl@1371
 13090
+
mgl@1371
 13091
+(define_insn "satadd_w"
mgl@1371
 13092
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13093
+        (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13094
+                    (match_operand:SI 2 "register_operand" "r")))]
mgl@1371
 13095
+  "TARGET_DSP"
mgl@1371
 13096
+  "satadd.w\t%0, %1, %2"
mgl@1371
 13097
+  [(set_attr "length" "4")
mgl@1371
 13098
+   (set_attr "cc" "none")
mgl@1371
 13099
+   (set_attr "type" "alu_sat")])
mgl@1371
 13100
+
mgl@1371
 13101
+(define_insn "satsub_w"
mgl@1371
 13102
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13103
+        (ss_minus:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13104
+                     (match_operand:SI 2 "register_operand" "r")))]
mgl@1371
 13105
+  "TARGET_DSP"
mgl@1371
 13106
+  "satsub.w\t%0, %1, %2"
mgl@1371
 13107
+  [(set_attr "length" "4")
mgl@1371
 13108
+   (set_attr "cc" "none")
mgl@1371
 13109
+   (set_attr "type" "alu_sat")])
mgl@1371
 13110
+
mgl@1371
 13111
+(define_insn "satadd_h"
mgl@1371
 13112
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 13113
+        (ss_plus:HI (match_operand:HI 1 "register_operand" "r")
mgl@1371
 13114
+                    (match_operand:HI 2 "register_operand" "r")))]
mgl@1371
 13115
+  "TARGET_DSP"
mgl@1371
 13116
+  "satadd.h\t%0, %1, %2"
mgl@1371
 13117
+  [(set_attr "length" "4")
mgl@1371
 13118
+   (set_attr "cc" "none")
mgl@1371
 13119
+   (set_attr "type" "alu_sat")])
mgl@1371
 13120
+
mgl@1371
 13121
+(define_insn "satsub_h"
mgl@1371
 13122
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 13123
+        (ss_minus:HI (match_operand:HI 1 "register_operand" "r")
mgl@1371
 13124
+                     (match_operand:HI 2 "register_operand" "r")))]
mgl@1371
 13125
+  "TARGET_DSP"
mgl@1371
 13126
+  "satsub.h\t%0, %1, %2"
mgl@1371
 13127
+  [(set_attr "length" "4")
mgl@1371
 13128
+   (set_attr "cc" "none")
mgl@1371
 13129
+   (set_attr "type" "alu_sat")])
mgl@1371
 13130
+
mgl@1371
 13131
+
mgl@1371
 13132
+;;=============================================================================
mgl@1371
 13133
+;; smin
mgl@1371
 13134
+;;-----------------------------------------------------------------------------
mgl@1371
 13135
+;; Set reg0 to the smallest value of reg1 and reg2. It is used for signed
mgl@1371
 13136
+;; values in the registers.
mgl@1371
 13137
+;;=============================================================================
mgl@1371
 13138
+(define_insn "sminsi3"
mgl@1371
 13139
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13140
+	(smin:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13141
+		 (match_operand:SI 2 "register_operand" "r")))]
mgl@1371
 13142
+  ""
mgl@1371
 13143
+  "min     %0, %1, %2"
mgl@1371
 13144
+  [(set_attr "length" "4")
mgl@1371
 13145
+   (set_attr "cc" "none")])
mgl@1371
 13146
+
mgl@1371
 13147
+;;=============================================================================
mgl@1371
 13148
+;; smax
mgl@1371
 13149
+;;-----------------------------------------------------------------------------
mgl@1371
 13150
+;; Set reg0 to the largest value of reg1 and reg2. It is used for signed
mgl@1371
 13151
+;; values in the registers.
mgl@1371
 13152
+;;=============================================================================
mgl@1371
 13153
+(define_insn "smaxsi3"
mgl@1371
 13154
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13155
+	(smax:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13156
+		 (match_operand:SI 2 "register_operand" "r")))]
mgl@1371
 13157
+  ""
mgl@1371
 13158
+  "max     %0, %1, %2"
mgl@1371
 13159
+  [(set_attr "length" "4")
mgl@1371
 13160
+   (set_attr "cc" "none")])
mgl@1371
 13161
+
mgl@1371
 13162
+
mgl@1371
 13163
+
mgl@1371
 13164
+;;=============================================================================
mgl@1371
 13165
+;; Logical operations
mgl@1371
 13166
+;;-----------------------------------------------------------------------------
mgl@1371
 13167
+
mgl@1371
 13168
+
mgl@1371
 13169
+;; Split up simple DImode logical operations.  Simply perform the logical
mgl@1371
 13170
+;; operation on the upper and lower halves of the registers.
mgl@1371
 13171
+(define_split
mgl@1371
 13172
+  [(set (match_operand:DI 0 "register_operand" "")
mgl@1371
 13173
+	(match_operator:DI 6 "logical_binary_operator"
mgl@1371
 13174
+	  [(match_operand:DI 1 "register_operand" "")
mgl@1371
 13175
+	   (match_operand:DI 2 "register_operand" "")]))]
mgl@1371
 13176
+  "reload_completed"
mgl@1371
 13177
+  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
mgl@1371
 13178
+   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
mgl@1371
 13179
+  "
mgl@1371
 13180
+  {
mgl@1371
 13181
+    operands[3] = gen_highpart (SImode, operands[0]);
mgl@1371
 13182
+    operands[0] = gen_lowpart (SImode, operands[0]);
mgl@1371
 13183
+    operands[4] = gen_highpart (SImode, operands[1]);
mgl@1371
 13184
+    operands[1] = gen_lowpart (SImode, operands[1]);
mgl@1371
 13185
+    operands[5] = gen_highpart (SImode, operands[2]);
mgl@1371
 13186
+    operands[2] = gen_lowpart (SImode, operands[2]);
mgl@1371
 13187
+  }"
mgl@1371
 13188
+)
mgl@1371
 13189
+
mgl@1371
 13190
+;;=============================================================================
mgl@1371
 13191
+;; Logical operations with shifted operand
mgl@1371
 13192
+;;=============================================================================
mgl@1371
 13193
+(define_insn "<code>si_lshift"
mgl@1371
 13194
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13195
+        (logical:SI (match_operator:SI 4 "logical_shift_operator"
mgl@1371
 13196
+                                       [(match_operand:SI 2 "register_operand" "r")
mgl@1371
 13197
+                                        (match_operand:SI 3 "immediate_operand" "Ku05")])
mgl@1371
 13198
+                    (match_operand:SI 1 "register_operand" "r")))]
mgl@1371
 13199
+  ""
mgl@1371
 13200
+  {
mgl@1371
 13201
+   if ( GET_CODE(operands[4]) == ASHIFT )
mgl@1371
 13202
+      return "<logical_insn>\t%0, %1, %2 << %3";
mgl@1371
 13203
+   else
mgl@1371
 13204
+      return "<logical_insn>\t%0, %1, %2 >> %3";
mgl@1371
 13205
+      }
mgl@1371
 13206
+
mgl@1371
 13207
+  [(set_attr "cc" "set_z")]
mgl@1371
 13208
+)
mgl@1371
 13209
+
mgl@1371
 13210
+
mgl@1371
 13211
+;;************************************************
mgl@1371
 13212
+;; Peepholes for detecting logical operantions
mgl@1371
 13213
+;; with shifted operands
mgl@1371
 13214
+;;************************************************
mgl@1371
 13215
+
mgl@1371
 13216
+(define_peephole
mgl@1371
 13217
+  [(set (match_operand:SI 3 "register_operand" "")
mgl@1371
 13218
+        (match_operator:SI 5 "logical_shift_operator"
mgl@1371
 13219
+                           [(match_operand:SI 1 "register_operand" "")
mgl@1371
 13220
+                            (match_operand:SI 2 "immediate_operand" "")]))
mgl@1371
 13221
+   (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 13222
+        (logical:SI (match_operand:SI 4 "register_operand" "")
mgl@1371
 13223
+                    (match_dup 3)))]
mgl@1371
 13224
+  "(dead_or_set_p(insn, operands[3])) || (REGNO(operands[3]) == REGNO(operands[0]))"
mgl@1371
 13225
+  {
mgl@1371
 13226
+   if ( GET_CODE(operands[5]) == ASHIFT )
mgl@1371
 13227
+      return "<logical_insn>\t%0, %4, %1 << %2";
mgl@1371
 13228
+   else
mgl@1371
 13229
+      return "<logical_insn>\t%0, %4, %1 >> %2";
mgl@1371
 13230
+  }
mgl@1371
 13231
+  [(set_attr "cc" "set_z")]
mgl@1371
 13232
+  )
mgl@1371
 13233
+
mgl@1371
 13234
+(define_peephole
mgl@1371
 13235
+  [(set (match_operand:SI 3 "register_operand" "")
mgl@1371
 13236
+        (match_operator:SI 5 "logical_shift_operator"
mgl@1371
 13237
+                           [(match_operand:SI 1 "register_operand" "")
mgl@1371
 13238
+                            (match_operand:SI 2 "immediate_operand" "")]))
mgl@1371
 13239
+   (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 13240
+        (logical:SI (match_dup 3)
mgl@1371
 13241
+                    (match_operand:SI 4 "register_operand" "")))]
mgl@1371
 13242
+  "(dead_or_set_p(insn, operands[3])) || (REGNO(operands[3]) == REGNO(operands[0]))"
mgl@1371
 13243
+  {
mgl@1371
 13244
+   if ( GET_CODE(operands[5]) == ASHIFT )
mgl@1371
 13245
+      return "<logical_insn>\t%0, %4, %1 << %2";
mgl@1371
 13246
+   else
mgl@1371
 13247
+      return "<logical_insn>\t%0, %4, %1 >> %2";
mgl@1371
 13248
+  }
mgl@1371
 13249
+  [(set_attr "cc" "set_z")]
mgl@1371
 13250
+  )
mgl@1371
 13251
+
mgl@1371
 13252
+
mgl@1371
 13253
+(define_peephole2
mgl@1371
 13254
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 13255
+        (match_operator:SI 5 "logical_shift_operator"
mgl@1371
 13256
+                           [(match_operand:SI 1 "register_operand" "")
mgl@1371
 13257
+                            (match_operand:SI 2 "immediate_operand" "")]))
mgl@1371
 13258
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 13259
+        (logical:SI (match_operand:SI 4 "register_operand" "")
mgl@1371
 13260
+                    (match_dup 0)))]
mgl@1371
 13261
+  "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[3]) == REGNO(operands[0]))"
mgl@1371
 13262
+
mgl@1371
 13263
+  [(set (match_dup 3)
mgl@1371
 13264
+        (logical:SI  (match_op_dup:SI 5 [(match_dup 1) (match_dup 2)])
mgl@1371
 13265
+                     (match_dup 4)))]
mgl@1371
 13266
+
mgl@1371
 13267
+  ""
mgl@1371
 13268
+)
mgl@1371
 13269
+
mgl@1371
 13270
+(define_peephole2
mgl@1371
 13271
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 13272
+        (match_operator:SI 5 "logical_shift_operator"
mgl@1371
 13273
+                           [(match_operand:SI 1 "register_operand" "")
mgl@1371
 13274
+                            (match_operand:SI 2 "immediate_operand" "")]))
mgl@1371
 13275
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 13276
+        (logical:SI (match_dup 0)
mgl@1371
 13277
+                    (match_operand:SI 4 "register_operand" "")))]
mgl@1371
 13278
+  "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[3]) == REGNO(operands[0]))"
mgl@1371
 13279
+
mgl@1371
 13280
+  [(set (match_dup 3)
mgl@1371
 13281
+        (logical:SI (match_op_dup:SI 5 [(match_dup 1) (match_dup 2)])
mgl@1371
 13282
+                    (match_dup 4)))]
mgl@1371
 13283
+
mgl@1371
 13284
+  ""
mgl@1371
 13285
+)
mgl@1371
 13286
+
mgl@1371
 13287
+
mgl@1371
 13288
+;;=============================================================================
mgl@1371
 13289
+;; and
mgl@1371
 13290
+;;-----------------------------------------------------------------------------
mgl@1371
 13291
+;; Store the result after a bitwise logical-and between reg0 and reg2 in reg0.
mgl@1371
 13292
+;;=============================================================================
mgl@1371
 13293
+
mgl@1371
 13294
+(define_insn "andnsi"
mgl@1371
 13295
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 13296
+        (and:SI (match_dup 0)
mgl@1371
 13297
+                (not:SI (match_operand:SI 1 "register_operand" "r"))))]
mgl@1371
 13298
+  ""
mgl@1371
 13299
+  "andn    %0, %1"
mgl@1371
 13300
+  [(set_attr "cc" "set_z")
mgl@1371
 13301
+   (set_attr "length" "2")]
mgl@1371
 13302
+)
mgl@1371
 13303
+
mgl@1371
 13304
+
mgl@1371
 13305
+(define_insn "andsi3"
mgl@1371
 13306
+  [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand"          "=Y,r,r,r,   r,   r,r,r,r,r")
mgl@1371
 13307
+	(and:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand"  "%0,r,0,0,   0,   0,0,0,0,r" )
mgl@1371
 13308
+		(match_operand:SI 2 "nonmemory_operand"                     " N,M,N,Ku16,Ks17,J,L,r,i,r")))]
mgl@1371
 13309
+  ""
mgl@1371
 13310
+  "@
mgl@1371
 13311
+   memc\t%0, %z2
mgl@1371
 13312
+   bfextu\t%0, %1, 0, %z2
mgl@1371
 13313
+   cbr\t%0, %z2
mgl@1371
 13314
+   andl\t%0, %2, COH
mgl@1371
 13315
+   andl\t%0, lo(%2)
mgl@1371
 13316
+   andh\t%0, hi(%2), COH
mgl@1371
 13317
+   andh\t%0, hi(%2)
mgl@1371
 13318
+   and\t%0, %2
mgl@1371
 13319
+   andh\t%0, hi(%2)\;andl\t%0, lo(%2)
mgl@1371
 13320
+   and\t%0, %1, %2"
mgl@1371
 13321
+  
mgl@1371
 13322
+  [(set_attr "length" "4,4,2,4,4,4,4,2,8,4")
mgl@1371
 13323
+   (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z,set_z,set_z,set_z,set_z")])
mgl@1371
 13324
+
mgl@1371
 13325
+(define_insn "anddi3"
mgl@1371
 13326
+  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
mgl@1371
 13327
+	(and:DI (match_operand:DI 1 "register_operand" "%0,r")
mgl@1371
 13328
+                (match_operand:DI 2 "register_operand" "r,r")))]
mgl@1371
 13329
+  ""
mgl@1371
 13330
+  "#"
mgl@1371
 13331
+  [(set_attr "length" "8")
mgl@1371
 13332
+   (set_attr "cc" "clobber")]
mgl@1371
 13333
+)
mgl@1371
 13334
+
mgl@1371
 13335
+;;=============================================================================
mgl@1371
 13336
+;; or
mgl@1371
 13337
+;;-----------------------------------------------------------------------------
mgl@1371
 13338
+;; Store the result after a bitwise inclusive-or between reg0 and reg2 in reg0.
mgl@1371
 13339
+;;=============================================================================
mgl@1371
 13340
+
mgl@1371
 13341
+(define_insn "iorsi3"
mgl@1371
 13342
+  [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand"          "=Y,r,r,   r,r,r,r")
mgl@1371
 13343
+	(ior:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand"  "%0,0,0,   0,0,0,r" )
mgl@1371
 13344
+		(match_operand:SI 2 "nonmemory_operand"                     " O,O,Ku16,J,r,i,r")))]
mgl@1371
 13345
+  ""
mgl@1371
 13346
+  "@
mgl@1371
 13347
+   mems\t%0, %p2
mgl@1371
 13348
+   sbr\t%0, %p2
mgl@1371
 13349
+   orl\t%0, %2
mgl@1371
 13350
+   orh\t%0, hi(%2)
mgl@1371
 13351
+   or\t%0, %2
mgl@1371
 13352
+   orh\t%0, hi(%2)\;orl\t%0, lo(%2)
mgl@1371
 13353
+   or\t%0, %1, %2"
mgl@1371
 13354
+
mgl@1371
 13355
+  [(set_attr "length" "4,2,4,4,2,8,4")
mgl@1371
 13356
+   (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z,set_z")])
mgl@1371
 13357
+
mgl@1371
 13358
+
mgl@1371
 13359
+(define_insn "iordi3"
mgl@1371
 13360
+  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
mgl@1371
 13361
+	(ior:DI (match_operand:DI 1 "register_operand" "%0,r")
mgl@1371
 13362
+                (match_operand:DI 2 "register_operand" "r,r")))]
mgl@1371
 13363
+  ""
mgl@1371
 13364
+  "#"
mgl@1371
 13365
+  [(set_attr "length" "8")
mgl@1371
 13366
+   (set_attr "cc" "clobber")]
mgl@1371
 13367
+)
mgl@1371
 13368
+
mgl@1371
 13369
+;;=============================================================================
mgl@1371
 13370
+;; xor bytes
mgl@1371
 13371
+;;-----------------------------------------------------------------------------
mgl@1371
 13372
+;; Store the result after a bitwise exclusive-or between reg0 and reg2 in reg0.
mgl@1371
 13373
+;;=============================================================================
mgl@1371
 13374
+
mgl@1371
 13375
+(define_insn "xorsi3"
mgl@1371
 13376
+  [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand"          "=Y,r,   r,r,r,r")
mgl@1371
 13377
+	(xor:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand"  "%0,0,   0,0,0,r" )
mgl@1371
 13378
+		(match_operand:SI 2 "nonmemory_operand"                     " O,Ku16,J,r,i,r")))]
mgl@1371
 13379
+  ""
mgl@1371
 13380
+  "@
mgl@1371
 13381
+   memt\t%0, %p2
mgl@1371
 13382
+   eorl\t%0, %2
mgl@1371
 13383
+   eorh\t%0, hi(%2)
mgl@1371
 13384
+   eor\t%0, %2
mgl@1371
 13385
+   eorh\t%0, hi(%2)\;eorl\t%0, lo(%2)
mgl@1371
 13386
+   eor\t%0, %1, %2"
mgl@1371
 13387
+  
mgl@1371
 13388
+  [(set_attr "length" "4,4,4,2,8,4")
mgl@1371
 13389
+   (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z")])
mgl@1371
 13390
+
mgl@1371
 13391
+
mgl@1371
 13392
+(define_insn "xordi3"
mgl@1371
 13393
+  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
mgl@1371
 13394
+	(xor:DI (match_operand:DI 1 "register_operand" "%0,r")
mgl@1371
 13395
+                (match_operand:DI 2 "register_operand" "r,r")))]
mgl@1371
 13396
+  ""
mgl@1371
 13397
+  "#"
mgl@1371
 13398
+  [(set_attr "length" "8")
mgl@1371
 13399
+   (set_attr "cc" "clobber")]
mgl@1371
 13400
+)
mgl@1371
 13401
+
mgl@1371
 13402
+;;=============================================================================
mgl@1371
 13403
+;; Three operand predicable insns
mgl@1371
 13404
+;;=============================================================================
mgl@1371
 13405
+
mgl@1371
 13406
+(define_insn "<predicable_insn3><mode>_predicable"
mgl@1371
 13407
+  [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 13408
+	(predicable_op3:INTM (match_operand:INTM 1 "register_operand" "<predicable_commutative3>r")
mgl@1371
 13409
+                             (match_operand:INTM 2 "register_operand" "r")))]
mgl@1371
 13410
+  "TARGET_V2_INSNS"
mgl@1371
 13411
+  "<predicable_insn3>%?\t%0, %1, %2"
mgl@1371
 13412
+  [(set_attr "length" "4")
mgl@1371
 13413
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13414
+   (set_attr "predicable" "yes")]
mgl@1371
 13415
+)
mgl@1371
 13416
+
mgl@1371
 13417
+(define_insn_and_split "<predicable_insn3><mode>_imm_clobber_predicable"
mgl@1371
 13418
+  [(parallel 
mgl@1371
 13419
+    [(set (match_operand:INTM 0 "register_operand" "=r")
mgl@1371
 13420
+          (predicable_op3:INTM (match_operand:INTM 1 "register_operand" "<predicable_commutative3>r")
mgl@1371
 13421
+                               (match_operand:INTM 2 "avr32_mov_immediate_operand" "JKs21")))
mgl@1371
 13422
+     (clobber (match_operand:INTM 3 "register_operand" "=&r"))])]
mgl@1371
 13423
+  "TARGET_V2_INSNS"
mgl@1371
 13424
+  {
mgl@1371
 13425
+   if ( current_insn_predicate != NULL_RTX ) 
mgl@1371
 13426
+      {
mgl@1371
 13427
+       if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks08") )
mgl@1371
 13428
+          return "%! mov%?\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13429
+       else if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks21") )
mgl@1371
 13430
+          return "%! mov\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13431
+       else
mgl@1371
 13432
+          return "%! movh\t%3, hi(%2)\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13433
+       }
mgl@1371
 13434
+   else
mgl@1371
 13435
+      {
mgl@1371
 13436
+       if ( !avr32_cond_imm_clobber_splittable (insn, operands) )
mgl@1371
 13437
+          {
mgl@1371
 13438
+                if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks08") )
mgl@1371
 13439
+                   return "mov%?\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13440
+                else if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks21") )
mgl@1371
 13441
+                   return "mov\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13442
+                else
mgl@1371
 13443
+                   return "movh\t%3, hi(%2)\;<predicable_insn3>%?\t%0, %1, %3";
mgl@1371
 13444
+          }
mgl@1371
 13445
+       return "#";
mgl@1371
 13446
+      }
mgl@1371
 13447
+      
mgl@1371
 13448
+  }
mgl@1371
 13449
+  ;; If we find out that we could not actually do if-conversion on the block
mgl@1371
 13450
+  ;; containing this insn we convert it back to normal immediate format
mgl@1371
 13451
+  ;; to avoid outputing a redundant move insn
mgl@1371
 13452
+  ;; Do not split until after we have checked if we can make the insn 
mgl@1371
 13453
+  ;; conditional.
mgl@1371
 13454
+  "(GET_CODE (PATTERN (insn)) != COND_EXEC
mgl@1371
 13455
+    && cfun->machine->ifcvt_after_reload
mgl@1371
 13456
+    && avr32_cond_imm_clobber_splittable (insn, operands))"
mgl@1371
 13457
+  [(set (match_dup 0)
mgl@1371
 13458
+        (predicable_op3:INTM (match_dup 1)
mgl@1371
 13459
+                             (match_dup 2)))]
mgl@1371
 13460
+  ""
mgl@1371
 13461
+  [(set_attr "length" "8")
mgl@1371
 13462
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13463
+   (set_attr "predicable" "yes")]
mgl@1371
 13464
+  )
mgl@1371
 13465
+
mgl@1371
 13466
+
mgl@1371
 13467
+;;=============================================================================
mgl@1371
 13468
+;; Zero extend predicable insns
mgl@1371
 13469
+;;=============================================================================
mgl@1371
 13470
+(define_insn_and_split "zero_extendhisi_clobber_predicable"
mgl@1371
 13471
+  [(parallel 
mgl@1371
 13472
+    [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13473
+          (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))
mgl@1371
 13474
+     (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
mgl@1371
 13475
+  "TARGET_V2_INSNS"
mgl@1371
 13476
+  {
mgl@1371
 13477
+   if ( current_insn_predicate != NULL_RTX ) 
mgl@1371
 13478
+      {
mgl@1371
 13479
+         return "%! mov\t%2, 0xffff\;and%?\t%0, %1, %2";
mgl@1371
 13480
+       }
mgl@1371
 13481
+   else
mgl@1371
 13482
+      {
mgl@1371
 13483
+       return "#";
mgl@1371
 13484
+      }
mgl@1371
 13485
+      
mgl@1371
 13486
+  }
mgl@1371
 13487
+  ;; If we find out that we could not actually do if-conversion on the block
mgl@1371
 13488
+  ;; containing this insn we convert it back to normal immediate format
mgl@1371
 13489
+  ;; to avoid outputing a redundant move insn
mgl@1371
 13490
+  ;; Do not split until after we have checked if we can make the insn 
mgl@1371
 13491
+  ;; conditional.
mgl@1371
 13492
+  "(GET_CODE (PATTERN (insn)) != COND_EXEC
mgl@1371
 13493
+    && cfun->machine->ifcvt_after_reload)"
mgl@1371
 13494
+  [(set (match_dup 0)
mgl@1371
 13495
+        (zero_extend:SI (match_dup 1)))]
mgl@1371
 13496
+  ""
mgl@1371
 13497
+  [(set_attr "length" "8")
mgl@1371
 13498
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13499
+   (set_attr "predicable" "yes")]
mgl@1371
 13500
+  )
mgl@1371
 13501
+
mgl@1371
 13502
+(define_insn_and_split "zero_extendqisi_clobber_predicable"
mgl@1371
 13503
+  [(parallel 
mgl@1371
 13504
+    [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13505
+          (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))
mgl@1371
 13506
+     (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
mgl@1371
 13507
+  "TARGET_V2_INSNS"
mgl@1371
 13508
+  {
mgl@1371
 13509
+   if ( current_insn_predicate != NULL_RTX ) 
mgl@1371
 13510
+      {
mgl@1371
 13511
+         return "%! mov\t%2, 0xff\;and%?\t%0, %1, %2";
mgl@1371
 13512
+       }
mgl@1371
 13513
+   else
mgl@1371
 13514
+      {
mgl@1371
 13515
+       return "#";
mgl@1371
 13516
+      }
mgl@1371
 13517
+      
mgl@1371
 13518
+  }
mgl@1371
 13519
+  ;; If we find out that we could not actually do if-conversion on the block
mgl@1371
 13520
+  ;; containing this insn we convert it back to normal immediate format
mgl@1371
 13521
+  ;; to avoid outputing a redundant move insn
mgl@1371
 13522
+  ;; Do not split until after we have checked if we can make the insn 
mgl@1371
 13523
+  ;; conditional.
mgl@1371
 13524
+  "(GET_CODE (PATTERN (insn)) != COND_EXEC
mgl@1371
 13525
+    && cfun->machine->ifcvt_after_reload)"
mgl@1371
 13526
+  [(set (match_dup 0)
mgl@1371
 13527
+        (zero_extend:SI (match_dup 1)))]
mgl@1371
 13528
+  ""
mgl@1371
 13529
+  [(set_attr "length" "8")
mgl@1371
 13530
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13531
+   (set_attr "predicable" "yes")]
mgl@1371
 13532
+  )
mgl@1371
 13533
+
mgl@1371
 13534
+(define_insn_and_split "zero_extendqihi_clobber_predicable"
mgl@1371
 13535
+  [(parallel 
mgl@1371
 13536
+    [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 13537
+          (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))
mgl@1371
 13538
+     (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
mgl@1371
 13539
+  "TARGET_V2_INSNS"
mgl@1371
 13540
+  {
mgl@1371
 13541
+   if ( current_insn_predicate != NULL_RTX ) 
mgl@1371
 13542
+      {
mgl@1371
 13543
+         return "%! mov\t%2, 0xff\;and%?\t%0, %1, %2";
mgl@1371
 13544
+       }
mgl@1371
 13545
+   else
mgl@1371
 13546
+      {
mgl@1371
 13547
+       return "#";
mgl@1371
 13548
+      }
mgl@1371
 13549
+      
mgl@1371
 13550
+  }
mgl@1371
 13551
+  ;; If we find out that we could not actually do if-conversion on the block
mgl@1371
 13552
+  ;; containing this insn we convert it back to normal immediate format
mgl@1371
 13553
+  ;; to avoid outputing a redundant move insn
mgl@1371
 13554
+  ;; Do not split until after we have checked if we can make the insn 
mgl@1371
 13555
+  ;; conditional.
mgl@1371
 13556
+  "(GET_CODE (PATTERN (insn)) != COND_EXEC
mgl@1371
 13557
+    && cfun->machine->ifcvt_after_reload)"
mgl@1371
 13558
+  [(set (match_dup 0)
mgl@1371
 13559
+        (zero_extend:HI (match_dup 1)))]
mgl@1371
 13560
+  ""
mgl@1371
 13561
+  [(set_attr "length" "8")
mgl@1371
 13562
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13563
+   (set_attr "predicable" "yes")]
mgl@1371
 13564
+  )
mgl@1371
 13565
+;;=============================================================================
mgl@1371
 13566
+;; divmod
mgl@1371
 13567
+;;-----------------------------------------------------------------------------
mgl@1371
 13568
+;; Signed division that produces both a quotient and a remainder.
mgl@1371
 13569
+;;=============================================================================
mgl@1371
 13570
+(define_expand "divmodsi4"
mgl@1371
 13571
+  [(parallel [
mgl@1371
 13572
+     (parallel [
mgl@1371
 13573
+       (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13574
+	    (div:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13575
+		    (match_operand:SI 2 "register_operand" "r")))
mgl@1371
 13576
+       (set (match_operand:SI 3 "register_operand" "=r")
mgl@1371
 13577
+	    (mod:SI (match_dup 1)
mgl@1371
 13578
+		    (match_dup 2)))])
mgl@1371
 13579
+     (use (match_dup 4))])]
mgl@1371
 13580
+  ""
mgl@1371
 13581
+  {
mgl@1371
 13582
+    if (! no_new_pseudos) {
mgl@1371
 13583
+      operands[4] = gen_reg_rtx (DImode);
mgl@1371
 13584
+
mgl@1371
 13585
+      emit_insn(gen_divmodsi4_internal(operands[4],operands[1],operands[2]));
mgl@1371
 13586
+      emit_move_insn(operands[0], gen_rtx_SUBREG( SImode, operands[4], 4));
mgl@1371
 13587
+      emit_move_insn(operands[3], gen_rtx_SUBREG( SImode, operands[4], 0));
mgl@1371
 13588
+
mgl@1371
 13589
+      DONE;
mgl@1371
 13590
+    } else {
mgl@1371
 13591
+      FAIL;
mgl@1371
 13592
+    }
mgl@1371
 13593
+
mgl@1371
 13594
+  })
mgl@1371
 13595
+
mgl@1371
 13596
+
mgl@1371
 13597
+(define_insn "divmodsi4_internal"
mgl@1371
 13598
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 13599
+	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
mgl@1371
 13600
+		    (match_operand:SI 2 "register_operand" "r")]
mgl@1371
 13601
+		   UNSPEC_DIVMODSI4_INTERNAL))]
mgl@1371
 13602
+  ""
mgl@1371
 13603
+  "divs    %0, %1, %2"
mgl@1371
 13604
+  [(set_attr "type" "div")
mgl@1371
 13605
+   (set_attr "cc" "none")])
mgl@1371
 13606
+
mgl@1371
 13607
+
mgl@1371
 13608
+;;=============================================================================
mgl@1371
 13609
+;; udivmod
mgl@1371
 13610
+;;-----------------------------------------------------------------------------
mgl@1371
 13611
+;; Unsigned division that produces both a quotient and a remainder.
mgl@1371
 13612
+;;=============================================================================
mgl@1371
 13613
+(define_expand "udivmodsi4"
mgl@1371
 13614
+ [(parallel [
mgl@1371
 13615
+    (parallel [
mgl@1371
 13616
+      (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13617
+	   (udiv:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 13618
+		    (match_operand:SI 2 "register_operand" "r")))
mgl@1371
 13619
+      (set (match_operand:SI 3 "register_operand" "=r")
mgl@1371
 13620
+	   (umod:SI (match_dup 1)
mgl@1371
 13621
+		    (match_dup 2)))])
mgl@1371
 13622
+    (use (match_dup 4))])]
mgl@1371
 13623
+  ""
mgl@1371
 13624
+  {
mgl@1371
 13625
+    if (! no_new_pseudos) {
mgl@1371
 13626
+      operands[4] = gen_reg_rtx (DImode);
mgl@1371
 13627
+
mgl@1371
 13628
+      emit_insn(gen_udivmodsi4_internal(operands[4],operands[1],operands[2]));
mgl@1371
 13629
+      emit_move_insn(operands[0], gen_rtx_SUBREG( SImode, operands[4], 4));
mgl@1371
 13630
+      emit_move_insn(operands[3], gen_rtx_SUBREG( SImode, operands[4], 0));
mgl@1371
 13631
+
mgl@1371
 13632
+      DONE;
mgl@1371
 13633
+    } else {
mgl@1371
 13634
+      FAIL;
mgl@1371
 13635
+    }
mgl@1371
 13636
+  })
mgl@1371
 13637
+
mgl@1371
 13638
+(define_insn "udivmodsi4_internal"
mgl@1371
 13639
+  [(set (match_operand:DI 0 "register_operand" "=r")
mgl@1371
 13640
+	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
mgl@1371
 13641
+		    (match_operand:SI 2 "register_operand" "r")]
mgl@1371
 13642
+		   UNSPEC_UDIVMODSI4_INTERNAL))]
mgl@1371
 13643
+  ""
mgl@1371
 13644
+  "divu    %0, %1, %2"
mgl@1371
 13645
+  [(set_attr "type" "div")
mgl@1371
 13646
+   (set_attr "cc" "none")])
mgl@1371
 13647
+
mgl@1371
 13648
+
mgl@1371
 13649
+;;=============================================================================
mgl@1371
 13650
+;; Arithmetic-shift left
mgl@1371
 13651
+;;-----------------------------------------------------------------------------
mgl@1371
 13652
+;; Arithmetic-shift reg0 left by reg2 or immediate value.
mgl@1371
 13653
+;;=============================================================================
mgl@1371
 13654
+
mgl@1371
 13655
+(define_insn "ashlsi3"
mgl@1371
 13656
+  [(set (match_operand:SI 0 "register_operand"           "=r,r,r")
mgl@1371
 13657
+	(ashift:SI (match_operand:SI 1 "register_operand" "r,0,r")
mgl@1371
 13658
+		   (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
mgl@1371
 13659
+  ""
mgl@1371
 13660
+  "@
mgl@1371
 13661
+   lsl     %0, %1, %2
mgl@1371
 13662
+   lsl     %0, %2
mgl@1371
 13663
+   lsl     %0, %1, %2"
mgl@1371
 13664
+  [(set_attr "length" "4,2,4")
mgl@1371
 13665
+   (set_attr "cc" "set_ncz")])
mgl@1371
 13666
+
mgl@1371
 13667
+;;=============================================================================
mgl@1371
 13668
+;; Arithmetic-shift right
mgl@1371
 13669
+;;-----------------------------------------------------------------------------
mgl@1371
 13670
+;; Arithmetic-shift reg0 right by an immediate value.
mgl@1371
 13671
+;;=============================================================================
mgl@1371
 13672
+
mgl@1371
 13673
+(define_insn "ashrsi3"
mgl@1371
 13674
+  [(set (match_operand:SI 0 "register_operand"             "=r,r,r")
mgl@1371
 13675
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r,0,r")
mgl@1371
 13676
+		     (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
mgl@1371
 13677
+  ""
mgl@1371
 13678
+  "@
mgl@1371
 13679
+   asr     %0, %1, %2
mgl@1371
 13680
+   asr     %0, %2
mgl@1371
 13681
+   asr     %0, %1, %2"
mgl@1371
 13682
+  [(set_attr "length" "4,2,4")
mgl@1371
 13683
+   (set_attr "cc" "set_ncz")])
mgl@1371
 13684
+
mgl@1371
 13685
+;;=============================================================================
mgl@1371
 13686
+;; Logical shift right
mgl@1371
 13687
+;;-----------------------------------------------------------------------------
mgl@1371
 13688
+;; Logical shift reg0 right by an immediate value.
mgl@1371
 13689
+;;=============================================================================
mgl@1371
 13690
+
mgl@1371
 13691
+(define_insn "lshrsi3"
mgl@1371
 13692
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
mgl@1371
 13693
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0,r")
mgl@1371
 13694
+		     (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
mgl@1371
 13695
+  ""
mgl@1371
 13696
+  "@
mgl@1371
 13697
+   lsr     %0, %1, %2
mgl@1371
 13698
+   lsr     %0, %2
mgl@1371
 13699
+   lsr     %0, %1, %2"
mgl@1371
 13700
+  [(set_attr "length" "4,2,4")
mgl@1371
 13701
+   (set_attr "cc" "set_ncz")])
mgl@1371
 13702
+
mgl@1371
 13703
+
mgl@1371
 13704
+;;=============================================================================
mgl@1371
 13705
+;; neg
mgl@1371
 13706
+;;-----------------------------------------------------------------------------
mgl@1371
 13707
+;; Negate operand 1 and store the result in operand 0.
mgl@1371
 13708
+;;=============================================================================
mgl@1371
 13709
+(define_insn "negsi2"
mgl@1371
 13710
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
mgl@1371
 13711
+	(neg:SI (match_operand:SI 1 "register_operand" "0,r")))]
mgl@1371
 13712
+  ""
mgl@1371
 13713
+  "@
mgl@1371
 13714
+   neg\t%0
mgl@1371
 13715
+   rsub\t%0, %1, 0"
mgl@1371
 13716
+  [(set_attr "length" "2,4")
mgl@1371
 13717
+   (set_attr "cc" "set_vncz")])
mgl@1371
 13718
+
mgl@1371
 13719
+(define_insn "negsi2_predicable"
mgl@1371
 13720
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 13721
+	(neg:SI (match_dup 0)))]
mgl@1371
 13722
+  "TARGET_V2_INSNS"
mgl@1371
 13723
+  "rsub%?\t%0, 0"
mgl@1371
 13724
+  [(set_attr "length" "4")
mgl@1371
 13725
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13726
+   (set_attr "predicable" "yes")])
mgl@1371
 13727
+
mgl@1371
 13728
+;;=============================================================================
mgl@1371
 13729
+;; abs
mgl@1371
 13730
+;;-----------------------------------------------------------------------------
mgl@1371
 13731
+;; Store the absolute value of operand 1 into operand 0.
mgl@1371
 13732
+;;=============================================================================
mgl@1371
 13733
+(define_insn "abssi2"
mgl@1371
 13734
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 13735
+	(abs:SI (match_operand:SI 1 "register_operand" "0")))]
mgl@1371
 13736
+  ""
mgl@1371
 13737
+  "abs\t%0"
mgl@1371
 13738
+  [(set_attr "length" "2")
mgl@1371
 13739
+   (set_attr "cc" "set_z")])
mgl@1371
 13740
+
mgl@1371
 13741
+
mgl@1371
 13742
+;;=============================================================================
mgl@1371
 13743
+;; one_cmpl
mgl@1371
 13744
+;;-----------------------------------------------------------------------------
mgl@1371
 13745
+;; Store the bitwise-complement of operand 1 into operand 0.
mgl@1371
 13746
+;;=============================================================================
mgl@1371
 13747
+
mgl@1371
 13748
+(define_insn "one_cmplsi2"
mgl@1371
 13749
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
mgl@1371
 13750
+	(not:SI (match_operand:SI 1 "register_operand" "0,r")))]
mgl@1371
 13751
+  ""
mgl@1371
 13752
+  "@
mgl@1371
 13753
+   com\t%0
mgl@1371
 13754
+   rsub\t%0, %1, -1"
mgl@1371
 13755
+  [(set_attr "length" "2,4")
mgl@1371
 13756
+   (set_attr "cc" "set_z")])
mgl@1371
 13757
+
mgl@1371
 13758
+
mgl@1371
 13759
+(define_insn "one_cmplsi2_predicable"
mgl@1371
 13760
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 13761
+	(not:SI (match_dup 0)))]
mgl@1371
 13762
+  "TARGET_V2_INSNS"
mgl@1371
 13763
+  "rsub%?\t%0, -1"
mgl@1371
 13764
+  [(set_attr "length" "4")
mgl@1371
 13765
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 13766
+   (set_attr "predicable" "yes")])
mgl@1371
 13767
+
mgl@1371
 13768
+
mgl@1371
 13769
+;;=============================================================================
mgl@1371
 13770
+;; Bit load
mgl@1371
 13771
+;;-----------------------------------------------------------------------------
mgl@1371
 13772
+;; Load a bit into Z and C flags
mgl@1371
 13773
+;;=============================================================================
mgl@1371
 13774
+(define_insn "bldsi"
mgl@1371
 13775
+  [(set (cc0)
mgl@1371
 13776
+        (and:SI (match_operand:SI 0 "register_operand" "r")
mgl@1371
 13777
+                (match_operand:SI 1 "one_bit_set_operand" "i")))]
mgl@1371
 13778
+  ""
mgl@1371
 13779
+  "bld\t%0, %p1"
mgl@1371
 13780
+  [(set_attr "length" "4")
mgl@1371
 13781
+   (set_attr "cc" "bld")]
mgl@1371
 13782
+  )
mgl@1371
 13783
+
mgl@1371
 13784
+
mgl@1371
 13785
+;;=============================================================================
mgl@1371
 13786
+;; Compare
mgl@1371
 13787
+;;-----------------------------------------------------------------------------
mgl@1371
 13788
+;; Compare reg0 with reg1 or an immediate value.
mgl@1371
 13789
+;;=============================================================================
mgl@1371
 13790
+
mgl@1371
 13791
+(define_expand "cmp<mode>"
mgl@1371
 13792
+  [(set (cc0)
mgl@1371
 13793
+	(compare:CMP
mgl@1371
 13794
+	 (match_operand:CMP 0 "register_operand" "")
mgl@1371
 13795
+	 (match_operand:CMP 1 "<CMP:cmp_predicate>"  "")))]
mgl@1371
 13796
+  ""
mgl@1371
 13797
+  "{
mgl@1371
 13798
+   avr32_compare_op0 = operands[0];
mgl@1371
 13799
+   avr32_compare_op1 = operands[1];
mgl@1371
 13800
+  }"
mgl@1371
 13801
+)
mgl@1371
 13802
+
mgl@1371
 13803
+(define_insn "cmp<mode>_internal"
mgl@1371
 13804
+  [(set (cc0)
mgl@1371
 13805
+        (compare:CMP
mgl@1371
 13806
+         (match_operand:CMP 0 "register_operand" "r")
mgl@1371
 13807
+         (match_operand:CMP 1 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")))]
mgl@1371
 13808
+  ""
mgl@1371
 13809
+  {
mgl@1371
 13810
+   set_next_insn_cond(insn,
mgl@1371
 13811
+                      avr32_output_cmp(get_next_insn_cond(insn), GET_MODE (operands[0]), operands[0], operands[1]));
mgl@1371
 13812
+   return "";
mgl@1371
 13813
+  }
mgl@1371
 13814
+  [(set_attr "length" "4")
mgl@1371
 13815
+   (set_attr "cc" "compare")])
mgl@1371
 13816
+
mgl@1371
 13817
+
mgl@1371
 13818
+;;;=============================================================================
mgl@1371
 13819
+;; Test if zero
mgl@1371
 13820
+;;-----------------------------------------------------------------------------
mgl@1371
 13821
+;; Compare reg against zero and set the condition codes.
mgl@1371
 13822
+;;=============================================================================
mgl@1371
 13823
+
mgl@1371
 13824
+
mgl@1371
 13825
+(define_expand "tstsi"
mgl@1371
 13826
+  [(set (cc0)
mgl@1371
 13827
+	(match_operand:SI 0 "register_operand" ""))]
mgl@1371
 13828
+  ""
mgl@1371
 13829
+  {
mgl@1371
 13830
+   avr32_compare_op0 = operands[0];
mgl@1371
 13831
+   avr32_compare_op1 = const0_rtx;
mgl@1371
 13832
+  }
mgl@1371
 13833
+)
mgl@1371
 13834
+
mgl@1371
 13835
+(define_insn "tstsi_internal"
mgl@1371
 13836
+  [(set (cc0)
mgl@1371
 13837
+	(match_operand:SI 0 "register_operand" "r"))]
mgl@1371
 13838
+  ""
mgl@1371
 13839
+  {
mgl@1371
 13840
+   set_next_insn_cond(insn,
mgl@1371
 13841
+     avr32_output_cmp(get_next_insn_cond(insn), SImode, operands[0], const0_rtx));
mgl@1371
 13842
+
mgl@1371
 13843
+   return "";
mgl@1371
 13844
+  }
mgl@1371
 13845
+  [(set_attr "length" "2")
mgl@1371
 13846
+   (set_attr "cc" "compare")])
mgl@1371
 13847
+
mgl@1371
 13848
+
mgl@1371
 13849
+(define_expand "tstdi"
mgl@1371
 13850
+  [(set (cc0)
mgl@1371
 13851
+	(match_operand:DI 0 "register_operand" ""))]
mgl@1371
 13852
+  ""
mgl@1371
 13853
+  {
mgl@1371
 13854
+   avr32_compare_op0 = operands[0];
mgl@1371
 13855
+   avr32_compare_op1 = const0_rtx;
mgl@1371
 13856
+  }
mgl@1371
 13857
+)
mgl@1371
 13858
+
mgl@1371
 13859
+(define_insn "tstdi_internal"
mgl@1371
 13860
+  [(set (cc0)
mgl@1371
 13861
+	(match_operand:DI 0 "register_operand" "r"))]
mgl@1371
 13862
+  ""
mgl@1371
 13863
+  {
mgl@1371
 13864
+   set_next_insn_cond(insn,
mgl@1371
 13865
+     avr32_output_cmp(get_next_insn_cond(insn), DImode, operands[0], const0_rtx));
mgl@1371
 13866
+   return "";
mgl@1371
 13867
+  }
mgl@1371
 13868
+  [(set_attr "length" "4")
mgl@1371
 13869
+   (set_attr "type" "alu2")
mgl@1371
 13870
+   (set_attr "cc" "compare")])
mgl@1371
 13871
+
mgl@1371
 13872
+
mgl@1371
 13873
+
mgl@1371
 13874
+;;=============================================================================
mgl@1371
 13875
+;; Convert operands
mgl@1371
 13876
+;;-----------------------------------------------------------------------------
mgl@1371
 13877
+;;
mgl@1371
 13878
+;;=============================================================================
mgl@1371
 13879
+(define_insn "truncdisi2"
mgl@1371
 13880
+  [(set (match_operand:SI 0 "general_operand" "")
mgl@1371
 13881
+	(truncate:SI (match_operand:DI 1 "general_operand" "")))]
mgl@1371
 13882
+  ""
mgl@1371
 13883
+  "truncdisi2")
mgl@1371
 13884
+
mgl@1371
 13885
+;;=============================================================================
mgl@1371
 13886
+;; Extend
mgl@1371
 13887
+;;-----------------------------------------------------------------------------
mgl@1371
 13888
+;;
mgl@1371
 13889
+;;=============================================================================
mgl@1371
 13890
+
mgl@1371
 13891
+
mgl@1371
 13892
+(define_insn "extendhisi2"
mgl@1371
 13893
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
mgl@1371
 13894
+	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
mgl@1371
 13895
+  ""
mgl@1371
 13896
+  {
mgl@1371
 13897
+   switch ( which_alternative ){
mgl@1371
 13898
+     case 0:
mgl@1371
 13899
+       return    "casts.h\t%0";
mgl@1371
 13900
+     case 1:
mgl@1371
 13901
+       return    "bfexts\t%0, %1, 0, 16";
mgl@1371
 13902
+     case 2:
mgl@1371
 13903
+     case 3:
mgl@1371
 13904
+       return    "ld.sh\t%0, %1";
mgl@1371
 13905
+     default:
mgl@1371
 13906
+       abort();
mgl@1371
 13907
+   }
mgl@1371
 13908
+  }
mgl@1371
 13909
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 13910
+   (set_attr "cc" "set_ncz,set_ncz,none,none")
mgl@1371
 13911
+   (set_attr "type" "alu,alu,load_rm,load_rm")])
mgl@1371
 13912
+
mgl@1371
 13913
+(define_insn "extendqisi2"
mgl@1371
 13914
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
mgl@1371
 13915
+	(sign_extend:SI (match_operand:QI 1 "extendqi_operand" "0,r,RKu00,m")))]
mgl@1371
 13916
+  ""
mgl@1371
 13917
+  {
mgl@1371
 13918
+   switch ( which_alternative ){
mgl@1371
 13919
+     case 0:
mgl@1371
 13920
+       return    "casts.b\t%0";
mgl@1371
 13921
+     case 1:
mgl@1371
 13922
+       return    "bfexts\t%0, %1, 0, 8";
mgl@1371
 13923
+     case 2:
mgl@1371
 13924
+     case 3:
mgl@1371
 13925
+       return    "ld.sb\t%0, %1";
mgl@1371
 13926
+     default:
mgl@1371
 13927
+       abort();
mgl@1371
 13928
+   }
mgl@1371
 13929
+  }
mgl@1371
 13930
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 13931
+   (set_attr "cc" "set_ncz,set_ncz,none,none")
mgl@1371
 13932
+   (set_attr "type" "alu,alu,load_rm,load_rm")])
mgl@1371
 13933
+
mgl@1371
 13934
+(define_insn "extendqihi2"
mgl@1371
 13935
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
mgl@1371
 13936
+	(sign_extend:HI (match_operand:QI 1 "extendqi_operand" "0,r,RKu00,m")))]
mgl@1371
 13937
+  ""
mgl@1371
 13938
+  {
mgl@1371
 13939
+   switch ( which_alternative ){
mgl@1371
 13940
+     case 0:
mgl@1371
 13941
+       return    "casts.b\t%0";
mgl@1371
 13942
+     case 1:
mgl@1371
 13943
+       return    "bfexts\t%0, %1, 0, 8";
mgl@1371
 13944
+     case 2:
mgl@1371
 13945
+     case 3:
mgl@1371
 13946
+       return    "ld.sb\t%0, %1";
mgl@1371
 13947
+     default:
mgl@1371
 13948
+       abort();
mgl@1371
 13949
+   }
mgl@1371
 13950
+  }
mgl@1371
 13951
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 13952
+   (set_attr "cc" "set_ncz,set_ncz,none,none")
mgl@1371
 13953
+   (set_attr "type" "alu,alu,load_rm,load_rm")])
mgl@1371
 13954
+
mgl@1371
 13955
+
mgl@1371
 13956
+;;=============================================================================
mgl@1371
 13957
+;; Zero-extend
mgl@1371
 13958
+;;-----------------------------------------------------------------------------
mgl@1371
 13959
+;;
mgl@1371
 13960
+;;=============================================================================
mgl@1371
 13961
+
mgl@1371
 13962
+(define_insn "zero_extendhisi2"
mgl@1371
 13963
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
mgl@1371
 13964
+	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
mgl@1371
 13965
+  ""
mgl@1371
 13966
+  {
mgl@1371
 13967
+   switch ( which_alternative ){
mgl@1371
 13968
+     case 0:
mgl@1371
 13969
+       return    "castu.h\t%0";
mgl@1371
 13970
+     case 1:
mgl@1371
 13971
+       return    "bfextu\t%0, %1, 0, 16";
mgl@1371
 13972
+     case 2:
mgl@1371
 13973
+     case 3:
mgl@1371
 13974
+       return    "ld.uh\t%0, %1";
mgl@1371
 13975
+     default:
mgl@1371
 13976
+       abort();
mgl@1371
 13977
+   }
mgl@1371
 13978
+  }
mgl@1371
 13979
+
mgl@1371
 13980
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 13981
+   (set_attr "cc" "set_ncz,set_ncz,none,none")
mgl@1371
 13982
+   (set_attr "type" "alu,alu,load_rm,load_rm")])
mgl@1371
 13983
+
mgl@1371
 13984
+(define_insn "zero_extendqisi2"
mgl@1371
 13985
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
mgl@1371
 13986
+	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
mgl@1371
 13987
+  ""
mgl@1371
 13988
+  {
mgl@1371
 13989
+   switch ( which_alternative ){
mgl@1371
 13990
+     case 0:
mgl@1371
 13991
+       return    "castu.b\t%0";
mgl@1371
 13992
+     case 1:
mgl@1371
 13993
+       return    "bfextu\t%0, %1, 0, 8";
mgl@1371
 13994
+     case 2:
mgl@1371
 13995
+     case 3:
mgl@1371
 13996
+       return    "ld.ub\t%0, %1";
mgl@1371
 13997
+     default:
mgl@1371
 13998
+       abort();
mgl@1371
 13999
+   }
mgl@1371
 14000
+  }
mgl@1371
 14001
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 14002
+   (set_attr "cc" "set_ncz, set_ncz, none, none")
mgl@1371
 14003
+   (set_attr "type" "alu, alu, load_rm, load_rm")])
mgl@1371
 14004
+
mgl@1371
 14005
+(define_insn "zero_extendqihi2"
mgl@1371
 14006
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
mgl@1371
 14007
+	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
mgl@1371
 14008
+  ""
mgl@1371
 14009
+  {
mgl@1371
 14010
+   switch ( which_alternative ){
mgl@1371
 14011
+     case 0:
mgl@1371
 14012
+       return    "castu.b\t%0";
mgl@1371
 14013
+     case 1:
mgl@1371
 14014
+       return    "bfextu\t%0, %1, 0, 8";
mgl@1371
 14015
+     case 2:
mgl@1371
 14016
+     case 3:
mgl@1371
 14017
+       return    "ld.ub\t%0, %1";
mgl@1371
 14018
+     default:
mgl@1371
 14019
+       abort();
mgl@1371
 14020
+   }
mgl@1371
 14021
+  }
mgl@1371
 14022
+  [(set_attr "length" "2,4,2,4")
mgl@1371
 14023
+   (set_attr "cc" "set_ncz, set_ncz, none, none")
mgl@1371
 14024
+   (set_attr "type" "alu, alu, load_rm, load_rm")])
mgl@1371
 14025
+
mgl@1371
 14026
+
mgl@1371
 14027
+;;=============================================================================
mgl@1371
 14028
+;; Conditional load and extend insns
mgl@1371
 14029
+;;=============================================================================
mgl@1371
 14030
+(define_insn "ldsi<mode>_predicable_se"
mgl@1371
 14031
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14032
+        (sign_extend:SI 
mgl@1371
 14033
+         (match_operand:INTM 1 "memory_operand" "<INTM:pred_mem_constraint>")))]
mgl@1371
 14034
+  "TARGET_V2_INSNS"
mgl@1371
 14035
+  "ld<INTM:load_postfix_s>%?\t%0, %1"
mgl@1371
 14036
+  [(set_attr "length" "4")
mgl@1371
 14037
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 14038
+   (set_attr "type" "load")
mgl@1371
 14039
+   (set_attr "predicable" "yes")]
mgl@1371
 14040
+)
mgl@1371
 14041
+
mgl@1371
 14042
+(define_insn "ldsi<mode>_predicable_ze"
mgl@1371
 14043
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14044
+        (zero_extend:SI 
mgl@1371
 14045
+         (match_operand:INTM 1 "memory_operand" "<INTM:pred_mem_constraint>")))]
mgl@1371
 14046
+  "TARGET_V2_INSNS"
mgl@1371
 14047
+  "ld<INTM:load_postfix_u>%?\t%0, %1"
mgl@1371
 14048
+  [(set_attr "length" "4")
mgl@1371
 14049
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 14050
+   (set_attr "type" "load")
mgl@1371
 14051
+   (set_attr "predicable" "yes")]
mgl@1371
 14052
+)
mgl@1371
 14053
+
mgl@1371
 14054
+(define_insn "ldhi_predicable_ze"
mgl@1371
 14055
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 14056
+        (zero_extend:HI 
mgl@1371
 14057
+         (match_operand:QI 1 "memory_operand" "RKs10")))]
mgl@1371
 14058
+  "TARGET_V2_INSNS"
mgl@1371
 14059
+  "ld.ub%?\t%0, %1"
mgl@1371
 14060
+  [(set_attr "length" "4")
mgl@1371
 14061
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 14062
+   (set_attr "type" "load")
mgl@1371
 14063
+   (set_attr "predicable" "yes")]
mgl@1371
 14064
+)
mgl@1371
 14065
+
mgl@1371
 14066
+(define_insn "ldhi_predicable_se"
mgl@1371
 14067
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 14068
+        (sign_extend:HI 
mgl@1371
 14069
+         (match_operand:QI 1 "memory_operand" "RKs10")))]
mgl@1371
 14070
+  "TARGET_V2_INSNS"
mgl@1371
 14071
+  "ld.sb%?\t%0, %1"
mgl@1371
 14072
+  [(set_attr "length" "4")
mgl@1371
 14073
+   (set_attr "cc" "cmp_cond_insn")
mgl@1371
 14074
+   (set_attr "type" "load")
mgl@1371
 14075
+   (set_attr "predicable" "yes")]
mgl@1371
 14076
+)
mgl@1371
 14077
+
mgl@1371
 14078
+;;=============================================================================
mgl@1371
 14079
+;; Conditional set register
mgl@1371
 14080
+;; sr{cond4}  rd
mgl@1371
 14081
+;;-----------------------------------------------------------------------------
mgl@1371
 14082
+
mgl@1371
 14083
+;;Because of the same issue as with conditional moves and adds we must
mgl@1371
 14084
+;;not separate the compare instrcution from the scc instruction as
mgl@1371
 14085
+;;they might be sheduled "badly".
mgl@1371
 14086
+
mgl@1371
 14087
+(define_insn "s<code>"
mgl@1371
 14088
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14089
+	(any_cond:SI (cc0)
mgl@1371
 14090
+                     (const_int 0)))]
mgl@1371
 14091
+  ""
mgl@1371
 14092
+  "sr<cond>\t%0"
mgl@1371
 14093
+  [(set_attr "length" "2")
mgl@1371
 14094
+   (set_attr "cc" "none")])
mgl@1371
 14095
+
mgl@1371
 14096
+(define_insn "smi"
mgl@1371
 14097
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14098
+	(unspec:SI [(cc0)
mgl@1371
 14099
+                    (const_int 0)] UNSPEC_COND_MI))]
mgl@1371
 14100
+  ""
mgl@1371
 14101
+  "srmi\t%0"
mgl@1371
 14102
+  [(set_attr "length" "2")
mgl@1371
 14103
+   (set_attr "cc" "none")])
mgl@1371
 14104
+
mgl@1371
 14105
+(define_insn "spl"
mgl@1371
 14106
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14107
+	(unspec:SI [(cc0)
mgl@1371
 14108
+                    (const_int 0)] UNSPEC_COND_PL))]
mgl@1371
 14109
+  ""
mgl@1371
 14110
+  "srpl\t%0"
mgl@1371
 14111
+  [(set_attr "length" "2")
mgl@1371
 14112
+   (set_attr "cc" "none")])
mgl@1371
 14113
+
mgl@1371
 14114
+
mgl@1371
 14115
+;;=============================================================================
mgl@1371
 14116
+;; Conditional branch
mgl@1371
 14117
+;;-----------------------------------------------------------------------------
mgl@1371
 14118
+;; Branch to label if the specified condition codes are set.
mgl@1371
 14119
+;;=============================================================================
mgl@1371
 14120
+; branch if negative
mgl@1371
 14121
+(define_insn "bmi"
mgl@1371
 14122
+  [(set (pc)
mgl@1371
 14123
+	(if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_MI)
mgl@1371
 14124
+		      (label_ref (match_operand 0 "" ""))
mgl@1371
 14125
+		      (pc)))]
mgl@1371
 14126
+  ""
mgl@1371
 14127
+  "brmi    %0"
mgl@1371
 14128
+  [(set_attr "type" "branch")
mgl@1371
 14129
+   (set (attr "length")
mgl@1371
 14130
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14131
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14132
+	       (const_int 2)] ; use compact branch
mgl@1371
 14133
+              (const_int 4))) ; use extended branch
mgl@1371
 14134
+   (set_attr "cc" "none")])
mgl@1371
 14135
+
mgl@1371
 14136
+(define_insn "*bmi-reverse"
mgl@1371
 14137
+  [(set (pc)
mgl@1371
 14138
+	(if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_MI)
mgl@1371
 14139
+		      (pc)
mgl@1371
 14140
+		      (label_ref (match_operand 0 "" ""))))]
mgl@1371
 14141
+  ""
mgl@1371
 14142
+  "brpl    %0"
mgl@1371
 14143
+  [(set_attr "type" "branch")
mgl@1371
 14144
+   (set (attr "length")
mgl@1371
 14145
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14146
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14147
+	       (const_int 2)] ; use compact branch
mgl@1371
 14148
+              (const_int 4))) ; use extended branch
mgl@1371
 14149
+   (set_attr "cc" "none")])
mgl@1371
 14150
+
mgl@1371
 14151
+; branch if positive
mgl@1371
 14152
+(define_insn "bpl"
mgl@1371
 14153
+  [(set (pc)
mgl@1371
 14154
+	(if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_PL)
mgl@1371
 14155
+		      (label_ref (match_operand 0 "" ""))
mgl@1371
 14156
+		      (pc)))]
mgl@1371
 14157
+  ""
mgl@1371
 14158
+  "brpl    %0"
mgl@1371
 14159
+  [(set_attr "type" "branch")
mgl@1371
 14160
+   (set (attr "length")
mgl@1371
 14161
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14162
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14163
+	       (const_int 2)] ; use compact branch
mgl@1371
 14164
+              (const_int 4))) ; use extended branch
mgl@1371
 14165
+   (set_attr "cc" "none")])
mgl@1371
 14166
+
mgl@1371
 14167
+(define_insn "*bpl-reverse"
mgl@1371
 14168
+  [(set (pc)
mgl@1371
 14169
+	(if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_PL)
mgl@1371
 14170
+		      (pc)
mgl@1371
 14171
+		      (label_ref (match_operand 0 "" ""))))]
mgl@1371
 14172
+  ""
mgl@1371
 14173
+  "brmi    %0"
mgl@1371
 14174
+  [(set_attr "type" "branch")
mgl@1371
 14175
+   (set (attr "length")
mgl@1371
 14176
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14177
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14178
+	       (const_int 2)] ; use compact branch
mgl@1371
 14179
+              (const_int 4))) ; use extended branch
mgl@1371
 14180
+   (set_attr "cc" "none")])
mgl@1371
 14181
+
mgl@1371
 14182
+; branch if equal
mgl@1371
 14183
+(define_insn "b<code>"
mgl@1371
 14184
+  [(set (pc)
mgl@1371
 14185
+	(if_then_else (any_cond:CC (cc0)
mgl@1371
 14186
+			  (const_int 0))
mgl@1371
 14187
+		      (label_ref (match_operand 0 "" ""))
mgl@1371
 14188
+		      (pc)))]
mgl@1371
 14189
+  ""
mgl@1371
 14190
+  "br<cond>    %0 "
mgl@1371
 14191
+  [(set_attr "type" "branch")
mgl@1371
 14192
+   (set (attr "length")
mgl@1371
 14193
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14194
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14195
+	       (const_int 2)] ; use compact branch
mgl@1371
 14196
+              (const_int 4))) ; use extended branch
mgl@1371
 14197
+   (set_attr "cc" "none")])
mgl@1371
 14198
+
mgl@1371
 14199
+
mgl@1371
 14200
+(define_insn "*b<code>-reverse"
mgl@1371
 14201
+  [(set (pc)
mgl@1371
 14202
+	(if_then_else (any_cond:CC (cc0)
mgl@1371
 14203
+			  (const_int 0))
mgl@1371
 14204
+		      (pc)
mgl@1371
 14205
+		      (label_ref (match_operand 0 "" ""))))]
mgl@1371
 14206
+  ""
mgl@1371
 14207
+  "br<invcond>    %0 "
mgl@1371
 14208
+  [(set_attr "type" "branch")
mgl@1371
 14209
+   (set (attr "length")
mgl@1371
 14210
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
mgl@1371
 14211
+		    (le (minus (pc) (match_dup 0)) (const_int 256)))
mgl@1371
 14212
+	       (const_int 2)] ; use compact branch
mgl@1371
 14213
+              (const_int 4))) ; use extended branch
mgl@1371
 14214
+   (set_attr "cc" "none")])
mgl@1371
 14215
+
mgl@1371
 14216
+
mgl@1371
 14217
+
mgl@1371
 14218
+;=============================================================================
mgl@1371
 14219
+; Conditional Add/Subtract
mgl@1371
 14220
+;-----------------------------------------------------------------------------
mgl@1371
 14221
+; sub{cond4}  Rd, imm
mgl@1371
 14222
+;=============================================================================
mgl@1371
 14223
+
mgl@1371
 14224
+
mgl@1371
 14225
+(define_expand "add<mode>cc"
mgl@1371
 14226
+  [(set (match_operand:ADDCC 0 "register_operand" "")
mgl@1371
 14227
+        (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator" 
mgl@1371
 14228
+                                            [(match_dup 4)
mgl@1371
 14229
+                                             (match_dup 5)])
mgl@1371
 14230
+                            (match_operand:ADDCC 2 "register_operand" "")
mgl@1371
 14231
+                            (plus:ADDCC 
mgl@1371
 14232
+                             (match_dup 2)
mgl@1371
 14233
+                             (match_operand:ADDCC 3 "" ""))))]
mgl@1371
 14234
+  ""
mgl@1371
 14235
+  {
mgl@1371
 14236
+   if ( !(GET_CODE (operands[3]) == CONST_INT
mgl@1371
 14237
+          || (TARGET_V2_INSNS && REG_P(operands[3]))) ){
mgl@1371
 14238
+      FAIL;
mgl@1371
 14239
+   }
mgl@1371
 14240
+
mgl@1371
 14241
+   /* Delete compare instruction as it is merged into this instruction */
mgl@1371
 14242
+   remove_insn (get_last_insn_anywhere ());
mgl@1371
 14243
+
mgl@1371
 14244
+   operands[4] = avr32_compare_op0;
mgl@1371
 14245
+   operands[5] = avr32_compare_op1;
mgl@1371
 14246
+   
mgl@1371
 14247
+   if ( TARGET_V2_INSNS 
mgl@1371
 14248
+        && REG_P(operands[3]) 
mgl@1371
 14249
+        && REGNO(operands[0]) != REGNO(operands[2]) ){
mgl@1371
 14250
+       emit_move_insn (operands[0], operands[2]);
mgl@1371
 14251
+       operands[2] = operands[0];
mgl@1371
 14252
+   }
mgl@1371
 14253
+  }
mgl@1371
 14254
+  )
mgl@1371
 14255
+
mgl@1371
 14256
+(define_insn "add<ADDCC:mode>cc_cmp<CMP:mode>_reg"
mgl@1371
 14257
+  [(set (match_operand:ADDCC 0 "register_operand" "=r")
mgl@1371
 14258
+        (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator" 
mgl@1371
 14259
+                                            [(match_operand:CMP 4 "register_operand" "r")
mgl@1371
 14260
+                                             (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])
mgl@1371
 14261
+                            (match_dup 0)
mgl@1371
 14262
+                            (plus:ADDCC 
mgl@1371
 14263
+                             (match_operand:ADDCC 2 "register_operand" "r")
mgl@1371
 14264
+                             (match_operand:ADDCC 3 "register_operand" "r"))))]
mgl@1371
 14265
+  "TARGET_V2_INSNS"
mgl@1371
 14266
+  {
mgl@1371
 14267
+   operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
mgl@1371
 14268
+   return "add%i1\t%0, %2, %3";
mgl@1371
 14269
+  }
mgl@1371
 14270
+  [(set_attr "length" "8")
mgl@1371
 14271
+   (set_attr "cc" "cmp_cond_insn")])
mgl@1371
 14272
+
mgl@1371
 14273
+(define_insn "add<ADDCC:mode>cc_cmp<CMP:mode>"
mgl@1371
 14274
+  [(set (match_operand:ADDCC 0 "register_operand" "=r")
mgl@1371
 14275
+        (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator" 
mgl@1371
 14276
+                                            [(match_operand:CMP 4 "register_operand" "r")
mgl@1371
 14277
+                                             (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])
mgl@1371
 14278
+                            (match_operand:ADDCC 2 "register_operand" "0")
mgl@1371
 14279
+                            (plus:ADDCC 
mgl@1371
 14280
+                             (match_dup 2)
mgl@1371
 14281
+                             (match_operand:ADDCC 3 "avr32_cond_immediate_operand" "Is08"))))]
mgl@1371
 14282
+  ""
mgl@1371
 14283
+  {
mgl@1371
 14284
+   operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
mgl@1371
 14285
+   return "sub%i1\t%0, -%3";
mgl@1371
 14286
+  }
mgl@1371
 14287
+  [(set_attr "length" "8")
mgl@1371
 14288
+   (set_attr "cc" "cmp_cond_insn")])
mgl@1371
 14289
+
mgl@1371
 14290
+;=============================================================================
mgl@1371
 14291
+; Conditional Move
mgl@1371
 14292
+;-----------------------------------------------------------------------------
mgl@1371
 14293
+; mov{cond4}  Rd, (Rs/imm)
mgl@1371
 14294
+;=============================================================================
mgl@1371
 14295
+(define_expand "mov<mode>cc"
mgl@1371
 14296
+  [(set (match_operand:MOVCC 0 "register_operand" "")
mgl@1371
 14297
+        (if_then_else:MOVCC (match_operator 1 "avr32_comparison_operator" 
mgl@1371
 14298
+                                            [(match_dup 4)
mgl@1371
 14299
+                                             (match_dup 5)])
mgl@1371
 14300
+                            (match_operand:MOVCC 2 "avr32_cond_register_immediate_operand" "")
mgl@1371
 14301
+                            (match_operand:MOVCC 3 "avr32_cond_register_immediate_operand" "")))]
mgl@1371
 14302
+  ""
mgl@1371
 14303
+  {
mgl@1371
 14304
+   /* Delete compare instruction as it is merged into this instruction */
mgl@1371
 14305
+   remove_insn (get_last_insn_anywhere ());
mgl@1371
 14306
+
mgl@1371
 14307
+   operands[4] = avr32_compare_op0;
mgl@1371
 14308
+   operands[5] = avr32_compare_op1;
mgl@1371
 14309
+  }
mgl@1371
 14310
+  )
mgl@1371
 14311
+
mgl@1371
 14312
+
mgl@1371
 14313
+(define_insn "mov<MOVCC:mode>cc_cmp<CMP:mode>"
mgl@1371
 14314
+  [(set (match_operand:MOVCC 0 "register_operand" "=r,r,r")
mgl@1371
 14315
+        (if_then_else:MOVCC (match_operator 1 "avr32_comparison_operator" 
mgl@1371
 14316
+                                            [(match_operand:CMP 4 "register_operand" "r,r,r")
mgl@1371
 14317
+                                             (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>,<CMP:cmp_constraint>,<CMP:cmp_constraint>")])
mgl@1371
 14318
+                            (match_operand:MOVCC 2 "avr32_cond_register_immediate_operand" "0, rKs08,rKs08")
mgl@1371
 14319
+                            (match_operand:MOVCC 3 "avr32_cond_register_immediate_operand" "rKs08,0,rKs08")))]
mgl@1371
 14320
+  ""
mgl@1371
 14321
+  {
mgl@1371
 14322
+   operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
mgl@1371
 14323
+           
mgl@1371
 14324
+   switch( which_alternative ){
mgl@1371
 14325
+    case 0:
mgl@1371
 14326
+      return "mov%i1    %0, %3";
mgl@1371
 14327
+    case 1:
mgl@1371
 14328
+      return "mov%1    %0, %2";
mgl@1371
 14329
+    case 2:
mgl@1371
 14330
+      return "mov%1    %0, %2\;mov%i1    %0, %3";
mgl@1371
 14331
+    default:
mgl@1371
 14332
+      abort();
mgl@1371
 14333
+    }
mgl@1371
 14334
+
mgl@1371
 14335
+  }
mgl@1371
 14336
+  [(set_attr "length" "8,8,12")
mgl@1371
 14337
+   (set_attr "cc" "cmp_cond_insn")])
mgl@1371
 14338
+
mgl@1371
 14339
+  
mgl@1371
 14340
+
mgl@1371
 14341
+
mgl@1371
 14342
+;;=============================================================================
mgl@1371
 14343
+;; jump
mgl@1371
 14344
+;;-----------------------------------------------------------------------------
mgl@1371
 14345
+;; Jump inside a function; an unconditional branch to a label.
mgl@1371
 14346
+;;=============================================================================
mgl@1371
 14347
+(define_insn "jump"
mgl@1371
 14348
+  [(set (pc)
mgl@1371
 14349
+	(label_ref (match_operand 0 "" "")))]
mgl@1371
 14350
+  ""
mgl@1371
 14351
+  {
mgl@1371
 14352
+    if (get_attr_length(insn) > 4)
mgl@1371
 14353
+      return "Can't jump this far";
mgl@1371
 14354
+    return (get_attr_length(insn) == 2 ?
mgl@1371
 14355
+	    "rjmp    %0" : "bral    %0");
mgl@1371
 14356
+  }
mgl@1371
 14357
+  [(set_attr "type" "branch")
mgl@1371
 14358
+   (set (attr "length")
mgl@1371
 14359
+	(cond [(and (le (minus (match_dup 0) (pc)) (const_int 1022))
mgl@1371
 14360
+		    (le (minus (pc) (match_dup 0)) (const_int 1024)))
mgl@1371
 14361
+	       (const_int 2) ; use rjmp
mgl@1371
 14362
+	       (le (match_dup 0) (const_int 1048575))
mgl@1371
 14363
+	       (const_int 4)] ; use bral
mgl@1371
 14364
+	      (const_int 8))) ; do something else
mgl@1371
 14365
+   (set_attr "cc" "none")])
mgl@1371
 14366
+
mgl@1371
 14367
+;;=============================================================================
mgl@1371
 14368
+;; call
mgl@1371
 14369
+;;-----------------------------------------------------------------------------
mgl@1371
 14370
+;; Subroutine call instruction returning no value.
mgl@1371
 14371
+;;=============================================================================
mgl@1371
 14372
+(define_insn "call_internal"
mgl@1371
 14373
+  [(parallel [(call (mem:SI (match_operand:SI 0 "avr32_call_operand" "r,U,T,W"))
mgl@1371
 14374
+                    (match_operand 1 "" ""))
mgl@1371
 14375
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 14376
+  ""
mgl@1371
 14377
+  {
mgl@1371
 14378
+   switch (which_alternative){
mgl@1371
 14379
+    case 0:
mgl@1371
 14380
+      return "icall\t%0";
mgl@1371
 14381
+    case 1:
mgl@1371
 14382
+      return "rcall\t%0";
mgl@1371
 14383
+    case 2:
mgl@1371
 14384
+      return "mcall\t%0";
mgl@1371
 14385
+    case 3:
mgl@1371
 14386
+      if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
mgl@1371
 14387
+        return "call\t%0";
mgl@1371
 14388
+      else
mgl@1371
 14389
+        return "mcall\tr6[%0@got]";
mgl@1371
 14390
+    default:
mgl@1371
 14391
+      abort();
mgl@1371
 14392
+   }
mgl@1371
 14393
+  }
mgl@1371
 14394
+  [(set_attr "type" "call")
mgl@1371
 14395
+   (set_attr "length" "2,4,4,10")
mgl@1371
 14396
+   (set_attr "cc" "clobber")])
mgl@1371
 14397
+
mgl@1371
 14398
+
mgl@1371
 14399
+(define_expand "call"
mgl@1371
 14400
+  [(parallel [(call (match_operand:SI 0 "" "")
mgl@1371
 14401
+                    (match_operand 1 "" ""))
mgl@1371
 14402
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 14403
+  ""
mgl@1371
 14404
+  {
mgl@1371
 14405
+   rtx call_address;
mgl@1371
 14406
+   if ( GET_CODE(operands[0]) != MEM )
mgl@1371
 14407
+      FAIL;
mgl@1371
 14408
+
mgl@1371
 14409
+   call_address = XEXP(operands[0], 0);
mgl@1371
 14410
+
mgl@1371
 14411
+   /* If assembler supports call pseudo insn and the call
mgl@1371
 14412
+      address is a symbol then nothing special needs to be done. */
mgl@1371
 14413
+   if ( TARGET_HAS_ASM_ADDR_PSEUDOS
mgl@1371
 14414
+        && (GET_CODE(call_address) == SYMBOL_REF) ){
mgl@1371
 14415
+      /* We must however mark the function as using the GOT if
mgl@1371
 14416
+         flag_pic is set, since the call insn might turn into
mgl@1371
 14417
+         a mcall using the GOT ptr register. */
mgl@1371
 14418
+      if ( flag_pic ){
mgl@1371
 14419
+         current_function_uses_pic_offset_table = 1;
mgl@1371
 14420
+         emit_call_insn(gen_call_internal(call_address, operands[1]));
mgl@1371
 14421
+         DONE;
mgl@1371
 14422
+      }
mgl@1371
 14423
+   } else {
mgl@1371
 14424
+     if ( flag_pic &&
mgl@1371
 14425
+          GET_CODE(call_address) == SYMBOL_REF ){
mgl@1371
 14426
+       current_function_uses_pic_offset_table = 1;
mgl@1371
 14427
+       emit_call_insn(gen_call_internal(call_address, operands[1]));
mgl@1371
 14428
+       DONE;
mgl@1371
 14429
+     }
mgl@1371
 14430
+
mgl@1371
 14431
+     if ( !SYMBOL_REF_RCALL_FUNCTION_P(operands[0]) ){
mgl@1371
 14432
+       if ( optimize_size &&
mgl@1371
 14433
+             GET_CODE(call_address) == SYMBOL_REF ){
mgl@1371
 14434
+         call_address = force_const_mem(SImode, call_address);
mgl@1371
 14435
+       } else {
mgl@1371
 14436
+         call_address = force_reg(SImode, call_address);
mgl@1371
 14437
+       }
mgl@1371
 14438
+     }
mgl@1371
 14439
+   }
mgl@1371
 14440
+   emit_call_insn(gen_call_internal(call_address, operands[1]));
mgl@1371
 14441
+   DONE;
mgl@1371
 14442
+  }
mgl@1371
 14443
+)
mgl@1371
 14444
+
mgl@1371
 14445
+;;=============================================================================
mgl@1371
 14446
+;; call_value
mgl@1371
 14447
+;;-----------------------------------------------------------------------------
mgl@1371
 14448
+;; Subrutine call instruction returning a value.
mgl@1371
 14449
+;;=============================================================================
mgl@1371
 14450
+(define_expand "call_value"
mgl@1371
 14451
+   [(parallel [(set (match_operand:SI 0 "" "")
mgl@1371
 14452
+                    (call (match_operand:SI 1 "" "")
mgl@1371
 14453
+                          (match_operand 2 "" "")))
mgl@1371
 14454
+               (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 14455
+   ""
mgl@1371
 14456
+   {
mgl@1371
 14457
+    rtx call_address;
mgl@1371
 14458
+    if ( GET_CODE(operands[1]) != MEM )
mgl@1371
 14459
+      FAIL;
mgl@1371
 14460
+
mgl@1371
 14461
+    call_address = XEXP(operands[1], 0);
mgl@1371
 14462
+
mgl@1371
 14463
+    /* If assembler supports call pseudo insn and the call
mgl@1371
 14464
+       address is a symbol then nothing special needs to be done. */
mgl@1371
 14465
+    if ( TARGET_HAS_ASM_ADDR_PSEUDOS
mgl@1371
 14466
+         && (GET_CODE(call_address) == SYMBOL_REF) ){
mgl@1371
 14467
+       /* We must however mark the function as using the GOT if
mgl@1371
 14468
+          flag_pic is set, since the call insn might turn into
mgl@1371
 14469
+          a mcall using the GOT ptr register. */
mgl@1371
 14470
+       if ( flag_pic ) {
mgl@1371
 14471
+          current_function_uses_pic_offset_table = 1;
mgl@1371
 14472
+          emit_call_insn(gen_call_value_internal(operands[0], call_address, operands[2]));
mgl@1371
 14473
+          DONE;
mgl@1371
 14474
+       }
mgl@1371
 14475
+    } else {
mgl@1371
 14476
+      if ( flag_pic &&
mgl@1371
 14477
+           GET_CODE(call_address) == SYMBOL_REF ){
mgl@1371
 14478
+        current_function_uses_pic_offset_table = 1;
mgl@1371
 14479
+        emit_call_insn(gen_call_value_internal(operands[0], call_address, operands[2]));
mgl@1371
 14480
+        DONE;
mgl@1371
 14481
+      }
mgl@1371
 14482
+
mgl@1371
 14483
+      if ( !SYMBOL_REF_RCALL_FUNCTION_P(operands[1]) ){
mgl@1371
 14484
+        if ( optimize_size &&
mgl@1371
 14485
+             GET_CODE(call_address) == SYMBOL_REF){
mgl@1371
 14486
+          call_address = force_const_mem(SImode, call_address);
mgl@1371
 14487
+        } else {
mgl@1371
 14488
+          call_address = force_reg(SImode, call_address);
mgl@1371
 14489
+        }
mgl@1371
 14490
+      }
mgl@1371
 14491
+    }
mgl@1371
 14492
+    emit_call_insn(gen_call_value_internal(operands[0], call_address,
mgl@1371
 14493
+                                           operands[2]));
mgl@1371
 14494
+    DONE;
mgl@1371
 14495
+
mgl@1371
 14496
+   })
mgl@1371
 14497
+
mgl@1371
 14498
+(define_insn "call_value_internal"
mgl@1371
 14499
+  [(parallel [(set (match_operand 0 "register_operand" "=r,r,r,r")
mgl@1371
 14500
+                   (call (mem:SI (match_operand:SI 1 "avr32_call_operand" "r,U,T,W"))
mgl@1371
 14501
+                         (match_operand 2 "" "")))
mgl@1371
 14502
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 14503
+  ;; Operand 2 not used on the AVR32.
mgl@1371
 14504
+  ""
mgl@1371
 14505
+  {
mgl@1371
 14506
+   switch (which_alternative){
mgl@1371
 14507
+    case 0:
mgl@1371
 14508
+      return "icall\t%1";
mgl@1371
 14509
+    case 1:
mgl@1371
 14510
+      return "rcall\t%1";
mgl@1371
 14511
+    case 2:
mgl@1371
 14512
+      return "mcall\t%1";
mgl@1371
 14513
+    case 3:
mgl@1371
 14514
+      if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
mgl@1371
 14515
+        return "call\t%1";
mgl@1371
 14516
+      else
mgl@1371
 14517
+        return "mcall\tr6[%1@got]";
mgl@1371
 14518
+    default:
mgl@1371
 14519
+      abort();
mgl@1371
 14520
+   }
mgl@1371
 14521
+  }
mgl@1371
 14522
+  [(set_attr "type" "call")
mgl@1371
 14523
+   (set_attr "length" "2,4,4,10")
mgl@1371
 14524
+   (set_attr "cc" "call_set")])
mgl@1371
 14525
+
mgl@1371
 14526
+
mgl@1371
 14527
+;;=============================================================================
mgl@1371
 14528
+;; untyped_call
mgl@1371
 14529
+;;-----------------------------------------------------------------------------
mgl@1371
 14530
+;; Subrutine call instruction returning a value of any type.
mgl@1371
 14531
+;; The code is copied from m68k.md (except gen_blockage is removed)
mgl@1371
 14532
+;; Fixme!
mgl@1371
 14533
+;;=============================================================================
mgl@1371
 14534
+(define_expand "untyped_call"
mgl@1371
 14535
+  [(parallel [(call (match_operand 0 "avr32_call_operand" "")
mgl@1371
 14536
+		    (const_int 0))
mgl@1371
 14537
+	      (match_operand 1 "" "")
mgl@1371
 14538
+	      (match_operand 2 "" "")])]
mgl@1371
 14539
+  ""
mgl@1371
 14540
+  {
mgl@1371
 14541
+    int i;
mgl@1371
 14542
+
mgl@1371
 14543
+    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
mgl@1371
 14544
+
mgl@1371
 14545
+    for (i = 0; i < XVECLEN (operands[2], 0); i++) {
mgl@1371
 14546
+      rtx set = XVECEXP (operands[2], 0, i);
mgl@1371
 14547
+      emit_move_insn (SET_DEST (set), SET_SRC (set));
mgl@1371
 14548
+    }
mgl@1371
 14549
+
mgl@1371
 14550
+    /* The optimizer does not know that the call sets the function value
mgl@1371
 14551
+       registers we stored in the result block.  We avoid problems by
mgl@1371
 14552
+       claiming that all hard registers are used and clobbered at this
mgl@1371
 14553
+       point.  */
mgl@1371
 14554
+    emit_insn (gen_blockage ());
mgl@1371
 14555
+
mgl@1371
 14556
+    DONE;
mgl@1371
 14557
+  })
mgl@1371
 14558
+
mgl@1371
 14559
+
mgl@1371
 14560
+;;=============================================================================
mgl@1371
 14561
+;; return
mgl@1371
 14562
+;;=============================================================================
mgl@1371
 14563
+
mgl@1371
 14564
+(define_insn "return"
mgl@1371
 14565
+  [(return)]
mgl@1371
 14566
+  "USE_RETURN_INSN (FALSE)"
mgl@1371
 14567
+  {
mgl@1371
 14568
+   avr32_output_return_instruction(TRUE, FALSE, NULL, NULL);
mgl@1371
 14569
+   return "";
mgl@1371
 14570
+  }
mgl@1371
 14571
+  [(set_attr "length" "4")
mgl@1371
 14572
+   (set_attr "type" "call")]
mgl@1371
 14573
+  )
mgl@1371
 14574
+
mgl@1371
 14575
+
mgl@1371
 14576
+(define_insn "return_cond"
mgl@1371
 14577
+  [(set (pc) 
mgl@1371
 14578
+        (if_then_else (match_operand 0 "avr32_comparison_operand" "")
mgl@1371
 14579
+                      (return)
mgl@1371
 14580
+                      (pc)))]
mgl@1371
 14581
+  "USE_RETURN_INSN (TRUE)"
mgl@1371
 14582
+  "ret%0\tr12";
mgl@1371
 14583
+  [(set_attr "type" "call")])
mgl@1371
 14584
+  
mgl@1371
 14585
+(define_insn "return_cond_predicable"
mgl@1371
 14586
+  [(return)]
mgl@1371
 14587
+  "USE_RETURN_INSN (TRUE)"
mgl@1371
 14588
+  "ret%?\tr12";
mgl@1371
 14589
+  [(set_attr "type" "call")
mgl@1371
 14590
+   (set_attr "predicable" "yes")])
mgl@1371
 14591
+
mgl@1371
 14592
+
mgl@1371
 14593
+(define_insn "return_imm"
mgl@1371
 14594
+  [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
mgl@1371
 14595
+              (use (reg RETVAL_REGNUM))
mgl@1371
 14596
+              (return)])]
mgl@1371
 14597
+  "USE_RETURN_INSN (FALSE) &&
mgl@1371
 14598
+   ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
mgl@1371
 14599
+  {
mgl@1371
 14600
+   avr32_output_return_instruction(TRUE, FALSE, NULL, operands[0]);
mgl@1371
 14601
+   return "";
mgl@1371
 14602
+  }
mgl@1371
 14603
+  [(set_attr "length" "4")
mgl@1371
 14604
+   (set_attr "type" "call")]
mgl@1371
 14605
+  )
mgl@1371
 14606
+
mgl@1371
 14607
+(define_insn "return_imm_cond"
mgl@1371
 14608
+  [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
mgl@1371
 14609
+              (use (reg RETVAL_REGNUM))
mgl@1371
 14610
+              (set (pc) 
mgl@1371
 14611
+                   (if_then_else (match_operand 1 "avr32_comparison_operand" "")
mgl@1371
 14612
+                                 (return)
mgl@1371
 14613
+                                 (pc)))])]
mgl@1371
 14614
+  "USE_RETURN_INSN (TRUE) &&
mgl@1371
 14615
+   ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
mgl@1371
 14616
+  "ret%1\t%0";
mgl@1371
 14617
+  [(set_attr "type" "call")]
mgl@1371
 14618
+  )
mgl@1371
 14619
+
mgl@1371
 14620
+(define_insn "return_imm_predicable"
mgl@1371
 14621
+  [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
mgl@1371
 14622
+              (use (reg RETVAL_REGNUM))
mgl@1371
 14623
+              (return)])]
mgl@1371
 14624
+  "USE_RETURN_INSN (TRUE) &&
mgl@1371
 14625
+   ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
mgl@1371
 14626
+  "ret%?\t%0";
mgl@1371
 14627
+  [(set_attr "type" "call")
mgl@1371
 14628
+   (set_attr "predicable" "yes")])
mgl@1371
 14629
+
mgl@1371
 14630
+(define_insn "return_<mode>reg"
mgl@1371
 14631
+  [(set (reg RETVAL_REGNUM) (match_operand:MOVM 0 "register_operand" "r"))
mgl@1371
 14632
+   (use (reg RETVAL_REGNUM))
mgl@1371
 14633
+   (return)]
mgl@1371
 14634
+  "USE_RETURN_INSN (TRUE)"
mgl@1371
 14635
+  "ret%?\t%0";
mgl@1371
 14636
+  [(set_attr "type" "call")
mgl@1371
 14637
+   (set_attr "predicable" "yes")])
mgl@1371
 14638
+
mgl@1371
 14639
+(define_insn "return_<mode>reg_cond"
mgl@1371
 14640
+  [(set (reg RETVAL_REGNUM) (match_operand:MOVM 0 "register_operand" "r"))
mgl@1371
 14641
+   (use (reg RETVAL_REGNUM))
mgl@1371
 14642
+   (set (pc) 
mgl@1371
 14643
+        (if_then_else (match_operator 1 "avr32_comparison_operator"
mgl@1371
 14644
+                                      [(cc0) (const_int 0)])
mgl@1371
 14645
+                      (return)
mgl@1371
 14646
+                      (pc)))]
mgl@1371
 14647
+  "USE_RETURN_INSN (TRUE)"
mgl@1371
 14648
+  "ret%1\t%0";
mgl@1371
 14649
+  [(set_attr "type" "call")])
mgl@1371
 14650
+  
mgl@1371
 14651
+;;=============================================================================
mgl@1371
 14652
+;; nop
mgl@1371
 14653
+;;-----------------------------------------------------------------------------
mgl@1371
 14654
+;; No-op instruction.
mgl@1371
 14655
+;;=============================================================================
mgl@1371
 14656
+(define_insn "nop"
mgl@1371
 14657
+  [(const_int 0)]
mgl@1371
 14658
+  ""
mgl@1371
 14659
+  "nop"
mgl@1371
 14660
+  [(set_attr "length" "2")
mgl@1371
 14661
+   (set_attr "type" "alu")
mgl@1371
 14662
+   (set_attr "cc" "none")])
mgl@1371
 14663
+
mgl@1371
 14664
+;;=============================================================================
mgl@1371
 14665
+;; nonlocal_goto_receiver
mgl@1371
 14666
+;;-----------------------------------------------------------------------------
mgl@1371
 14667
+;; For targets with a return stack we must make sure to flush the return stack
mgl@1371
 14668
+;; since it will be corrupt after a nonlocal goto.
mgl@1371
 14669
+;;=============================================================================
mgl@1371
 14670
+(define_expand "nonlocal_goto_receiver"
mgl@1371
 14671
+  [(const_int 0)]
mgl@1371
 14672
+  "TARGET_RETURN_STACK"
mgl@1371
 14673
+  "
mgl@1371
 14674
+   {
mgl@1371
 14675
+    emit_insn ( gen_frs() );
mgl@1371
 14676
+    DONE;
mgl@1371
 14677
+   }
mgl@1371
 14678
+  "
mgl@1371
 14679
+  )
mgl@1371
 14680
+
mgl@1371
 14681
+
mgl@1371
 14682
+;;=============================================================================
mgl@1371
 14683
+;; builtin_setjmp_receiver
mgl@1371
 14684
+;;-----------------------------------------------------------------------------
mgl@1371
 14685
+;; For pic code we need to reload the pic register.
mgl@1371
 14686
+;; For targets with a return stack we must make sure to flush the return stack
mgl@1371
 14687
+;; since it will probably be corrupted.
mgl@1371
 14688
+;;=============================================================================
mgl@1371
 14689
+(define_expand "builtin_setjmp_receiver"
mgl@1371
 14690
+  [(label_ref (match_operand 0 "" ""))]
mgl@1371
 14691
+  "flag_pic"
mgl@1371
 14692
+  "
mgl@1371
 14693
+   {
mgl@1371
 14694
+    if ( TARGET_RETURN_STACK ) 
mgl@1371
 14695
+     emit_insn ( gen_frs() );
mgl@1371
 14696
+
mgl@1371
 14697
+    avr32_load_pic_register ();
mgl@1371
 14698
+    DONE;
mgl@1371
 14699
+   }
mgl@1371
 14700
+  "
mgl@1371
 14701
+)
mgl@1371
 14702
+
mgl@1371
 14703
+
mgl@1371
 14704
+;;=============================================================================
mgl@1371
 14705
+;; indirect_jump
mgl@1371
 14706
+;;-----------------------------------------------------------------------------
mgl@1371
 14707
+;; Jump to an address in reg or memory.
mgl@1371
 14708
+;;=============================================================================
mgl@1371
 14709
+(define_expand "indirect_jump"
mgl@1371
 14710
+  [(set (pc)
mgl@1371
 14711
+	(match_operand:SI 0 "general_operand" ""))]
mgl@1371
 14712
+  ""
mgl@1371
 14713
+  {
mgl@1371
 14714
+    /* One of the ops has to be in a register.  */
mgl@1371
 14715
+    if ( (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS )
mgl@1371
 14716
+         && !avr32_legitimate_pic_operand_p(operands[0]) )
mgl@1371
 14717
+      operands[0] = legitimize_pic_address (operands[0], SImode, 0);
mgl@1371
 14718
+    else if ( flag_pic && avr32_address_operand(operands[0], GET_MODE(operands[0])) )
mgl@1371
 14719
+      /* If we have an address operand then this function uses the pic register. */
mgl@1371
 14720
+      current_function_uses_pic_offset_table = 1;
mgl@1371
 14721
+  })
mgl@1371
 14722
+
mgl@1371
 14723
+
mgl@1371
 14724
+(define_insn "indirect_jump_internal"
mgl@1371
 14725
+  [(set (pc)
mgl@1371
 14726
+	(match_operand:SI 0 "avr32_non_rmw_general_operand" "r,m,W"))]
mgl@1371
 14727
+  ""
mgl@1371
 14728
+  {
mgl@1371
 14729
+    switch( which_alternative ){
mgl@1371
 14730
+      case 0:
mgl@1371
 14731
+        return "mov\tpc, %0";
mgl@1371
 14732
+      case 1:
mgl@1371
 14733
+        if ( avr32_const_pool_ref_operand(operands[0], GET_MODE(operands[0])) )
mgl@1371
 14734
+          return "lddpc\tpc, %0";
mgl@1371
 14735
+        else
mgl@1371
 14736
+          return "ld.w\tpc, %0";
mgl@1371
 14737
+      case 2:
mgl@1371
 14738
+        if ( flag_pic )
mgl@1371
 14739
+          return "ld.w\tpc, r6[%0@got]";
mgl@1371
 14740
+        else
mgl@1371
 14741
+          return "lda.w\tpc, %0";
mgl@1371
 14742
+      default:
mgl@1371
 14743
+	abort();
mgl@1371
 14744
+    }
mgl@1371
 14745
+   }
mgl@1371
 14746
+  [(set_attr "length" "2,4,8")
mgl@1371
 14747
+   (set_attr "type" "call,call,call")
mgl@1371
 14748
+   (set_attr "cc" "none,none,clobber")])
mgl@1371
 14749
+
mgl@1371
 14750
+
mgl@1371
 14751
+
mgl@1371
 14752
+;;=============================================================================
mgl@1371
 14753
+;; casesi and tablejump
mgl@1371
 14754
+;;=============================================================================
mgl@1371
 14755
+(define_insn "tablejump_add"
mgl@1371
 14756
+  [(set (pc)
mgl@1371
 14757
+	(plus:SI (match_operand:SI 0 "register_operand" "r")
mgl@1371
 14758
+                 (mult:SI (match_operand:SI 1 "register_operand" "r")
mgl@1371
 14759
+                          (match_operand:SI 2 "immediate_operand" "Ku04" ))))
mgl@1371
 14760
+   (use (label_ref (match_operand 3 "" "")))]
mgl@1371
 14761
+  "flag_pic &&
mgl@1371
 14762
+   ((INTVAL(operands[2]) == 0) || (INTVAL(operands[2]) == 2) ||
mgl@1371
 14763
+    (INTVAL(operands[2]) == 4) || (INTVAL(operands[2]) == 8))"
mgl@1371
 14764
+  "add\tpc, %0, %1 << %p2"
mgl@1371
 14765
+  [(set_attr "length" "4")
mgl@1371
 14766
+   (set_attr "cc" "clobber")])
mgl@1371
 14767
+
mgl@1371
 14768
+(define_insn "tablejump_insn"
mgl@1371
 14769
+  [(set (pc) (match_operand:SI 0 "memory_operand" "m"))
mgl@1371
 14770
+   (use (label_ref (match_operand 1 "" "")))]
mgl@1371
 14771
+  "!flag_pic"
mgl@1371
 14772
+  "ld.w\tpc, %0"
mgl@1371
 14773
+  [(set_attr "length" "4")
mgl@1371
 14774
+   (set_attr "type" "call")
mgl@1371
 14775
+   (set_attr "cc" "none")])
mgl@1371
 14776
+
mgl@1371
 14777
+(define_expand "casesi"
mgl@1371
 14778
+  [(match_operand:SI 0 "register_operand" "")	; index to jump on
mgl@1371
 14779
+   (match_operand:SI 1 "const_int_operand" "")	; lower bound
mgl@1371
 14780
+   (match_operand:SI 2 "const_int_operand" "")	; total range
mgl@1371
 14781
+   (match_operand:SI 3 "" "")			; table label
mgl@1371
 14782
+   (match_operand:SI 4 "" "")]			; Out of range label
mgl@1371
 14783
+  ""
mgl@1371
 14784
+  "
mgl@1371
 14785
+  {
mgl@1371
 14786
+    rtx reg;
mgl@1371
 14787
+    rtx index = operands[0];
mgl@1371
 14788
+    rtx low_bound = operands[1];
mgl@1371
 14789
+    rtx range = operands[2];
mgl@1371
 14790
+    rtx table_label = operands[3];
mgl@1371
 14791
+    rtx oor_label = operands[4];
mgl@1371
 14792
+
mgl@1371
 14793
+    index = force_reg ( SImode, index );
mgl@1371
 14794
+    if (low_bound != const0_rtx)
mgl@1371
 14795
+      {
mgl@1371
 14796
+        if (!avr32_const_ok_for_constraint_p(INTVAL (low_bound), 'I', \"Is21\")){
mgl@1371
 14797
+          reg = force_reg(SImode, GEN_INT (INTVAL (low_bound)));
mgl@1371
 14798
+	  emit_insn (gen_subsi3 (reg, index,
mgl@1371
 14799
+			         reg));
mgl@1371
 14800
+        } else {
mgl@1371
 14801
+          reg = gen_reg_rtx (SImode);
mgl@1371
 14802
+          emit_insn (gen_addsi3 (reg, index,
mgl@1371
 14803
+		         	 GEN_INT (-INTVAL (low_bound))));
mgl@1371
 14804
+        }
mgl@1371
 14805
+	index = reg;
mgl@1371
 14806
+      }
mgl@1371
 14807
+
mgl@1371
 14808
+    if (!avr32_const_ok_for_constraint_p (INTVAL (range), 'K', \"Ks21\"))
mgl@1371
 14809
+      range = force_reg (SImode, range);
mgl@1371
 14810
+
mgl@1371
 14811
+    emit_cmp_and_jump_insns ( index, range, GTU, NULL_RTX, SImode, 1, oor_label );
mgl@1371
 14812
+    reg = gen_reg_rtx (SImode);
mgl@1371
 14813
+    emit_move_insn ( reg, gen_rtx_LABEL_REF (VOIDmode, table_label));
mgl@1371
 14814
+
mgl@1371
 14815
+    if ( flag_pic ) 
mgl@1371
 14816
+       emit_jump_insn ( gen_tablejump_add ( reg, index, GEN_INT(4), table_label));
mgl@1371
 14817
+    else
mgl@1371
 14818
+       emit_jump_insn ( 
mgl@1371
 14819
+           gen_tablejump_insn ( gen_rtx_MEM ( SImode, 
mgl@1371
 14820
+                                              gen_rtx_PLUS ( SImode, 
mgl@1371
 14821
+                                                             reg, 
mgl@1371
 14822
+                                                             gen_rtx_MULT ( SImode, 
mgl@1371
 14823
+                                                                            index, 
mgl@1371
 14824
+                                                                            GEN_INT(4)))),
mgl@1371
 14825
+                                table_label));
mgl@1371
 14826
+    DONE;
mgl@1371
 14827
+  }"
mgl@1371
 14828
+)
mgl@1371
 14829
+
mgl@1371
 14830
+
mgl@1371
 14831
+
mgl@1371
 14832
+(define_insn "prefetch"
mgl@1371
 14833
+  [(prefetch (match_operand:SI 0 "avr32_ks16_address_operand" "p")
mgl@1371
 14834
+	     (match_operand 1 "const_int_operand" "")
mgl@1371
 14835
+	     (match_operand 2 "const_int_operand" ""))]
mgl@1371
 14836
+  ""
mgl@1371
 14837
+  {
mgl@1371
 14838
+     return "pref\t%0";
mgl@1371
 14839
+  }
mgl@1371
 14840
+
mgl@1371
 14841
+  [(set_attr "length" "4")
mgl@1371
 14842
+   (set_attr "type" "load")
mgl@1371
 14843
+   (set_attr "cc" "none")])
mgl@1371
 14844
+
mgl@1371
 14845
+
mgl@1371
 14846
+
mgl@1371
 14847
+;;=============================================================================
mgl@1371
 14848
+;; prologue
mgl@1371
 14849
+;;-----------------------------------------------------------------------------
mgl@1371
 14850
+;; This pattern, if defined, emits RTL for entry to a function. The function
mgl@1371
 14851
+;; entry i responsible for setting up the stack frame, initializing the frame
mgl@1371
 14852
+;; pointer register, saving callee saved registers, etc.
mgl@1371
 14853
+;;=============================================================================
mgl@1371
 14854
+(define_expand "prologue"
mgl@1371
 14855
+  [(clobber (const_int 0))]
mgl@1371
 14856
+  ""
mgl@1371
 14857
+  "
mgl@1371
 14858
+  avr32_expand_prologue();
mgl@1371
 14859
+  DONE;
mgl@1371
 14860
+  "
mgl@1371
 14861
+  )
mgl@1371
 14862
+
mgl@1371
 14863
+;;=============================================================================
mgl@1371
 14864
+;; eh_return
mgl@1371
 14865
+;;-----------------------------------------------------------------------------
mgl@1371
 14866
+;; This pattern, if defined, affects the way __builtin_eh_return, and
mgl@1371
 14867
+;; thence the call frame exception handling library routines, are
mgl@1371
 14868
+;; built. It is intended to handle non-trivial actions needed along
mgl@1371
 14869
+;; the abnormal return path.
mgl@1371
 14870
+;;
mgl@1371
 14871
+;; The address of the exception handler to which the function should
mgl@1371
 14872
+;; return is passed as operand to this pattern. It will normally need
mgl@1371
 14873
+;; to copied by the pattern to some special register or memory
mgl@1371
 14874
+;; location. If the pattern needs to determine the location of the
mgl@1371
 14875
+;; target call frame in order to do so, it may use
mgl@1371
 14876
+;; EH_RETURN_STACKADJ_RTX, if defined; it will have already been
mgl@1371
 14877
+;; assigned.
mgl@1371
 14878
+;;
mgl@1371
 14879
+;; If this pattern is not defined, the default action will be to
mgl@1371
 14880
+;; simply copy the return address to EH_RETURN_HANDLER_RTX. Either
mgl@1371
 14881
+;; that macro or this pattern needs to be defined if call frame
mgl@1371
 14882
+;; exception handling is to be used.
mgl@1371
 14883
+
mgl@1371
 14884
+;; We can't expand this before we know where the link register is stored.
mgl@1371
 14885
+(define_insn_and_split "eh_return"
mgl@1371
 14886
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
mgl@1371
 14887
+		    VUNSPEC_EH_RETURN)
mgl@1371
 14888
+   (clobber (match_scratch:SI 1 "=&r"))]
mgl@1371
 14889
+  ""
mgl@1371
 14890
+  "#"
mgl@1371
 14891
+  "reload_completed"
mgl@1371
 14892
+  [(const_int 0)]
mgl@1371
 14893
+  "
mgl@1371
 14894
+  {
mgl@1371
 14895
+    avr32_set_return_address (operands[0], operands[1]);
mgl@1371
 14896
+    DONE;
mgl@1371
 14897
+  }"
mgl@1371
 14898
+  )
mgl@1371
 14899
+
mgl@1371
 14900
+
mgl@1371
 14901
+;;=============================================================================
mgl@1371
 14902
+;; ffssi2
mgl@1371
 14903
+;;-----------------------------------------------------------------------------
mgl@1371
 14904
+(define_insn "ffssi2"
mgl@1371
 14905
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14906
+         (ffs:SI (match_operand:SI 1 "register_operand" "r"))) ]
mgl@1371
 14907
+  ""
mgl@1371
 14908
+  "mov    %0, %1
mgl@1371
 14909
+   brev   %0
mgl@1371
 14910
+   clz    %0, %0
mgl@1371
 14911
+   sub    %0, -1
mgl@1371
 14912
+   cp     %0, 33
mgl@1371
 14913
+   moveq  %0, 0"
mgl@1371
 14914
+  [(set_attr "length" "18")
mgl@1371
 14915
+   (set_attr "cc" "clobber")]
mgl@1371
 14916
+  )
mgl@1371
 14917
+
mgl@1371
 14918
+
mgl@1371
 14919
+
mgl@1371
 14920
+;;=============================================================================
mgl@1371
 14921
+;; swap_h
mgl@1371
 14922
+;;-----------------------------------------------------------------------------
mgl@1371
 14923
+(define_insn "*swap_h"
mgl@1371
 14924
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 14925
+         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
mgl@1371
 14926
+                 (lshiftrt:SI (match_dup 0) (const_int 16))))]
mgl@1371
 14927
+  ""
mgl@1371
 14928
+  "swap.h    %0"
mgl@1371
 14929
+  [(set_attr "length" "2")]
mgl@1371
 14930
+  )
mgl@1371
 14931
+
mgl@1371
 14932
+(define_insn_and_split "bswap_16"
mgl@1371
 14933
+  [ (set (match_operand:HI 0 "avr32_bswap_operand" "=r,RKs13,r")
mgl@1371
 14934
+         (ior:HI (and:HI (lshiftrt:HI (match_operand:HI 1 "avr32_bswap_operand" "r,r,RKs13")
mgl@1371
 14935
+                                      (const_int 8))
mgl@1371
 14936
+                         (const_int 255))
mgl@1371
 14937
+                 (ashift:HI (and:HI (match_dup 1)
mgl@1371
 14938
+                                    (const_int 255))
mgl@1371
 14939
+                            (const_int 8))))]
mgl@1371
 14940
+  ""
mgl@1371
 14941
+  {
mgl@1371
 14942
+   switch ( which_alternative ){
mgl@1371
 14943
+     case 0:
mgl@1371
 14944
+       if ( REGNO(operands[0]) == REGNO(operands[1]))
mgl@1371
 14945
+         return "swap.bh\t%0";
mgl@1371
 14946
+       else
mgl@1371
 14947
+         return "mov\t%0, %1\;swap.bh\t%0";
mgl@1371
 14948
+     case 1:
mgl@1371
 14949
+       return "stswp.h\t%0, %1";
mgl@1371
 14950
+     case 2:
mgl@1371
 14951
+       return "ldswp.sh\t%0, %1";
mgl@1371
 14952
+     default:
mgl@1371
 14953
+       abort();
mgl@1371
 14954
+     }
mgl@1371
 14955
+  }
mgl@1371
 14956
+
mgl@1371
 14957
+  "(reload_completed &&
mgl@1371
 14958
+     REG_P(operands[0]) && REG_P(operands[1])
mgl@1371
 14959
+     && (REGNO(operands[0]) != REGNO(operands[1])))"
mgl@1371
 14960
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 14961
+   (set (match_dup 0)
mgl@1371
 14962
+        (ior:HI (and:HI (lshiftrt:HI (match_dup 0)
mgl@1371
 14963
+                                     (const_int 8))
mgl@1371
 14964
+                        (const_int 255))
mgl@1371
 14965
+                (ashift:HI (and:HI (match_dup 0)
mgl@1371
 14966
+                                   (const_int 255))
mgl@1371
 14967
+                           (const_int 8))))]
mgl@1371
 14968
+  ""
mgl@1371
 14969
+
mgl@1371
 14970
+  [(set_attr "length" "4,4,4")
mgl@1371
 14971
+   (set_attr "type" "alu,store,load_rm")]
mgl@1371
 14972
+  )
mgl@1371
 14973
+
mgl@1371
 14974
+(define_insn_and_split "bswap_32"
mgl@1371
 14975
+  [ (set (match_operand:SI 0 "avr32_bswap_operand" "=r,RKs14,r")
mgl@1371
 14976
+         (ior:SI (ior:SI (lshiftrt:SI (and:SI (match_operand:SI 1 "avr32_bswap_operand" "r,r,RKs14")
mgl@1371
 14977
+                                              (const_int -16777216))
mgl@1371
 14978
+                                      (const_int 24))
mgl@1371
 14979
+                         (lshiftrt:SI (and:SI (match_dup 1)
mgl@1371
 14980
+                                              (const_int 16711680))
mgl@1371
 14981
+                                      (const_int 8)))
mgl@1371
 14982
+                 (ior:SI (ashift:SI (and:SI (match_dup 1)
mgl@1371
 14983
+                                            (const_int 65280))
mgl@1371
 14984
+                                    (const_int 8))
mgl@1371
 14985
+                         (ashift:SI (and:SI (match_dup 1)
mgl@1371
 14986
+                                            (const_int 255))
mgl@1371
 14987
+                                    (const_int 24)))))]
mgl@1371
 14988
+  ""
mgl@1371
 14989
+  {
mgl@1371
 14990
+    switch ( which_alternative ){
mgl@1371
 14991
+     case 0:
mgl@1371
 14992
+       if ( REGNO(operands[0]) == REGNO(operands[1]))
mgl@1371
 14993
+         return "swap.b\t%0";
mgl@1371
 14994
+       else
mgl@1371
 14995
+         return "#";
mgl@1371
 14996
+     case 1:
mgl@1371
 14997
+       return "stswp.w\t%0, %1";
mgl@1371
 14998
+     case 2:
mgl@1371
 14999
+       return "ldswp.w\t%0, %1";
mgl@1371
 15000
+     default:
mgl@1371
 15001
+       abort();
mgl@1371
 15002
+    }
mgl@1371
 15003
+  }
mgl@1371
 15004
+  "(reload_completed &&
mgl@1371
 15005
+    REG_P(operands[0]) && REG_P(operands[1])
mgl@1371
 15006
+    && (REGNO(operands[0]) != REGNO(operands[1])))"
mgl@1371
 15007
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 15008
+   (set (match_dup 0)
mgl@1371
 15009
+        (ior:SI (ior:SI (lshiftrt:SI (and:SI (match_dup 0)
mgl@1371
 15010
+                                             (const_int -16777216))
mgl@1371
 15011
+                                     (const_int 24))
mgl@1371
 15012
+                        (lshiftrt:SI (and:SI (match_dup 0)
mgl@1371
 15013
+                                             (const_int 16711680))
mgl@1371
 15014
+                                     (const_int 8)))
mgl@1371
 15015
+                (ior:SI (ashift:SI (and:SI (match_dup 0)
mgl@1371
 15016
+                                           (const_int 65280))
mgl@1371
 15017
+                                   (const_int 8))
mgl@1371
 15018
+                        (ashift:SI (and:SI (match_dup 0)
mgl@1371
 15019
+                                           (const_int 255))
mgl@1371
 15020
+                                   (const_int 24)))))]
mgl@1371
 15021
+  ""
mgl@1371
 15022
+
mgl@1371
 15023
+  [(set_attr "length" "4,4,4")
mgl@1371
 15024
+   (set_attr "type" "alu,store,load_rm")]
mgl@1371
 15025
+  )
mgl@1371
 15026
+
mgl@1371
 15027
+
mgl@1371
 15028
+;;=============================================================================
mgl@1371
 15029
+;; blockage
mgl@1371
 15030
+;;-----------------------------------------------------------------------------
mgl@1371
 15031
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
mgl@1371
 15032
+;; all of memory.  This blocks insns from being moved across this point.
mgl@1371
 15033
+
mgl@1371
 15034
+(define_insn "blockage"
mgl@1371
 15035
+  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
mgl@1371
 15036
+  ""
mgl@1371
 15037
+  ""
mgl@1371
 15038
+  [(set_attr "length" "0")]
mgl@1371
 15039
+)
mgl@1371
 15040
+
mgl@1371
 15041
+;;=============================================================================
mgl@1371
 15042
+;; clzsi2
mgl@1371
 15043
+;;-----------------------------------------------------------------------------
mgl@1371
 15044
+(define_insn "clzsi2"
mgl@1371
 15045
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15046
+         (clz:SI (match_operand:SI 1 "register_operand" "r"))) ]
mgl@1371
 15047
+  ""
mgl@1371
 15048
+  "clz    %0, %1"
mgl@1371
 15049
+  [(set_attr "length" "4")
mgl@1371
 15050
+   (set_attr "cc" "set_z")]
mgl@1371
 15051
+  )
mgl@1371
 15052
+
mgl@1371
 15053
+;;=============================================================================
mgl@1371
 15054
+;; ctzsi2
mgl@1371
 15055
+;;-----------------------------------------------------------------------------
mgl@1371
 15056
+(define_insn "ctzsi2"
mgl@1371
 15057
+  [ (set (match_operand:SI 0 "register_operand" "=r,r")
mgl@1371
 15058
+         (ctz:SI (match_operand:SI 1 "register_operand" "0,r"))) ]
mgl@1371
 15059
+  ""
mgl@1371
 15060
+  "@
mgl@1371
 15061
+   brev\t%0\;clz\t%0, %0
mgl@1371
 15062
+   mov\t%0, %1\;brev\t%0\;clz\t%0, %0"
mgl@1371
 15063
+  [(set_attr "length" "8")
mgl@1371
 15064
+   (set_attr "cc" "set_z")]
mgl@1371
 15065
+  )
mgl@1371
 15066
+
mgl@1371
 15067
+;;=============================================================================
mgl@1371
 15068
+;; cache instructions
mgl@1371
 15069
+;;-----------------------------------------------------------------------------
mgl@1371
 15070
+(define_insn "cache"
mgl@1371
 15071
+  [ (unspec_volatile [(match_operand:SI 0 "avr32_ks11_address_operand" "p")
mgl@1371
 15072
+                      (match_operand:SI 1 "immediate_operand" "Ku05")] VUNSPEC_CACHE)]
mgl@1371
 15073
+  ""
mgl@1371
 15074
+  "cache    %0, %1"
mgl@1371
 15075
+  [(set_attr "length" "4")]
mgl@1371
 15076
+  )
mgl@1371
 15077
+
mgl@1371
 15078
+(define_insn "sync"
mgl@1371
 15079
+  [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku08")] VUNSPEC_SYNC)]
mgl@1371
 15080
+  ""
mgl@1371
 15081
+  "sync    %0"
mgl@1371
 15082
+  [(set_attr "length" "4")]
mgl@1371
 15083
+  )
mgl@1371
 15084
+
mgl@1371
 15085
+;;=============================================================================
mgl@1371
 15086
+;; TLB instructions
mgl@1371
 15087
+;;-----------------------------------------------------------------------------
mgl@1371
 15088
+(define_insn "tlbr"
mgl@1371
 15089
+  [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBR)]
mgl@1371
 15090
+  ""
mgl@1371
 15091
+  "tlbr"
mgl@1371
 15092
+  [(set_attr "length" "2")]
mgl@1371
 15093
+  )
mgl@1371
 15094
+
mgl@1371
 15095
+(define_insn "tlbw"
mgl@1371
 15096
+  [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBW)]
mgl@1371
 15097
+  ""
mgl@1371
 15098
+  "tlbw"
mgl@1371
 15099
+  [(set_attr "length" "2")]
mgl@1371
 15100
+  )
mgl@1371
 15101
+
mgl@1371
 15102
+(define_insn "tlbs"
mgl@1371
 15103
+  [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBS)]
mgl@1371
 15104
+  ""
mgl@1371
 15105
+  "tlbs"
mgl@1371
 15106
+  [(set_attr "length" "2")]
mgl@1371
 15107
+  )
mgl@1371
 15108
+
mgl@1371
 15109
+;;=============================================================================
mgl@1371
 15110
+;; Breakpoint instruction
mgl@1371
 15111
+;;-----------------------------------------------------------------------------
mgl@1371
 15112
+(define_insn "breakpoint"
mgl@1371
 15113
+  [ (unspec_volatile [(const_int 0)] VUNSPEC_BREAKPOINT)]
mgl@1371
 15114
+  ""
mgl@1371
 15115
+  "breakpoint"
mgl@1371
 15116
+  [(set_attr "length" "2")]
mgl@1371
 15117
+  )
mgl@1371
 15118
+
mgl@1371
 15119
+
mgl@1371
 15120
+;;=============================================================================
mgl@1371
 15121
+;; mtsr/mfsr instruction
mgl@1371
 15122
+;;-----------------------------------------------------------------------------
mgl@1371
 15123
+(define_insn "mtsr"
mgl@1371
 15124
+  [ (unspec_volatile [(match_operand 0 "immediate_operand" "i")
mgl@1371
 15125
+                      (match_operand:SI 1 "register_operand" "r")] VUNSPEC_MTSR)]
mgl@1371
 15126
+  ""
mgl@1371
 15127
+  "mtsr\t%0, %1"
mgl@1371
 15128
+  [(set_attr "length" "4")]
mgl@1371
 15129
+  )
mgl@1371
 15130
+
mgl@1371
 15131
+(define_insn "mfsr"
mgl@1371
 15132
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15133
+         (unspec_volatile:SI [(match_operand 1 "immediate_operand" "i")] VUNSPEC_MFSR)) ]
mgl@1371
 15134
+  ""
mgl@1371
 15135
+  "mfsr\t%0, %1"
mgl@1371
 15136
+  [(set_attr "length" "4")]
mgl@1371
 15137
+  )
mgl@1371
 15138
+
mgl@1371
 15139
+;;=============================================================================
mgl@1371
 15140
+;; mtdr/mfdr instruction
mgl@1371
 15141
+;;-----------------------------------------------------------------------------
mgl@1371
 15142
+(define_insn "mtdr"
mgl@1371
 15143
+  [ (unspec_volatile [(match_operand 0 "immediate_operand" "i")
mgl@1371
 15144
+                      (match_operand:SI 1 "register_operand" "r")] VUNSPEC_MTDR)]
mgl@1371
 15145
+  ""
mgl@1371
 15146
+  "mtdr\t%0, %1"
mgl@1371
 15147
+  [(set_attr "length" "4")]
mgl@1371
 15148
+  )
mgl@1371
 15149
+
mgl@1371
 15150
+(define_insn "mfdr"
mgl@1371
 15151
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15152
+         (unspec_volatile:SI [(match_operand 1 "immediate_operand" "i")] VUNSPEC_MFDR)) ]
mgl@1371
 15153
+  ""
mgl@1371
 15154
+  "mfdr\t%0, %1"
mgl@1371
 15155
+  [(set_attr "length" "4")]
mgl@1371
 15156
+  )
mgl@1371
 15157
+
mgl@1371
 15158
+;;=============================================================================
mgl@1371
 15159
+;; musfr
mgl@1371
 15160
+;;-----------------------------------------------------------------------------
mgl@1371
 15161
+(define_insn "musfr"
mgl@1371
 15162
+  [ (unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_MUSFR)]
mgl@1371
 15163
+  ""
mgl@1371
 15164
+  "musfr\t%0"
mgl@1371
 15165
+  [(set_attr "length" "2")
mgl@1371
 15166
+   (set_attr "cc" "clobber")]
mgl@1371
 15167
+  )
mgl@1371
 15168
+
mgl@1371
 15169
+(define_insn "mustr"
mgl@1371
 15170
+  [ (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15171
+         (unspec_volatile:SI [(const_int 0)] VUNSPEC_MUSTR)) ]
mgl@1371
 15172
+  ""
mgl@1371
 15173
+  "mustr\t%0"
mgl@1371
 15174
+  [(set_attr "length" "2")]
mgl@1371
 15175
+  )
mgl@1371
 15176
+
mgl@1371
 15177
+(define_insn "ssrf"
mgl@1371
 15178
+  [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku05")] VUNSPEC_SSRF)]
mgl@1371
 15179
+  ""
mgl@1371
 15180
+  "ssrf    %0"
mgl@1371
 15181
+  [(set_attr "length" "2")
mgl@1371
 15182
+   (set_attr "cc" "clobber")]
mgl@1371
 15183
+  )
mgl@1371
 15184
+
mgl@1371
 15185
+(define_insn "csrf"
mgl@1371
 15186
+  [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku05")] VUNSPEC_CSRF)]
mgl@1371
 15187
+  ""
mgl@1371
 15188
+  "csrf    %0"
mgl@1371
 15189
+  [(set_attr "length" "2")
mgl@1371
 15190
+   (set_attr "cc" "clobber")]
mgl@1371
 15191
+  )
mgl@1371
 15192
+
mgl@1371
 15193
+;;=============================================================================
mgl@1371
 15194
+;; Flush Return Stack instruction
mgl@1371
 15195
+;;-----------------------------------------------------------------------------
mgl@1371
 15196
+(define_insn "frs"
mgl@1371
 15197
+  [ (unspec_volatile [(const_int 0)] VUNSPEC_FRS)]
mgl@1371
 15198
+  ""
mgl@1371
 15199
+  "frs"
mgl@1371
 15200
+  [(set_attr "length" "2")
mgl@1371
 15201
+   (set_attr "cc" "none")]
mgl@1371
 15202
+  )
mgl@1371
 15203
+
mgl@1371
 15204
+
mgl@1371
 15205
+;;=============================================================================
mgl@1371
 15206
+;; Saturation Round Scale instruction
mgl@1371
 15207
+;;-----------------------------------------------------------------------------
mgl@1371
 15208
+(define_insn "sats"
mgl@1371
 15209
+  [ (set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 15210
+         (unspec:SI [(match_dup 0)
mgl@1371
 15211
+                     (match_operand 1 "immediate_operand" "Ku05")
mgl@1371
 15212
+                     (match_operand 2 "immediate_operand" "Ku05")]
mgl@1371
 15213
+                    UNSPEC_SATS)) ]
mgl@1371
 15214
+  "TARGET_DSP"
mgl@1371
 15215
+  "sats\t%0 >> %1, %2"
mgl@1371
 15216
+  [(set_attr "type" "alu_sat")
mgl@1371
 15217
+   (set_attr "length" "4")]
mgl@1371
 15218
+  )
mgl@1371
 15219
+
mgl@1371
 15220
+(define_insn "satu"
mgl@1371
 15221
+  [ (set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 15222
+         (unspec:SI [(match_dup 0)
mgl@1371
 15223
+                     (match_operand 1 "immediate_operand" "Ku05")
mgl@1371
 15224
+                     (match_operand 2 "immediate_operand" "Ku05")]
mgl@1371
 15225
+                    UNSPEC_SATU)) ]
mgl@1371
 15226
+  "TARGET_DSP"
mgl@1371
 15227
+  "satu\t%0 >> %1, %2"
mgl@1371
 15228
+  [(set_attr "type" "alu_sat")
mgl@1371
 15229
+   (set_attr "length" "4")]
mgl@1371
 15230
+  )
mgl@1371
 15231
+
mgl@1371
 15232
+(define_insn "satrnds"
mgl@1371
 15233
+  [ (set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 15234
+         (unspec:SI [(match_dup 0)
mgl@1371
 15235
+                     (match_operand 1 "immediate_operand" "Ku05")
mgl@1371
 15236
+                     (match_operand 2 "immediate_operand" "Ku05")]
mgl@1371
 15237
+                    UNSPEC_SATRNDS)) ]
mgl@1371
 15238
+  "TARGET_DSP"
mgl@1371
 15239
+  "satrnds\t%0 >> %1, %2"
mgl@1371
 15240
+  [(set_attr "type" "alu_sat")
mgl@1371
 15241
+   (set_attr "length" "4")]
mgl@1371
 15242
+  )
mgl@1371
 15243
+
mgl@1371
 15244
+(define_insn "satrndu"
mgl@1371
 15245
+  [ (set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 15246
+         (unspec:SI [(match_dup 0)
mgl@1371
 15247
+                     (match_operand 1 "immediate_operand" "Ku05")
mgl@1371
 15248
+                     (match_operand 2 "immediate_operand" "Ku05")]
mgl@1371
 15249
+                    UNSPEC_SATRNDU)) ]
mgl@1371
 15250
+  "TARGET_DSP"
mgl@1371
 15251
+  "sats\t%0 >> %1, %2"
mgl@1371
 15252
+  [(set_attr "type" "alu_sat")
mgl@1371
 15253
+   (set_attr "length" "4")]
mgl@1371
 15254
+  )
mgl@1371
 15255
+
mgl@1371
 15256
+;; Special patterns for dealing with the constant pool
mgl@1371
 15257
+
mgl@1371
 15258
+(define_insn "align_4"
mgl@1371
 15259
+  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
mgl@1371
 15260
+  ""
mgl@1371
 15261
+  {
mgl@1371
 15262
+   assemble_align (32);
mgl@1371
 15263
+   return "";
mgl@1371
 15264
+  }
mgl@1371
 15265
+  [(set_attr "length" "2")]
mgl@1371
 15266
+)
mgl@1371
 15267
+
mgl@1371
 15268
+(define_insn "consttable_start"
mgl@1371
 15269
+  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_START)]
mgl@1371
 15270
+  ""
mgl@1371
 15271
+  {
mgl@1371
 15272
+   return ".cpool";
mgl@1371
 15273
+  }
mgl@1371
 15274
+  [(set_attr "length" "0")]
mgl@1371
 15275
+  )
mgl@1371
 15276
+
mgl@1371
 15277
+(define_insn "consttable_end"
mgl@1371
 15278
+  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
mgl@1371
 15279
+  ""
mgl@1371
 15280
+  {
mgl@1371
 15281
+   making_const_table = FALSE;
mgl@1371
 15282
+   return "";
mgl@1371
 15283
+  }
mgl@1371
 15284
+  [(set_attr "length" "0")]
mgl@1371
 15285
+)
mgl@1371
 15286
+
mgl@1371
 15287
+
mgl@1371
 15288
+(define_insn "consttable_4"
mgl@1371
 15289
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
mgl@1371
 15290
+  ""
mgl@1371
 15291
+  {
mgl@1371
 15292
+    making_const_table = TRUE;
mgl@1371
 15293
+    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
mgl@1371
 15294
+      {
mgl@1371
 15295
+      case MODE_FLOAT:
mgl@1371
 15296
+      {
mgl@1371
 15297
+        REAL_VALUE_TYPE r;
mgl@1371
 15298
+        char real_string[1024];
mgl@1371
 15299
+        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
mgl@1371
 15300
+        real_to_decimal(real_string, &r, 1024, 0, 1);
mgl@1371
 15301
+        asm_fprintf (asm_out_file, "\t.float\t%s\n", real_string);
mgl@1371
 15302
+        break;
mgl@1371
 15303
+      }
mgl@1371
 15304
+      default:
mgl@1371
 15305
+        assemble_integer (operands[0], 4, 0, 1);
mgl@1371
 15306
+        break;
mgl@1371
 15307
+      }
mgl@1371
 15308
+    return "";
mgl@1371
 15309
+  }
mgl@1371
 15310
+  [(set_attr "length" "4")]
mgl@1371
 15311
+)
mgl@1371
 15312
+
mgl@1371
 15313
+(define_insn "consttable_8"
mgl@1371
 15314
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
mgl@1371
 15315
+  ""
mgl@1371
 15316
+  {
mgl@1371
 15317
+    making_const_table = TRUE;
mgl@1371
 15318
+    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
mgl@1371
 15319
+      {
mgl@1371
 15320
+       case MODE_FLOAT:
mgl@1371
 15321
+        {
mgl@1371
 15322
+         REAL_VALUE_TYPE r; 
mgl@1371
 15323
+         char real_string[1024];
mgl@1371
 15324
+         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
mgl@1371
 15325
+         real_to_decimal(real_string, &r, 1024, 0, 1);
mgl@1371
 15326
+         asm_fprintf (asm_out_file, "\t.double\t%s\n", real_string);
mgl@1371
 15327
+         break;
mgl@1371
 15328
+        }
mgl@1371
 15329
+       default:
mgl@1371
 15330
+         assemble_integer(operands[0], 8, 0, 1);
mgl@1371
 15331
+        break;
mgl@1371
 15332
+     }
mgl@1371
 15333
+    return "";
mgl@1371
 15334
+  }
mgl@1371
 15335
+  [(set_attr "length" "8")]
mgl@1371
 15336
+)
mgl@1371
 15337
+
mgl@1371
 15338
+(define_insn "consttable_16"
mgl@1371
 15339
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
mgl@1371
 15340
+  ""
mgl@1371
 15341
+  {
mgl@1371
 15342
+    making_const_table = TRUE;
mgl@1371
 15343
+    assemble_integer(operands[0], 16, 0, 1);
mgl@1371
 15344
+    return "";
mgl@1371
 15345
+  }
mgl@1371
 15346
+  [(set_attr "length" "16")]
mgl@1371
 15347
+)
mgl@1371
 15348
+
mgl@1371
 15349
+;;=============================================================================
mgl@1371
 15350
+;; coprocessor instructions
mgl@1371
 15351
+;;-----------------------------------------------------------------------------
mgl@1371
 15352
+(define_insn "cop"
mgl@1371
 15353
+  [ (unspec_volatile [(match_operand 0 "immediate_operand" "Ku03")
mgl@1371
 15354
+                      (match_operand 1 "immediate_operand" "Ku04")
mgl@1371
 15355
+                      (match_operand 2 "immediate_operand" "Ku04")
mgl@1371
 15356
+                      (match_operand 3 "immediate_operand" "Ku04")
mgl@1371
 15357
+                      (match_operand 4 "immediate_operand" "Ku07")] VUNSPEC_COP)]
mgl@1371
 15358
+  ""
mgl@1371
 15359
+  "cop\tcp%0, cr%1, cr%2, cr%3, %4"
mgl@1371
 15360
+  [(set_attr "length" "4")]
mgl@1371
 15361
+  )
mgl@1371
 15362
+
mgl@1371
 15363
+(define_insn "mvcrsi"
mgl@1371
 15364
+  [ (set (match_operand:SI 0 "avr32_cop_move_operand" "=r,<,Z")
mgl@1371
 15365
+         (unspec_volatile:SI [(match_operand 1 "immediate_operand" "Ku03,Ku03,Ku03")
mgl@1371
 15366
+                              (match_operand 2 "immediate_operand" "Ku04,Ku04,Ku04")]
mgl@1371
 15367
+                             VUNSPEC_MVCR)) ]
mgl@1371
 15368
+  ""
mgl@1371
 15369
+  "@
mgl@1371
 15370
+   mvcr.w\tcp%1, %0, cr%2
mgl@1371
 15371
+   stcm.w\tcp%1, %0, cr%2
mgl@1371
 15372
+   stc.w\tcp%1, %0, cr%2"
mgl@1371
 15373
+  [(set_attr "length" "4")]
mgl@1371
 15374
+  )
mgl@1371
 15375
+
mgl@1371
 15376
+(define_insn "mvcrdi"
mgl@1371
 15377
+  [ (set (match_operand:DI 0 "avr32_cop_move_operand" "=r,<,Z")
mgl@1371
 15378
+         (unspec_volatile:DI [(match_operand 1 "immediate_operand" "Ku03,Ku03,Ku03")
mgl@1371
 15379
+                              (match_operand 2 "immediate_operand" "Ku04,Ku04,Ku04")]
mgl@1371
 15380
+                             VUNSPEC_MVCR)) ]
mgl@1371
 15381
+  ""
mgl@1371
 15382
+  "@
mgl@1371
 15383
+   mvcr.d\tcp%1, %0, cr%2
mgl@1371
 15384
+   stcm.d\tcp%1, %0, cr%2-cr%i2
mgl@1371
 15385
+   stc.d\tcp%1, %0, cr%2"
mgl@1371
 15386
+  [(set_attr "length" "4")]
mgl@1371
 15387
+  )
mgl@1371
 15388
+
mgl@1371
 15389
+(define_insn "mvrcsi"
mgl@1371
 15390
+  [ (unspec_volatile:SI [(match_operand 0 "immediate_operand" "Ku03,Ku03,Ku03")
mgl@1371
 15391
+                         (match_operand 1 "immediate_operand" "Ku04,Ku04,Ku04")
mgl@1371
 15392
+                         (match_operand:SI 2 "avr32_cop_move_operand" "r,>,Z")]
mgl@1371
 15393
+                        VUNSPEC_MVRC)]
mgl@1371
 15394
+  ""
mgl@1371
 15395
+  {
mgl@1371
 15396
+   switch (which_alternative){
mgl@1371
 15397
+    case 0:
mgl@1371
 15398
+      return "mvrc.w\tcp%0, cr%1, %2";
mgl@1371
 15399
+    case 1:
mgl@1371
 15400
+      return "ldcm.w\tcp%0, %2, cr%1";
mgl@1371
 15401
+    case 2:
mgl@1371
 15402
+      return "ldc.w\tcp%0, cr%1, %2";
mgl@1371
 15403
+    default:
mgl@1371
 15404
+      abort();
mgl@1371
 15405
+   }
mgl@1371
 15406
+  }
mgl@1371
 15407
+  [(set_attr "length" "4")]
mgl@1371
 15408
+  )
mgl@1371
 15409
+
mgl@1371
 15410
+(define_insn "mvrcdi"
mgl@1371
 15411
+  [ (unspec_volatile:DI [(match_operand 0 "immediate_operand" "Ku03,Ku03,Ku03")
mgl@1371
 15412
+                         (match_operand 1 "immediate_operand" "Ku04,Ku04,Ku04")
mgl@1371
 15413
+                         (match_operand:DI 2 "avr32_cop_move_operand" "r,>,Z")]
mgl@1371
 15414
+                        VUNSPEC_MVRC)]
mgl@1371
 15415
+  ""
mgl@1371
 15416
+  {
mgl@1371
 15417
+   switch (which_alternative){
mgl@1371
 15418
+    case 0:
mgl@1371
 15419
+      return "mvrc.d\tcp%0, cr%1, %2";
mgl@1371
 15420
+    case 1:
mgl@1371
 15421
+      return "ldcm.d\tcp%0, %2, cr%1-cr%i1";
mgl@1371
 15422
+    case 2:
mgl@1371
 15423
+      return "ldc.d\tcp%0, cr%1, %2";
mgl@1371
 15424
+    default:
mgl@1371
 15425
+      abort();
mgl@1371
 15426
+   }
mgl@1371
 15427
+  }
mgl@1371
 15428
+  [(set_attr "length" "4")]
mgl@1371
 15429
+  )
mgl@1371
 15430
+
mgl@1371
 15431
+;;=============================================================================
mgl@1371
 15432
+;; epilogue
mgl@1371
 15433
+;;-----------------------------------------------------------------------------
mgl@1371
 15434
+;; This pattern emits RTL for exit from a function. The function exit is
mgl@1371
 15435
+;; responsible for deallocating the stack frame, restoring callee saved
mgl@1371
 15436
+;; registers and emitting the return instruction.
mgl@1371
 15437
+;; ToDo: using TARGET_ASM_FUNCTION_PROLOGUE instead.
mgl@1371
 15438
+;;=============================================================================
mgl@1371
 15439
+(define_expand "epilogue"
mgl@1371
 15440
+  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
mgl@1371
 15441
+  ""
mgl@1371
 15442
+  "
mgl@1371
 15443
+  if (USE_RETURN_INSN (FALSE)){
mgl@1371
 15444
+      emit_jump_insn (gen_return ());
mgl@1371
 15445
+      DONE;
mgl@1371
 15446
+  }
mgl@1371
 15447
+  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
mgl@1371
 15448
+	gen_rtvec (1,
mgl@1371
 15449
+		gen_rtx_RETURN (VOIDmode)),
mgl@1371
 15450
+	VUNSPEC_EPILOGUE));
mgl@1371
 15451
+  DONE;
mgl@1371
 15452
+  "
mgl@1371
 15453
+  )
mgl@1371
 15454
+
mgl@1371
 15455
+(define_insn "*epilogue_insns"
mgl@1371
 15456
+  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
mgl@1371
 15457
+  ""
mgl@1371
 15458
+  {
mgl@1371
 15459
+    avr32_output_return_instruction (FALSE, FALSE, NULL, NULL);
mgl@1371
 15460
+    return "";
mgl@1371
 15461
+  }
mgl@1371
 15462
+  ; Length is absolute worst case
mgl@1371
 15463
+  [(set_attr "type" "branch")
mgl@1371
 15464
+   (set_attr "length" "12")]
mgl@1371
 15465
+  )
mgl@1371
 15466
+
mgl@1371
 15467
+(define_insn "*epilogue_insns_ret_imm"
mgl@1371
 15468
+  [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
mgl@1371
 15469
+              (use (reg RETVAL_REGNUM))
mgl@1371
 15470
+              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
mgl@1371
 15471
+  "((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
mgl@1371
 15472
+  {
mgl@1371
 15473
+    avr32_output_return_instruction (FALSE, FALSE, NULL, operands[0]);
mgl@1371
 15474
+    return "";
mgl@1371
 15475
+  }
mgl@1371
 15476
+  ; Length is absolute worst case
mgl@1371
 15477
+  [(set_attr "type" "branch")
mgl@1371
 15478
+   (set_attr "length" "12")]
mgl@1371
 15479
+  )
mgl@1371
 15480
+
mgl@1371
 15481
+(define_insn "sibcall_epilogue"
mgl@1371
 15482
+  [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
mgl@1371
 15483
+  ""
mgl@1371
 15484
+  {
mgl@1371
 15485
+   avr32_output_return_instruction (FALSE, FALSE,  NULL, NULL);
mgl@1371
 15486
+   return "";
mgl@1371
 15487
+  }
mgl@1371
 15488
+;; Length is absolute worst case
mgl@1371
 15489
+  [(set_attr "type" "branch")
mgl@1371
 15490
+   (set_attr "length" "12")]
mgl@1371
 15491
+  )
mgl@1371
 15492
+
mgl@1371
 15493
+(define_insn "*sibcall_epilogue_insns_ret_imm"
mgl@1371
 15494
+  [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
mgl@1371
 15495
+              (use (reg RETVAL_REGNUM))
mgl@1371
 15496
+              (unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)])]
mgl@1371
 15497
+  "((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
mgl@1371
 15498
+  {
mgl@1371
 15499
+    avr32_output_return_instruction (FALSE, FALSE, NULL, operands[0]);
mgl@1371
 15500
+    return "";
mgl@1371
 15501
+  }
mgl@1371
 15502
+  ; Length is absolute worst case
mgl@1371
 15503
+  [(set_attr "type" "branch")
mgl@1371
 15504
+   (set_attr "length" "12")]
mgl@1371
 15505
+  )
mgl@1371
 15506
+
mgl@1371
 15507
+(define_insn "ldxi"
mgl@1371
 15508
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15509
+	(mem:SI (plus:SI
mgl@1371
 15510
+                 (match_operand:SI 1 "register_operand" "r")
mgl@1371
 15511
+                 (mult:SI (zero_extract:SI (match_operand:SI 2 "register_operand" "r")
mgl@1371
 15512
+                                           (const_int 8)
mgl@1371
 15513
+                                           (match_operand:SI 3 "immediate_operand" "Ku05"))
mgl@1371
 15514
+                          (const_int 4)))))]
mgl@1371
 15515
+  "(INTVAL(operands[3]) == 24 || INTVAL(operands[3]) == 16 || INTVAL(operands[3]) == 8
mgl@1371
 15516
+   || INTVAL(operands[3]) == 0)"
mgl@1371
 15517
+  {
mgl@1371
 15518
+   switch ( INTVAL(operands[3]) ){
mgl@1371
 15519
+    case 0:
mgl@1371
 15520
+         return "ld.w    %0, %1[%2:b << 2]";
mgl@1371
 15521
+    case 8:
mgl@1371
 15522
+         return "ld.w    %0, %1[%2:l << 2]";
mgl@1371
 15523
+    case 16:
mgl@1371
 15524
+         return "ld.w    %0, %1[%2:u << 2]";
mgl@1371
 15525
+    case 24:
mgl@1371
 15526
+         return "ld.w    %0, %1[%2:t << 2]";
mgl@1371
 15527
+    default:
mgl@1371
 15528
+         internal_error("illegal operand for ldxi");
mgl@1371
 15529
+   }
mgl@1371
 15530
+  }
mgl@1371
 15531
+  [(set_attr "type" "load")
mgl@1371
 15532
+   (set_attr "length" "4")
mgl@1371
 15533
+   (set_attr "cc" "none")])
mgl@1371
 15534
+
mgl@1371
 15535
+
mgl@1371
 15536
+
mgl@1371
 15537
+
mgl@1371
 15538
+
mgl@1371
 15539
+
mgl@1371
 15540
+;;=============================================================================
mgl@1371
 15541
+;; Peephole optimizing
mgl@1371
 15542
+;;-----------------------------------------------------------------------------
mgl@1371
 15543
+;; Changing
mgl@1371
 15544
+;;   sub     r8, r7, 8
mgl@1371
 15545
+;;   st.w    r8[0x0], r12
mgl@1371
 15546
+;; to
mgl@1371
 15547
+;;   sub     r8, r7, 8
mgl@1371
 15548
+;;   st.w    r7[-0x8], r12
mgl@1371
 15549
+;;=============================================================================
mgl@1371
 15550
+; (set (reg:SI 9 r8)
mgl@1371
 15551
+;      (plus:SI (reg/f:SI 6 r7)
mgl@1371
 15552
+;               (const_int ...)))
mgl@1371
 15553
+; (set (mem:SI (reg:SI 9 r8))
mgl@1371
 15554
+;      (reg:SI 12 r12))
mgl@1371
 15555
+(define_peephole2
mgl@1371
 15556
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15557
+	(plus:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15558
+		 (match_operand:SI 2 "immediate_operand" "")))
mgl@1371
 15559
+   (set (mem:SI (match_dup 0))
mgl@1371
 15560
+	(match_operand:SI 3 "register_operand" ""))]
mgl@1371
 15561
+  "REGNO(operands[0]) != REGNO(operands[1]) && avr32_const_ok_for_constraint_p(INTVAL(operands[2]), 'K', \"Ks16\")"
mgl@1371
 15562
+  [(set (match_dup 0)
mgl@1371
 15563
+	(plus:SI (match_dup 1)
mgl@1371
 15564
+		 (match_dup 2)))
mgl@1371
 15565
+   (set (mem:SI (plus:SI (match_dup 1)
mgl@1371
 15566
+			 (match_dup 2)))
mgl@1371
 15567
+	(match_dup 3))]
mgl@1371
 15568
+  "")
mgl@1371
 15569
+
mgl@1371
 15570
+;;=============================================================================
mgl@1371
 15571
+;; Peephole optimizing
mgl@1371
 15572
+;;-----------------------------------------------------------------------------
mgl@1371
 15573
+;; Changing
mgl@1371
 15574
+;;   sub     r6, r7, 4
mgl@1371
 15575
+;;   ld.w    r6, r6[0x0]
mgl@1371
 15576
+;; to
mgl@1371
 15577
+;;   sub     r6, r7, 4
mgl@1371
 15578
+;;   ld.w    r6, r7[-0x4]
mgl@1371
 15579
+;;=============================================================================
mgl@1371
 15580
+; (set (reg:SI 7 r6)
mgl@1371
 15581
+;      (plus:SI (reg/f:SI 6 r7)
mgl@1371
 15582
+;               (const_int -4 [0xfffffffc])))
mgl@1371
 15583
+; (set (reg:SI 7 r6)
mgl@1371
 15584
+;      (mem:SI (reg:SI 7 r6)))
mgl@1371
 15585
+(define_peephole2
mgl@1371
 15586
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15587
+	(plus:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15588
+		 (match_operand:SI 2 "immediate_operand" "")))
mgl@1371
 15589
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 15590
+	(mem:SI (match_dup 0)))]
mgl@1371
 15591
+  "REGNO(operands[0]) != REGNO(operands[1]) && avr32_const_ok_for_constraint_p(INTVAL(operands[2]), 'K', \"Ks16\")"
mgl@1371
 15592
+  [(set (match_dup 0)
mgl@1371
 15593
+	(plus:SI (match_dup 1)
mgl@1371
 15594
+		 (match_dup 2)))
mgl@1371
 15595
+   (set (match_dup 3)
mgl@1371
 15596
+	(mem:SI (plus:SI (match_dup 1)
mgl@1371
 15597
+			 (match_dup 2))))]
mgl@1371
 15598
+  "")
mgl@1371
 15599
+
mgl@1371
 15600
+;;=============================================================================
mgl@1371
 15601
+;; Peephole optimizing
mgl@1371
 15602
+;;-----------------------------------------------------------------------------
mgl@1371
 15603
+;; Changing
mgl@1371
 15604
+;;   ld.sb   r0, r7[-0x6]
mgl@1371
 15605
+;;   cashs.b r0
mgl@1371
 15606
+;; to
mgl@1371
 15607
+;;   ld.sb   r0, r7[-0x6]
mgl@1371
 15608
+;;=============================================================================
mgl@1371
 15609
+(define_peephole2
mgl@1371
 15610
+  [(set (match_operand:QI 0 "register_operand" "")
mgl@1371
 15611
+	(match_operand:QI 1 "load_sb_memory_operand" ""))
mgl@1371
 15612
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15613
+	(sign_extend:SI (match_dup 0)))]
mgl@1371
 15614
+  "(REGNO(operands[0]) == REGNO(operands[2]) || peep2_reg_dead_p(2, operands[0]))"
mgl@1371
 15615
+  [(set (match_dup 2)
mgl@1371
 15616
+	(sign_extend:SI (match_dup 1)))]
mgl@1371
 15617
+  "")
mgl@1371
 15618
+
mgl@1371
 15619
+;;=============================================================================
mgl@1371
 15620
+;; Peephole optimizing
mgl@1371
 15621
+;;-----------------------------------------------------------------------------
mgl@1371
 15622
+;; Changing
mgl@1371
 15623
+;;   ld.ub   r0, r7[-0x6]
mgl@1371
 15624
+;;   cashu.b r0
mgl@1371
 15625
+;; to
mgl@1371
 15626
+;;   ld.ub   r0, r7[-0x6]
mgl@1371
 15627
+;;=============================================================================
mgl@1371
 15628
+(define_peephole2
mgl@1371
 15629
+  [(set (match_operand:QI 0 "register_operand" "")
mgl@1371
 15630
+	(match_operand:QI 1 "memory_operand" ""))
mgl@1371
 15631
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15632
+	(zero_extend:SI (match_dup 0)))]
mgl@1371
 15633
+  "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15634
+  [(set (match_dup 2)
mgl@1371
 15635
+	(zero_extend:SI (match_dup 1)))]
mgl@1371
 15636
+  "")
mgl@1371
 15637
+
mgl@1371
 15638
+;;=============================================================================
mgl@1371
 15639
+;; Peephole optimizing
mgl@1371
 15640
+;;-----------------------------------------------------------------------------
mgl@1371
 15641
+;; Changing
mgl@1371
 15642
+;;   ld.sh   r0, r7[-0x6]
mgl@1371
 15643
+;;   casts.h r0
mgl@1371
 15644
+;; to
mgl@1371
 15645
+;;   ld.sh   r0, r7[-0x6]
mgl@1371
 15646
+;;=============================================================================
mgl@1371
 15647
+(define_peephole2
mgl@1371
 15648
+  [(set (match_operand:HI 0 "register_operand" "")
mgl@1371
 15649
+	(match_operand:HI 1 "memory_operand" ""))
mgl@1371
 15650
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15651
+	(sign_extend:SI (match_dup 0)))]
mgl@1371
 15652
+  "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15653
+  [(set (match_dup 2)
mgl@1371
 15654
+	(sign_extend:SI (match_dup 1)))]
mgl@1371
 15655
+  "")
mgl@1371
 15656
+
mgl@1371
 15657
+;;=============================================================================
mgl@1371
 15658
+;; Peephole optimizing
mgl@1371
 15659
+;;-----------------------------------------------------------------------------
mgl@1371
 15660
+;; Changing
mgl@1371
 15661
+;;   ld.uh   r0, r7[-0x6]
mgl@1371
 15662
+;;   castu.h r0
mgl@1371
 15663
+;; to
mgl@1371
 15664
+;;   ld.uh   r0, r7[-0x6]
mgl@1371
 15665
+;;=============================================================================
mgl@1371
 15666
+(define_peephole2
mgl@1371
 15667
+  [(set (match_operand:HI 0 "register_operand" "")
mgl@1371
 15668
+	(match_operand:HI 1 "memory_operand" ""))
mgl@1371
 15669
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15670
+	(zero_extend:SI (match_dup 0)))]
mgl@1371
 15671
+  "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15672
+  [(set (match_dup 2)
mgl@1371
 15673
+	(zero_extend:SI (match_dup 1)))]
mgl@1371
 15674
+  "")
mgl@1371
 15675
+
mgl@1371
 15676
+;;=============================================================================
mgl@1371
 15677
+;; Peephole optimizing
mgl@1371
 15678
+;;-----------------------------------------------------------------------------
mgl@1371
 15679
+;; Changing
mgl@1371
 15680
+;;   mul     rd, rx, ry
mgl@1371
 15681
+;;   add     rd2, rd  
mgl@1371
 15682
+;; or
mgl@1371
 15683
+;;   add     rd2, rd, rd2  
mgl@1371
 15684
+;; to
mgl@1371
 15685
+;;   mac     rd2, rx, ry
mgl@1371
 15686
+;;=============================================================================
mgl@1371
 15687
+(define_peephole2
mgl@1371
 15688
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15689
+        (mult:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15690
+                (match_operand:SI 2 "register_operand" "")))
mgl@1371
 15691
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 15692
+        (plus:SI (match_dup 3)
mgl@1371
 15693
+                 (match_dup 0)))]
mgl@1371
 15694
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15695
+  [(set (match_dup 3)
mgl@1371
 15696
+	(plus:SI (mult:SI (match_dup 1)
mgl@1371
 15697
+			  (match_dup 2))
mgl@1371
 15698
+		 (match_dup 3)))]
mgl@1371
 15699
+  "")
mgl@1371
 15700
+
mgl@1371
 15701
+(define_peephole2
mgl@1371
 15702
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15703
+        (mult:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15704
+                (match_operand:SI 2 "register_operand" "")))
mgl@1371
 15705
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 15706
+        (plus:SI (match_dup 0)
mgl@1371
 15707
+                 (match_dup 3)))]
mgl@1371
 15708
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15709
+  [(set (match_dup 3)
mgl@1371
 15710
+	(plus:SI (mult:SI (match_dup 1)
mgl@1371
 15711
+			  (match_dup 2))
mgl@1371
 15712
+		 (match_dup 3)))]
mgl@1371
 15713
+  "")
mgl@1371
 15714
+
mgl@1371
 15715
+
mgl@1371
 15716
+;;=============================================================================
mgl@1371
 15717
+;; Peephole optimizing
mgl@1371
 15718
+;;-----------------------------------------------------------------------------
mgl@1371
 15719
+;; Changing
mgl@1371
 15720
+;;   bfextu  rd, rs, k5, 1 or and(h/l) rd, one_bit_set_mask
mgl@1371
 15721
+;; to
mgl@1371
 15722
+;;   bld     rs, k5
mgl@1371
 15723
+;;
mgl@1371
 15724
+;; If rd is dead after the operation.
mgl@1371
 15725
+;;=============================================================================
mgl@1371
 15726
+(define_peephole2
mgl@1371
 15727
+  [ (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15728
+         (zero_extract:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15729
+                          (const_int 1)
mgl@1371
 15730
+                          (match_operand:SI 2 "immediate_operand" "")))
mgl@1371
 15731
+    (set (cc0)
mgl@1371
 15732
+         (match_dup 0))]
mgl@1371
 15733
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15734
+  [(set (cc0)
mgl@1371
 15735
+        (and:SI (match_dup 1)
mgl@1371
 15736
+                (match_dup 2)))]
mgl@1371
 15737
+  "operands[2] = GEN_INT(1 << INTVAL(operands[2]));")
mgl@1371
 15738
+
mgl@1371
 15739
+(define_peephole2
mgl@1371
 15740
+  [ (set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15741
+         (and:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15742
+                 (match_operand:SI 2 "one_bit_set_operand" "")))
mgl@1371
 15743
+    (set (cc0)
mgl@1371
 15744
+         (match_dup 0))]
mgl@1371
 15745
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15746
+  [(set (cc0)
mgl@1371
 15747
+        (and:SI (match_dup 1)
mgl@1371
 15748
+                (match_dup 2)))]
mgl@1371
 15749
+  "")
mgl@1371
 15750
+
mgl@1371
 15751
+;;=============================================================================
mgl@1371
 15752
+;; Peephole optimizing
mgl@1371
 15753
+;;-----------------------------------------------------------------------------
mgl@1371
 15754
+;; Load with extracted index: ld.w  Rd, Rb[Ri:{t/u/b/l} << 2]
mgl@1371
 15755
+;;
mgl@1371
 15756
+;;=============================================================================
mgl@1371
 15757
+
mgl@1371
 15758
+
mgl@1371
 15759
+(define_peephole
mgl@1371
 15760
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15761
+        (zero_extract:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15762
+                         (const_int 8)
mgl@1371
 15763
+                         (match_operand:SI 2 "avr32_extract_shift_operand" "")))
mgl@1371
 15764
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 15765
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15766
+                         (match_operand:SI 4 "register_operand" ""))))]
mgl@1371
 15767
+
mgl@1371
 15768
+  "(dead_or_set_p(insn, operands[0]))"
mgl@1371
 15769
+  {
mgl@1371
 15770
+   switch ( INTVAL(operands[2]) ){
mgl@1371
 15771
+    case 0:
mgl@1371
 15772
+         return "ld.w    %3, %4[%1:b << 2]";
mgl@1371
 15773
+    case 8:
mgl@1371
 15774
+         return "ld.w    %3, %4[%1:l << 2]";
mgl@1371
 15775
+    case 16:
mgl@1371
 15776
+         return "ld.w    %3, %4[%1:u << 2]";
mgl@1371
 15777
+    case 24:
mgl@1371
 15778
+         return "ld.w    %3, %4[%1:t << 2]";
mgl@1371
 15779
+    default:
mgl@1371
 15780
+         internal_error("illegal operand for ldxi");
mgl@1371
 15781
+   }
mgl@1371
 15782
+  }
mgl@1371
 15783
+  [(set_attr "type" "load")
mgl@1371
 15784
+   (set_attr "length" "4")
mgl@1371
 15785
+   (set_attr "cc" "clobber")]
mgl@1371
 15786
+  )
mgl@1371
 15787
+
mgl@1371
 15788
+
mgl@1371
 15789
+
mgl@1371
 15790
+(define_peephole
mgl@1371
 15791
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15792
+        (and:SI (match_operand:SI 1 "register_operand" "") (const_int 255)))
mgl@1371
 15793
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15794
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15795
+                         (match_operand:SI 3 "register_operand" ""))))]
mgl@1371
 15796
+
mgl@1371
 15797
+  "(dead_or_set_p(insn, operands[0]))"
mgl@1371
 15798
+
mgl@1371
 15799
+  "ld.w    %2, %3[%1:b << 2]"
mgl@1371
 15800
+  [(set_attr "type" "load")
mgl@1371
 15801
+   (set_attr "length" "4")
mgl@1371
 15802
+   (set_attr "cc" "clobber")]
mgl@1371
 15803
+  )
mgl@1371
 15804
+
mgl@1371
 15805
+
mgl@1371
 15806
+(define_peephole2
mgl@1371
 15807
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15808
+        (zero_extract:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15809
+                         (const_int 8)
mgl@1371
 15810
+                         (match_operand:SI 2 "avr32_extract_shift_operand" "")))
mgl@1371
 15811
+   (set (match_operand:SI 3 "register_operand" "")
mgl@1371
 15812
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15813
+                         (match_operand:SI 4 "register_operand" ""))))]
mgl@1371
 15814
+
mgl@1371
 15815
+  "(peep2_reg_dead_p(2, operands[0]))
mgl@1371
 15816
+   || (REGNO(operands[0]) == REGNO(operands[3]))"
mgl@1371
 15817
+  [(set (match_dup 3)
mgl@1371
 15818
+	(mem:SI (plus:SI
mgl@1371
 15819
+                 (match_dup 4)
mgl@1371
 15820
+                 (mult:SI (zero_extract:SI (match_dup 1)
mgl@1371
 15821
+                                           (const_int 8)
mgl@1371
 15822
+                                           (match_dup 2))
mgl@1371
 15823
+                          (const_int 4)))))]
mgl@1371
 15824
+  )
mgl@1371
 15825
+
mgl@1371
 15826
+(define_peephole2
mgl@1371
 15827
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15828
+        (zero_extend:SI (match_operand:QI 1 "register_operand" "")))
mgl@1371
 15829
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15830
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15831
+                         (match_operand:SI 3 "register_operand" ""))))]
mgl@1371
 15832
+
mgl@1371
 15833
+  "(peep2_reg_dead_p(2, operands[0]))
mgl@1371
 15834
+   || (REGNO(operands[0]) == REGNO(operands[2]))"
mgl@1371
 15835
+  [(set (match_dup 2)
mgl@1371
 15836
+	(mem:SI (plus:SI
mgl@1371
 15837
+                 (match_dup 3)
mgl@1371
 15838
+                 (mult:SI (zero_extract:SI (match_dup 1)
mgl@1371
 15839
+                                           (const_int 8)
mgl@1371
 15840
+                                           (const_int 0))
mgl@1371
 15841
+                          (const_int 4)))))]
mgl@1371
 15842
+  "operands[1] = gen_rtx_REG(SImode, REGNO(operands[1]));"
mgl@1371
 15843
+  )
mgl@1371
 15844
+
mgl@1371
 15845
+
mgl@1371
 15846
+(define_peephole2
mgl@1371
 15847
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15848
+        (and:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15849
+                (const_int 255)))
mgl@1371
 15850
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15851
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15852
+                         (match_operand:SI 3 "register_operand" ""))))]
mgl@1371
 15853
+
mgl@1371
 15854
+  "(peep2_reg_dead_p(2, operands[0]))
mgl@1371
 15855
+   || (REGNO(operands[0]) == REGNO(operands[2]))"
mgl@1371
 15856
+  [(set (match_dup 2)
mgl@1371
 15857
+	(mem:SI (plus:SI
mgl@1371
 15858
+                 (match_dup 3)
mgl@1371
 15859
+                 (mult:SI (zero_extract:SI (match_dup 1)
mgl@1371
 15860
+                                           (const_int 8)
mgl@1371
 15861
+                                           (const_int 0))
mgl@1371
 15862
+                          (const_int 4)))))]
mgl@1371
 15863
+  ""
mgl@1371
 15864
+  )
mgl@1371
 15865
+
mgl@1371
 15866
+
mgl@1371
 15867
+
mgl@1371
 15868
+(define_peephole2
mgl@1371
 15869
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15870
+        (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
mgl@1371
 15871
+                     (const_int 24)))
mgl@1371
 15872
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15873
+        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
mgl@1371
 15874
+                         (match_operand:SI 3 "register_operand" ""))))]
mgl@1371
 15875
+
mgl@1371
 15876
+  "(peep2_reg_dead_p(2, operands[0]))
mgl@1371
 15877
+   || (REGNO(operands[0]) == REGNO(operands[2]))"
mgl@1371
 15878
+  [(set (match_dup 2)
mgl@1371
 15879
+	(mem:SI (plus:SI
mgl@1371
 15880
+                 (match_dup 3)
mgl@1371
 15881
+                 (mult:SI (zero_extract:SI (match_dup 1)
mgl@1371
 15882
+                                           (const_int 8)
mgl@1371
 15883
+                                           (const_int 24))
mgl@1371
 15884
+                          (const_int 4)))))]
mgl@1371
 15885
+  ""
mgl@1371
 15886
+  )
mgl@1371
 15887
+
mgl@1371
 15888
+
mgl@1371
 15889
+;;************************************************
mgl@1371
 15890
+;; ANDN
mgl@1371
 15891
+;;
mgl@1371
 15892
+;;************************************************
mgl@1371
 15893
+
mgl@1371
 15894
+
mgl@1371
 15895
+(define_peephole2
mgl@1371
 15896
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15897
+        (not:SI (match_operand:SI 1 "register_operand" "")))
mgl@1371
 15898
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15899
+        (and:SI (match_dup 2)
mgl@1371
 15900
+                (match_dup 0)))]
mgl@1371
 15901
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15902
+
mgl@1371
 15903
+  [(set (match_dup 2)
mgl@1371
 15904
+        (and:SI  (match_dup 2)
mgl@1371
 15905
+                 (not:SI (match_dup 1))
mgl@1371
 15906
+                 ))]
mgl@1371
 15907
+  ""
mgl@1371
 15908
+)
mgl@1371
 15909
+
mgl@1371
 15910
+(define_peephole2
mgl@1371
 15911
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15912
+        (not:SI (match_operand:SI 1 "register_operand" "")))
mgl@1371
 15913
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 15914
+        (and:SI (match_dup 0)
mgl@1371
 15915
+                (match_dup 2)
mgl@1371
 15916
+                ))]
mgl@1371
 15917
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 15918
+
mgl@1371
 15919
+  [(set (match_dup 2)
mgl@1371
 15920
+        (and:SI  (match_dup 2)
mgl@1371
 15921
+                 (not:SI (match_dup 1))
mgl@1371
 15922
+                 ))]
mgl@1371
 15923
+
mgl@1371
 15924
+  ""
mgl@1371
 15925
+)
mgl@1371
 15926
+
mgl@1371
 15927
+
mgl@1371
 15928
+;;=================================================================
mgl@1371
 15929
+;; Addabs peephole
mgl@1371
 15930
+;;=================================================================
mgl@1371
 15931
+
mgl@1371
 15932
+(define_peephole
mgl@1371
 15933
+  [(set (match_operand:SI 2 "register_operand" "=r")
mgl@1371
 15934
+ 	(abs:SI (match_operand:SI 1 "register_operand" "r")))
mgl@1371
 15935
+   (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15936
+ 	(plus:SI (match_operand:SI 3 "register_operand" "r")
mgl@1371
 15937
+ 		 (match_dup 2)))]
mgl@1371
 15938
+  "dead_or_set_p(insn, operands[2])"
mgl@1371
 15939
+  "addabs  %0, %3, %1"
mgl@1371
 15940
+  [(set_attr "length" "4")
mgl@1371
 15941
+   (set_attr "cc" "set_z")])
mgl@1371
 15942
+
mgl@1371
 15943
+(define_peephole
mgl@1371
 15944
+  [(set (match_operand:SI 2 "register_operand" "=r")
mgl@1371
 15945
+ 	(abs:SI (match_operand:SI 1 "register_operand" "r")))
mgl@1371
 15946
+   (set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 15947
+ 	(plus:SI (match_dup 2)
mgl@1371
 15948
+                 (match_operand:SI 3 "register_operand" "r")))]
mgl@1371
 15949
+  "dead_or_set_p(insn, operands[2])"
mgl@1371
 15950
+  "addabs  %0, %3, %1"
mgl@1371
 15951
+  [(set_attr "length" "4")
mgl@1371
 15952
+   (set_attr "cc" "set_z")])
mgl@1371
 15953
+
mgl@1371
 15954
+
mgl@1371
 15955
+;;=================================================================
mgl@1371
 15956
+;; Detect roundings
mgl@1371
 15957
+;;=================================================================
mgl@1371
 15958
+
mgl@1371
 15959
+(define_insn "*round"
mgl@1371
 15960
+  [(set (match_operand:SI 0 "register_operand" "+r")
mgl@1371
 15961
+        (ashiftrt:SI (plus:SI (match_dup 0)
mgl@1371
 15962
+                              (match_operand:SI 1 "immediate_operand" "i"))
mgl@1371
 15963
+                     (match_operand:SI 2 "immediate_operand" "i")))]
mgl@1371
 15964
+  "avr32_rnd_operands(operands[1], operands[2])"
mgl@1371
 15965
+
mgl@1371
 15966
+  "satrnds    %0 >> %2, 31"
mgl@1371
 15967
+
mgl@1371
 15968
+  [(set_attr "type" "alu_sat")
mgl@1371
 15969
+   (set_attr "length" "4")]
mgl@1371
 15970
+
mgl@1371
 15971
+  )
mgl@1371
 15972
+
mgl@1371
 15973
+
mgl@1371
 15974
+(define_peephole2
mgl@1371
 15975
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 15976
+	(plus:SI (match_dup 0)
mgl@1371
 15977
+                 (match_operand:SI 1 "immediate_operand" "")))
mgl@1371
 15978
+   (set (match_dup 0)
mgl@1371
 15979
+	(ashiftrt:SI (match_dup 0)
mgl@1371
 15980
+                     (match_operand:SI 2 "immediate_operand" "")))]
mgl@1371
 15981
+  "avr32_rnd_operands(operands[1], operands[2])"
mgl@1371
 15982
+
mgl@1371
 15983
+  [(set (match_dup 0)
mgl@1371
 15984
+        (ashiftrt:SI (plus:SI (match_dup 0)
mgl@1371
 15985
+                              (match_dup 1))
mgl@1371
 15986
+                     (match_dup 2)))]
mgl@1371
 15987
+  )
mgl@1371
 15988
+
mgl@1371
 15989
+(define_peephole
mgl@1371
 15990
+  [(set (match_operand:SI 0 "register_operand" "r")
mgl@1371
 15991
+	(plus:SI (match_dup 0)
mgl@1371
 15992
+                 (match_operand:SI 1 "immediate_operand" "i")))
mgl@1371
 15993
+   (set (match_dup 0)
mgl@1371
 15994
+	(ashiftrt:SI (match_dup 0)
mgl@1371
 15995
+                     (match_operand:SI 2 "immediate_operand" "i")))]
mgl@1371
 15996
+  "avr32_rnd_operands(operands[1], operands[2])"
mgl@1371
 15997
+
mgl@1371
 15998
+  "satrnds    %0 >> %2, 31"
mgl@1371
 15999
+
mgl@1371
 16000
+  [(set_attr "type" "alu_sat")
mgl@1371
 16001
+   (set_attr "length" "4")
mgl@1371
 16002
+   (set_attr "cc" "clobber")]
mgl@1371
 16003
+
mgl@1371
 16004
+  )
mgl@1371
 16005
+
mgl@1371
 16006
+
mgl@1371
 16007
+;;=================================================================
mgl@1371
 16008
+;; mcall
mgl@1371
 16009
+;;=================================================================
mgl@1371
 16010
+(define_peephole
mgl@1371
 16011
+  [(set (match_operand:SI 0 "register_operand"        "")
mgl@1371
 16012
+	(match_operand 1 "avr32_const_pool_ref_operand"  ""))
mgl@1371
 16013
+   (parallel [(call (mem:SI (match_dup 0))
mgl@1371
 16014
+                    (match_operand 2 "" ""))
mgl@1371
 16015
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16016
+  "dead_or_set_p(insn, operands[0])"
mgl@1371
 16017
+  "mcall    %1"
mgl@1371
 16018
+  [(set_attr "type" "call")
mgl@1371
 16019
+   (set_attr "length" "4")
mgl@1371
 16020
+   (set_attr "cc" "clobber")]
mgl@1371
 16021
+)
mgl@1371
 16022
+
mgl@1371
 16023
+(define_peephole
mgl@1371
 16024
+  [(set (match_operand:SI 2 "register_operand"        "")
mgl@1371
 16025
+	(match_operand 1 "avr32_const_pool_ref_operand"  ""))
mgl@1371
 16026
+   (parallel [(set (match_operand 0 "register_operand" "")
mgl@1371
 16027
+                   (call (mem:SI (match_dup 2))
mgl@1371
 16028
+                         (match_operand 3 "" "")))
mgl@1371
 16029
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16030
+  "dead_or_set_p(insn, operands[2])"
mgl@1371
 16031
+  "mcall    %1"
mgl@1371
 16032
+  [(set_attr "type" "call")
mgl@1371
 16033
+   (set_attr "length" "4")
mgl@1371
 16034
+   (set_attr "cc" "call_set")]
mgl@1371
 16035
+)
mgl@1371
 16036
+
mgl@1371
 16037
+
mgl@1371
 16038
+(define_peephole2
mgl@1371
 16039
+  [(set (match_operand:SI 0 "register_operand"    "")
mgl@1371
 16040
+	(match_operand 1 "avr32_const_pool_ref_operand"  ""))
mgl@1371
 16041
+   (parallel [(call (mem:SI (match_dup 0))
mgl@1371
 16042
+                    (match_operand 2 "" ""))
mgl@1371
 16043
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16044
+  "peep2_reg_dead_p(2, operands[0])"
mgl@1371
 16045
+  [(parallel [(call (mem:SI (match_dup 1))
mgl@1371
 16046
+                    (match_dup 2))
mgl@1371
 16047
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16048
+  ""
mgl@1371
 16049
+)
mgl@1371
 16050
+
mgl@1371
 16051
+(define_peephole2
mgl@1371
 16052
+  [(set (match_operand:SI 0 "register_operand"        "")
mgl@1371
 16053
+	(match_operand 1 "avr32_const_pool_ref_operand"  ""))
mgl@1371
 16054
+   (parallel [(set (match_operand 2 "register_operand" "")
mgl@1371
 16055
+                   (call (mem:SI (match_dup 0))
mgl@1371
 16056
+                         (match_operand 3 "" "")))
mgl@1371
 16057
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16058
+  "(peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[2]) == REGNO(operands[0])))"
mgl@1371
 16059
+  [(parallel [(set (match_dup 2)
mgl@1371
 16060
+                   (call (mem:SI (match_dup 1))
mgl@1371
 16061
+                         (match_dup 3)))
mgl@1371
 16062
+              (clobber (reg:SI LR_REGNUM))])]
mgl@1371
 16063
+  ""
mgl@1371
 16064
+)
mgl@1371
 16065
+
mgl@1371
 16066
+;;=================================================================
mgl@1371
 16067
+;; Returning a value
mgl@1371
 16068
+;;=================================================================
mgl@1371
 16069
+
mgl@1371
 16070
+
mgl@1371
 16071
+(define_peephole
mgl@1371
 16072
+  [(set (match_operand 0 "register_operand" "")
mgl@1371
 16073
+        (match_operand 1 "register_operand" ""))
mgl@1371
 16074
+   (return)]
mgl@1371
 16075
+  "USE_RETURN_INSN (TRUE) && (REGNO(operands[0]) == RETVAL_REGNUM)
mgl@1371
 16076
+   && (REGNO(operands[1]) != LR_REGNUM)
mgl@1371
 16077
+   && (REGNO_REG_CLASS(REGNO(operands[1])) == GENERAL_REGS)"
mgl@1371
 16078
+  "retal    %1"
mgl@1371
 16079
+  [(set_attr "type" "call")
mgl@1371
 16080
+   (set_attr "length" "2")]
mgl@1371
 16081
+  )
mgl@1371
 16082
+
mgl@1371
 16083
+
mgl@1371
 16084
+(define_peephole
mgl@1371
 16085
+  [(set (match_operand 0 "register_operand" "r")
mgl@1371
 16086
+        (match_operand 1 "immediate_operand" "i"))
mgl@1371
 16087
+   (return)]
mgl@1371
 16088
+  "(USE_RETURN_INSN (FALSE) && (REGNO(operands[0]) == RETVAL_REGNUM) &&
mgl@1371
 16089
+   ((INTVAL(operands[1]) == -1) || (INTVAL(operands[1]) == 0) || (INTVAL(operands[1]) == 1)))"
mgl@1371
 16090
+  {
mgl@1371
 16091
+    avr32_output_return_instruction (TRUE, FALSE, NULL, operands[1]);
mgl@1371
 16092
+    return "";
mgl@1371
 16093
+  }
mgl@1371
 16094
+  [(set_attr "type" "call")
mgl@1371
 16095
+   (set_attr "length" "4")]
mgl@1371
 16096
+  )
mgl@1371
 16097
+
mgl@1371
 16098
+(define_peephole
mgl@1371
 16099
+  [(set (match_operand 0 "register_operand" "r")
mgl@1371
 16100
+        (match_operand 1 "immediate_operand" "i"))
mgl@1371
 16101
+   (unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
mgl@1371
 16102
+  "(REGNO(operands[0]) == RETVAL_REGNUM) &&
mgl@1371
 16103
+   ((INTVAL(operands[1]) == -1) || (INTVAL(operands[1]) == 0) || (INTVAL(operands[1]) == 1))"
mgl@1371
 16104
+  {
mgl@1371
 16105
+    avr32_output_return_instruction (FALSE, FALSE, NULL, operands[1]);
mgl@1371
 16106
+    return "";
mgl@1371
 16107
+  }
mgl@1371
 16108
+  ; Length is absolute worst case
mgl@1371
 16109
+  [(set_attr "type" "branch")
mgl@1371
 16110
+   (set_attr "length" "12")]
mgl@1371
 16111
+  )
mgl@1371
 16112
+
mgl@1371
 16113
+(define_peephole
mgl@1371
 16114
+  [(set (match_operand 0 "register_operand" "=r")
mgl@1371
 16115
+        (if_then_else (match_operator 1 "avr32_comparison_operator"
mgl@1371
 16116
+                                      [(match_operand 4 "register_operand" "r")
mgl@1371
 16117
+                                       (match_operand 5 "register_immediate_operand" "rKs21")])
mgl@1371
 16118
+                      (match_operand 2 "avr32_cond_register_immediate_operand" "rKs08")
mgl@1371
 16119
+                      (match_operand 3 "avr32_cond_register_immediate_operand" "rKs08")))
mgl@1371
 16120
+   (return)]
mgl@1371
 16121
+  "USE_RETURN_INSN (TRUE) && (REGNO(operands[0]) == RETVAL_REGNUM)"
mgl@1371
 16122
+  {
mgl@1371
 16123
+   operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
mgl@1371
 16124
+
mgl@1371
 16125
+   if ( GET_CODE(operands[2]) == REG
mgl@1371
 16126
+        && GET_CODE(operands[3]) == REG
mgl@1371
 16127
+        && REGNO(operands[2]) != LR_REGNUM
mgl@1371
 16128
+        && REGNO(operands[3]) != LR_REGNUM ){
mgl@1371
 16129
+      return "ret%1    %2\;ret%i1    %3";
mgl@1371
 16130
+   } else if ( GET_CODE(operands[2]) == REG
mgl@1371
 16131
+               && GET_CODE(operands[3]) == CONST_INT ){
mgl@1371
 16132
+      if ( INTVAL(operands[3]) == -1
mgl@1371
 16133
+           || INTVAL(operands[3]) == 0
mgl@1371
 16134
+           || INTVAL(operands[3]) == 1 ){
mgl@1371
 16135
+        return "ret%1    %2\;ret%i1    %d3";
mgl@1371
 16136
+      } else {
mgl@1371
 16137
+        return "mov%1    r12, %2\;mov%i1    r12, %3\;retal    r12";
mgl@1371
 16138
+      }
mgl@1371
 16139
+   } else if ( GET_CODE(operands[2]) == CONST_INT
mgl@1371
 16140
+               && GET_CODE(operands[3]) == REG ){
mgl@1371
 16141
+      if ( INTVAL(operands[2]) == -1
mgl@1371
 16142
+           || INTVAL(operands[2]) == 0
mgl@1371
 16143
+           || INTVAL(operands[2]) == 1 ){
mgl@1371
 16144
+        return "ret%1    %d2\;ret%i1    %3";
mgl@1371
 16145
+      } else {
mgl@1371
 16146
+        return "mov%1    r12, %2\;mov%i1    r12, %3\;retal    r12";
mgl@1371
 16147
+      }
mgl@1371
 16148
+   } else {
mgl@1371
 16149
+      if ( (INTVAL(operands[2]) == -1
mgl@1371
 16150
+            || INTVAL(operands[2]) == 0
mgl@1371
 16151
+            || INTVAL(operands[2]) == 1 )
mgl@1371
 16152
+           && (INTVAL(operands[3]) == -1
mgl@1371
 16153
+               || INTVAL(operands[3]) == 0
mgl@1371
 16154
+               || INTVAL(operands[3]) == 1 )){
mgl@1371
 16155
+        return "ret%1    %d2\;ret%i1    %d3";
mgl@1371
 16156
+      } else {
mgl@1371
 16157
+        return "mov%1    r12, %2\;mov%i1    r12, %3\;retal    r12";
mgl@1371
 16158
+      }
mgl@1371
 16159
+   }
mgl@1371
 16160
+  }
mgl@1371
 16161
+
mgl@1371
 16162
+  [(set_attr "length" "10")
mgl@1371
 16163
+   (set_attr "cc" "none")
mgl@1371
 16164
+   (set_attr "type" "call")])
mgl@1371
 16165
+  
mgl@1371
 16166
+
mgl@1371
 16167
+
mgl@1371
 16168
+;;=================================================================
mgl@1371
 16169
+;; mulnhh.w
mgl@1371
 16170
+;;=================================================================
mgl@1371
 16171
+
mgl@1371
 16172
+(define_peephole2
mgl@1371
 16173
+  [(set (match_operand:HI 0 "register_operand" "")
mgl@1371
 16174
+        (neg:HI (match_operand:HI 1 "register_operand" "")))
mgl@1371
 16175
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 16176
+        (mult:SI
mgl@1371
 16177
+         (sign_extend:SI (match_dup 0))
mgl@1371
 16178
+         (sign_extend:SI (match_operand:HI 3 "register_operand" ""))))]
mgl@1371
 16179
+  "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[2]) == REGNO(operands[0]))"
mgl@1371
 16180
+  [ (set (match_dup 2)
mgl@1371
 16181
+         (mult:SI
mgl@1371
 16182
+          (sign_extend:SI (neg:HI (match_dup 1)))
mgl@1371
 16183
+          (sign_extend:SI (match_dup 3))))]
mgl@1371
 16184
+  ""
mgl@1371
 16185
+  )
mgl@1371
 16186
+
mgl@1371
 16187
+(define_peephole2
mgl@1371
 16188
+  [(set (match_operand:HI 0 "register_operand" "")
mgl@1371
 16189
+        (neg:HI (match_operand:HI 1 "register_operand" "")))
mgl@1371
 16190
+   (set (match_operand:SI 2 "register_operand" "")
mgl@1371
 16191
+        (mult:SI
mgl@1371
 16192
+         (sign_extend:SI (match_operand:HI 3 "register_operand" ""))
mgl@1371
 16193
+         (sign_extend:SI (match_dup 0))))]
mgl@1371
 16194
+  "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[2]) == REGNO(operands[0]))"
mgl@1371
 16195
+  [ (set (match_dup 2)
mgl@1371
 16196
+         (mult:SI
mgl@1371
 16197
+          (sign_extend:SI (neg:HI (match_dup 1)))
mgl@1371
 16198
+          (sign_extend:SI (match_dup 3))))]
mgl@1371
 16199
+  ""
mgl@1371
 16200
+  )
mgl@1371
 16201
+
mgl@1371
 16202
+
mgl@1371
 16203
+
mgl@1371
 16204
+;;=================================================================
mgl@1371
 16205
+;; Vector set and extract operations
mgl@1371
 16206
+;;=================================================================
mgl@1371
 16207
+(define_insn "vec_setv2hi_hi"
mgl@1371
 16208
+  [(set (match_operand:V2HI 0 "register_operand" "=r")
mgl@1371
 16209
+        (vec_merge:V2HI
mgl@1371
 16210
+         (match_dup 0)
mgl@1371
 16211
+         (vec_duplicate:V2HI
mgl@1371
 16212
+          (match_operand:HI 1 "register_operand" "r"))
mgl@1371
 16213
+         (const_int 1)))]
mgl@1371
 16214
+  ""
mgl@1371
 16215
+  "bfins\t%0, %1, 16, 16"
mgl@1371
 16216
+  [(set_attr "type" "alu")
mgl@1371
 16217
+   (set_attr "length" "4")
mgl@1371
 16218
+   (set_attr "cc" "clobber")])
mgl@1371
 16219
+
mgl@1371
 16220
+(define_insn "vec_setv2hi_lo"
mgl@1371
 16221
+  [(set (match_operand:V2HI 0 "register_operand" "+r")
mgl@1371
 16222
+        (vec_merge:V2HI
mgl@1371
 16223
+         (match_dup 0)
mgl@1371
 16224
+         (vec_duplicate:V2HI
mgl@1371
 16225
+          (match_operand:HI 1 "register_operand" "r"))
mgl@1371
 16226
+         (const_int 2)))]
mgl@1371
 16227
+  ""
mgl@1371
 16228
+  "bfins\t%0, %1, 0, 16"
mgl@1371
 16229
+  [(set_attr "type" "alu")
mgl@1371
 16230
+   (set_attr "length" "4")
mgl@1371
 16231
+   (set_attr "cc" "clobber")])
mgl@1371
 16232
+
mgl@1371
 16233
+(define_expand "vec_setv2hi"
mgl@1371
 16234
+  [(set (match_operand:V2HI 0 "register_operand" "")
mgl@1371
 16235
+        (vec_merge:V2HI
mgl@1371
 16236
+         (match_dup 0)
mgl@1371
 16237
+         (vec_duplicate:V2HI
mgl@1371
 16238
+          (match_operand:HI 1 "register_operand" ""))
mgl@1371
 16239
+         (match_operand 2 "immediate_operand" "")))]
mgl@1371
 16240
+  ""
mgl@1371
 16241
+  { operands[2] = GEN_INT(INTVAL(operands[2]) + 1); }
mgl@1371
 16242
+  )
mgl@1371
 16243
+
mgl@1371
 16244
+(define_insn "vec_extractv2hi"
mgl@1371
 16245
+  [(set (match_operand:HI 0 "register_operand" "=r")
mgl@1371
 16246
+        (vec_select:HI
mgl@1371
 16247
+         (match_operand:V2HI 1 "register_operand" "r")
mgl@1371
 16248
+         (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
mgl@1371
 16249
+  ""
mgl@1371
 16250
+  {
mgl@1371
 16251
+   if ( INTVAL(operands[2]) == 0 )
mgl@1371
 16252
+      return "bfextu\t%0, %1, 16, 16";
mgl@1371
 16253
+   else
mgl@1371
 16254
+      return "bfextu\t%0, %1, 0, 16";
mgl@1371
 16255
+  }
mgl@1371
 16256
+  [(set_attr "type" "alu")
mgl@1371
 16257
+   (set_attr "length" "4")
mgl@1371
 16258
+   (set_attr "cc" "clobber")])
mgl@1371
 16259
+
mgl@1371
 16260
+(define_insn "vec_extractv4qi"
mgl@1371
 16261
+  [(set (match_operand:QI 0 "register_operand" "=r")
mgl@1371
 16262
+        (vec_select:QI
mgl@1371
 16263
+         (match_operand:V4QI 1 "register_operand" "r")
mgl@1371
 16264
+         (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
mgl@1371
 16265
+  ""
mgl@1371
 16266
+  {
mgl@1371
 16267
+   switch ( INTVAL(operands[2]) ){
mgl@1371
 16268
+     case 0:
mgl@1371
 16269
+       return "bfextu\t%0, %1, 24, 8";
mgl@1371
 16270
+     case 1:
mgl@1371
 16271
+       return "bfextu\t%0, %1, 16, 8";
mgl@1371
 16272
+     case 2:
mgl@1371
 16273
+       return "bfextu\t%0, %1, 8, 8";
mgl@1371
 16274
+     case 3:
mgl@1371
 16275
+       return "bfextu\t%0, %1, 0, 8";
mgl@1371
 16276
+     default:
mgl@1371
 16277
+       abort();
mgl@1371
 16278
+   }
mgl@1371
 16279
+  }
mgl@1371
 16280
+  [(set_attr "type" "alu")
mgl@1371
 16281
+   (set_attr "length" "4")
mgl@1371
 16282
+   (set_attr "cc" "clobber")])
mgl@1371
 16283
+
mgl@1371
 16284
+
mgl@1371
 16285
+(define_insn "concatv2hi"
mgl@1371
 16286
+  [(set (match_operand:V2HI 0 "register_operand" "=r, r, r")
mgl@1371
 16287
+        (vec_concat:V2HI
mgl@1371
 16288
+         (match_operand:HI 1 "register_operand" "r, r, 0")
mgl@1371
 16289
+         (match_operand:HI 2 "register_operand" "r, 0, r")))]
mgl@1371
 16290
+  ""
mgl@1371
 16291
+  "@
mgl@1371
 16292
+   mov\t%0, %1\;bfins\t%0, %2, 0, 16
mgl@1371
 16293
+   bfins\t%0, %2, 0, 16
mgl@1371
 16294
+   bfins\t%0, %1, 16, 16"
mgl@1371
 16295
+  [(set_attr "length" "6, 4, 4")
mgl@1371
 16296
+   (set_attr "type" "alu")])
mgl@1371
 16297
+
mgl@1371
 16298
+
mgl@1371
 16299
+;; Load the atomic operation description
mgl@1371
 16300
+(include "sync.md")
mgl@1371
 16301
+
mgl@1371
 16302
+;; Load the SIMD description
mgl@1371
 16303
+(include "simd.md")
mgl@1371
 16304
+
mgl@1371
 16305
+;; Load the FP coprAocessor patterns
mgl@1371
 16306
+(include "fpcp.md")
mgl@1371
 16307
--- /dev/null
mgl@1371
 16308
+++ b/gcc/config/avr32/avr32-modes.def
mgl@1371
 16309
@@ -0,0 +1 @@
mgl@1371
 16310
+VECTOR_MODES (INT, 4);        /*            V4QI V2HI */
mgl@1371
 16311
--- /dev/null
mgl@1371
 16312
+++ b/gcc/config/avr32/avr32.opt
mgl@1371
 16313
@@ -0,0 +1,86 @@
mgl@1371
 16314
+; Options for the ATMEL AVR32 port of the compiler.
mgl@1371
 16315
+
mgl@1371
 16316
+; Copyright 2007 Atmel Corporation.
mgl@1371
 16317
+;
mgl@1371
 16318
+; This file is part of GCC.
mgl@1371
 16319
+;
mgl@1371
 16320
+; GCC is free software; you can redistribute it and/or modify it under
mgl@1371
 16321
+; the terms of the GNU General Public License as published by the Free
mgl@1371
 16322
+; Software Foundation; either version 2, or (at your option) any later
mgl@1371
 16323
+; version.
mgl@1371
 16324
+;
mgl@1371
 16325
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
mgl@1371
 16326
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
mgl@1371
 16327
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
mgl@1371
 16328
+; for more details.
mgl@1371
 16329
+;
mgl@1371
 16330
+; You should have received a copy of the GNU General Public License
mgl@1371
 16331
+; along with GCC; see the file COPYING.  If not, write to the Free
mgl@1371
 16332
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
mgl@1371
 16333
+; 02110-1301, USA.
mgl@1371
 16334
+
mgl@1371
 16335
+muse-rodata-section
mgl@1371
 16336
+Target Report Mask(USE_RODATA_SECTION)
mgl@1371
 16337
+Use section .rodata for read-only data instead of .text.
mgl@1371
 16338
+
mgl@1371
 16339
+mhard-float
mgl@1371
 16340
+Target Report Undocumented Mask(HARD_FLOAT)
mgl@1371
 16341
+Use floating point coprocessor instructions.
mgl@1371
 16342
+
mgl@1371
 16343
+msoft-float
mgl@1371
 16344
+Target Report Undocumented InverseMask(HARD_FLOAT, SOFT_FLOAT)
mgl@1371
 16345
+Use software floating-point library for floating-point operations.
mgl@1371
 16346
+
mgl@1371
 16347
+mforce-double-align
mgl@1371
 16348
+Target Report RejectNegative Mask(FORCE_DOUBLE_ALIGN)
mgl@1371
 16349
+Force double-word alignment for double-word memory accesses.
mgl@1371
 16350
+
mgl@1371
 16351
+mno-init-got
mgl@1371
 16352
+Target Report RejectNegative Mask(NO_INIT_GOT)
mgl@1371
 16353
+Do not initialize GOT register before using it when compiling PIC code.
mgl@1371
 16354
+
mgl@1371
 16355
+mrelax
mgl@1371
 16356
+Target Report Mask(RELAX)
mgl@1371
 16357
+Let invoked assembler and linker do relaxing (Enabled by default when optimization level is >1).
mgl@1371
 16358
+
mgl@1371
 16359
+mmd-reorg-opt
mgl@1371
 16360
+Target Report Undocumented Mask(MD_REORG_OPTIMIZATION)
mgl@1371
 16361
+Perform machine dependent optimizations in reorg stage.
mgl@1371
 16362
+
mgl@1371
 16363
+masm-addr-pseudos
mgl@1371
 16364
+Target Report Mask(HAS_ASM_ADDR_PSEUDOS) 
mgl@1371
 16365
+Use assembler pseudo-instructions lda.w and call for handling direct addresses. (Enabled by default)
mgl@1371
 16366
+
mgl@1371
 16367
+mpart=
mgl@1371
 16368
+Target Report RejectNegative Joined Var(avr32_part_name)
mgl@1371
 16369
+Specify the AVR32 part name
mgl@1371
 16370
+
mgl@1371
 16371
+mcpu=
mgl@1371
 16372
+Target Report RejectNegative Joined Undocumented Var(avr32_part_name)
mgl@1371
 16373
+Specify the AVR32 part name (deprecated)
mgl@1371
 16374
+
mgl@1371
 16375
+march=
mgl@1371
 16376
+Target Report RejectNegative Joined Var(avr32_arch_name)
mgl@1371
 16377
+Specify the AVR32 architecture name
mgl@1371
 16378
+
mgl@1371
 16379
+mfast-float
mgl@1371
 16380
+Target Report Mask(FAST_FLOAT)
mgl@1371
 16381
+Enable fast floating-point library. Enabled by default if the -funsafe-math-optimizations switch is specified.
mgl@1371
 16382
+
mgl@1371
 16383
+mimm-in-const-pool
mgl@1371
 16384
+Target Report Var(avr32_imm_in_const_pool) Init(-1)
mgl@1371
 16385
+Put large immediates in constant pool. This is enabled by default for archs with insn-cache.
mgl@1371
 16386
+
mgl@1371
 16387
+mno-pic
mgl@1371
 16388
+Target Report RejectNegative Mask(NO_PIC)
mgl@1371
 16389
+Do not generate position-independent code. (deprecated, use -fno-pic instead)
mgl@1371
 16390
+
mgl@1371
 16391
+mcond-exec-before-reload
mgl@1371
 16392
+Target Report Undocumented Mask(COND_EXEC_BEFORE_RELOAD) 
mgl@1371
 16393
+Enable experimental conditional execution preparation before the reload stage. 
mgl@1371
 16394
+
mgl@1371
 16395
+mrmw-addressable-data
mgl@1371
 16396
+Target Report Mask(RMW_ADDRESSABLE_DATA)
mgl@1371
 16397
+Signal that all data is in range for the Atomic Read-Modify-Write memory instructions, and that
mgl@1371
 16398
+gcc can safely generate these whenever possible. 
mgl@1371
 16399
+
mgl@1371
 16400
--- /dev/null
mgl@1371
 16401
+++ b/gcc/config/avr32/avr32-protos.h
mgl@1371
 16402
@@ -0,0 +1,196 @@
mgl@1371
 16403
+/*
mgl@1371
 16404
+   Prototypes for exported functions defined in avr32.c
mgl@1371
 16405
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 16406
+
mgl@1371
 16407
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 16408
+   Initial porting by Anders �dland.
mgl@1371
 16409
+
mgl@1371
 16410
+   This file is part of GCC.
mgl@1371
 16411
+
mgl@1371
 16412
+   This program is free software; you can redistribute it and/or modify
mgl@1371
 16413
+   it under the terms of the GNU General Public License as published by
mgl@1371
 16414
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 16415
+   (at your option) any later version.
mgl@1371
 16416
+
mgl@1371
 16417
+   This program is distributed in the hope that it will be useful,
mgl@1371
 16418
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 16419
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 16420
+   GNU General Public License for more details.
mgl@1371
 16421
+
mgl@1371
 16422
+   You should have received a copy of the GNU General Public License
mgl@1371
 16423
+   along with this program; if not, write to the Free Software
mgl@1371
 16424
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
 16425
+
mgl@1371
 16426
+
mgl@1371
 16427
+#ifndef AVR32_PROTOS_H
mgl@1371
 16428
+#define AVR32_PROTOS_H
mgl@1371
 16429
+
mgl@1371
 16430
+extern const int swap_reg[];
mgl@1371
 16431
+
mgl@1371
 16432
+extern int avr32_valid_macmac_bypass (rtx, rtx);
mgl@1371
 16433
+extern int avr32_valid_mulmac_bypass (rtx, rtx);
mgl@1371
 16434
+
mgl@1371
 16435
+extern int avr32_decode_lcomm_symbol_offset (rtx, int *);
mgl@1371
 16436
+extern void avr32_encode_lcomm_symbol_offset (tree, char *, int);
mgl@1371
 16437
+
mgl@1371
 16438
+extern const char *avr32_strip_name_encoding (const char *);
mgl@1371
 16439
+
mgl@1371
 16440
+extern rtx avr32_get_note_reg_equiv (rtx insn);
mgl@1371
 16441
+
mgl@1371
 16442
+extern int avr32_use_return_insn (int iscond);
mgl@1371
 16443
+
mgl@1371
 16444
+extern void avr32_make_reglist16 (int reglist16_vect, char *reglist16_string);
mgl@1371
 16445
+
mgl@1371
 16446
+extern void avr32_make_reglist8 (int reglist8_vect, char *reglist8_string);
mgl@1371
 16447
+extern void avr32_make_fp_reglist_w (int reglist_mask, char *reglist_string);
mgl@1371
 16448
+extern void avr32_make_fp_reglist_d (int reglist_mask, char *reglist_string);
mgl@1371
 16449
+
mgl@1371
 16450
+extern void avr32_output_return_instruction (int single_ret_inst,
mgl@1371
 16451
+					     int iscond, rtx cond,
mgl@1371
 16452
+					     rtx r12_imm);
mgl@1371
 16453
+extern void avr32_expand_prologue (void);
mgl@1371
 16454
+extern void avr32_set_return_address (rtx source, rtx scratch);
mgl@1371
 16455
+
mgl@1371
 16456
+extern int avr32_hard_regno_mode_ok (int regno, enum machine_mode mode);
mgl@1371
 16457
+extern int avr32_extra_constraint_s (rtx value, const int strict);
mgl@1371
 16458
+extern int avr32_eh_return_data_regno (const int n);
mgl@1371
 16459
+extern int avr32_initial_elimination_offset (const int from, const int to);
mgl@1371
 16460
+extern rtx avr32_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
mgl@1371
 16461
+			       tree type, int named);
mgl@1371
 16462
+extern void avr32_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
mgl@1371
 16463
+					rtx libname, tree fndecl);
mgl@1371
 16464
+extern void avr32_function_arg_advance (CUMULATIVE_ARGS * cum,
mgl@1371
 16465
+					enum machine_mode mode,
mgl@1371
 16466
+					tree type, int named);
mgl@1371
 16467
+#ifdef ARGS_SIZE_RTX
mgl@1371
 16468
+/* expr.h defines ARGS_SIZE_RTX and `enum direction'.  */
mgl@1371
 16469
+extern enum direction avr32_function_arg_padding (enum machine_mode mode,
mgl@1371
 16470
+						  tree type);
mgl@1371
 16471
+#endif /* ARGS_SIZE_RTX */
mgl@1371
 16472
+extern rtx avr32_function_value (tree valtype, tree func, bool outgoing);
mgl@1371
 16473
+extern rtx avr32_libcall_value (enum machine_mode mode);
mgl@1371
 16474
+extern int avr32_sched_use_dfa_pipeline_interface (void);
mgl@1371
 16475
+extern bool avr32_return_in_memory (tree type, tree fntype);
mgl@1371
 16476
+extern void avr32_regs_to_save (char *operand);
mgl@1371
 16477
+extern void avr32_target_asm_function_prologue (FILE * file,
mgl@1371
 16478
+						HOST_WIDE_INT size);
mgl@1371
 16479
+extern void avr32_target_asm_function_epilogue (FILE * file,
mgl@1371
 16480
+						HOST_WIDE_INT size);
mgl@1371
 16481
+extern void avr32_trampoline_template (FILE * file);
mgl@1371
 16482
+extern void avr32_initialize_trampoline (rtx addr, rtx fnaddr,
mgl@1371
 16483
+					 rtx static_chain);
mgl@1371
 16484
+extern int avr32_legitimate_address (enum machine_mode mode, rtx x,
mgl@1371
 16485
+				     int strict);
mgl@1371
 16486
+extern int avr32_legitimate_constant_p (rtx x);
mgl@1371
 16487
+
mgl@1371
 16488
+extern int avr32_legitimate_pic_operand_p (rtx x);
mgl@1371
 16489
+
mgl@1371
 16490
+extern rtx avr32_find_symbol (rtx x);
mgl@1371
 16491
+extern void avr32_select_section (rtx exp, int reloc, int align);
mgl@1371
 16492
+extern void avr32_encode_section_info (tree decl, rtx rtl, int first);
mgl@1371
 16493
+extern void avr32_asm_file_end (FILE * stream);
mgl@1371
 16494
+extern void avr32_asm_output_ascii (FILE * stream, char *ptr, int len);
mgl@1371
 16495
+extern void avr32_asm_output_common (FILE * stream, const char *name,
mgl@1371
 16496
+				     int size, int rounded);
mgl@1371
 16497
+extern void avr32_asm_output_label (FILE * stream, const char *name);
mgl@1371
 16498
+extern void avr32_asm_declare_object_name (FILE * stream, char *name,
mgl@1371
 16499
+					   tree decl);
mgl@1371
 16500
+extern void avr32_asm_globalize_label (FILE * stream, const char *name);
mgl@1371
 16501
+extern void avr32_asm_weaken_label (FILE * stream, const char *name);
mgl@1371
 16502
+extern void avr32_asm_output_external (FILE * stream, tree decl,
mgl@1371
 16503
+				       const char *name);
mgl@1371
 16504
+extern void avr32_asm_output_external_libcall (FILE * stream, rtx symref);
mgl@1371
 16505
+extern void avr32_asm_output_labelref (FILE * stream, const char *name);
mgl@1371
 16506
+extern void avr32_notice_update_cc (rtx exp, rtx insn);
mgl@1371
 16507
+extern void avr32_print_operand (FILE * stream, rtx x, int code);
mgl@1371
 16508
+extern void avr32_print_operand_address (FILE * stream, rtx x);
mgl@1371
 16509
+
mgl@1371
 16510
+extern int avr32_symbol (rtx x);
mgl@1371
 16511
+
mgl@1371
 16512
+extern void avr32_select_rtx_section (enum machine_mode mode, rtx x,
mgl@1371
 16513
+				      unsigned HOST_WIDE_INT align);
mgl@1371
 16514
+
mgl@1371
 16515
+extern int avr32_load_multiple_operation (rtx op, enum machine_mode mode);
mgl@1371
 16516
+extern int avr32_store_multiple_operation (rtx op, enum machine_mode mode);
mgl@1371
 16517
+
mgl@1371
 16518
+extern int avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c,
mgl@1371
 16519
+					    const char *str);
mgl@1371
 16520
+
mgl@1371
 16521
+extern bool avr32_cannot_force_const_mem (rtx x);
mgl@1371
 16522
+
mgl@1371
 16523
+extern void avr32_init_builtins (void);
mgl@1371
 16524
+
mgl@1371
 16525
+extern rtx avr32_expand_builtin (tree exp, rtx target, rtx subtarget,
mgl@1371
 16526
+				 enum machine_mode mode, int ignore);
mgl@1371
 16527
+
mgl@1371
 16528
+extern bool avr32_must_pass_in_stack (enum machine_mode mode, tree type);
mgl@1371
 16529
+
mgl@1371
 16530
+extern bool avr32_strict_argument_naming (CUMULATIVE_ARGS * ca);
mgl@1371
 16531
+
mgl@1371
 16532
+extern bool avr32_pass_by_reference (CUMULATIVE_ARGS * cum,
mgl@1371
 16533
+				     enum machine_mode mode,
mgl@1371
 16534
+				     tree type, bool named);
mgl@1371
 16535
+
mgl@1371
 16536
+extern rtx avr32_gen_load_multiple (rtx * regs, int count, rtx from,
mgl@1371
 16537
+				    int write_back, int in_struct_p,
mgl@1371
 16538
+				    int scalar_p);
mgl@1371
 16539
+extern rtx avr32_gen_store_multiple (rtx * regs, int count, rtx to,
mgl@1371
 16540
+				     int in_struct_p, int scalar_p);
mgl@1371
 16541
+extern int avr32_gen_movmemsi (rtx * operands);
mgl@1371
 16542
+
mgl@1371
 16543
+extern int avr32_rnd_operands (rtx add, rtx shift);
mgl@1371
 16544
+extern int avr32_adjust_insn_length (rtx insn, int length);
mgl@1371
 16545
+
mgl@1371
 16546
+extern int symbol_mentioned_p (rtx x);
mgl@1371
 16547
+extern int label_mentioned_p (rtx x);
mgl@1371
 16548
+extern rtx legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg);
mgl@1371
 16549
+extern int avr32_address_register_rtx_p (rtx x, int strict_p);
mgl@1371
 16550
+extern int avr32_legitimate_index_p (enum machine_mode mode, rtx index,
mgl@1371
 16551
+				     int strict_p);
mgl@1371
 16552
+
mgl@1371
 16553
+extern int avr32_const_double_immediate (rtx value);
mgl@1371
 16554
+extern void avr32_init_expanders (void);
mgl@1371
 16555
+extern rtx avr32_return_addr (int count, rtx frame);
mgl@1371
 16556
+extern bool avr32_got_mentioned_p (rtx addr);
mgl@1371
 16557
+
mgl@1371
 16558
+extern void avr32_final_prescan_insn (rtx insn, rtx * opvec, int noperands);
mgl@1371
 16559
+
mgl@1371
 16560
+extern int avr32_expand_movcc (enum machine_mode mode, rtx operands[]);
mgl@1371
 16561
+extern int avr32_expand_addcc (enum machine_mode mode, rtx operands[]);
mgl@1371
 16562
+#ifdef RTX_CODE
mgl@1371
 16563
+extern int avr32_expand_scc (RTX_CODE cond, rtx * operands);
mgl@1371
 16564
+#endif
mgl@1371
 16565
+
mgl@1371
 16566
+extern int avr32_store_bypass (rtx insn_out, rtx insn_in);
mgl@1371
 16567
+extern int avr32_mul_waw_bypass (rtx insn_out, rtx insn_in);
mgl@1371
 16568
+extern int avr32_valid_load_double_bypass (rtx insn_out, rtx insn_in);
mgl@1371
 16569
+extern int avr32_valid_load_quad_bypass (rtx insn_out, rtx insn_in);
mgl@1371
 16570
+extern rtx avr32_output_cmp (rtx cond, enum machine_mode mode,
mgl@1371
 16571
+			     rtx op0, rtx op1);
mgl@1371
 16572
+
mgl@1371
 16573
+rtx get_next_insn_cond (rtx cur_insn);
mgl@1371
 16574
+int set_next_insn_cond (rtx cur_insn, rtx cond);
mgl@1371
 16575
+void avr32_override_options (void);
mgl@1371
 16576
+void avr32_load_pic_register (void);
mgl@1371
 16577
+#ifdef GCC_BASIC_BLOCK_H
mgl@1371
 16578
+rtx avr32_ifcvt_modify_insn (ce_if_block_t *ce_info, rtx pattern, rtx insn, 
mgl@1371
 16579
+                             int *num_true_changes);
mgl@1371
 16580
+rtx avr32_ifcvt_modify_test (ce_if_block_t *ce_info, rtx test );
mgl@1371
 16581
+void avr32_ifcvt_modify_cancel ( ce_if_block_t *ce_info, int *num_true_changes);
mgl@1371
 16582
+#endif
mgl@1371
 16583
+void avr32_optimization_options (int level, int size);
mgl@1371
 16584
+int avr32_const_ok_for_move (HOST_WIDE_INT c);
mgl@1371
 16585
+
mgl@1371
 16586
+void avr32_split_const_expr (enum machine_mode mode,
mgl@1371
 16587
+                             enum machine_mode new_mode,
mgl@1371
 16588
+                             rtx expr, 
mgl@1371
 16589
+                             rtx *split_expr);
mgl@1371
 16590
+void avr32_get_intval (enum machine_mode mode,
mgl@1371
 16591
+                       rtx const_expr, 
mgl@1371
 16592
+                       HOST_WIDE_INT *val);
mgl@1371
 16593
+
mgl@1371
 16594
+int avr32_cond_imm_clobber_splittable (rtx insn, 
mgl@1371
 16595
+                                       rtx operands[]);
mgl@1371
 16596
+
mgl@1371
 16597
+
mgl@1371
 16598
+#endif /* AVR32_PROTOS_H */
mgl@1371
 16599
--- /dev/null
mgl@1371
 16600
+++ b/gcc/config/avr32/crti.asm
mgl@1371
 16601
@@ -0,0 +1,64 @@
mgl@1371
 16602
+/*
mgl@1371
 16603
+   Init/fini stuff for AVR32.
mgl@1371
 16604
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 16605
+
mgl@1371
 16606
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 16607
+
mgl@1371
 16608
+   This file is part of GCC.
mgl@1371
 16609
+
mgl@1371
 16610
+   This program is free software; you can redistribute it and/or modify
mgl@1371
 16611
+   it under the terms of the GNU General Public License as published by
mgl@1371
 16612
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 16613
+   (at your option) any later version.
mgl@1371
 16614
+
mgl@1371
 16615
+   This program is distributed in the hope that it will be useful,
mgl@1371
 16616
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 16617
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 16618
+   GNU General Public License for more details.
mgl@1371
 16619
+
mgl@1371
 16620
+   You should have received a copy of the GNU General Public License
mgl@1371
 16621
+   along with this program; if not, write to the Free Software
mgl@1371
 16622
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
 16623
+
mgl@1371
 16624
+	
mgl@1371
 16625
+/* The code in sections .init and .fini is supposed to be a single
mgl@1371
 16626
+   regular function.  The function in .init is called directly from
mgl@1371
 16627
+   start in crt1.asm.  The function in .fini is atexit()ed in crt1.asm
mgl@1371
 16628
+   too.
mgl@1371
 16629
+
mgl@1371
 16630
+   crti.asm contributes the prologue of a function to these sections,
mgl@1371
 16631
+   and crtn.asm comes up the epilogue.  STARTFILE_SPEC should list
mgl@1371
 16632
+   crti.o before any other object files that might add code to .init
mgl@1371
 16633
+   or .fini sections, and ENDFILE_SPEC should list crtn.o after any
mgl@1371
 16634
+   such object files.  */
mgl@1371
 16635
+		
mgl@1371
 16636
+	.file		"crti.asm"
mgl@1371
 16637
+
mgl@1371
 16638
+	.section	".init"
mgl@1371
 16639
+/* Just load the GOT */
mgl@1371
 16640
+	.align 2
mgl@1371
 16641
+	.global	_init
mgl@1371
 16642
+_init:
mgl@1371
 16643
+	stm	--sp, r6, lr
mgl@1371
 16644
+	lddpc	r6, 1f		
mgl@1371
 16645
+0:	
mgl@1371
 16646
+	rsub	r6, pc
mgl@1371
 16647
+	rjmp	2f
mgl@1371
 16648
+	.align	2
mgl@1371
 16649
+1:	.long	0b - _GLOBAL_OFFSET_TABLE_		
mgl@1371
 16650
+2:	
mgl@1371
 16651
+				
mgl@1371
 16652
+	.section	".fini"
mgl@1371
 16653
+/* Just load the GOT */
mgl@1371
 16654
+	.align	2
mgl@1371
 16655
+	.global	_fini
mgl@1371
 16656
+_fini:
mgl@1371
 16657
+	stm	--sp, r6, lr
mgl@1371
 16658
+	lddpc	r6, 1f		
mgl@1371
 16659
+0:	
mgl@1371
 16660
+	rsub	r6, pc
mgl@1371
 16661
+	rjmp	2f
mgl@1371
 16662
+	.align	2
mgl@1371
 16663
+1:	.long	0b - _GLOBAL_OFFSET_TABLE_		
mgl@1371
 16664
+2:	
mgl@1371
 16665
+
mgl@1371
 16666
--- /dev/null
mgl@1371
 16667
+++ b/gcc/config/avr32/crtn.asm
mgl@1371
 16668
@@ -0,0 +1,44 @@
mgl@1371
 16669
+/*   Copyright (C) 2001 Free Software Foundation, Inc.
mgl@1371
 16670
+    Written By Nick Clifton
mgl@1371
 16671
+
mgl@1371
 16672
+  This file is free software; you can redistribute it and/or modify it
mgl@1371
 16673
+  under the terms of the GNU General Public License as published by the
mgl@1371
 16674
+  Free Software Foundation; either version 2, or (at your option) any
mgl@1371
 16675
+  later version.
mgl@1371
 16676
+
mgl@1371
 16677
+  In addition to the permissions in the GNU General Public License, the
mgl@1371
 16678
+  Free Software Foundation gives you unlimited permission to link the
mgl@1371
 16679
+  compiled version of this file with other programs, and to distribute
mgl@1371
 16680
+  those programs without any restriction coming from the use of this
mgl@1371
 16681
+  file.  (The General Public License restrictions do apply in other
mgl@1371
 16682
+  respects; for example, they cover modification of the file, and
mgl@1371
 16683
+  distribution when not linked into another program.)
mgl@1371
 16684
+
mgl@1371
 16685
+  This file is distributed in the hope that it will be useful, but
mgl@1371
 16686
+  WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 16687
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
mgl@1371
 16688
+  General Public License for more details.
mgl@1371
 16689
+
mgl@1371
 16690
+  You should have received a copy of the GNU General Public License
mgl@1371
 16691
+  along with this program; see the file COPYING.  If not, write to
mgl@1371
 16692
+  the Free Software Foundation, 59 Temple Place - Suite 330,
mgl@1371
 16693
+  Boston, MA 02111-1307, USA.
mgl@1371
 16694
+
mgl@1371
 16695
+     As a special exception, if you link this library with files
mgl@1371
 16696
+     compiled with GCC to produce an executable, this does not cause
mgl@1371
 16697
+     the resulting executable to be covered by the GNU General Public License.
mgl@1371
 16698
+     This exception does not however invalidate any other reasons why
mgl@1371
 16699
+     the executable file might be covered by the GNU General Public License.
mgl@1371
 16700
+*/
mgl@1371
 16701
+
mgl@1371
 16702
+
mgl@1371
 16703
+
mgl@1371
 16704
+	
mgl@1371
 16705
+	.file		"crtn.asm"
mgl@1371
 16706
+
mgl@1371
 16707
+	.section	".init"
mgl@1371
 16708
+	ldm	sp++, r6, pc
mgl@1371
 16709
+			
mgl@1371
 16710
+	.section	".fini"
mgl@1371
 16711
+	ldm	sp++, r6, pc
mgl@1371
 16712
+		
mgl@1371
 16713
--- /dev/null
mgl@1371
 16714
+++ b/gcc/config/avr32/fpcp.md
mgl@1371
 16715
@@ -0,0 +1,551 @@
mgl@1371
 16716
+;;   AVR32 machine description file for Floating-Point instructions.
mgl@1371
 16717
+;;   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 16718
+;;
mgl@1371
 16719
+;;   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 16720
+;;
mgl@1371
 16721
+;;   This file is part of GCC.
mgl@1371
 16722
+;;
mgl@1371
 16723
+;;   This program is free software; you can redistribute it and/or modify
mgl@1371
 16724
+;;   it under the terms of the GNU General Public License as published by
mgl@1371
 16725
+;;   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 16726
+;;   (at your option) any later version.
mgl@1371
 16727
+;;
mgl@1371
 16728
+;;   This program is distributed in the hope that it will be useful,
mgl@1371
 16729
+;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 16730
+;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 16731
+;;   GNU General Public License for more details.
mgl@1371
 16732
+;;
mgl@1371
 16733
+;;   You should have received a copy of the GNU General Public License
mgl@1371
 16734
+;;   along with this program; if not, write to the Free Software
mgl@1371
 16735
+;;   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
mgl@1371
 16736
+
mgl@1371
 16737
+;; -*- Mode: Scheme -*-
mgl@1371
 16738
+
mgl@1371
 16739
+;;******************************************************************************
mgl@1371
 16740
+;; Automaton pipeline description for floating-point coprocessor insns
mgl@1371
 16741
+;;******************************************************************************
mgl@1371
 16742
+(define_cpu_unit "fid,fm1,fm2,fm3,fm4,fwb,fcmp,fcast" "avr32_ap")
mgl@1371
 16743
+
mgl@1371
 16744
+(define_insn_reservation "fmv_op" 1
mgl@1371
 16745
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16746
+       (eq_attr "type" "fmv"))
mgl@1371
 16747
+  "is,da,d,fid,fwb")
mgl@1371
 16748
+
mgl@1371
 16749
+(define_insn_reservation "fmul_op" 5
mgl@1371
 16750
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16751
+       (eq_attr "type" "fmul"))
mgl@1371
 16752
+  "is,da,d,fid,fm1,fm2,fm3,fm4,fwb")
mgl@1371
 16753
+
mgl@1371
 16754
+(define_insn_reservation "fcmps_op" 1
mgl@1371
 16755
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16756
+       (eq_attr "type" "fcmps"))
mgl@1371
 16757
+  "is,da,d,fid,fcmp")
mgl@1371
 16758
+
mgl@1371
 16759
+(define_insn_reservation "fcmpd_op" 2
mgl@1371
 16760
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16761
+       (eq_attr "type" "fcmpd"))
mgl@1371
 16762
+  "is,da,d,fid*2,fcmp")
mgl@1371
 16763
+
mgl@1371
 16764
+(define_insn_reservation "fcast_op" 3
mgl@1371
 16765
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16766
+       (eq_attr "type" "fcast"))
mgl@1371
 16767
+  "is,da,d,fid,fcmp,fcast,fwb")
mgl@1371
 16768
+
mgl@1371
 16769
+(define_insn_reservation "fmvcpu_op" 2
mgl@1371
 16770
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16771
+       (eq_attr "type" "fmvcpu"))
mgl@1371
 16772
+  "is,da,d")
mgl@1371
 16773
+
mgl@1371
 16774
+(define_insn_reservation "fldd_op" 1
mgl@1371
 16775
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16776
+       (eq_attr "type" "fldd"))
mgl@1371
 16777
+  "is,da,d,fwb")
mgl@1371
 16778
+
mgl@1371
 16779
+(define_insn_reservation "flds_op" 1
mgl@1371
 16780
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16781
+       (eq_attr "type" "flds"))
mgl@1371
 16782
+  "is,da,d,fwb")
mgl@1371
 16783
+
mgl@1371
 16784
+(define_insn_reservation "fsts_op" 0
mgl@1371
 16785
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16786
+       (eq_attr "type" "fsts"))
mgl@1371
 16787
+  "is,da*2,d")
mgl@1371
 16788
+
mgl@1371
 16789
+(define_insn_reservation "fstd_op" 0
mgl@1371
 16790
+  (and (eq_attr "pipeline" "ap")
mgl@1371
 16791
+       (eq_attr "type" "fstd"))
mgl@1371
 16792
+  "is,da*2,d")
mgl@1371
 16793
+
mgl@1371
 16794
+
mgl@1371
 16795
+(define_insn "*movsf_fpcp"
mgl@1371
 16796
+  [(set (match_operand:SF 0 "nonimmediate_operand"     "=f,f,r,f,m,r,r,r,m")
mgl@1371
 16797
+	(match_operand:SF 1 "general_operand"          " f,r,f,m,f,r,G,m,r"))]
mgl@1371
 16798
+  "TARGET_HARD_FLOAT"
mgl@1371
 16799
+  "@
mgl@1371
 16800
+   fmov.s\t%0, %1
mgl@1371
 16801
+   fmov.s\t%0, %1
mgl@1371
 16802
+   fmov.s\t%0, %1
mgl@1371
 16803
+   fld.s\t%0, %1
mgl@1371
 16804
+   fst.s\t%0, %1
mgl@1371
 16805
+   mov\t%0, %1
mgl@1371
 16806
+   mov\t%0, %1
mgl@1371
 16807
+   ld.w\t%0, %1
mgl@1371
 16808
+   st.w\t%0, %1"
mgl@1371
 16809
+  [(set_attr "length" "4,4,4,4,4,2,4,4,4")
mgl@1371
 16810
+   (set_attr "type" "fmv,flds,fmvcpu,flds,fsts,alu,alu,load,store")])
mgl@1371
 16811
+
mgl@1371
 16812
+(define_insn_and_split "*movdf_fpcp"
mgl@1371
 16813
+  [(set (match_operand:DF 0 "nonimmediate_operand"     "=f,f,r,f,m,r,r,m")
mgl@1371
 16814
+	(match_operand:DF 1 "general_operand"          " f,r,f,m,f,r,m,r"))]
mgl@1371
 16815
+  "TARGET_HARD_FLOAT"
mgl@1371
 16816
+  "@
mgl@1371
 16817
+   fmov.d\t%0, %1
mgl@1371
 16818
+   fmov.d\t%0, %1
mgl@1371
 16819
+   fmov.d\t%0, %1
mgl@1371
 16820
+   fld.d\t%0, %1
mgl@1371
 16821
+   fst.d\t%0, %1
mgl@1371
 16822
+   mov\t%0, %1\;mov\t%m0, %m1
mgl@1371
 16823
+   ld.d\t%0, %1
mgl@1371
 16824
+   st.d\t%0, %1"
mgl@1371
 16825
+
mgl@1371
 16826
+  "TARGET_HARD_FLOAT
mgl@1371
 16827
+   && reload_completed
mgl@1371
 16828
+   && (REG_P(operands[0]) &&  (REGNO_REG_CLASS(REGNO(operands[0])) == GENERAL_REGS))
mgl@1371
 16829
+   && (REG_P(operands[1]) &&  (REGNO_REG_CLASS(REGNO(operands[1])) == GENERAL_REGS))"
mgl@1371
 16830
+  [(set (match_dup 0) (match_dup 1))
mgl@1371
 16831
+   (set (match_dup 2) (match_dup 3))]
mgl@1371
 16832
+  "
mgl@1371
 16833
+   {
mgl@1371
 16834
+    operands[2] = gen_highpart (SImode, operands[0]);
mgl@1371
 16835
+    operands[0] = gen_lowpart (SImode, operands[0]);
mgl@1371
 16836
+    operands[3] = gen_highpart(SImode, operands[1]);
mgl@1371
 16837
+    operands[1] = gen_lowpart(SImode, operands[1]);
mgl@1371
 16838
+   }
mgl@1371
 16839
+  "
mgl@1371
 16840
+
mgl@1371
 16841
+  [(set_attr "length" "4,4,4,4,4,4,4,4")
mgl@1371
 16842
+   (set_attr "type" "fmv,fldd,fmvcpu,fldd,fstd,alu2,load2,store2")])
mgl@1371
 16843
+
mgl@1371
 16844
+
mgl@1371
 16845
+(define_insn "mulsf3"
mgl@1371
 16846
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16847
+	(mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16848
+		 (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 16849
+  "TARGET_HARD_FLOAT"
mgl@1371
 16850
+  "fmul.s\t%0, %1, %2"
mgl@1371
 16851
+  [(set_attr "length" "4")
mgl@1371
 16852
+   (set_attr "type" "fmul")])
mgl@1371
 16853
+
mgl@1371
 16854
+(define_insn "nmulsf3"
mgl@1371
 16855
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16856
+	(neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16857
+                         (match_operand:SF 2 "avr32_fp_register_operand" "f"))))]
mgl@1371
 16858
+  "TARGET_HARD_FLOAT"
mgl@1371
 16859
+  "fnmul.s\t%0, %1, %2"
mgl@1371
 16860
+  [(set_attr "length" "4")
mgl@1371
 16861
+   (set_attr "type" "fmul")])
mgl@1371
 16862
+
mgl@1371
 16863
+(define_peephole2
mgl@1371
 16864
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "")
mgl@1371
 16865
+	(mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
mgl@1371
 16866
+		 (match_operand:SF 2 "avr32_fp_register_operand" "")))
mgl@1371
 16867
+   (set (match_operand:SF          3 "avr32_fp_register_operand" "")
mgl@1371
 16868
+	(neg:SF (match_dup 0)))]
mgl@1371
 16869
+  "TARGET_HARD_FLOAT &&
mgl@1371
 16870
+   (peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[3]) == REGNO(operands[0])))"
mgl@1371
 16871
+  [(set (match_dup 3)
mgl@1371
 16872
+	(neg:SF (mult:SF (match_dup 1)
mgl@1371
 16873
+			 (match_dup 2))))]
mgl@1371
 16874
+)
mgl@1371
 16875
+
mgl@1371
 16876
+
mgl@1371
 16877
+(define_insn "macsf3"
mgl@1371
 16878
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16879
+	(plus:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16880
+                          (match_operand:SF 2 "avr32_fp_register_operand" "f"))
mgl@1371
 16881
+                 (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 16882
+  "TARGET_HARD_FLOAT"
mgl@1371
 16883
+  "fmac.s\t%0, %1, %2"
mgl@1371
 16884
+  [(set_attr "length" "4")
mgl@1371
 16885
+   (set_attr "type" "fmul")])
mgl@1371
 16886
+
mgl@1371
 16887
+(define_insn "nmacsf3"
mgl@1371
 16888
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16889
+	(plus:SF  (neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16890
+                                   (match_operand:SF 2 "avr32_fp_register_operand" "f")))
mgl@1371
 16891
+                  (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 16892
+  "TARGET_HARD_FLOAT"
mgl@1371
 16893
+  "fnmac.s\t%0, %1, %2"
mgl@1371
 16894
+  [(set_attr "length" "4")
mgl@1371
 16895
+   (set_attr "type" "fmul")])
mgl@1371
 16896
+
mgl@1371
 16897
+(define_peephole2
mgl@1371
 16898
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "")
mgl@1371
 16899
+	(mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
mgl@1371
 16900
+		 (match_operand:SF 2 "avr32_fp_register_operand" "")))
mgl@1371
 16901
+   (set (match_operand:SF          3 "avr32_fp_register_operand" "")
mgl@1371
 16902
+	(minus:SF
mgl@1371
 16903
+	 (match_dup 3)
mgl@1371
 16904
+	 (match_dup 0)))]
mgl@1371
 16905
+  "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
mgl@1371
 16906
+  [(set (match_dup 3)
mgl@1371
 16907
+	(plus:SF  (neg:SF (mult:SF (match_dup 1)
mgl@1371
 16908
+                                   (match_dup 2)))
mgl@1371
 16909
+                  (match_dup 3)))]
mgl@1371
 16910
+)
mgl@1371
 16911
+
mgl@1371
 16912
+
mgl@1371
 16913
+(define_insn "msubacsf3"
mgl@1371
 16914
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16915
+	(minus:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16916
+                           (match_operand:SF 2 "avr32_fp_register_operand" "f"))
mgl@1371
 16917
+                  (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 16918
+  "TARGET_HARD_FLOAT"
mgl@1371
 16919
+  "fmsc.s\t%0, %1, %2"
mgl@1371
 16920
+  [(set_attr "length" "4")
mgl@1371
 16921
+   (set_attr "type" "fmul")])
mgl@1371
 16922
+
mgl@1371
 16923
+(define_peephole2
mgl@1371
 16924
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "")
mgl@1371
 16925
+	(mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
mgl@1371
 16926
+		 (match_operand:SF 2 "avr32_fp_register_operand" "")))
mgl@1371
 16927
+   (set (match_operand:SF          3 "avr32_fp_register_operand" "")
mgl@1371
 16928
+	(minus:SF
mgl@1371
 16929
+	 (match_dup 0)
mgl@1371
 16930
+	 (match_dup 3)))]
mgl@1371
 16931
+  "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
mgl@1371
 16932
+  [(set (match_dup 3)
mgl@1371
 16933
+	(minus:SF  (mult:SF (match_dup 1)
mgl@1371
 16934
+			    (match_dup 2))
mgl@1371
 16935
+		   (match_dup 3)))]
mgl@1371
 16936
+)
mgl@1371
 16937
+
mgl@1371
 16938
+(define_insn "nmsubacsf3"
mgl@1371
 16939
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16940
+	(minus:SF  (neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16941
+                                    (match_operand:SF 2 "avr32_fp_register_operand" "f")))
mgl@1371
 16942
+                   (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 16943
+  "TARGET_HARD_FLOAT"
mgl@1371
 16944
+  "fnmsc.s\t%0, %1, %2"
mgl@1371
 16945
+  [(set_attr "length" "4")
mgl@1371
 16946
+   (set_attr "type" "fmul")])
mgl@1371
 16947
+
mgl@1371
 16948
+
mgl@1371
 16949
+
mgl@1371
 16950
+(define_insn "addsf3"
mgl@1371
 16951
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16952
+	(plus:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16953
+		 (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 16954
+  "TARGET_HARD_FLOAT"
mgl@1371
 16955
+  "fadd.s\t%0, %1, %2"
mgl@1371
 16956
+  [(set_attr "length" "4")
mgl@1371
 16957
+   (set_attr "type" "fmul")])
mgl@1371
 16958
+
mgl@1371
 16959
+(define_insn "subsf3"
mgl@1371
 16960
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16961
+	(minus:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
mgl@1371
 16962
+                  (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 16963
+  "TARGET_HARD_FLOAT"
mgl@1371
 16964
+  "fsub.s\t%0, %1, %2"
mgl@1371
 16965
+  [(set_attr "length" "4")
mgl@1371
 16966
+   (set_attr "type" "fmul")])
mgl@1371
 16967
+
mgl@1371
 16968
+
mgl@1371
 16969
+(define_insn "negsf2"
mgl@1371
 16970
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16971
+	(neg:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 16972
+  "TARGET_HARD_FLOAT"
mgl@1371
 16973
+  "fneg.s\t%0, %1"
mgl@1371
 16974
+  [(set_attr "length" "4")
mgl@1371
 16975
+   (set_attr "type" "fmv")])
mgl@1371
 16976
+
mgl@1371
 16977
+(define_insn "abssf2"
mgl@1371
 16978
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16979
+	(abs:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 16980
+  "TARGET_HARD_FLOAT"
mgl@1371
 16981
+  "fabs.s\t%0, %1"
mgl@1371
 16982
+  [(set_attr "length" "4")
mgl@1371
 16983
+   (set_attr "type" "fmv")])
mgl@1371
 16984
+
mgl@1371
 16985
+(define_insn "truncdfsf2"
mgl@1371
 16986
+  [(set (match_operand:SF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16987
+	(float_truncate:SF
mgl@1371
 16988
+         (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 16989
+  "TARGET_HARD_FLOAT"
mgl@1371
 16990
+  "fcastd.s\t%0, %1"
mgl@1371
 16991
+  [(set_attr "length" "4")
mgl@1371
 16992
+   (set_attr "type" "fcast")])
mgl@1371
 16993
+
mgl@1371
 16994
+(define_insn "extendsfdf2"
mgl@1371
 16995
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 16996
+	(float_extend:DF
mgl@1371
 16997
+         (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 16998
+  "TARGET_HARD_FLOAT"
mgl@1371
 16999
+  "fcasts.d\t%0, %1"
mgl@1371
 17000
+  [(set_attr "length" "4")
mgl@1371
 17001
+   (set_attr "type" "fcast")])
mgl@1371
 17002
+
mgl@1371
 17003
+(define_insn "muldf3"
mgl@1371
 17004
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17005
+	(mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17006
+		 (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 17007
+  "TARGET_HARD_FLOAT"
mgl@1371
 17008
+  "fmul.d\t%0, %1, %2"
mgl@1371
 17009
+  [(set_attr "length" "4")
mgl@1371
 17010
+   (set_attr "type" "fmul")])
mgl@1371
 17011
+
mgl@1371
 17012
+(define_insn "nmuldf3"
mgl@1371
 17013
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17014
+	(neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17015
+                         (match_operand:DF 2 "avr32_fp_register_operand" "f"))))]
mgl@1371
 17016
+  "TARGET_HARD_FLOAT"
mgl@1371
 17017
+  "fnmul.d\t%0, %1, %2"
mgl@1371
 17018
+  [(set_attr "length" "4")
mgl@1371
 17019
+   (set_attr "type" "fmul")])
mgl@1371
 17020
+
mgl@1371
 17021
+(define_peephole2
mgl@1371
 17022
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "")
mgl@1371
 17023
+	(mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
mgl@1371
 17024
+		 (match_operand:DF 2 "avr32_fp_register_operand" "")))
mgl@1371
 17025
+   (set (match_operand:DF          3 "avr32_fp_register_operand" "")
mgl@1371
 17026
+	(neg:DF (match_dup 0)))]
mgl@1371
 17027
+  "TARGET_HARD_FLOAT &&
mgl@1371
 17028
+   (peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[3]) == REGNO(operands[0])))"
mgl@1371
 17029
+  [(set (match_dup 3)
mgl@1371
 17030
+	(neg:DF (mult:DF (match_dup 1)
mgl@1371
 17031
+			 (match_dup 2))))]
mgl@1371
 17032
+)
mgl@1371
 17033
+
mgl@1371
 17034
+(define_insn "macdf3"
mgl@1371
 17035
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17036
+	(plus:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17037
+                          (match_operand:DF 2 "avr32_fp_register_operand" "f"))
mgl@1371
 17038
+                 (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 17039
+  "TARGET_HARD_FLOAT"
mgl@1371
 17040
+  "fmac.d\t%0, %1, %2"
mgl@1371
 17041
+  [(set_attr "length" "4")
mgl@1371
 17042
+   (set_attr "type" "fmul")])
mgl@1371
 17043
+
mgl@1371
 17044
+(define_insn "msubacdf3"
mgl@1371
 17045
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17046
+	(minus:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17047
+                           (match_operand:DF 2 "avr32_fp_register_operand" "f"))
mgl@1371
 17048
+                  (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 17049
+  "TARGET_HARD_FLOAT"
mgl@1371
 17050
+  "fmsc.d\t%0, %1, %2"
mgl@1371
 17051
+  [(set_attr "length" "4")
mgl@1371
 17052
+   (set_attr "type" "fmul")])
mgl@1371
 17053
+
mgl@1371
 17054
+(define_peephole2
mgl@1371
 17055
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "")
mgl@1371
 17056
+	(mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
mgl@1371
 17057
+		 (match_operand:DF 2 "avr32_fp_register_operand" "")))
mgl@1371
 17058
+   (set (match_operand:DF          3 "avr32_fp_register_operand" "")
mgl@1371
 17059
+	(minus:DF
mgl@1371
 17060
+	 (match_dup 0)
mgl@1371
 17061
+	 (match_dup 3)))]
mgl@1371
 17062
+  "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
mgl@1371
 17063
+  [(set (match_dup 3)
mgl@1371
 17064
+	(minus:DF  (mult:DF (match_dup 1)
mgl@1371
 17065
+			    (match_dup 2))
mgl@1371
 17066
+		   (match_dup 3)))]
mgl@1371
 17067
+  )
mgl@1371
 17068
+
mgl@1371
 17069
+(define_insn "nmsubacdf3"
mgl@1371
 17070
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17071
+	(minus:DF  (neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17072
+                                    (match_operand:DF 2 "avr32_fp_register_operand" "f")))
mgl@1371
 17073
+                   (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 17074
+  "TARGET_HARD_FLOAT"
mgl@1371
 17075
+  "fnmsc.d\t%0, %1, %2"
mgl@1371
 17076
+  [(set_attr "length" "4")
mgl@1371
 17077
+   (set_attr "type" "fmul")])
mgl@1371
 17078
+
mgl@1371
 17079
+(define_insn "nmacdf3"
mgl@1371
 17080
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17081
+	(plus:DF  (neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17082
+                                   (match_operand:DF 2 "avr32_fp_register_operand" "f")))
mgl@1371
 17083
+                  (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
mgl@1371
 17084
+  "TARGET_HARD_FLOAT"
mgl@1371
 17085
+  "fnmac.d\t%0, %1, %2"
mgl@1371
 17086
+  [(set_attr "length" "4")
mgl@1371
 17087
+   (set_attr "type" "fmul")])
mgl@1371
 17088
+
mgl@1371
 17089
+(define_peephole2
mgl@1371
 17090
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "")
mgl@1371
 17091
+	(mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
mgl@1371
 17092
+		 (match_operand:DF 2 "avr32_fp_register_operand" "")))
mgl@1371
 17093
+   (set (match_operand:DF          3 "avr32_fp_register_operand" "")
mgl@1371
 17094
+	(minus:DF
mgl@1371
 17095
+	 (match_dup 3)
mgl@1371
 17096
+	 (match_dup 0)))]
mgl@1371
 17097
+  "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
mgl@1371
 17098
+  [(set (match_dup 3)
mgl@1371
 17099
+	(plus:DF  (neg:DF (mult:DF (match_dup 1)
mgl@1371
 17100
+                                   (match_dup 2)))
mgl@1371
 17101
+                  (match_dup 3)))]
mgl@1371
 17102
+)
mgl@1371
 17103
+
mgl@1371
 17104
+(define_insn "adddf3"
mgl@1371
 17105
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17106
+	(plus:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17107
+		 (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 17108
+  "TARGET_HARD_FLOAT"
mgl@1371
 17109
+  "fadd.d\t%0, %1, %2"
mgl@1371
 17110
+  [(set_attr "length" "4")
mgl@1371
 17111
+   (set_attr "type" "fmul")])
mgl@1371
 17112
+
mgl@1371
 17113
+(define_insn "subdf3"
mgl@1371
 17114
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17115
+	(minus:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
mgl@1371
 17116
+                  (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
mgl@1371
 17117
+  "TARGET_HARD_FLOAT"
mgl@1371
 17118
+  "fsub.d\t%0, %1, %2"
mgl@1371
 17119
+  [(set_attr "length" "4")
mgl@1371
 17120
+   (set_attr "type" "fmul")])
mgl@1371
 17121
+
mgl@1371
 17122
+(define_insn "negdf2"
mgl@1371
 17123
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17124
+	(neg:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 17125
+  "TARGET_HARD_FLOAT"
mgl@1371
 17126
+  "fneg.d\t%0, %1"
mgl@1371
 17127
+  [(set_attr "length" "4")
mgl@1371
 17128
+   (set_attr "type" "fmv")])
mgl@1371
 17129
+
mgl@1371
 17130
+(define_insn "absdf2"
mgl@1371
 17131
+  [(set (match_operand:DF          0 "avr32_fp_register_operand" "=f")
mgl@1371
 17132
+	(abs:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 17133
+  "TARGET_HARD_FLOAT"
mgl@1371
 17134
+  "fabs.d\t%0, %1"
mgl@1371
 17135
+  [(set_attr "length" "4")
mgl@1371
 17136
+   (set_attr "type" "fmv")])
mgl@1371
 17137
+
mgl@1371
 17138
+
mgl@1371
 17139
+(define_expand "cmpdf"
mgl@1371
 17140
+  [(set (cc0)
mgl@1371
 17141
+	(compare:DF
mgl@1371
 17142
+	 (match_operand:DF 0 "general_operand" "")
mgl@1371
 17143
+	 (match_operand:DF 1 "general_operand"  "")))]
mgl@1371
 17144
+  "TARGET_HARD_FLOAT"
mgl@1371
 17145
+  "{
mgl@1371
 17146
+   rtx tmpreg;
mgl@1371
 17147
+   if ( !REG_P(operands[0]) )
mgl@1371
 17148
+     operands[0] = force_reg(DFmode, operands[0]);
mgl@1371
 17149
+
mgl@1371
 17150
+   if ( !REG_P(operands[1]) )
mgl@1371
 17151
+     operands[1] = force_reg(DFmode, operands[1]);
mgl@1371
 17152
+
mgl@1371
 17153
+   avr32_compare_op0 = operands[0];
mgl@1371
 17154
+   avr32_compare_op1 = operands[1];
mgl@1371
 17155
+
mgl@1371
 17156
+   emit_insn(gen_cmpdf_internal(operands[0], operands[1]));
mgl@1371
 17157
+
mgl@1371
 17158
+   tmpreg = gen_reg_rtx(SImode);
mgl@1371
 17159
+   emit_insn(gen_fpcc_to_reg(tmpreg));
mgl@1371
 17160
+   emit_insn(gen_reg_to_cc(tmpreg));
mgl@1371
 17161
+
mgl@1371
 17162
+   DONE;
mgl@1371
 17163
+  }"
mgl@1371
 17164
+)
mgl@1371
 17165
+
mgl@1371
 17166
+(define_insn "cmpdf_internal"
mgl@1371
 17167
+  [(set (reg:CC FPCC_REGNUM)
mgl@1371
 17168
+	(compare:CC
mgl@1371
 17169
+	 (match_operand:DF 0 "avr32_fp_register_operand" "f")
mgl@1371
 17170
+	 (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 17171
+  "TARGET_HARD_FLOAT"
mgl@1371
 17172
+  {
mgl@1371
 17173
+   if (!rtx_equal_p(cc_prev_status.mdep.fpvalue, SET_SRC(PATTERN (insn))) )
mgl@1371
 17174
+      return "fcmp.d\t%0, %1";
mgl@1371
 17175
+   return "";
mgl@1371
 17176
+  }
mgl@1371
 17177
+  [(set_attr "length" "4")
mgl@1371
 17178
+   (set_attr "type" "fcmpd")
mgl@1371
 17179
+   (set_attr "cc" "fpcompare")])
mgl@1371
 17180
+
mgl@1371
 17181
+(define_expand "cmpsf"
mgl@1371
 17182
+  [(set (cc0)
mgl@1371
 17183
+	(compare:SF
mgl@1371
 17184
+	 (match_operand:SF 0 "general_operand" "")
mgl@1371
 17185
+	 (match_operand:SF 1 "general_operand"  "")))]
mgl@1371
 17186
+  "TARGET_HARD_FLOAT"
mgl@1371
 17187
+  "{
mgl@1371
 17188
+   rtx tmpreg;
mgl@1371
 17189
+   if ( !REG_P(operands[0]) )
mgl@1371
 17190
+     operands[0] = force_reg(SFmode, operands[0]);
mgl@1371
 17191
+
mgl@1371
 17192
+   if ( !REG_P(operands[1]) )
mgl@1371
 17193
+     operands[1] = force_reg(SFmode, operands[1]);
mgl@1371
 17194
+
mgl@1371
 17195
+   avr32_compare_op0 = operands[0];
mgl@1371
 17196
+   avr32_compare_op1 = operands[1];
mgl@1371
 17197
+
mgl@1371
 17198
+   emit_insn(gen_cmpsf_internal(operands[0], operands[1]));
mgl@1371
 17199
+
mgl@1371
 17200
+   tmpreg = gen_reg_rtx(SImode);
mgl@1371
 17201
+   emit_insn(gen_fpcc_to_reg(tmpreg));
mgl@1371
 17202
+   emit_insn(gen_reg_to_cc(tmpreg));
mgl@1371
 17203
+
mgl@1371
 17204
+   DONE;
mgl@1371
 17205
+  }"
mgl@1371
 17206
+)
mgl@1371
 17207
+
mgl@1371
 17208
+(define_insn "cmpsf_internal"
mgl@1371
 17209
+  [(set (reg:CC FPCC_REGNUM)
mgl@1371
 17210
+	(compare:CC
mgl@1371
 17211
+	 (match_operand:SF 0 "avr32_fp_register_operand" "f")
mgl@1371
 17212
+	 (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
mgl@1371
 17213
+  "TARGET_HARD_FLOAT"
mgl@1371
 17214
+  {
mgl@1371
 17215
+   if (!rtx_equal_p(cc_prev_status.mdep.fpvalue, SET_SRC(PATTERN (insn))) )
mgl@1371
 17216
+      return "fcmp.s\t%0, %1";
mgl@1371
 17217
+   return "";
mgl@1371
 17218
+  }
mgl@1371
 17219
+  [(set_attr "length" "4")
mgl@1371
 17220
+   (set_attr "type" "fcmps")
mgl@1371
 17221
+   (set_attr "cc" "fpcompare")])
mgl@1371
 17222
+
mgl@1371
 17223
+(define_insn "fpcc_to_reg"
mgl@1371
 17224
+  [(set (match_operand:SI 0 "register_operand" "=r")
mgl@1371
 17225
+	(unspec:SI [(reg:CC FPCC_REGNUM)]
mgl@1371
 17226
+		   UNSPEC_FPCC_TO_REG))]
mgl@1371
 17227
+  "TARGET_HARD_FLOAT"
mgl@1371
 17228
+  "fmov.s\t%0, fsr"
mgl@1371
 17229
+  [(set_attr "length" "4")
mgl@1371
 17230
+   (set_attr "type" "fmvcpu")])
mgl@1371
 17231
+
mgl@1371
 17232
+(define_insn "reg_to_cc"
mgl@1371
 17233
+  [(set (cc0)
mgl@1371
 17234
+	(unspec:SI [(match_operand:SI 0 "register_operand" "r")]
mgl@1371
 17235
+		   UNSPEC_REG_TO_CC))]
mgl@1371
 17236
+  "TARGET_HARD_FLOAT"
mgl@1371
 17237
+  "musfr\t%0"
mgl@1371
 17238
+  [(set_attr "length" "2")
mgl@1371
 17239
+   (set_attr "type" "alu")
mgl@1371
 17240
+   (set_attr "cc" "from_fpcc")])
mgl@1371
 17241
+
mgl@1371
 17242
+(define_insn "stm_fp"
mgl@1371
 17243
+  [(unspec [(match_operand 0 "register_operand" "r")
mgl@1371
 17244
+            (match_operand 1 "const_int_operand" "")
mgl@1371
 17245
+            (match_operand 2 "const_int_operand" "")]
mgl@1371
 17246
+	   UNSPEC_STMFP)]
mgl@1371
 17247
+  "TARGET_HARD_FLOAT"
mgl@1371
 17248
+  {
mgl@1371
 17249
+    int cop_reglist = INTVAL(operands[1]);
mgl@1371
 17250
+
mgl@1371
 17251
+    if (INTVAL(operands[2]) != 0)
mgl@1371
 17252
+      return "stcm.w\tcp0, --%0, %C1";
mgl@1371
 17253
+    else
mgl@1371
 17254
+      return "stcm.w\tcp0, %0, %C1";
mgl@1371
 17255
+
mgl@1371
 17256
+    if ( cop_reglist & ~0xff ){
mgl@1371
 17257
+      operands[1] = GEN_INT(cop_reglist & ~0xff);
mgl@1371
 17258
+      if (INTVAL(operands[2]) != 0)
mgl@1371
 17259
+         return "stcm.d\tcp0, --%0, %D1";
mgl@1371
 17260
+      else
mgl@1371
 17261
+         return "stcm.d\tcp0, %0, %D1";
mgl@1371
 17262
+    }
mgl@1371
 17263
+  }
mgl@1371
 17264
+  [(set_attr "type" "fstm")
mgl@1371
 17265
+   (set_attr "length" "4")
mgl@1371
 17266
+   (set_attr "cc" "none")])
mgl@1371
 17267
--- /dev/null
mgl@1371
 17268
+++ b/gcc/config/avr32/lib1funcs.S
mgl@1371
 17269
@@ -0,0 +1,2874 @@
mgl@1371
 17270
+/* Macro for moving immediate value to register. */	
mgl@1371
 17271
+.macro mov_imm	reg, imm
mgl@1371
 17272
+.if	(((\imm & 0xfffff) == \imm) || ((\imm | 0xfff00000) == \imm))
mgl@1371
 17273
+	mov	\reg, \imm
mgl@1371
 17274
+#if __AVR32_UC__ >= 2
mgl@1371
 17275
+.elseif	((\imm & 0xffff) == 0)
mgl@1371
 17276
+	movh	\reg, hi(\imm)
mgl@1371
 17277
+
mgl@1371
 17278
+#endif
mgl@1371
 17279
+.else
mgl@1371
 17280
+	mov	\reg, lo(\imm)
mgl@1371
 17281
+	orh	\reg, hi(\imm)
mgl@1371
 17282
+.endif
mgl@1371
 17283
+.endm
mgl@1371
 17284
+	
mgl@1371
 17285
+	
mgl@1371
 17286
+	 
mgl@1371
 17287
+/* Adjust the unpacked double number if it is a subnormal number.
mgl@1371
 17288
+   The exponent and mantissa pair are stored
mgl@1371
 17289
+   in [mant_hi,mant_lo] and [exp]. A register with the correct sign bit in
mgl@1371
 17290
+   the MSB is passed in [sign]. Needs two scratch
mgl@1371
 17291
+   registers [scratch1] and [scratch2]. An adjusted and packed double float
mgl@1371
 17292
+   is present in [mant_hi,mant_lo] after macro has executed */
mgl@1371
 17293
+.macro  adjust_subnormal_df     exp, mant_lo, mant_hi, sign, scratch1, scratch2 
mgl@1371
 17294
+        /* We have an exponent which is <=0 indicating a subnormal number
mgl@1371
 17295
+           As it should be stored as if the exponent was 1 (although the
mgl@1371
 17296
+           exponent field is all zeros to indicate a subnormal number)
mgl@1371
 17297
+           we have to shift down the mantissa to its correct position. */
mgl@1371
 17298
+        neg     \exp
mgl@1371
 17299
+        sub     \exp,-1                   /* amount to shift down */
mgl@1371
 17300
+        cp.w    \exp,54
mgl@1371
 17301
+        brlo    50f                     /* if more than 53 shift steps, the
mgl@1371
 17302
+                                           entire mantissa will disappear
mgl@1371
 17303
+                                           without any rounding to occur */
mgl@1371
 17304
+        mov     \mant_hi, 0
mgl@1371
 17305
+        mov     \mant_lo, 0
mgl@1371
 17306
+        rjmp    52f
mgl@1371
 17307
+50:     
mgl@1371
 17308
+        sub     \exp,-10                /* do the shift to position the
mgl@1371
 17309
+                                           mantissa at the same time
mgl@1371
 17310
+                                           note! this does not include the
mgl@1371
 17311
+                                           final 1 step shift to add the sign */
mgl@1371
 17312
+ 
mgl@1371
 17313
+        /* when shifting, save all shifted out bits in [scratch2]. we may need to
mgl@1371
 17314
+           look at them to make correct rounding. */
mgl@1371
 17315
+ 
mgl@1371
 17316
+        rsub    \scratch1,\exp,32       /* get inverted shift count */
mgl@1371
 17317
+        cp.w    \exp,32                 /* handle shifts >= 32 separately */
mgl@1371
 17318
+        brhs    51f
mgl@1371
 17319
+ 
mgl@1371
 17320
+        /* small (<32) shift amount, both words are part of the shift */
mgl@1371
 17321
+        lsl     \scratch2,\mant_lo,\scratch1               /* save bits to shift out from lsw*/
mgl@1371
 17322
+        lsl     \scratch1,\mant_hi,\scratch1               /* get bits from msw destined for lsw*/
mgl@1371
 17323
+        lsr     \mant_lo,\mant_lo,\exp                     /* shift down lsw */
mgl@1371
 17324
+        lsr     \mant_hi,\mant_hi,\exp                     /* shift down msw */
mgl@1371
 17325
+        or      \mant_hi,\scratch1                         /* add bits from msw with prepared lsw */
mgl@1371
 17326
+        rjmp    50f
mgl@1371
 17327
+ 
mgl@1371
 17328
+        /* large (>=32) shift amount, only lsw will have bits left after shift.
mgl@1371
 17329
+           note that shift operations will use ((shift count) mod 32) so
mgl@1371
 17330
+           we do not need to subtract 32 from shift count. */
mgl@1371
 17331
+51:
mgl@1371
 17332
+        lsl     \scratch2,\mant_hi,\scratch1               /* save bits to shift out from msw */
mgl@1371
 17333
+        or      \scratch2,\mant_lo                         /* also save all bits from lsw */
mgl@1371
 17334
+        mov     \mant_lo,\mant_hi                          /* msw -> lsw (i.e. "shift 32 first") */
mgl@1371
 17335
+        mov     \mant_hi,0                                 /* clear msw */
mgl@1371
 17336
+        lsr     \mant_lo,\mant_lo,\exp                     /* make rest of shift inside lsw */
mgl@1371
 17337
+ 
mgl@1371
 17338
+50:
mgl@1371
 17339
+        /* result is almost ready to return, except that least significant bit
mgl@1371
 17340
+           and the part we already shifted out may cause the result to be
mgl@1371
 17341
+           rounded */
mgl@1371
 17342
+        bld     \mant_lo,0                   /* get bit to be shifted out */
mgl@1371
 17343
+        brcc    51f                          /* if bit was 0, no rounding */
mgl@1371
 17344
+ 
mgl@1371
 17345
+        /* msb of part to remove is 1, so rounding depends on rest of bits */
mgl@1371
 17346
+        tst     \scratch2,\scratch2                   /* get shifted out tail */
mgl@1371
 17347
+        brne    50f     /* if rest > 0, do round */
mgl@1371
 17348
+        bld     \mant_lo,1                   /* we have to look at lsb in result */
mgl@1371
 17349
+        brcc    51f   /* if lsb is 0, don't round */
mgl@1371
 17350
+ 
mgl@1371
 17351
+50:
mgl@1371
 17352
+        /* subnormal result requires rounding
mgl@1371
 17353
+           rounding may cause subnormal to become smallest normal number
mgl@1371
 17354
+           luckily, smallest normal number has exactly the representation
mgl@1371
 17355
+           we got by rippling a one bit up from mantissa into exponent field. */
mgl@1371
 17356
+        sub     \mant_lo,-1
mgl@1371
 17357
+        subcc   \mant_hi,-1
mgl@1371
 17358
+ 
mgl@1371
 17359
+51:
mgl@1371
 17360
+        /* shift and return packed double with correct sign */
mgl@1371
 17361
+        rol     \sign
mgl@1371
 17362
+        ror     \mant_hi
mgl@1371
 17363
+        ror     \mant_lo        
mgl@1371
 17364
+52:     
mgl@1371
 17365
+.endm
mgl@1371
 17366
+ 
mgl@1371
 17367
+ 
mgl@1371
 17368
+/* Adjust subnormal single float number with exponent [exp]
mgl@1371
 17369
+   and mantissa [mant] and round.    */
mgl@1371
 17370
+.macro  adjust_subnormal_sf     sf, exp, mant, sign, scratch
mgl@1371
 17371
+        /* subnormal number */
mgl@1371
 17372
+        rsub    \exp,\exp, 1            /* shift amount */
mgl@1371
 17373
+        cp.w    \exp, 25
mgl@1371
 17374
+        movhs   \mant, 0                
mgl@1371
 17375
+        brhs    90f                     /* Return zero */
mgl@1371
 17376
+        rsub    \scratch, \exp, 32
mgl@1371
 17377
+        lsl     \scratch, \mant,\scratch/* Check if there are any bits set
mgl@1371
 17378
+                                           in the bits discarded in the mantissa */
mgl@1371
 17379
+        srne    \scratch                /* If so set the lsb of the shifted mantissa */ 
mgl@1371
 17380
+        lsr     \mant,\mant,\exp        /* Shift the mantissa */
mgl@1371
 17381
+        or      \mant, \scratch         /* Round lsb if any bits were shifted out  */
mgl@1371
 17382
+        /* Rounding :   For explaination, see round_sf. */
mgl@1371
 17383
+        mov     \scratch, 0x7f          /* Set rounding constant */
mgl@1371
 17384
+        bld     \mant, 8                
mgl@1371
 17385
+        subeq   \scratch, -1            /* For odd numbers use rounding constant 0x80 */
mgl@1371
 17386
+        add     \mant, \scratch         /* Add rounding constant to mantissa */
mgl@1371
 17387
+        /* We can't overflow because mantissa is at least shifted one position
mgl@1371
 17388
+           to the right so the implicit bit is zero. We can however get the implicit
mgl@1371
 17389
+           bit set after rounding which means that we have the lowest normal number
mgl@1371
 17390
+           but this is ok since this bit has the same position as the LSB of the
mgl@1371
 17391
+           exponent */
mgl@1371
 17392
+        lsr     \sf, \mant, 7
mgl@1371
 17393
+        /* Rotate in sign */
mgl@1371
 17394
+        lsl     \sign, 1
mgl@1371
 17395
+        ror     \sf
mgl@1371
 17396
+90:     
mgl@1371
 17397
+.endm
mgl@1371
 17398
+ 
mgl@1371
 17399
+ 
mgl@1371
 17400
+/* Round the unpacked df number with exponent [exp] and
mgl@1371
 17401
+   mantissa [mant_hi, mant_lo]. Uses scratch register
mgl@1371
 17402
+   [scratch] */
mgl@1371
 17403
+.macro  round_df        exp, mant_lo, mant_hi, scratch
mgl@1371
 17404
+        mov     \scratch, 0x3ff         /* Rounding constant */
mgl@1371
 17405
+        bld     \mant_lo,11             /* Check if lsb in the final result is  
mgl@1371
 17406
+                                           set */
mgl@1371
 17407
+        subeq   \scratch, -1            /* Adjust rounding constant to 0x400
mgl@1371
 17408
+                                           if rounding 0.5 upwards */   
mgl@1371
 17409
+        add     \mant_lo, \scratch      /* Round */
mgl@1371
 17410
+        acr     \mant_hi                /* If overflowing we know that
mgl@1371
 17411
+                                           we have all zeros in the bits not
mgl@1371
 17412
+                                           scaled out so we can leave them
mgl@1371
 17413
+                                           but we must increase the exponent with
mgl@1371
 17414
+                                           two since we had an implicit bit
mgl@1371
 17415
+                                           which is lost + the extra overflow bit */
mgl@1371
 17416
+        subcs   \exp, -2                /* Update exponent */
mgl@1371
 17417
+.endm           
mgl@1371
 17418
+ 
mgl@1371
 17419
+/* Round single float number stored in [mant] and [exp] */
mgl@1371
 17420
+.macro  round_sf        exp, mant, scratch
mgl@1371
 17421
+        /* Round:       
mgl@1371
 17422
+                For 0.5 we round to nearest even integer
mgl@1371
 17423
+                for all other cases we round to nearest integer.
mgl@1371
 17424
+                This means that if the digit left of the "point" (.)
mgl@1371
 17425
+                is 1 we can add 0x80 to the mantissa since the
mgl@1371
 17426
+                corner case 0x180 will round up to 0x200. If the
mgl@1371
 17427
+                digit left of the "point" is 0 we will have to
mgl@1371
 17428
+                add 0x7f since this will give 0xff and hence a
mgl@1371
 17429
+                truncation/rounding downwards for the corner
mgl@1371
 17430
+                case when the 9 lowest bits are 0x080 */
mgl@1371
 17431
+        mov     \scratch, 0x7f  /* Set rounding constant */
mgl@1371
 17432
+        /* Check if the mantissa is even or odd */
mgl@1371
 17433
+        bld     \mant, 8
mgl@1371
 17434
+        subeq   \scratch, -1    /* Rounding constant should be 0x80 */
mgl@1371
 17435
+        add     \mant, \scratch
mgl@1371
 17436
+        subcs   \exp, -2        /* Adjust exponent if we overflowed */          
mgl@1371
 17437
+.endm
mgl@1371
 17438
+ 
mgl@1371
 17439
+                 
mgl@1371
 17440
+ 
mgl@1371
 17441
+/* Pack a single float number stored in [mant] and [exp]
mgl@1371
 17442
+   into a single float number in [sf]  */
mgl@1371
 17443
+.macro  pack_sf sf, exp, mant
mgl@1371
 17444
+        bld     \mant,31                  /* implicit bit to z */
mgl@1371
 17445
+        subne   \exp,1                   /* if subnormal (implicit bit 0)
mgl@1371
 17446
+                                          adjust exponent to storage format */
mgl@1371
 17447
+        
mgl@1371
 17448
+        lsr     \sf, \mant, 7
mgl@1371
 17449
+        bfins   \sf, \exp, 24, 8
mgl@1371
 17450
+.endm   
mgl@1371
 17451
+ 
mgl@1371
 17452
+/* Pack exponent [exp] and mantissa [mant_hi, mant_lo]
mgl@1371
 17453
+   into [df_hi, df_lo].  [df_hi] is shifted
mgl@1371
 17454
+   one bit up so the sign bit can be shifted into it */
mgl@1371
 17455
+        
mgl@1371
 17456
+.macro  pack_df         exp, mant_lo, mant_hi, df_lo, df_hi
mgl@1371
 17457
+        bld     \mant_hi,31                  /* implicit bit to z */
mgl@1371
 17458
+        subne   \exp,1                   /* if subnormal (implicit bit 0)
mgl@1371
 17459
+                                          adjust exponent to storage format */
mgl@1371
 17460
+ 
mgl@1371
 17461
+        lsr     \mant_lo,11                  /* shift back lsw */
mgl@1371
 17462
+        or      \df_lo,\mant_lo,\mant_hi<<21          /* combine with low bits from msw */
mgl@1371
 17463
+        lsl     \mant_hi,1                   /* get rid of implicit bit */
mgl@1371
 17464
+        lsr     \mant_hi,11                  /* shift back msw except for one step*/
mgl@1371
 17465
+        or      \df_hi,\mant_hi,\exp<<21          /* combine msw with exponent */
mgl@1371
 17466
+.endm
mgl@1371
 17467
+ 
mgl@1371
 17468
+/* Normalize single float number stored in [mant] and [exp]
mgl@1371
 17469
+   using scratch register [scratch] */
mgl@1371
 17470
+.macro  normalize_sf    exp, mant, scratch
mgl@1371
 17471
+        /* Adjust exponent and mantissa */
mgl@1371
 17472
+        clz     \scratch, \mant
mgl@1371
 17473
+        sub     \exp, \scratch
mgl@1371
 17474
+        lsl     \mant, \mant, \scratch
mgl@1371
 17475
+.endm
mgl@1371
 17476
+ 
mgl@1371
 17477
+/* Normalize the exponent and mantissa pair stored
mgl@1371
 17478
+   in [mant_hi,mant_lo] and [exp]. Needs two scratch
mgl@1371
 17479
+   registers [scratch1] and [scratch2]. */
mgl@1371
 17480
+.macro  normalize_df            exp, mant_lo, mant_hi, scratch1, scratch2
mgl@1371
 17481
+        clz     \scratch1,\mant_hi     /* Check if we have zeros in high bits */
mgl@1371
 17482
+        breq    80f                     /* No need for scaling if no zeros in high bits */
mgl@1371
 17483
+        brcs    81f                     /* Check for all zeros */           
mgl@1371
 17484
+ 
mgl@1371
 17485
+        /* shift amount is smaller than 32, and involves both msw and lsw*/
mgl@1371
 17486
+        rsub    \scratch2,\scratch1,32  /* shift mantissa */
mgl@1371
 17487
+        lsl     \mant_hi,\mant_hi,\scratch1
mgl@1371
 17488
+        lsr     \scratch2,\mant_lo,\scratch2
mgl@1371
 17489
+        or      \mant_hi,\scratch2
mgl@1371
 17490
+        lsl     \mant_lo,\mant_lo,\scratch1
mgl@1371
 17491
+        sub     \exp,\scratch1          /* adjust exponent */
mgl@1371
 17492
+        rjmp    80f                     /* Finished */  
mgl@1371
 17493
+81:
mgl@1371
 17494
+        /* shift amount is greater than 32 */
mgl@1371
 17495
+        clz     \scratch1,\mant_lo      /* shift mantissa */
mgl@1371
 17496
+        movcs   \scratch1, 0
mgl@1371
 17497
+        subcc   \scratch1,-32
mgl@1371
 17498
+        lsl     \mant_hi,\mant_lo,\scratch1
mgl@1371
 17499
+        mov     \mant_lo,0
mgl@1371
 17500
+        sub     \exp,\scratch1          /* adjust exponent */
mgl@1371
 17501
+80:     
mgl@1371
 17502
+.endm
mgl@1371
 17503
+        
mgl@1371
 17504
+ 
mgl@1371
 17505
+/* Fast but approximate multiply of two 64-bit numbers to give a 64 bit result.
mgl@1371
 17506
+   The multiplication of [al]x[bl] is discarded.
mgl@1371
 17507
+   Operands in [ah], [al], [bh], [bl].
mgl@1371
 17508
+   Scratch registers in [sh], [sl].
mgl@1371
 17509
+   Returns results in registers [rh], [rl].*/
mgl@1371
 17510
+.macro  mul_approx_df   ah, al, bh, bl, rh, rl, sh, sl
mgl@1371
 17511
+        mulu.d  \sl, \ah, \bl
mgl@1371
 17512
+        macu.d  \sl, \al, \bh
mgl@1371
 17513
+        mulu.d  \rl, \ah, \bh
mgl@1371
 17514
+        add     \rl, \sh
mgl@1371
 17515
+        acr     \rh
mgl@1371
 17516
+.endm           
mgl@1371
 17517
+ 
mgl@1371
 17518
+ 
mgl@1371
 17519
+        
mgl@1371
 17520
+#if defined(L_avr32_f64_mul) || defined(L_avr32_f64_mul_fast)
mgl@1371
 17521
+        .align  2
mgl@1371
 17522
+#if defined(L_avr32_f64_mul)
mgl@1371
 17523
+        .global __avr32_f64_mul
mgl@1371
 17524
+        .type  __avr32_f64_mul,@function
mgl@1371
 17525
+__avr32_f64_mul:
mgl@1371
 17526
+#else 
mgl@1371
 17527
+        .global __avr32_f64_mul_fast
mgl@1371
 17528
+        .type  __avr32_f64_mul_fast,@function
mgl@1371
 17529
+__avr32_f64_mul_fast:
mgl@1371
 17530
+#endif                
mgl@1371
 17531
+        or      r12, r10, r11 << 1 
mgl@1371
 17532
+        breq   __avr32_f64_mul_op1_zero        
mgl@1371
 17533
+
mgl@1371
 17534
+#if defined(L_avr32_f64_mul)
mgl@1371
 17535
+	pushm	r4-r7, lr
mgl@1371
 17536
+#else
mgl@1371
 17537
+        stm     --sp, r5,r6,r7,lr       
mgl@1371
 17538
+#endif
mgl@1371
 17539
+
mgl@1371
 17540
+#define AVR32_F64_MUL_OP1_INT_BITS 1
mgl@1371
 17541
+#define AVR32_F64_MUL_OP2_INT_BITS 10
mgl@1371
 17542
+#define AVR32_F64_MUL_RES_INT_BITS 11
mgl@1371
 17543
+	
mgl@1371
 17544
+        /* op1 in {r11,r10}*/
mgl@1371
 17545
+        /* op2 in {r9,r8}*/
mgl@1371
 17546
+        eor     lr, r11, r9             /* MSB(lr) = Sign(op1) ^ Sign(op2) */
mgl@1371
 17547
+ 
mgl@1371
 17548
+        /* Unpack op1 to 1.63 format*/        
mgl@1371
 17549
+        /* exp: r7 */
mgl@1371
 17550
+        /* sf:  r11, r10 */
mgl@1371
 17551
+	bfextu	r7, r11, 20, 11 /* Extract exponent */
mgl@1371
 17552
+
mgl@1371
 17553
+	mov	r5, 1
mgl@1371
 17554
+
mgl@1371
 17555
+        /* Check if normalization is needed */
mgl@1371
 17556
+        breq    __avr32_f64_mul_op1_subnormal /*If number is subnormal, normalize it */ 
mgl@1371
 17557
+
mgl@1371
 17558
+        lsl     r11, (12-AVR32_F64_MUL_OP1_INT_BITS-1) /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 17559
+        or      r11, r11, r10>>(32-(12-AVR32_F64_MUL_OP1_INT_BITS-1))
mgl@1371
 17560
+        lsl     r10, (12-AVR32_F64_MUL_OP1_INT_BITS-1)
mgl@1371
 17561
+	bfins	r11, r5, 32 - (1 + AVR32_F64_MUL_OP1_INT_BITS), 1 + AVR32_F64_MUL_OP1_INT_BITS /* Insert implicit bit */
mgl@1371
 17562
+
mgl@1371
 17563
+
mgl@1371
 17564
+22:     
mgl@1371
 17565
+        /* Unpack op2 to 10.54 format */
mgl@1371
 17566
+        /* exp: r6 */
mgl@1371
 17567
+        /* sf:  r9, r8 */
mgl@1371
 17568
+	bfextu	r6, r9, 20, 11 /* Extract exponent */
mgl@1371
 17569
+
mgl@1371
 17570
+        /* Check if normalization is needed */
mgl@1371
 17571
+        breq    __avr32_f64_mul_op2_subnormal /*If number is subnormal, normalize it */ 
mgl@1371
 17572
+
mgl@1371
 17573
+	lsl	r8, 1 /* Extract mantissa, leave room for implicit bit */
mgl@1371
 17574
+	rol	r9	
mgl@1371
 17575
+	bfins	r9, r5, 32 - (1 + AVR32_F64_MUL_OP2_INT_BITS), 1 + AVR32_F64_MUL_OP2_INT_BITS /* Insert implicit bit */
mgl@1371
 17576
+
mgl@1371
 17577
+23:     
mgl@1371
 17578
+ 
mgl@1371
 17579
+        /* Check if any operands are NaN or INF */
mgl@1371
 17580
+        cp      r7, 0x7ff
mgl@1371
 17581
+        breq    __avr32_f64_mul_op_nan_or_inf /* Check op1 for NaN or Inf */
mgl@1371
 17582
+        cp      r6, 0x7ff
mgl@1371
 17583
+        breq    __avr32_f64_mul_op_nan_or_inf  /* Check op2 for NaN or Inf */
mgl@1371
 17584
+ 
mgl@1371
 17585
+ 
mgl@1371
 17586
+        /* Calculate new exponent in r12*/
mgl@1371
 17587
+        add     r12, r7, r6
mgl@1371
 17588
+        sub     r12, (1023-1)
mgl@1371
 17589
+ 
mgl@1371
 17590
+#if defined(L_avr32_f64_mul)
mgl@1371
 17591
+	/* Do the multiplication.
mgl@1371
 17592
+           Place result in [r11, r10, r7, r6]. The result is in 11.117 format.  */
mgl@1371
 17593
+        mulu.d  r4, r11, r8
mgl@1371
 17594
+        macu.d  r4, r10, r9
mgl@1371
 17595
+        mulu.d  r6, r10, r8
mgl@1371
 17596
+        mulu.d  r10, r11, r9
mgl@1371
 17597
+	add	r7, r4
mgl@1371
 17598
+	adc	r10, r10, r5	
mgl@1371
 17599
+	acr	r11
mgl@1371
 17600
+#else
mgl@1371
 17601
+	/* Do the multiplication using approximate calculation. discard the al x bl
mgl@1371
 17602
+	   calculation.
mgl@1371
 17603
+           Place result in [r11, r10, r7]. The result is in 11.85 format.  */
mgl@1371
 17604
+
mgl@1371
 17605
+        /* Do the multiplication using approximate calculation.
mgl@1371
 17606
+         Place result in r11, r10. Use r7, r6 as scratch registers */
mgl@1371
 17607
+        mulu.d  r6, r11, r8
mgl@1371
 17608
+        macu.d  r6, r10, r9
mgl@1371
 17609
+        mulu.d  r10, r11, r9
mgl@1371
 17610
+        add     r10, r7
mgl@1371
 17611
+        acr     r11
mgl@1371
 17612
+#endif 
mgl@1371
 17613
+        /* Adjust exponent and mantissa */
mgl@1371
 17614
+        /* [r12]:exp, [r11, r10]:mant [r7, r6]:sticky bits */
mgl@1371
 17615
+        /* Mantissa may be of the format 00000000000.0xxx or 00000000000.1xxx. */
mgl@1371
 17616
+        /* In the first case, shift one pos to left.*/
mgl@1371
 17617
+        bld     r11, 32-AVR32_F64_MUL_RES_INT_BITS-1
mgl@1371
 17618
+	breq	0f	
mgl@1371
 17619
+	lsl	r7, 1
mgl@1371
 17620
+	rol	r10
mgl@1371
 17621
+	rol	r11
mgl@1371
 17622
+	sub	r12, 1
mgl@1371
 17623
+0:	
mgl@1371
 17624
+        cp      r12, 0  
mgl@1371
 17625
+        brle    __avr32_f64_mul_res_subnormal /*Result was subnormal.*/
mgl@1371
 17626
+ 
mgl@1371
 17627
+        /* Check for Inf. */
mgl@1371
 17628
+        cp.w    r12, 0x7ff
mgl@1371
 17629
+        brge    __avr32_f64_mul_res_inf
mgl@1371
 17630
+
mgl@1371
 17631
+	/* Insert exponent. */
mgl@1371
 17632
+	bfins	r11, r12, 20, 11  
mgl@1371
 17633
+
mgl@1371
 17634
+        /* Result was not subnormal. Perform rounding. */
mgl@1371
 17635
+        /* For the fast version we discard the sticky bits and always round
mgl@1371
 17636
+	   the halfwaycase up. */
mgl@1371
 17637
+24:	
mgl@1371
 17638
+#if defined(L_avr32_f64_mul)
mgl@1371
 17639
+	or	r6, r6, r10 << 31 /* Or in parity bit into stickybits */
mgl@1371
 17640
+	or	r7, r7, r6 >> 1   /* Or together sticky and still make the msb 
mgl@1371
 17641
+				     of r7 represent the halfway bit. */
mgl@1371
 17642
+	eorh	r7, 0x8000	  /* Toggle halfway bit. */
mgl@1371
 17643
+	/* We should now round up by adding one for the following cases:
mgl@1371
 17644
+
mgl@1371
 17645
+		halfway   sticky|parity  round-up
mgl@1371
 17646
+		   0            x           no
mgl@1371
 17647
+		   1            0           no
mgl@1371
 17648
+	           1            1           yes
mgl@1371
 17649
+
mgl@1371
 17650
+	   Since we have inverted the halfway bit we can use the satu instruction
mgl@1371
 17651
+           by saturating to 1 bit to implement this. 
mgl@1371
 17652
+	*/ 
mgl@1371
 17653
+	satu	r7 >> 0, 1
mgl@1371
 17654
+#else
mgl@1371
 17655
+	lsr	r7, 31
mgl@1371
 17656
+#endif	
mgl@1371
 17657
+	add	r10, r7
mgl@1371
 17658
+	acr	r11	
mgl@1371
 17659
+        
mgl@1371
 17660
+        /* Insert sign bit*/
mgl@1371
 17661
+        bld     lr, 31
mgl@1371
 17662
+        bst     r11, 31
mgl@1371
 17663
+        
mgl@1371
 17664
+        /* Return result in [r11,r10] */
mgl@1371
 17665
+#if defined(L_avr32_f64_mul)
mgl@1371
 17666
+	popm	r4-r7, pc
mgl@1371
 17667
+#else
mgl@1371
 17668
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 17669
+#endif
mgl@1371
 17670
+ 
mgl@1371
 17671
+ 
mgl@1371
 17672
+__avr32_f64_mul_op1_subnormal:
mgl@1371
 17673
+	andh	r11, 0x000f /* Remove sign bit and exponent */
mgl@1371
 17674
+        clz     r12, r10    /* Count leading zeros in lsw */
mgl@1371
 17675
+        clz     r6, r11     /* Count leading zeros in msw */
mgl@1371
 17676
+        subcs	r12, -32 + AVR32_F64_MUL_OP1_INT_BITS 
mgl@1371
 17677
+	movcs	r6, r12
mgl@1371
 17678
+	subcc	r6, AVR32_F64_MUL_OP1_INT_BITS
mgl@1371
 17679
+	cp.w	r6, 32
mgl@1371
 17680
+	brge	0f
mgl@1371
 17681
+		
mgl@1371
 17682
+        /* shifting involves both msw and lsw*/
mgl@1371
 17683
+        rsub    r12, r6, 32  /* shift mantissa */
mgl@1371
 17684
+        lsl     r11, r11, r6
mgl@1371
 17685
+        lsr     r12, r10, r12
mgl@1371
 17686
+        or      r11, r12
mgl@1371
 17687
+        lsl     r10, r10, r6
mgl@1371
 17688
+	sub	r6, 12-AVR32_F64_MUL_OP1_INT_BITS
mgl@1371
 17689
+        sub     r7, r6          /* adjust exponent */
mgl@1371
 17690
+        rjmp    22b             /* Finished */  
mgl@1371
 17691
+0:
mgl@1371
 17692
+        /* msw is zero so only need to consider lsw */
mgl@1371
 17693
+        lsl     r11, r10, r6
mgl@1371
 17694
+	breq	__avr32_f64_mul_res_zero
mgl@1371
 17695
+        mov     r10, 0
mgl@1371
 17696
+	sub	r6, 12-AVR32_F64_MUL_OP1_INT_BITS
mgl@1371
 17697
+        sub     r7, r6            /* adjust exponent */
mgl@1371
 17698
+        rjmp    22b
mgl@1371
 17699
+
mgl@1371
 17700
+ 
mgl@1371
 17701
+__avr32_f64_mul_op2_subnormal:
mgl@1371
 17702
+	andh	r9, 0x000f  /* Remove sign bit and exponent */
mgl@1371
 17703
+        clz     r12, r8    /* Count leading zeros in lsw */
mgl@1371
 17704
+        clz     r5, r9     /* Count leading zeros in msw */
mgl@1371
 17705
+        subcs	r12, -32 + AVR32_F64_MUL_OP2_INT_BITS 
mgl@1371
 17706
+	movcs	r5, r12
mgl@1371
 17707
+	subcc	r5, AVR32_F64_MUL_OP2_INT_BITS
mgl@1371
 17708
+	cp.w	r5, 32
mgl@1371
 17709
+	brge	0f
mgl@1371
 17710
+		
mgl@1371
 17711
+        /* shifting involves both msw and lsw*/
mgl@1371
 17712
+        rsub    r12, r5, 32  /* shift mantissa */
mgl@1371
 17713
+        lsl     r9, r9, r5
mgl@1371
 17714
+        lsr     r12, r8, r12
mgl@1371
 17715
+        or      r9, r12
mgl@1371
 17716
+        lsl     r8, r8, r5
mgl@1371
 17717
+	sub	r5, 12 - AVR32_F64_MUL_OP2_INT_BITS
mgl@1371
 17718
+        sub     r6, r5          /* adjust exponent */
mgl@1371
 17719
+        rjmp    23b             /* Finished */  
mgl@1371
 17720
+0:
mgl@1371
 17721
+        /* msw is zero so only need to consider lsw */
mgl@1371
 17722
+        lsl     r9, r8, r5
mgl@1371
 17723
+	breq	__avr32_f64_mul_res_zero
mgl@1371
 17724
+        mov     r8, 0
mgl@1371
 17725
+	sub	r5, 12 - AVR32_F64_MUL_OP2_INT_BITS
mgl@1371
 17726
+        sub     r6, r5            /* adjust exponent */
mgl@1371
 17727
+        rjmp    23b
mgl@1371
 17728
+                
mgl@1371
 17729
+ 
mgl@1371
 17730
+__avr32_f64_mul_op_nan_or_inf:
mgl@1371
 17731
+        /* Same code for OP1 and OP2*/
mgl@1371
 17732
+        /* Since we are here, at least one of the OPs were NaN or INF*/
mgl@1371
 17733
+	andh	r9, 0x000f  /* Remove sign bit and exponent */
mgl@1371
 17734
+	andh	r11, 0x000f  /* Remove sign bit and exponent */
mgl@1371
 17735
+        /* Merge the regs in each operand to check for zero*/
mgl@1371
 17736
+        or      r11, r10 /* op1 */
mgl@1371
 17737
+        or      r9, r8 /* op2 */
mgl@1371
 17738
+        /* Check if op1 is NaN or INF */
mgl@1371
 17739
+        cp      r7, 0x7ff
mgl@1371
 17740
+        brne    __avr32_f64_mul_op1_not_naninf
mgl@1371
 17741
+        /* op1 was NaN or INF.*/
mgl@1371
 17742
+        cp      r11, 0
mgl@1371
 17743
+        brne    __avr32_f64_mul_res_nan /* op1 was NaN. Result will be NaN*/
mgl@1371
 17744
+        /*op1 was INF. check if op2 is NaN or INF*/
mgl@1371
 17745
+        cp      r6, 0x7ff
mgl@1371
 17746
+        brne    __avr32_f64_mul_res_inf /*op1 was INF, op2 was neither NaN nor INF*/
mgl@1371
 17747
+        /* op1 is INF, op2 is either NaN or INF*/
mgl@1371
 17748
+        cp      r9, 0
mgl@1371
 17749
+        breq    __avr32_f64_mul_res_inf /*op2 was also INF*/
mgl@1371
 17750
+        rjmp    __avr32_f64_mul_res_nan /*op2 was NaN*/
mgl@1371
 17751
+ 
mgl@1371
 17752
+__avr32_f64_mul_op1_not_naninf:
mgl@1371
 17753
+        /* op1 was not NaN nor INF. Then op2 must be NaN or INF*/
mgl@1371
 17754
+        cp      r9, 0
mgl@1371
 17755
+        breq    __avr32_f64_mul_res_inf /*op2 was INF, return INF*/
mgl@1371
 17756
+        rjmp   __avr32_f64_mul_res_nan /*else return NaN*/
mgl@1371
 17757
+        
mgl@1371
 17758
+__avr32_f64_mul_res_subnormal:/* Multiply result was subnormal. */
mgl@1371
 17759
+#if defined(L_avr32_f64_mul)
mgl@1371
 17760
+	/* Check how much we must scale down the mantissa. */
mgl@1371
 17761
+	neg	r12
mgl@1371
 17762
+	sub	r12, -1     /* We do no longer have an implicit bit. */
mgl@1371
 17763
+	satu	r12 >> 0, 6 /* Saturate shift amount to max 63. */
mgl@1371
 17764
+	cp.w	r12, 32
mgl@1371
 17765
+	brge	0f
mgl@1371
 17766
+	/* Shift amount <32 */
mgl@1371
 17767
+	rsub	r8, r12, 32
mgl@1371
 17768
+	or	r6, r7 
mgl@1371
 17769
+	lsr	r7, r7, r12
mgl@1371
 17770
+	lsl	r9, r10, r8
mgl@1371
 17771
+	or	r7, r9
mgl@1371
 17772
+	lsr	r10, r10, r12
mgl@1371
 17773
+	lsl	r9, r11, r8
mgl@1371
 17774
+	or	r10, r9
mgl@1371
 17775
+	lsr	r11, r11, r12
mgl@1371
 17776
+	rjmp	24b
mgl@1371
 17777
+0:
mgl@1371
 17778
+	/* Shift amount >=32 */
mgl@1371
 17779
+	rsub	r8, r12, 32
mgl@1371
 17780
+	moveq	r9, 0
mgl@1371
 17781
+	breq	0f
mgl@1371
 17782
+	lsl	r9, r11, r8
mgl@1371
 17783
+0:	
mgl@1371
 17784
+	or	r6, r7
mgl@1371
 17785
+	or	r6, r6, r10 << 1 
mgl@1371
 17786
+	lsr	r10, r10, r12
mgl@1371
 17787
+	or	r7, r9, r10
mgl@1371
 17788
+	lsr	r10, r11, r12
mgl@1371
 17789
+	mov	r11, 0	
mgl@1371
 17790
+	rjmp	24b				
mgl@1371
 17791
+#else
mgl@1371
 17792
+	/* Flush to zero for the fast version. */
mgl@1371
 17793
+        mov     r11, lr /*Get correct sign*/
mgl@1371
 17794
+        andh    r11, 0x8000, COH
mgl@1371
 17795
+        mov     r10, 0
mgl@1371
 17796
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 17797
+#endif
mgl@1371
 17798
+
mgl@1371
 17799
+__avr32_f64_mul_res_zero:/* Multiply result is zero. */
mgl@1371
 17800
+        mov     r11, lr /*Get correct sign*/
mgl@1371
 17801
+        andh    r11, 0x8000, COH
mgl@1371
 17802
+        mov     r10, 0
mgl@1371
 17803
+#if defined(L_avr32_f64_mul)
mgl@1371
 17804
+	popm	r4-r7, pc
mgl@1371
 17805
+#else
mgl@1371
 17806
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 17807
+#endif
mgl@1371
 17808
+ 
mgl@1371
 17809
+__avr32_f64_mul_res_nan:        /* Return NaN. */
mgl@1371
 17810
+        mov     r11, -1
mgl@1371
 17811
+        mov     r10, -1
mgl@1371
 17812
+#if defined(L_avr32_f64_mul)
mgl@1371
 17813
+	popm	r4-r7, pc
mgl@1371
 17814
+#else
mgl@1371
 17815
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 17816
+#endif
mgl@1371
 17817
+        
mgl@1371
 17818
+__avr32_f64_mul_res_inf:        /* Return INF. */
mgl@1371
 17819
+	mov	r11, 0xfff00000
mgl@1371
 17820
+        bld     lr, 31
mgl@1371
 17821
+        bst     r11, 31
mgl@1371
 17822
+        mov     r10, 0
mgl@1371
 17823
+#if defined(L_avr32_f64_mul)
mgl@1371
 17824
+	popm	r4-r7, pc
mgl@1371
 17825
+#else
mgl@1371
 17826
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 17827
+#endif
mgl@1371
 17828
+
mgl@1371
 17829
+__avr32_f64_mul_op1_zero:
mgl@1371
 17830
+        /* Get sign */
mgl@1371
 17831
+        eor     r11, r11, r9
mgl@1371
 17832
+        andh    r11, 0x8000, COH  
mgl@1371
 17833
+        /* Check if op2 is Inf or NaN. */
mgl@1371
 17834
+        bfextu  r12, r9, 20, 11
mgl@1371
 17835
+        cp.w    r12, 0x7ff
mgl@1371
 17836
+        retne   r12     /* Return 0.0 */
mgl@1371
 17837
+        /* Return NaN */
mgl@1371
 17838
+        mov     r10, -1
mgl@1371
 17839
+        mov     r11, -1
mgl@1371
 17840
+        ret     r12
mgl@1371
 17841
+         
mgl@1371
 17842
+
mgl@1371
 17843
+ 
mgl@1371
 17844
+#endif
mgl@1371
 17845
+                
mgl@1371
 17846
+ 
mgl@1371
 17847
+#if  defined(L_avr32_f64_addsub) || defined(L_avr32_f64_addsub_fast)
mgl@1371
 17848
+        .align  2
mgl@1371
 17849
+
mgl@1371
 17850
+__avr32_f64_sub_from_add:
mgl@1371
 17851
+        /* Switch sign on op2 */
mgl@1371
 17852
+        eorh    r9, 0x8000
mgl@1371
 17853
+
mgl@1371
 17854
+#if  defined(L_avr32_f64_addsub_fast)
mgl@1371
 17855
+        .global __avr32_f64_sub_fast
mgl@1371
 17856
+        .type  __avr32_f64_sub_fast,@function
mgl@1371
 17857
+__avr32_f64_sub_fast:
mgl@1371
 17858
+#else	
mgl@1371
 17859
+        .global __avr32_f64_sub
mgl@1371
 17860
+        .type  __avr32_f64_sub,@function
mgl@1371
 17861
+__avr32_f64_sub:
mgl@1371
 17862
+#endif
mgl@1371
 17863
+        
mgl@1371
 17864
+        /* op1 in {r11,r10}*/
mgl@1371
 17865
+        /* op2 in {r9,r8}*/
mgl@1371
 17866
+
mgl@1371
 17867
+#if  defined(L_avr32_f64_addsub_fast)
mgl@1371
 17868
+        /* If op2 is zero just return op1 */
mgl@1371
 17869
+        or      r12, r8, r9 << 1
mgl@1371
 17870
+        reteq   r12 
mgl@1371
 17871
+#endif
mgl@1371
 17872
+ 
mgl@1371
 17873
+        /* Check signs */
mgl@1371
 17874
+        eor     r12, r11, r9
mgl@1371
 17875
+        /* Different signs, use addition. */
mgl@1371
 17876
+        brmi    __avr32_f64_add_from_sub
mgl@1371
 17877
+ 
mgl@1371
 17878
+        stm     --sp, r5, r6, r7, lr
mgl@1371
 17879
+ 
mgl@1371
 17880
+        /* Get sign of op1 into r12 */
mgl@1371
 17881
+        mov     r12, r11
mgl@1371
 17882
+        andh    r12, 0x8000, COH                
mgl@1371
 17883
+ 
mgl@1371
 17884
+        /* Remove sign from operands */
mgl@1371
 17885
+        cbr     r11, 31
mgl@1371
 17886
+        cbr     r9, 31
mgl@1371
 17887
+ 
mgl@1371
 17888
+        /* Put the largest number in [r11, r10]
mgl@1371
 17889
+           and the smallest number in [r9, r8] */
mgl@1371
 17890
+        cp      r10, r8
mgl@1371
 17891
+        cpc     r11, r9
mgl@1371
 17892
+        brhs    1f /* Skip swap if operands already correctly ordered*/
mgl@1371
 17893
+        /* Operands were not correctly ordered, swap them*/
mgl@1371
 17894
+        mov     r7, r11
mgl@1371
 17895
+        mov     r11, r9
mgl@1371
 17896
+        mov     r9, r7
mgl@1371
 17897
+        mov     r7, r10
mgl@1371
 17898
+        mov     r10, r8
mgl@1371
 17899
+        mov     r8, r7
mgl@1371
 17900
+        eorh    r12, 0x8000 /* Invert sign in r12*/
mgl@1371
 17901
+1:      
mgl@1371
 17902
+        /* Unpack largest operand - opH */      
mgl@1371
 17903
+        /* exp: r7 */
mgl@1371
 17904
+        /* sf:  r11, r10 */
mgl@1371
 17905
+        lsr     r7, r11, 20 /* Extract exponent */
mgl@1371
 17906
+        lsl     r11, 11 /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 17907
+        or      r11, r11, r10>>21
mgl@1371
 17908
+        lsl     r10, 11
mgl@1371
 17909
+        sbr     r11, 31 /* Insert implicit bit */
mgl@1371
 17910
+ 
mgl@1371
 17911
+        
mgl@1371
 17912
+        /* Unpack smallest operand - opL */
mgl@1371
 17913
+        /* exp: r6 */
mgl@1371
 17914
+        /* sf:  r9, r8 */
mgl@1371
 17915
+        lsr     r6, r9, 20 /* Extract exponent */
mgl@1371
 17916
+        breq    __avr32_f64_sub_opL_subnormal /* If either zero or subnormal */
mgl@1371
 17917
+        lsl     r9, 11 /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 17918
+        or      r9, r9, r8>>21
mgl@1371
 17919
+        lsl     r8, 11
mgl@1371
 17920
+        sbr     r9, 31 /* Insert implicit bit */
mgl@1371
 17921
+ 
mgl@1371
 17922
+
mgl@1371
 17923
+__avr32_f64_sub_opL_subnormal_done:     
mgl@1371
 17924
+        /* opH is NaN or Inf. */
mgl@1371
 17925
+        cp.w    r7, 0x7ff
mgl@1371
 17926
+        breq    __avr32_f64_sub_opH_nan_or_inf
mgl@1371
 17927
+
mgl@1371
 17928
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 17929
+        rsub    r6, r7
mgl@1371
 17930
+        breq    __avr32_f64_sub_shift_done /* No need to shift, exponents are equal*/
mgl@1371
 17931
+ 
mgl@1371
 17932
+        /* Scale mantissa [r9, r8] with amount [r6].
mgl@1371
 17933
+        Uses scratch registers [r5] and [lr].
mgl@1371
 17934
+        In IEEE mode:Must not forget the sticky bits we intend to shift out. */
mgl@1371
 17935
+ 
mgl@1371
 17936
+        rsub    r5,r6,32 /* get (32 - shift count)
mgl@1371
 17937
+                            (if shift count > 32 we get a
mgl@1371
 17938
+                            negative value, but that will
mgl@1371
 17939
+                            work as well in the code below.) */
mgl@1371
 17940
+ 
mgl@1371
 17941
+        cp.w    r6,32       /* handle shifts >= 32 separately */
mgl@1371
 17942
+        brhs    __avr32_f64_sub_longshift
mgl@1371
 17943
+ 
mgl@1371
 17944
+        /* small (<32) shift amount, both words are part of the shift
mgl@1371
 17945
+           first remember whether part that is lost contains any 1 bits ... */
mgl@1371
 17946
+        lsl     lr,r8,r5  /* shift away bits that are part of
mgl@1371
 17947
+                             final mantissa. only part that goes
mgl@1371
 17948
+                             to lr are bits that will be lost */
mgl@1371
 17949
+ 
mgl@1371
 17950
+        /* ... and now to the actual shift */
mgl@1371
 17951
+        lsl     r5,r9,r5  /* get bits from msw destined for lsw*/
mgl@1371
 17952
+        lsr     r8,r8,r6  /* shift down lsw of mantissa */
mgl@1371
 17953
+        lsr     r9,r9,r6  /* shift down msw of mantissa */
mgl@1371
 17954
+        or      r8,r5     /* combine these bits with prepared lsw*/
mgl@1371
 17955
+#if  defined(L_avr32_f64_addsub)
mgl@1371
 17956
+        cp.w    lr,0      /* if any '1' bit in part we lost ...*/
mgl@1371
 17957
+        srne    lr
mgl@1371
 17958
+        or      r8, lr     /* ... we need to set sticky bit*/
mgl@1371
 17959
+#endif
mgl@1371
 17960
+        
mgl@1371
 17961
+__avr32_f64_sub_shift_done:     
mgl@1371
 17962
+        /* Now subtract the mantissas. */
mgl@1371
 17963
+        sub     r10, r8
mgl@1371
 17964
+        sbc     r11, r11, r9
mgl@1371
 17965
+ 
mgl@1371
 17966
+        /* Normalize the exponent and mantissa pair stored in
mgl@1371
 17967
+        [r11,r10] and exponent in [r7]. Needs two scratch registers [r6] and [lr]. */
mgl@1371
 17968
+        clz     r6,r11     /* Check if we have zeros in high bits */
mgl@1371
 17969
+        breq    __avr32_f64_sub_longnormalize_done  /* No need for scaling if no zeros in high bits */
mgl@1371
 17970
+        brcs    __avr32_f64_sub_longnormalize
mgl@1371
 17971
+ 
mgl@1371
 17972
+	
mgl@1371
 17973
+        /* shift amount is smaller than 32, and involves both msw and lsw*/
mgl@1371
 17974
+        rsub    lr,r6,32  /* shift mantissa */
mgl@1371
 17975
+        lsl     r11,r11,r6
mgl@1371
 17976
+        lsr     lr,r10,lr
mgl@1371
 17977
+        or      r11,lr
mgl@1371
 17978
+        lsl     r10,r10,r6
mgl@1371
 17979
+ 
mgl@1371
 17980
+        sub     r7,r6    /* adjust exponent */
mgl@1371
 17981
+        brle    __avr32_f64_sub_subnormal_result
mgl@1371
 17982
+__avr32_f64_sub_longnormalize_done:     
mgl@1371
 17983
+        
mgl@1371
 17984
+#if defined(L_avr32_f64_addsub)
mgl@1371
 17985
+        /* Insert the bits we will remove from the mantissa r9[31:21] */
mgl@1371
 17986
+        lsl     r9, r10, (32 - 11)
mgl@1371
 17987
+#else
mgl@1371
 17988
+        /* Keep the last bit shifted out. */
mgl@1371
 17989
+        bfextu  r9, r10, 10, 1
mgl@1371
 17990
+#endif
mgl@1371
 17991
+ 
mgl@1371
 17992
+        /* Pack final result*/
mgl@1371
 17993
+        /* Input: [r7]:exp, [r11, r10]:mant, [r12]:sign in MSB */
mgl@1371
 17994
+        /* Result in [r11,r10] */
mgl@1371
 17995
+        /* Insert mantissa */
mgl@1371
 17996
+        lsr     r10, 11
mgl@1371
 17997
+        or      r10, r10, r11<<21
mgl@1371
 17998
+        lsr     r11, 11
mgl@1371
 17999
+        /* Insert exponent and sign bit*/
mgl@1371
 18000
+	bfins	r11, r7, 20, 11
mgl@1371
 18001
+        or      r11, r12
mgl@1371
 18002
+        
mgl@1371
 18003
+        /* Round */     
mgl@1371
 18004
+__avr32_f64_sub_round:
mgl@1371
 18005
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18006
+	mov_imm	r7, 0x80000000
mgl@1371
 18007
+        bld     r10, 0
mgl@1371
 18008
+        subne   r7, -1  
mgl@1371
 18009
+ 
mgl@1371
 18010
+        cp.w    r9, r7
mgl@1371
 18011
+        srhs    r9
mgl@1371
 18012
+#endif
mgl@1371
 18013
+        add     r10, r9
mgl@1371
 18014
+        acr     r11
mgl@1371
 18015
+        
mgl@1371
 18016
+        /* Return result in [r11,r10] */
mgl@1371
 18017
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 18018
+ 
mgl@1371
 18019
+ 
mgl@1371
 18020
+ 
mgl@1371
 18021
+__avr32_f64_sub_opL_subnormal:
mgl@1371
 18022
+        /* Extract the of mantissa */
mgl@1371
 18023
+        lsl     r9, 11 /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 18024
+        or      r9, r9, r8>>21
mgl@1371
 18025
+        lsl     r8, 11
mgl@1371
 18026
+ 
mgl@1371
 18027
+        /* Set exponent to 1 if we do not have a zero. */
mgl@1371
 18028
+        or      lr, r9, r8
mgl@1371
 18029
+        movne   r6,1
mgl@1371
 18030
+	
mgl@1371
 18031
+        /* Check if opH is also subnormal. If so, clear implicit bit in r11*/
mgl@1371
 18032
+        rsub    lr, r7, 0
mgl@1371
 18033
+        moveq   r7,1
mgl@1371
 18034
+        bst     r11, 31
mgl@1371
 18035
+	
mgl@1371
 18036
+        /* Check if op1 is zero, if so set exponent to 0. */
mgl@1371
 18037
+        or      lr, r11, r10
mgl@1371
 18038
+        moveq   r7,0
mgl@1371
 18039
+	                 
mgl@1371
 18040
+        rjmp    __avr32_f64_sub_opL_subnormal_done
mgl@1371
 18041
+ 
mgl@1371
 18042
+__avr32_f64_sub_opH_nan_or_inf: 
mgl@1371
 18043
+        /* Check if opH is NaN, if so return NaN */
mgl@1371
 18044
+        cbr     r11, 31
mgl@1371
 18045
+        or      lr, r11, r10
mgl@1371
 18046
+        brne    __avr32_f64_sub_return_nan
mgl@1371
 18047
+ 
mgl@1371
 18048
+        /* opH is Inf. */
mgl@1371
 18049
+        /* Check if opL is Inf. or NaN */
mgl@1371
 18050
+        cp.w    r6, 0x7ff
mgl@1371
 18051
+        breq    __avr32_f64_sub_return_nan
mgl@1371
 18052
+	/* Return infinity with correct sign. */	
mgl@1371
 18053
+	or      r11, r12, r7 << 20
mgl@1371
 18054
+        ldm     sp++, r5, r6, r7, pc/* opL not Inf or NaN, return opH */
mgl@1371
 18055
+__avr32_f64_sub_return_nan:     
mgl@1371
 18056
+        mov     r10, -1 /* Generate NaN in r11, r10 */
mgl@1371
 18057
+        mov     r11, -1
mgl@1371
 18058
+        ldm     sp++, r5, r6, r7, pc/* opL Inf or NaN, return NaN */
mgl@1371
 18059
+ 
mgl@1371
 18060
+ 
mgl@1371
 18061
+__avr32_f64_sub_subnormal_result:
mgl@1371
 18062
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18063
+	/* Check how much we must scale down the mantissa. */
mgl@1371
 18064
+	neg	r7
mgl@1371
 18065
+	sub	r7, -1     /* We do no longer have an implicit bit. */
mgl@1371
 18066
+	satu	r7 >> 0, 6 /* Saturate shift amount to max 63. */
mgl@1371
 18067
+	cp.w	r7, 32
mgl@1371
 18068
+	brge	0f
mgl@1371
 18069
+	/* Shift amount <32 */
mgl@1371
 18070
+	rsub	r8, r7, 32
mgl@1371
 18071
+	lsl	r9, r10, r8
mgl@1371
 18072
+	srne	r6
mgl@1371
 18073
+	lsr	r10, r10, r7
mgl@1371
 18074
+	or	r10, r6		/* Sticky bit from the
mgl@1371
 18075
+				   part that was shifted out. */
mgl@1371
 18076
+	lsl	r9, r11, r8
mgl@1371
 18077
+	or	r10, r10, r9
mgl@1371
 18078
+	lsr	r11, r10, r7
mgl@1371
 18079
+	/* Set exponent */
mgl@1371
 18080
+	mov	r7, 0
mgl@1371
 18081
+	rjmp	__avr32_f64_sub_longnormalize_done
mgl@1371
 18082
+0:
mgl@1371
 18083
+	/* Shift amount >=32 */
mgl@1371
 18084
+	rsub	r8, r7, 64
mgl@1371
 18085
+	lsl	r9, r11, r8
mgl@1371
 18086
+	or	r9, r10
mgl@1371
 18087
+	srne	r6
mgl@1371
 18088
+	lsr	r10, r11, r7
mgl@1371
 18089
+	or	r10, r6		/* Sticky bit from the
mgl@1371
 18090
+				   part that was shifted out. */
mgl@1371
 18091
+	mov	r11, 0
mgl@1371
 18092
+	/* Set exponent */
mgl@1371
 18093
+	mov	r7, 0
mgl@1371
 18094
+	rjmp	__avr32_f64_sub_longnormalize_done
mgl@1371
 18095
+#else
mgl@1371
 18096
+        /* Just flush subnormals to zero. */
mgl@1371
 18097
+        mov     r10, 0
mgl@1371
 18098
+        mov     r11, 0
mgl@1371
 18099
+#endif
mgl@1371
 18100
+        ldm     sp++, r5, r6, r7, pc
mgl@1371
 18101
+ 
mgl@1371
 18102
+__avr32_f64_sub_longshift:
mgl@1371
 18103
+        /* large (>=32) shift amount, only lsw will have bits left after shift.
mgl@1371
 18104
+           note that shift operations will use ((shift count=r6) mod 32) so
mgl@1371
 18105
+           we do not need to subtract 32 from shift count. */
mgl@1371
 18106
+        /* Saturate the shift amount to 63. If the amount
mgl@1371
 18107
+           is any larger op2 is insignificant. */
mgl@1371
 18108
+        satu    r6 >> 0, 6
mgl@1371
 18109
+	
mgl@1371
 18110
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18111
+        /* first remember whether part that is lost contains any 1 bits ... */
mgl@1371
 18112
+	moveq	lr, r8	   /* If shift amount is 32, no bits from msw are lost. */
mgl@1371
 18113
+	breq	0f
mgl@1371
 18114
+        lsl     lr,r9,r5   /* save all lost bits from msw */
mgl@1371
 18115
+        or      lr,r8      /* also save lost bits (all) from lsw
mgl@1371
 18116
+                              now lr != 0 if we lose any bits */
mgl@1371
 18117
+#endif  
mgl@1371
 18118
+0:	
mgl@1371
 18119
+        /* ... and now to the actual shift */
mgl@1371
 18120
+        lsr     r8,r9,r6   /* Move msw to lsw and shift. */
mgl@1371
 18121
+        mov     r9,0       /* clear msw */
mgl@1371
 18122
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18123
+        cp.w    lr,0       /* if any '1' bit in part we lost ...*/
mgl@1371
 18124
+        srne    lr
mgl@1371
 18125
+        or      r8, lr      /* ... we need to set sticky bit*/
mgl@1371
 18126
+#endif
mgl@1371
 18127
+        rjmp    __avr32_f64_sub_shift_done
mgl@1371
 18128
+ 
mgl@1371
 18129
+__avr32_f64_sub_longnormalize:
mgl@1371
 18130
+        /* shift amount is greater than 32 */
mgl@1371
 18131
+        clz     r6,r10      /* shift mantissa */
mgl@1371
 18132
+        /* If the resulting mantissa is zero the result is 
mgl@1371
 18133
+           zero so force exponent to zero. */
mgl@1371
 18134
+        movcs   r7, 0
mgl@1371
 18135
+        movcs   r6, 0
mgl@1371
 18136
+        movcs   r12, 0  /* Also clear sign bit. A zero result from subtraction
mgl@1371
 18137
+			   always is +0.0 */
mgl@1371
 18138
+        subcc   r6,-32
mgl@1371
 18139
+        lsl     r11,r10,r6
mgl@1371
 18140
+        mov     r10,0
mgl@1371
 18141
+        sub     r7,r6          /* adjust exponent */
mgl@1371
 18142
+        brle    __avr32_f64_sub_subnormal_result
mgl@1371
 18143
+        rjmp    __avr32_f64_sub_longnormalize_done
mgl@1371
 18144
+        
mgl@1371
 18145
+ 
mgl@1371
 18146
+        
mgl@1371
 18147
+	 .align  2
mgl@1371
 18148
+__avr32_f64_add_from_sub:
mgl@1371
 18149
+        /* Switch sign on op2 */
mgl@1371
 18150
+        eorh    r9, 0x8000
mgl@1371
 18151
+
mgl@1371
 18152
+#if defined(L_avr32_f64_addsub_fast)
mgl@1371
 18153
+        .global __avr32_f64_add_fast
mgl@1371
 18154
+        .type  __avr32_f64_add_fast,@function
mgl@1371
 18155
+__avr32_f64_add_fast:
mgl@1371
 18156
+#else	
mgl@1371
 18157
+        .global __avr32_f64_add
mgl@1371
 18158
+        .type  __avr32_f64_add,@function
mgl@1371
 18159
+__avr32_f64_add:
mgl@1371
 18160
+#endif
mgl@1371
 18161
+        
mgl@1371
 18162
+        /* op1 in {r11,r10}*/
mgl@1371
 18163
+        /* op2 in {r9,r8}*/
mgl@1371
 18164
+ 
mgl@1371
 18165
+#if defined(L_avr32_f64_addsub_fast)
mgl@1371
 18166
+        /* If op2 is zero just return op1 */
mgl@1371
 18167
+        or      r12, r8, r9 << 1
mgl@1371
 18168
+        reteq   r12 
mgl@1371
 18169
+#endif
mgl@1371
 18170
+
mgl@1371
 18171
+        /* Check signs */
mgl@1371
 18172
+        eor     r12, r11, r9
mgl@1371
 18173
+        /* Different signs, use subtraction. */
mgl@1371
 18174
+        brmi    __avr32_f64_sub_from_add
mgl@1371
 18175
+ 
mgl@1371
 18176
+        stm     --sp, r5, r6, r7, lr
mgl@1371
 18177
+ 
mgl@1371
 18178
+        /* Get sign of op1 into r12 */
mgl@1371
 18179
+        mov     r12, r11
mgl@1371
 18180
+        andh    r12, 0x8000, COH                
mgl@1371
 18181
+ 
mgl@1371
 18182
+        /* Remove sign from operands */
mgl@1371
 18183
+        cbr     r11, 31
mgl@1371
 18184
+        cbr     r9, 31
mgl@1371
 18185
+ 
mgl@1371
 18186
+        /* Put the number with the largest exponent in [r11, r10]
mgl@1371
 18187
+           and the number with the smallest exponent in [r9, r8] */
mgl@1371
 18188
+        cp      r11, r9
mgl@1371
 18189
+        brhs    1f /* Skip swap if operands already correctly ordered */
mgl@1371
 18190
+        /* Operands were not correctly ordered, swap them */
mgl@1371
 18191
+        mov     r7, r11
mgl@1371
 18192
+        mov     r11, r9
mgl@1371
 18193
+        mov     r9, r7
mgl@1371
 18194
+        mov     r7, r10
mgl@1371
 18195
+        mov     r10, r8
mgl@1371
 18196
+        mov     r8, r7
mgl@1371
 18197
+1:      
mgl@1371
 18198
+	mov	lr, 0 /* Set sticky bits to zero */
mgl@1371
 18199
+        /* Unpack largest operand - opH */      
mgl@1371
 18200
+        /* exp: r7 */
mgl@1371
 18201
+        /* sf:  r11, r10 */
mgl@1371
 18202
+	bfextu	R7, R11, 20, 11 /* Extract exponent */
mgl@1371
 18203
+	bfextu	r11, r11, 0, 20 /* Extract mantissa */
mgl@1371
 18204
+        sbr     r11, 20 /* Insert implicit bit */
mgl@1371
 18205
+ 
mgl@1371
 18206
+        /* Unpack smallest operand - opL */
mgl@1371
 18207
+        /* exp: r6 */
mgl@1371
 18208
+        /* sf:  r9, r8 */
mgl@1371
 18209
+	bfextu	R6, R9, 20, 11	/* Extract exponent */
mgl@1371
 18210
+	breq	__avr32_f64_add_op2_subnormal
mgl@1371
 18211
+	bfextu	r9, r9, 0, 20   /* Extract mantissa */
mgl@1371
 18212
+        sbr     r9, 20		/* Insert implicit bit */
mgl@1371
 18213
+
mgl@1371
 18214
+2:		 
mgl@1371
 18215
+        /* opH is NaN or Inf. */
mgl@1371
 18216
+        cp.w    r7, 0x7ff
mgl@1371
 18217
+        breq    __avr32_f64_add_opH_nan_or_inf
mgl@1371
 18218
+
mgl@1371
 18219
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 18220
+        rsub    r6, r7
mgl@1371
 18221
+        breq    __avr32_f64_add_shift_done /* No need to shift, exponents are equal*/
mgl@1371
 18222
+ 
mgl@1371
 18223
+        /* Scale mantissa [r9, r8] with amount [r6].
mgl@1371
 18224
+        Uses scratch registers [r5] and [lr].
mgl@1371
 18225
+        In IEEE mode:Must not forget the sticky bits we intend to shift out. */
mgl@1371
 18226
+        rsub    r5,r6,32 /* get (32 - shift count)
mgl@1371
 18227
+                            (if shift count > 32 we get a
mgl@1371
 18228
+                            negative value, but that will
mgl@1371
 18229
+                            work as well in the code below.) */
mgl@1371
 18230
+ 
mgl@1371
 18231
+        cp.w    r6,32       /* handle shifts >= 32 separately */
mgl@1371
 18232
+        brhs    __avr32_f64_add_longshift
mgl@1371
 18233
+ 
mgl@1371
 18234
+        /* small (<32) shift amount, both words are part of the shift
mgl@1371
 18235
+           first remember whether part that is lost contains any 1 bits ... */
mgl@1371
 18236
+        lsl     lr,r8,r5  /* shift away bits that are part of
mgl@1371
 18237
+                             final mantissa. only part that goes
mgl@1371
 18238
+                             to lr are bits that will be lost */
mgl@1371
 18239
+ 
mgl@1371
 18240
+        /* ... and now to the actual shift */
mgl@1371
 18241
+        lsl     r5,r9,r5  /* get bits from msw destined for lsw*/
mgl@1371
 18242
+        lsr     r8,r8,r6  /* shift down lsw of mantissa */
mgl@1371
 18243
+        lsr     r9,r9,r6  /* shift down msw of mantissa */
mgl@1371
 18244
+        or      r8,r5     /* combine these bits with prepared lsw*/
mgl@1371
 18245
+        
mgl@1371
 18246
+__avr32_f64_add_shift_done:     
mgl@1371
 18247
+        /* Now add the mantissas. */
mgl@1371
 18248
+        add     r10, r8
mgl@1371
 18249
+        adc     r11, r11, r9
mgl@1371
 18250
+
mgl@1371
 18251
+        /* Check if we overflowed. */
mgl@1371
 18252
+	bld	r11, 21 
mgl@1371
 18253
+        breq	__avr32_f64_add_res_of:
mgl@1371
 18254
+
mgl@1371
 18255
+__avr32_f64_add_res_of_done:    
mgl@1371
 18256
+        
mgl@1371
 18257
+        /* Pack final result*/
mgl@1371
 18258
+        /* Input: [r7]:exp, [r11, r10]:mant, [r12]:sign in MSB */
mgl@1371
 18259
+        /* Result in [r11,r10] */
mgl@1371
 18260
+        /* Insert exponent and sign bit*/
mgl@1371
 18261
+	bfins	r11, r7, 20, 11
mgl@1371
 18262
+	or	r11, r12
mgl@1371
 18263
+        
mgl@1371
 18264
+        /* Round */     
mgl@1371
 18265
+__avr32_f64_add_round:
mgl@1371
 18266
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18267
+	bfextu	r12, r10, 0, 1 /* Extract parity bit.*/
mgl@1371
 18268
+	or	lr, r12	       /* or it together with the sticky bits. */	
mgl@1371
 18269
+	eorh	lr, 0x8000     /* Toggle round bit. */	
mgl@1371
 18270
+	/* We should now round up by adding one for the following cases:
mgl@1371
 18271
+
mgl@1371
 18272
+		halfway   sticky|parity  round-up
mgl@1371
 18273
+		   0            x           no
mgl@1371
 18274
+		   1            0           no
mgl@1371
 18275
+	           1            1           yes
mgl@1371
 18276
+
mgl@1371
 18277
+	   Since we have inverted the halfway bit we can use the satu instruction
mgl@1371
 18278
+           by saturating to 1 bit to implement this. 
mgl@1371
 18279
+	*/ 
mgl@1371
 18280
+	satu	lr >> 0, 1
mgl@1371
 18281
+#else
mgl@1371
 18282
+	lsr	lr, 31
mgl@1371
 18283
+#endif
mgl@1371
 18284
+        add     r10, lr
mgl@1371
 18285
+        acr     r11
mgl@1371
 18286
+        
mgl@1371
 18287
+        /* Return result in [r11,r10] */
mgl@1371
 18288
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 18289
+ 
mgl@1371
 18290
+  
mgl@1371
 18291
+__avr32_f64_add_opH_nan_or_inf: 
mgl@1371
 18292
+        /* Check if opH is NaN, if so return NaN */
mgl@1371
 18293
+        cbr     r11, 20
mgl@1371
 18294
+        or      lr, r11, r10
mgl@1371
 18295
+        brne    __avr32_f64_add_return_nan
mgl@1371
 18296
+ 
mgl@1371
 18297
+        /* opH is Inf. */
mgl@1371
 18298
+        /* Check if opL is Inf. or NaN */
mgl@1371
 18299
+        cp.w    r6, 0x7ff
mgl@1371
 18300
+        breq    __avr32_f64_add_opL_nan_or_inf
mgl@1371
 18301
+        ldm     sp++, r5, r6, r7, pc/* opL not Inf or NaN, return opH */
mgl@1371
 18302
+__avr32_f64_add_opL_nan_or_inf:
mgl@1371
 18303
+        cbr     r9, 20
mgl@1371
 18304
+        or      lr, r9, r8
mgl@1371
 18305
+        brne    __avr32_f64_add_return_nan
mgl@1371
 18306
+        mov     r10, 0  /* Generate Inf in r11, r10 */
mgl@1371
 18307
+	mov_imm r11, 0x7ff00000
mgl@1371
 18308
+        ldm     sp++, r5, r6, r7, pc/* opL Inf, return Inf */
mgl@1371
 18309
+__avr32_f64_add_return_nan:     
mgl@1371
 18310
+        mov     r10, -1 /* Generate NaN in r11, r10 */
mgl@1371
 18311
+        mov     r11, -1
mgl@1371
 18312
+        ldm     sp++, r5, r6, r7, pc/* opL Inf or NaN, return NaN */
mgl@1371
 18313
+ 
mgl@1371
 18314
+ 
mgl@1371
 18315
+__avr32_f64_add_longshift:
mgl@1371
 18316
+        /* large (>=32) shift amount, only lsw will have bits left after shift.
mgl@1371
 18317
+           note that shift operations will use ((shift count=r6) mod 32) so
mgl@1371
 18318
+           we do not need to subtract 32 from shift count. */
mgl@1371
 18319
+        /* Saturate the shift amount to 63. If the amount
mgl@1371
 18320
+           is any larger op2 is insignificant. */
mgl@1371
 18321
+        satu    r6 >> 0, 6
mgl@1371
 18322
+	/* If shift amount is 32 there are no bits from the msw that are lost. */
mgl@1371
 18323
+	moveq	lr, r8
mgl@1371
 18324
+	breq	0f	
mgl@1371
 18325
+        /* first remember whether part that is lost contains any 1 bits ... */
mgl@1371
 18326
+        lsl     lr,r9,r5   /* save all lost bits from msw */
mgl@1371
 18327
+#if defined(L_avr32_f64_addsub)
mgl@1371
 18328
+	cp.w	r8, 0
mgl@1371
 18329
+	srne	r8	
mgl@1371
 18330
+        or      lr,r8      /* also save lost bits (all) from lsw
mgl@1371
 18331
+                              now lr != 0 if we lose any bits */
mgl@1371
 18332
+#endif  
mgl@1371
 18333
+0:	
mgl@1371
 18334
+        /* ... and now to the actual shift */
mgl@1371
 18335
+        lsr     r8,r9,r6   /* msw -> lsw and make rest of shift inside lsw*/
mgl@1371
 18336
+        mov     r9,0       /* clear msw */
mgl@1371
 18337
+        rjmp    __avr32_f64_add_shift_done
mgl@1371
 18338
+ 
mgl@1371
 18339
+__avr32_f64_add_res_of:
mgl@1371
 18340
+	/* We overflowed. Scale down mantissa by shifting right one position. */
mgl@1371
 18341
+	or	lr, lr, lr << 1 /* Remember stickybits*/
mgl@1371
 18342
+	lsr	r11, 1
mgl@1371
 18343
+	ror	r10
mgl@1371
 18344
+	ror	lr
mgl@1371
 18345
+	sub	r7, -1	/* Increment exponent */
mgl@1371
 18346
+ 
mgl@1371
 18347
+        /* Clear mantissa to set result to Inf if the exponent is 255. */
mgl@1371
 18348
+        cp.w    r7, 0x7ff
mgl@1371
 18349
+        moveq   r10, 0
mgl@1371
 18350
+        moveq   r11, 0
mgl@1371
 18351
+        moveq   lr, 0
mgl@1371
 18352
+        rjmp    __avr32_f64_add_res_of_done
mgl@1371
 18353
+        
mgl@1371
 18354
+__avr32_f64_add_op2_subnormal:	
mgl@1371
 18355
+	/* Set epxponent to 1 */
mgl@1371
 18356
+	mov	r6, 1
mgl@1371
 18357
+
mgl@1371
 18358
+	/* Check if op2 is also subnormal. */
mgl@1371
 18359
+	cp.w	r7, 0
mgl@1371
 18360
+	brne	2b
mgl@1371
 18361
+
mgl@1371
 18362
+	cbr	r11, 20
mgl@1371
 18363
+	/* Both operands are subnormal. Just addd the mantissas
mgl@1371
 18364
+	   and the exponent will automatically be set to 1 if
mgl@1371
 18365
+	   we overflow into a normal number. */
mgl@1371
 18366
+	add	r10, r8
mgl@1371
 18367
+	adc	r11, r11, r9
mgl@1371
 18368
+
mgl@1371
 18369
+	/* Add sign bit */
mgl@1371
 18370
+	or	r11, r12
mgl@1371
 18371
+	
mgl@1371
 18372
+        /* Return result in [r11,r10] */
mgl@1371
 18373
+        ldm     sp++, r5, r6, r7,pc
mgl@1371
 18374
+	
mgl@1371
 18375
+			
mgl@1371
 18376
+	 
mgl@1371
 18377
+#endif
mgl@1371
 18378
+ 
mgl@1371
 18379
+#ifdef L_avr32_f64_to_u32
mgl@1371
 18380
+        /* This goes into L_fixdfsi */
mgl@1371
 18381
+#endif
mgl@1371
 18382
+        
mgl@1371
 18383
+ 
mgl@1371
 18384
+#ifdef L_avr32_f64_to_s32
mgl@1371
 18385
+        .global __avr32_f64_to_u32
mgl@1371
 18386
+        .type  __avr32_f64_to_u32,@function
mgl@1371
 18387
+__avr32_f64_to_u32:
mgl@1371
 18388
+        cp.w    r11, 0
mgl@1371
 18389
+        retmi   0       /* Negative returns 0 */
mgl@1371
 18390
+ 
mgl@1371
 18391
+        /* Fallthrough to df to signed si conversion */ 
mgl@1371
 18392
+        .global __avr32_f64_to_s32
mgl@1371
 18393
+        .type  __avr32_f64_to_s32,@function
mgl@1371
 18394
+__avr32_f64_to_s32:
mgl@1371
 18395
+        lsl     r12,r11,1
mgl@1371
 18396
+        lsr     r12,21                  /* extract exponent*/
mgl@1371
 18397
+        sub     r12,1023                /* convert to unbiased exponent.*/
mgl@1371
 18398
+        retlo   0                       /* too small exponent implies zero. */
mgl@1371
 18399
+ 
mgl@1371
 18400
+1:      
mgl@1371
 18401
+        rsub    r12,r12,31              /* shift count = 31 - exponent */
mgl@1371
 18402
+        mov     r9,r11                  /* save sign for later...*/
mgl@1371
 18403
+        lsl     r11,11                  /* remove exponent and sign*/
mgl@1371
 18404
+        sbr     r11,31                  /* add implicit bit*/
mgl@1371
 18405
+        or      r11,r11,r10>>21         /* get rest of bits from lsw of double */
mgl@1371
 18406
+        lsr     r11,r11,r12             /* shift down mantissa to final place */
mgl@1371
 18407
+        lsl     r9,1                    /* sign -> carry */
mgl@1371
 18408
+        retcc   r11                     /* if positive, we are done */
mgl@1371
 18409
+        neg     r11                     /* if negative float, negate result */
mgl@1371
 18410
+        ret     r11
mgl@1371
 18411
+ 
mgl@1371
 18412
+#endif  /* L_fixdfsi*/
mgl@1371
 18413
+ 
mgl@1371
 18414
+#ifdef L_avr32_f64_to_u64
mgl@1371
 18415
+        /* Actual function is in L_fixdfdi */
mgl@1371
 18416
+#endif
mgl@1371
 18417
+        
mgl@1371
 18418
+#ifdef L_avr32_f64_to_s64
mgl@1371
 18419
+        .global __avr32_f64_to_u64
mgl@1371
 18420
+        .type  __avr32_f64_to_u64,@function
mgl@1371
 18421
+__avr32_f64_to_u64:
mgl@1371
 18422
+        cp.w    r11,0
mgl@1371
 18423
+        /* Negative numbers return zero */
mgl@1371
 18424
+        movmi   r10, 0
mgl@1371
 18425
+        movmi   r11, 0
mgl@1371
 18426
+        retmi   r11
mgl@1371
 18427
+ 
mgl@1371
 18428
+        
mgl@1371
 18429
+ 
mgl@1371
 18430
+        /* Fallthrough */
mgl@1371
 18431
+        .global __avr32_f64_to_s64
mgl@1371
 18432
+        .type  __avr32_f64_to_s64,@function
mgl@1371
 18433
+__avr32_f64_to_s64:
mgl@1371
 18434
+        lsl     r9,r11,1
mgl@1371
 18435
+        lsr     r9,21                   /* get exponent*/
mgl@1371
 18436
+        sub     r9,1023                 /* convert to correct range*/
mgl@1371
 18437
+        /* Return zero if exponent to small */
mgl@1371
 18438
+        movlo   r10, 0
mgl@1371
 18439
+        movlo   r11, 0
mgl@1371
 18440
+        retlo   r11
mgl@1371
 18441
+ 
mgl@1371
 18442
+        mov     r8,r11                  /* save sign for later...*/
mgl@1371
 18443
+1:      
mgl@1371
 18444
+        lsl     r11,11                  /* remove exponent */
mgl@1371
 18445
+        sbr     r11,31                  /* add implicit bit*/
mgl@1371
 18446
+        or      r11,r11,r10>>21         /* get rest of bits from lsw of double*/
mgl@1371
 18447
+        lsl     r10,11                  /* align lsw correctly as well */
mgl@1371
 18448
+        rsub    r9,r9,63                /* shift count = 63 - exponent */
mgl@1371
 18449
+        breq    1f
mgl@1371
 18450
+ 
mgl@1371
 18451
+        cp.w    r9,32                   /* is shift count more than one reg? */
mgl@1371
 18452
+        brhs    0f
mgl@1371
 18453
+ 
mgl@1371
 18454
+        mov     r12,r11                 /* save msw */
mgl@1371
 18455
+        lsr     r10,r10,r9              /* small shift count, shift down lsw */
mgl@1371
 18456
+        lsr     r11,r11,r9              /* small shift count, shift down msw */
mgl@1371
 18457
+        rsub    r9,r9,32                /* get 32-size of shifted out tail */
mgl@1371
 18458
+        lsl     r12,r12,r9              /* align part to move from msw to lsw */
mgl@1371
 18459
+        or      r10,r12                 /* combine to get new lsw */
mgl@1371
 18460
+        rjmp    1f
mgl@1371
 18461
+ 
mgl@1371
 18462
+0:
mgl@1371
 18463
+        lsr     r10,r11,r9              /* large shift count,only lsw get bits
mgl@1371
 18464
+                                           note that shift count is modulo 32*/
mgl@1371
 18465
+        mov     r11,0                   /* msw will be 0 */
mgl@1371
 18466
+ 
mgl@1371
 18467
+1:
mgl@1371
 18468
+        lsl     r8,1                    /* sign -> carry */
mgl@1371
 18469
+        retcc   r11                     /* if positive, we are done */
mgl@1371
 18470
+ 
mgl@1371
 18471
+        neg     r11                     /* if negative float, negate result */
mgl@1371
 18472
+        neg     r10
mgl@1371
 18473
+        scr     r11
mgl@1371
 18474
+        ret     r11 
mgl@1371
 18475
+ 
mgl@1371
 18476
+#endif
mgl@1371
 18477
+ 
mgl@1371
 18478
+#ifdef L_avr32_u32_to_f64
mgl@1371
 18479
+        /* Code located in L_floatsidf */
mgl@1371
 18480
+#endif
mgl@1371
 18481
+        
mgl@1371
 18482
+#ifdef L_avr32_s32_to_f64
mgl@1371
 18483
+        .global __avr32_u32_to_f64
mgl@1371
 18484
+        .type  __avr32_u32_to_f64,@function
mgl@1371
 18485
+__avr32_u32_to_f64:
mgl@1371
 18486
+        sub     r11, r12, 0 /* Move to r11 and force Z flag to be updated */
mgl@1371
 18487
+        mov     r12, 0      /* always positive */
mgl@1371
 18488
+        rjmp    0f          /* Jump to common code for floatsidf */
mgl@1371
 18489
+        
mgl@1371
 18490
+        .global __avr32_s32_to_f64
mgl@1371
 18491
+        .type  __avr32_s32_to_f64,@function
mgl@1371
 18492
+__avr32_s32_to_f64:
mgl@1371
 18493
+        mov     r11, r12        /* Keep original value in r12 for sign */
mgl@1371
 18494
+        abs     r11             /* Absolute value if r12 */
mgl@1371
 18495
+0:      
mgl@1371
 18496
+        mov     r10,0           /* let remaining bits be zero */
mgl@1371
 18497
+        reteq   r11             /* zero long will return zero float */
mgl@1371
 18498
+ 
mgl@1371
 18499
+        pushm   lr
mgl@1371
 18500
+        mov     r9,31+1023              /* set exponent */
mgl@1371
 18501
+                
mgl@1371
 18502
+        normalize_df    r9 /*exp*/, r10, r11 /* mantissa */, r8, lr /* scratch */
mgl@1371
 18503
+ 
mgl@1371
 18504
+        /* Check if a subnormal result was created */
mgl@1371
 18505
+        cp.w    r9, 0
mgl@1371
 18506
+        brgt    0f
mgl@1371
 18507
+        
mgl@1371
 18508
+        adjust_subnormal_df     r9 /* exp */, r10, r11 /* Mantissa */, r12 /*sign*/, r8, lr /* scratch */
mgl@1371
 18509
+        popm    pc
mgl@1371
 18510
+0:
mgl@1371
 18511
+        
mgl@1371
 18512
+        /* Round result */
mgl@1371
 18513
+        round_df        r9 /*exp*/, r10, r11 /* Mantissa */, r8 /*scratch*/
mgl@1371
 18514
+        cp.w    r9,0x7ff
mgl@1371
 18515
+        brlt    0f
mgl@1371
 18516
+        /*Return infinity */
mgl@1371
 18517
+        mov     r10, 0
mgl@1371
 18518
+	mov_imm	r11, 0xffe00000
mgl@1371
 18519
+        rjmp    __floatsidf_return_op1
mgl@1371
 18520
+        
mgl@1371
 18521
+0:
mgl@1371
 18522
+ 
mgl@1371
 18523
+        /* Pack */
mgl@1371
 18524
+        pack_df r9 /*exp*/, r10, r11 /* mantissa */, r10, r11 /* Output df number*/
mgl@1371
 18525
+__floatsidf_return_op1: 
mgl@1371
 18526
+        lsl     r12,1                  /* shift in sign bit */
mgl@1371
 18527
+        ror     r11
mgl@1371
 18528
+ 
mgl@1371
 18529
+        popm    pc
mgl@1371
 18530
+#endif
mgl@1371
 18531
+ 
mgl@1371
 18532
+ 
mgl@1371
 18533
+#ifdef L_avr32_f32_cmp_eq
mgl@1371
 18534
+        .global __avr32_f32_cmp_eq
mgl@1371
 18535
+        .type  __avr32_f32_cmp_eq,@function
mgl@1371
 18536
+__avr32_f32_cmp_eq:     
mgl@1371
 18537
+        cp.w    r12, r11
mgl@1371
 18538
+        breq    0f      
mgl@1371
 18539
+        /* If not equal check for +/-0 */
mgl@1371
 18540
+        /* Or together the two values and shift out the sign bit.
mgl@1371
 18541
+           If the result is zero, then the two values are both zero. */
mgl@1371
 18542
+        or      r12, r11
mgl@1371
 18543
+        lsl     r12, 1
mgl@1371
 18544
+        reteq   1
mgl@1371
 18545
+        ret     0
mgl@1371
 18546
+0:                      
mgl@1371
 18547
+        /* Numbers were equal. Check for NaN or Inf */
mgl@1371
 18548
+	mov_imm	r11, 0xff000000
mgl@1371
 18549
+        lsl     r12, 1
mgl@1371
 18550
+        cp.w    r12, r11
mgl@1371
 18551
+        retls   1     /* 0 if NaN, 1 otherwise */
mgl@1371
 18552
+        ret     0     
mgl@1371
 18553
+#endif
mgl@1371
 18554
+        
mgl@1371
 18555
+#if defined(L_avr32_f32_cmp_ge) || defined(L_avr32_f32_cmp_lt)
mgl@1371
 18556
+#ifdef L_avr32_f32_cmp_ge
mgl@1371
 18557
+        .global __avr32_f32_cmp_ge
mgl@1371
 18558
+        .type  __avr32_f32_cmp_ge,@function
mgl@1371
 18559
+__avr32_f32_cmp_ge:
mgl@1371
 18560
+#endif  
mgl@1371
 18561
+#ifdef L_avr32_f32_cmp_lt
mgl@1371
 18562
+        .global __avr32_f32_cmp_lt
mgl@1371
 18563
+        .type  __avr32_f32_cmp_lt,@function
mgl@1371
 18564
+__avr32_f32_cmp_lt:
mgl@1371
 18565
+#endif  
mgl@1371
 18566
+        lsl     r10, r12, 1     /* Remove sign bits */
mgl@1371
 18567
+        lsl     r9, r11, 1
mgl@1371
 18568
+	subfeq	r10, 0
mgl@1371
 18569
+#ifdef L_avr32_f32_cmp_ge
mgl@1371
 18570
+	reteq	1		/* Both number are zero. Return true. */
mgl@1371
 18571
+#endif	
mgl@1371
 18572
+#ifdef L_avr32_f32_cmp_lt
mgl@1371
 18573
+	reteq	0		/* Both number are zero. Return false. */
mgl@1371
 18574
+#endif	
mgl@1371
 18575
+	mov_imm	r8, 0xff000000
mgl@1371
 18576
+        cp.w    r10, r8
mgl@1371
 18577
+        rethi   0               /* Op0 is NaN */                
mgl@1371
 18578
+        cp.w    r9, r8
mgl@1371
 18579
+        rethi   0               /* Op1 is Nan */
mgl@1371
 18580
+ 
mgl@1371
 18581
+        eor     r8, r11, r12
mgl@1371
 18582
+        bld     r12, 31
mgl@1371
 18583
+#ifdef L_avr32_f32_cmp_ge
mgl@1371
 18584
+        srcc    r8      /* Set result to true if op0 is positive*/
mgl@1371
 18585
+#endif
mgl@1371
 18586
+#ifdef L_avr32_f32_cmp_lt
mgl@1371
 18587
+        srcs    r8      /* Set result to true if op0 is negative*/
mgl@1371
 18588
+#endif
mgl@1371
 18589
+        retmi   r8      /* Return if signs are different */
mgl@1371
 18590
+        brcs    0f      /* Both signs negative? */
mgl@1371
 18591
+ 
mgl@1371
 18592
+        /* Both signs positive */
mgl@1371
 18593
+        cp.w    r12, r11
mgl@1371
 18594
+#ifdef L_avr32_f32_cmp_ge
mgl@1371
 18595
+        reths    1
mgl@1371
 18596
+        retlo    0
mgl@1371
 18597
+#endif
mgl@1371
 18598
+#ifdef L_avr32_f32_cmp_lt
mgl@1371
 18599
+        reths    0
mgl@1371
 18600
+        retlo    1
mgl@1371
 18601
+#endif
mgl@1371
 18602
+0:
mgl@1371
 18603
+        /* Both signs negative */
mgl@1371
 18604
+        cp.w    r11, r12
mgl@1371
 18605
+#ifdef L_avr32_f32_cmp_ge
mgl@1371
 18606
+        reths    1
mgl@1371
 18607
+        retlo    0
mgl@1371
 18608
+#endif
mgl@1371
 18609
+#ifdef L_avr32_f32_cmp_lt
mgl@1371
 18610
+        reths    0
mgl@1371
 18611
+        retlo    1
mgl@1371
 18612
+#endif
mgl@1371
 18613
+#endif
mgl@1371
 18614
+        
mgl@1371
 18615
+ 
mgl@1371
 18616
+#ifdef L_avr32_f64_cmp_eq
mgl@1371
 18617
+        .global __avr32_f64_cmp_eq
mgl@1371
 18618
+        .type  __avr32_f64_cmp_eq,@function
mgl@1371
 18619
+__avr32_f64_cmp_eq:     
mgl@1371
 18620
+        cp.w    r10,r8
mgl@1371
 18621
+        cpc     r11,r9
mgl@1371
 18622
+        breq    0f
mgl@1371
 18623
+        
mgl@1371
 18624
+        /* Args were not equal*/
mgl@1371
 18625
+        /* Both args could be zero with different sign bits */
mgl@1371
 18626
+        lsl     r11,1                   /* get rid of sign bits */
mgl@1371
 18627
+        lsl     r9,1
mgl@1371
 18628
+        or      r11,r10                 /* Check if all bits are zero */
mgl@1371
 18629
+        or      r11,r9
mgl@1371
 18630
+        or      r11,r8
mgl@1371
 18631
+        reteq   1                       /* If all zeros the arguments are equal
mgl@1371
 18632
+                                           so return 1 else return 0 */
mgl@1371
 18633
+        ret     0
mgl@1371
 18634
+0:      
mgl@1371
 18635
+        /* check for NaN */
mgl@1371
 18636
+        lsl     r11,1
mgl@1371
 18637
+	mov_imm	r12, 0xffe00000
mgl@1371
 18638
+        cp.w    r10,0
mgl@1371
 18639
+        cpc     r11,r12                 /* check if nan or inf */
mgl@1371
 18640
+        retls   1                       /* If Arg is NaN return 0 else 1*/
mgl@1371
 18641
+        ret     0                       /* Return  */
mgl@1371
 18642
+ 
mgl@1371
 18643
+#endif
mgl@1371
 18644
+ 
mgl@1371
 18645
+ 
mgl@1371
 18646
+#if   defined(L_avr32_f64_cmp_ge) || defined(L_avr32_f64_cmp_lt)
mgl@1371
 18647
+ 
mgl@1371
 18648
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18649
+        .global __avr32_f64_cmp_ge
mgl@1371
 18650
+        .type  __avr32_f64_cmp_ge,@function
mgl@1371
 18651
+__avr32_f64_cmp_ge:
mgl@1371
 18652
+#endif  
mgl@1371
 18653
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18654
+        .global __avr32_f64_cmp_lt
mgl@1371
 18655
+        .type  __avr32_f64_cmp_lt,@function
mgl@1371
 18656
+__avr32_f64_cmp_lt:
mgl@1371
 18657
+#endif  
mgl@1371
 18658
+ 
mgl@1371
 18659
+        /* compare magnitude of op1 and op2 */
mgl@1371
 18660
+        lsl     r11,1                   /* Remove sign bit of op1 */
mgl@1371
 18661
+        srcs    r12                     /* Sign op1 to lsb of r12*/
mgl@1371
 18662
+	subfeq	r10, 0
mgl@1371
 18663
+	breq	3f			/* op1 zero */
mgl@1371
 18664
+        lsl     r9,1                    /* Remove sign bit of op2 */
mgl@1371
 18665
+        rol     r12                     /* Sign op2 to lsb of lr, sign bit op1 bit 1 of r12*/
mgl@1371
 18666
+	
mgl@1371
 18667
+ 
mgl@1371
 18668
+        /* Check for Nan */
mgl@1371
 18669
+	pushm	lr
mgl@1371
 18670
+	mov_imm	lr, 0xffe00000
mgl@1371
 18671
+        cp.w    r10,0
mgl@1371
 18672
+        cpc     r11,lr
mgl@1371
 18673
+        brhi    0f      /* We have NaN */
mgl@1371
 18674
+        cp.w    r8,0
mgl@1371
 18675
+        cpc     r9,lr
mgl@1371
 18676
+        brhi    0f      /* We have NaN */
mgl@1371
 18677
+	popm	lr
mgl@1371
 18678
+ 
mgl@1371
 18679
+        cp.w    r12,3                   /* both operands negative ?*/    
mgl@1371
 18680
+        breq    1f
mgl@1371
 18681
+ 
mgl@1371
 18682
+        cp.w    r12,1                   /* both operands positive? */
mgl@1371
 18683
+        brlo    2f
mgl@1371
 18684
+ 
mgl@1371
 18685
+        /* Different signs. If sign of op1 is negative the difference
mgl@1371
 18686
+           between op1 and op2 will always be negative, and if op1 is
mgl@1371
 18687
+           positive the difference will always be positive */           
mgl@1371
 18688
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18689
+	reteq	1
mgl@1371
 18690
+	retne	0
mgl@1371
 18691
+#endif
mgl@1371
 18692
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18693
+	reteq	0
mgl@1371
 18694
+	retne	1
mgl@1371
 18695
+#endif
mgl@1371
 18696
+  
mgl@1371
 18697
+2:
mgl@1371
 18698
+        /* Both operands positive. Just compute the difference */
mgl@1371
 18699
+        cp.w    r10,r8
mgl@1371
 18700
+        cpc     r11,r9
mgl@1371
 18701
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18702
+	reths	1
mgl@1371
 18703
+	retlo	0
mgl@1371
 18704
+#endif
mgl@1371
 18705
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18706
+	reths	0
mgl@1371
 18707
+	retlo	1
mgl@1371
 18708
+#endif
mgl@1371
 18709
+                
mgl@1371
 18710
+1:
mgl@1371
 18711
+        /* Both operands negative. Compute the difference with operands switched */
mgl@1371
 18712
+        cp     r8,r10
mgl@1371
 18713
+        cpc    r9,r11
mgl@1371
 18714
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18715
+	reths	1
mgl@1371
 18716
+	retlo	0
mgl@1371
 18717
+#endif
mgl@1371
 18718
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18719
+	reths	0
mgl@1371
 18720
+	retlo	1
mgl@1371
 18721
+#endif
mgl@1371
 18722
+
mgl@1371
 18723
+0:      
mgl@1371
 18724
+        popm    pc, r12=0
mgl@1371
 18725
+#endif
mgl@1371
 18726
+ 
mgl@1371
 18727
+3:
mgl@1371
 18728
+        lsl     r9,1                   /* Remove sign bit of op1 */
mgl@1371
 18729
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18730
+        srcs    r12		       /* If op2 is negative then op1 >= op2. */	
mgl@1371
 18731
+#endif
mgl@1371
 18732
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18733
+        srcc    r12		       /* If op2 is positve then op1 <= op2. */
mgl@1371
 18734
+#endif
mgl@1371
 18735
+	subfeq	r8, 0		       
mgl@1371
 18736
+#ifdef L_avr32_f64_cmp_ge
mgl@1371
 18737
+	reteq	1		       /* Both operands are zero. Return true. */
mgl@1371
 18738
+#endif
mgl@1371
 18739
+#ifdef L_avr32_f64_cmp_lt
mgl@1371
 18740
+	reteq	0		       /* Both operands are zero. Return false. */
mgl@1371
 18741
+#endif
mgl@1371
 18742
+	ret	r12
mgl@1371
 18743
+				        
mgl@1371
 18744
+ 
mgl@1371
 18745
+#if defined(L_avr32_f64_div) || defined(L_avr32_f64_div_fast)
mgl@1371
 18746
+        .align  2
mgl@1371
 18747
+
mgl@1371
 18748
+#if defined(L_avr32_f64_div_fast)
mgl@1371
 18749
+        .global __avr32_f64_div_fast
mgl@1371
 18750
+        .type  __avr32_f64_div_fast,@function
mgl@1371
 18751
+__avr32_f64_div_fast:
mgl@1371
 18752
+#else
mgl@1371
 18753
+        .global __avr32_f64_div
mgl@1371
 18754
+        .type  __avr32_f64_div,@function
mgl@1371
 18755
+__avr32_f64_div:
mgl@1371
 18756
+#endif
mgl@1371
 18757
+        stm     --sp, r0, r1, r2, r3, r4, r5, r6, r7,lr 
mgl@1371
 18758
+        /* op1 in {r11,r10}*/
mgl@1371
 18759
+        /* op2 in {r9,r8}*/
mgl@1371
 18760
+        eor     lr, r11, r9             /* MSB(lr) = Sign(op1) ^ Sign(op2) */
mgl@1371
 18761
+ 
mgl@1371
 18762
+        
mgl@1371
 18763
+        /* Unpack op1 to 2.62 format*/  
mgl@1371
 18764
+        /* exp: r7 */
mgl@1371
 18765
+        /* sf:  r11, r10 */
mgl@1371
 18766
+        lsr     r7, r11, 20 /* Extract exponent */
mgl@1371
 18767
+                
mgl@1371
 18768
+        lsl     r11, 9 /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 18769
+        or      r11, r11, r10>>23
mgl@1371
 18770
+        lsl     r10, 9
mgl@1371
 18771
+        sbr     r11, 29 /* Insert implicit bit */
mgl@1371
 18772
+        andh    r11, 0x3fff /*Mask last part of exponent since we use 2.62 format*/
mgl@1371
 18773
+ 
mgl@1371
 18774
+        cbr     r7, 11       /* Clear sign bit */
mgl@1371
 18775
+        /* Check if normalization is needed */
mgl@1371
 18776
+        breq    11f /*If number is subnormal, normalize it */
mgl@1371
 18777
+22:     
mgl@1371
 18778
+        cp      r7, 0x7ff
mgl@1371
 18779
+        brge    2f  /* Check op1 for NaN or Inf */
mgl@1371
 18780
+
mgl@1371
 18781
+        /* Unpack op2 to 2.62 format*/
mgl@1371
 18782
+        /* exp: r6 */
mgl@1371
 18783
+        /* sf:  r9, r8 */
mgl@1371
 18784
+        lsr     r6, r9, 20 /* Extract exponent */
mgl@1371
 18785
+                
mgl@1371
 18786
+        lsl     r9, 9 /* Extract mantissa, leave room for implicit bit */ 
mgl@1371
 18787
+        or      r9, r9, r8>>23
mgl@1371
 18788
+        lsl     r8, 9
mgl@1371
 18789
+        sbr     r9, 29 /* Insert implicit bit */
mgl@1371
 18790
+        andh    r9, 0x3fff /*Mask last part of exponent since we use 2.62 format*/
mgl@1371
 18791
+ 
mgl@1371
 18792
+        cbr     r6, 11       /* Clear sign bit */
mgl@1371
 18793
+        /* Check if normalization is needed */
mgl@1371
 18794
+        breq    13f /*If number is subnormal, normalize it */
mgl@1371
 18795
+23:             
mgl@1371
 18796
+        cp      r6, 0x7ff
mgl@1371
 18797
+        brge    3f  /* Check op2 for NaN or Inf */
mgl@1371
 18798
+
mgl@1371
 18799
+        /* Calculate new exponent */
mgl@1371
 18800
+        sub     r7, r6
mgl@1371
 18801
+        sub     r7,-1023
mgl@1371
 18802
+ 
mgl@1371
 18803
+        /* Divide */
mgl@1371
 18804
+        /* Approximating 1/d with the following recurrence: */
mgl@1371
 18805
+        /* R[j+1] = R[j]*(2-R[j]*d) */
mgl@1371
 18806
+        /* Using 2.62 format */
mgl@1371
 18807
+        /* TWO:  r12 */
mgl@1371
 18808
+        /* d = op2 = divisor (2.62 format): r9,r8 */
mgl@1371
 18809
+        /* Multiply result :     r5, r4 */
mgl@1371
 18810
+        /* Initial guess :       r3, r2 */
mgl@1371
 18811
+        /* New approximations :  r3, r2 */
mgl@1371
 18812
+        /* op1 = Dividend (2.62 format) : r11, r10 */
mgl@1371
 18813
+ 
mgl@1371
 18814
+	mov_imm	r12, 0x80000000
mgl@1371
 18815
+         
mgl@1371
 18816
+        /* Load initial guess, using look-up table */
mgl@1371
 18817
+        /* Initial guess is of format 01.XY, where XY is constructed as follows: */
mgl@1371
 18818
+        /* Let d be of following format: 00.1xy....., then XY=~xy */
mgl@1371
 18819
+        /* For d=00.100 = 0,5   -> initial guess=01.11 = 1,75 */
mgl@1371
 18820
+        /* For d=00.101 = 0,625 -> initial guess=01.11 = 1,5  */
mgl@1371
 18821
+        /* For d=00.110 = 0,75  -> initial guess=01.11 = 1,25 */
mgl@1371
 18822
+        /* For d=00.111 = 0,875 -> initial guess=01.11 = 1,0  */
mgl@1371
 18823
+        /* r2 is also part of the reg pair forming initial guess, but it*/
mgl@1371
 18824
+        /* is kept uninitialized to save one cycle since it has so low significance*/
mgl@1371
 18825
+ 
mgl@1371
 18826
+        lsr     r3, r12, 1
mgl@1371
 18827
+        bfextu  r4, r9, 27, 2
mgl@1371
 18828
+        com     r4
mgl@1371
 18829
+        bfins   r3, r4, 28, 2
mgl@1371
 18830
+ 
mgl@1371
 18831
+        /* First approximation */
mgl@1371
 18832
+        /* Approximating to 32 bits */
mgl@1371
 18833
+        /* r5 = R[j]*d */
mgl@1371
 18834
+        mulu.d  r4, r3, r9
mgl@1371
 18835
+        /* r5 = 2-R[j]*d */
mgl@1371
 18836
+        sub    r5, r12, r5<<2
mgl@1371
 18837
+        /* r3 = R[j]*(2-R[j]*d) */
mgl@1371
 18838
+        mulu.d  r4, r3, r5
mgl@1371
 18839
+        lsl     r3, r5, 2
mgl@1371
 18840
+         
mgl@1371
 18841
+        /* Second approximation */
mgl@1371
 18842
+        /* Approximating to 32 bits */
mgl@1371
 18843
+        /* r5 = R[j]*d */
mgl@1371
 18844
+        mulu.d  r4, r3, r9
mgl@1371
 18845
+        /* r5 = 2-R[j]*d */
mgl@1371
 18846
+        sub    r5, r12, r5<<2
mgl@1371
 18847
+        /* r3 = R[j]*(2-R[j]*d) */
mgl@1371
 18848
+        mulu.d  r4, r3, r5
mgl@1371
 18849
+        lsl     r3, r5, 2
mgl@1371
 18850
+         
mgl@1371
 18851
+        /* Third approximation */
mgl@1371
 18852
+        /* Approximating to 32 bits */
mgl@1371
 18853
+        /* r5 = R[j]*d */
mgl@1371
 18854
+        mulu.d  r4, r3, r9
mgl@1371
 18855
+        /* r5 = 2-R[j]*d */
mgl@1371
 18856
+        sub    r5, r12, r5<<2
mgl@1371
 18857
+        /* r3 = R[j]*(2-R[j]*d) */
mgl@1371
 18858
+        mulu.d  r4, r3, r5
mgl@1371
 18859
+        lsl     r3, r5, 2
mgl@1371
 18860
+ 
mgl@1371
 18861
+        /* Fourth approximation */
mgl@1371
 18862
+        /* Approximating to 64 bits */
mgl@1371
 18863
+        /* r5,r4 = R[j]*d */
mgl@1371
 18864
+        mul_approx_df        r3 /*ah*/, r2 /*al*/, r9 /*bh*/, r8 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
mgl@1371
 18865
+        lsl    r5, 2
mgl@1371
 18866
+        or     r5, r5, r4>>30
mgl@1371
 18867
+        lsl    r4, 2
mgl@1371
 18868
+        /* r5,r4 = 2-R[j]*d */
mgl@1371
 18869
+        neg    r4
mgl@1371
 18870
+        sbc    r5, r12, r5
mgl@1371
 18871
+        /* r3,r2 = R[j]*(2-R[j]*d) */
mgl@1371
 18872
+        mul_approx_df        r3 /*ah*/, r2 /*al*/, r5 /*bh*/, r4 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
mgl@1371
 18873
+        lsl    r3, r5, 2
mgl@1371
 18874
+        or     r3, r3, r4>>30
mgl@1371
 18875
+        lsl    r2, r4, 2
mgl@1371
 18876
+ 
mgl@1371
 18877
+ 
mgl@1371
 18878
+        /* Fifth approximation */
mgl@1371
 18879
+        /* Approximating to 64 bits */
mgl@1371
 18880
+        /* r5,r4 = R[j]*d */
mgl@1371
 18881
+        mul_approx_df        r3 /*ah*/, r2 /*al*/, r9 /*bh*/, r8 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
mgl@1371
 18882
+        lsl    r5, 2
mgl@1371
 18883
+        or     r5, r5, r4>>30
mgl@1371
 18884
+        lsl    r4, 2
mgl@1371
 18885
+        /* r5,r4 = 2-R[j]*d */
mgl@1371
 18886
+        neg    r4
mgl@1371
 18887
+        sbc    r5, r12, r5
mgl@1371
 18888
+        /* r3,r2 = R[j]*(2-R[j]*d) */
mgl@1371
 18889
+        mul_approx_df        r3 /*ah*/, r2 /*al*/, r5 /*bh*/, r4 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
mgl@1371
 18890
+        lsl    r3, r5, 2
mgl@1371
 18891
+        or     r3, r3, r4>>30
mgl@1371
 18892
+        lsl    r2, r4, 2
mgl@1371
 18893
+ 
mgl@1371
 18894
+ 
mgl@1371
 18895
+        /* Multiply with dividend to get quotient */
mgl@1371
 18896
+        mul_approx_df        r3 /*ah*/, r2 /*al*/, r11 /*bh*/, r10 /*bl*/, r3 /*rh*/, r2 /*rl*/, r1 /*sh*/, r0 /*sl*/
mgl@1371
 18897
+ 
mgl@1371
 18898
+ 
mgl@1371
 18899
+        /* To increase speed, this result is not corrected before final rounding.*/
mgl@1371
 18900
+        /* This may give a difference to IEEE compliant code of 1 ULP.*/
mgl@1371
 18901
+		
mgl@1371
 18902
+ 
mgl@1371
 18903
+        /* Adjust exponent and mantissa */
mgl@1371
 18904
+        /* r7:exp, [r3, r2]:mant, [r5, r4]:scratch*/
mgl@1371
 18905
+        /* Mantissa may be of the format 0.xxxx or 1.xxxx. */
mgl@1371
 18906
+        /* In the first case, shift one pos to left.*/
mgl@1371
 18907
+        bld     r3, 31-3
mgl@1371
 18908
+	breq	0f
mgl@1371
 18909
+	lsl	r2, 1
mgl@1371
 18910
+	rol	r3
mgl@1371
 18911
+	sub	r7, 1
mgl@1371
 18912
+#if defined(L_avr32_f64_div)
mgl@1371
 18913
+	/* We must scale down the dividend to 5.59 format. */
mgl@1371
 18914
+	lsr	r10, 3
mgl@1371
 18915
+	or	r10, r10, r11 << 29
mgl@1371
 18916
+	lsr	r11, 3
mgl@1371
 18917
+	rjmp    1f
mgl@1371
 18918
+#endif	
mgl@1371
 18919
+0:	
mgl@1371
 18920
+#if defined(L_avr32_f64_div)
mgl@1371
 18921
+	/* We must scale down the dividend to 6.58 format. */
mgl@1371
 18922
+	lsr	r10, 4
mgl@1371
 18923
+	or	r10, r10, r11 << 28
mgl@1371
 18924
+	lsr	r11, 4
mgl@1371
 18925
+1:	
mgl@1371
 18926
+#endif
mgl@1371
 18927
+        cp      r7, 0   
mgl@1371
 18928
+        brle    __avr32_f64_div_res_subnormal /* Result was subnormal. */
mgl@1371
 18929
+ 
mgl@1371
 18930
+ 
mgl@1371
 18931
+#if defined(L_avr32_f64_div)
mgl@1371
 18932
+	/* In order to round correctly we calculate the remainder:	
mgl@1371
 18933
+	   Remainder = dividend[11:r10] - divisor[r9:r8]*quotient[r3:r2] 
mgl@1371
 18934
+	   for the case when the quotient is halfway between the round-up
mgl@1371
 18935
+	   value and the round down value. If the remainder then is negative
mgl@1371
 18936
+	   it means that the quotient was to big and that it should not be
mgl@1371
 18937
+           rounded up, if the remainder is positive the quotient was to small
mgl@1371
 18938
+	   and we need to round up. If the remainder is zero it means that the
mgl@1371
 18939
+	   quotient is exact but since we need to remove the guard bit we should
mgl@1371
 18940
+	   round to even. */
mgl@1371
 18941
+
mgl@1371
 18942
+	/* Truncate and add guard bit. */
mgl@1371
 18943
+	andl	r2, 0xff00
mgl@1371
 18944
+	orl	r2, 0x0080	
mgl@1371
 18945
+	
mgl@1371
 18946
+
mgl@1371
 18947
+	/* Now do the multiplication. The quotient has the format 4.60
mgl@1371
 18948
+	   while the divisor has the format 2.62 which gives a result
mgl@1371
 18949
+	   of 6.58 */
mgl@1371
 18950
+        mulu.d  r0, r3, r8
mgl@1371
 18951
+        macu.d  r0, r2, r9
mgl@1371
 18952
+        mulu.d  r4, r2, r8
mgl@1371
 18953
+        mulu.d  r8, r3, r9
mgl@1371
 18954
+	add	r5, r0
mgl@1371
 18955
+	adc	r8, r8, r1	
mgl@1371
 18956
+	acr	r9
mgl@1371
 18957
+
mgl@1371
 18958
+
mgl@1371
 18959
+	/* Check if remainder is positive, negative or equal. */
mgl@1371
 18960
+	bfextu	r12, r2, 8, 1  /* Get parity bit into bit 0 of r0 */ 
mgl@1371
 18961
+	cp	r4, 0
mgl@1371
 18962
+	cpc	r5
mgl@1371
 18963
+__avr32_f64_div_round_subnormal:	
mgl@1371
 18964
+	cpc	r8, r10
mgl@1371
 18965
+	cpc	r9, r11
mgl@1371
 18966
+	srlo	r6	/* Remainder positive:	 we need to round up.*/
mgl@1371
 18967
+	moveq	r6, r12  /* Remainder zero:	 round up if mantissa odd. */
mgl@1371
 18968
+#else
mgl@1371
 18969
+	bfextu	r6, r2, 7, 1  /* Get guard bit */ 	
mgl@1371
 18970
+#endif
mgl@1371
 18971
+	/* Final packing, scale down mantissa. */
mgl@1371
 18972
+	lsr	r10, r2, 8
mgl@1371
 18973
+        or      r10, r10, r3<<24
mgl@1371
 18974
+        lsr     r11, r3, 8
mgl@1371
 18975
+	/* Insert exponent and sign bit*/
mgl@1371
 18976
+	bfins	r11, r7, 20, 11
mgl@1371
 18977
+        bld     lr, 31
mgl@1371
 18978
+        bst     r11, 31
mgl@1371
 18979
+
mgl@1371
 18980
+	/* Final rounding */
mgl@1371
 18981
+	add	r10, r6
mgl@1371
 18982
+	acr	r11		
mgl@1371
 18983
+	        
mgl@1371
 18984
+        /* Return result in [r11,r10] */
mgl@1371
 18985
+        ldm     sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
mgl@1371
 18986
+ 
mgl@1371
 18987
+                
mgl@1371
 18988
+2:
mgl@1371
 18989
+        /* Op1 is NaN or inf */
mgl@1371
 18990
+        andh    r11, 0x000f /* Extract mantissa */
mgl@1371
 18991
+        or      r11, r10
mgl@1371
 18992
+        brne    16f     /* Return NaN if op1 is NaN */
mgl@1371
 18993
+        /* Op1 is inf check op2 */
mgl@1371
 18994
+        lsr     r6, r9, 20 /* Extract exponent */
mgl@1371
 18995
+        cbr     r6, 8       /* Clear sign bit */
mgl@1371
 18996
+        cp      r6, 0x7ff
mgl@1371
 18997
+        brne    17f     /* Inf/number gives inf, return inf */
mgl@1371
 18998
+        rjmp    16f     /* The rest gives NaN*/
mgl@1371
 18999
+        
mgl@1371
 19000
+3:      
mgl@1371
 19001
+        /* Op1 is a valid number. Op 2 is NaN or inf */
mgl@1371
 19002
+        andh    r9, 0x000f /* Extract mantissa */
mgl@1371
 19003
+        or      r9, r8
mgl@1371
 19004
+        brne    16f     /* Return NaN if op2 is NaN */
mgl@1371
 19005
+        rjmp    15f     /* Op2 was inf, return zero*/
mgl@1371
 19006
+                
mgl@1371
 19007
+11:     /* Op1 was denormal. Fix it. */
mgl@1371
 19008
+        lsl     r11, 3
mgl@1371
 19009
+        or      r11, r11, r10 >> 29
mgl@1371
 19010
+        lsl     r10, 3
mgl@1371
 19011
+        /* Check if op1 is zero. */
mgl@1371
 19012
+        or      r4, r10, r11
mgl@1371
 19013
+        breq    __avr32_f64_div_op1_zero
mgl@1371
 19014
+        normalize_df    r7 /*exp*/, r10, r11 /*Mantissa*/, r4, r5 /*scratch*/
mgl@1371
 19015
+        lsr     r10, 2
mgl@1371
 19016
+        or      r10, r10, r11 << 30
mgl@1371
 19017
+        lsr     r11, 2
mgl@1371
 19018
+        rjmp    22b
mgl@1371
 19019
+ 
mgl@1371
 19020
+ 
mgl@1371
 19021
+13:     /* Op2 was denormal. Fix it */
mgl@1371
 19022
+        lsl     r9, 3
mgl@1371
 19023
+        or      r9, r9, r8 >> 29
mgl@1371
 19024
+        lsl     r8, 3
mgl@1371
 19025
+        /* Check if op2 is zero. */
mgl@1371
 19026
+        or      r4, r9, r8
mgl@1371
 19027
+        breq    17f     /* Divisor is zero -> return Inf */
mgl@1371
 19028
+        normalize_df    r6 /*exp*/, r8, r9 /*Mantissa*/, r4, r5 /*scratch*/     
mgl@1371
 19029
+        lsr     r8, 2
mgl@1371
 19030
+        or      r8, r8, r9 << 30
mgl@1371
 19031
+        lsr     r9, 2
mgl@1371
 19032
+        rjmp    23b
mgl@1371
 19033
+        
mgl@1371
 19034
+ 
mgl@1371
 19035
+__avr32_f64_div_res_subnormal:/* Divide result was subnormal. */
mgl@1371
 19036
+#if defined(L_avr32_f64_div)
mgl@1371
 19037
+	/* Check how much we must scale down the mantissa. */
mgl@1371
 19038
+	neg	r7
mgl@1371
 19039
+	sub	r7, -1     /* We do no longer have an implicit bit. */
mgl@1371
 19040
+	satu	r7 >> 0, 6 /* Saturate shift amount to max 63. */
mgl@1371
 19041
+	cp.w	r7, 32
mgl@1371
 19042
+	brge	0f
mgl@1371
 19043
+	/* Shift amount <32 */
mgl@1371
 19044
+	/* Scale down quotient */
mgl@1371
 19045
+	rsub	r6, r7, 32
mgl@1371
 19046
+	lsr	r2, r2, r7
mgl@1371
 19047
+	lsl	r12, r3, r6
mgl@1371
 19048
+	or	r2, r12
mgl@1371
 19049
+	lsr	r3, r3, r7
mgl@1371
 19050
+	/* Scale down the dividend to match the scaling of the quotient. */
mgl@1371
 19051
+	lsl	r1, r10, r6
mgl@1371
 19052
+	lsr	r10, r10, r7
mgl@1371
 19053
+	lsl	r12, r11, r6
mgl@1371
 19054
+	or	r10, r12
mgl@1371
 19055
+	lsr	r11, r11, r7
mgl@1371
 19056
+	mov	r0, 0
mgl@1371
 19057
+	rjmp	1f
mgl@1371
 19058
+0:
mgl@1371
 19059
+	/* Shift amount >=32 */
mgl@1371
 19060
+	rsub	r6, r7, 32
mgl@1371
 19061
+	moveq	r0, 0
mgl@1371
 19062
+	moveq	r12, 0
mgl@1371
 19063
+	breq	0f
mgl@1371
 19064
+	lsl	r0, r10, r6
mgl@1371
 19065
+	lsl	r12, r11, r6
mgl@1371
 19066
+0:	
mgl@1371
 19067
+	lsr	r2, r3, r7
mgl@1371
 19068
+	mov	r3, 0
mgl@1371
 19069
+	/* Scale down the dividend to match the scaling of the quotient. */
mgl@1371
 19070
+	lsr	r1, r10, r7
mgl@1371
 19071
+	or	r1, r12
mgl@1371
 19072
+	lsr	r10, r11, r7
mgl@1371
 19073
+	mov	r11, 0
mgl@1371
 19074
+1:	
mgl@1371
 19075
+	/* Start performing the same rounding as done for normal numbers
mgl@1371
 19076
+	   but this time we have scaled the quotient and dividend and hence
mgl@1371
 19077
+	   need a little different comparison. */
mgl@1371
 19078
+	/* Truncate and add guard bit. */
mgl@1371
 19079
+	andl	r2, 0xff00
mgl@1371
 19080
+	orl	r2, 0x0080	
mgl@1371
 19081
+	
mgl@1371
 19082
+	/* Now do the multiplication. */
mgl@1371
 19083
+        mulu.d  r6, r3, r8
mgl@1371
 19084
+        macu.d  r6, r2, r9
mgl@1371
 19085
+        mulu.d  r4, r2, r8
mgl@1371
 19086
+        mulu.d  r8, r3, r9
mgl@1371
 19087
+	add	r5, r6
mgl@1371
 19088
+	adc	r8, r8, r7	
mgl@1371
 19089
+	acr	r9
mgl@1371
 19090
+
mgl@1371
 19091
+	/* Set exponent to 0 */
mgl@1371
 19092
+	mov	r7, 0	
mgl@1371
 19093
+
mgl@1371
 19094
+	/* Check if remainder is positive, negative or equal. */
mgl@1371
 19095
+	bfextu	r12, r2, 8, 1  /* Get parity bit into bit 0 of r0 */ 
mgl@1371
 19096
+	cp	r4, r0
mgl@1371
 19097
+	cpc	r5, r1
mgl@1371
 19098
+	/* Now the rest of the rounding is the same as for normals. */
mgl@1371
 19099
+	rjmp	__avr32_f64_div_round_subnormal
mgl@1371
 19100
+	
mgl@1371
 19101
+#endif
mgl@1371
 19102
+15:	
mgl@1371
 19103
+	/* Flush to zero for the fast version. */
mgl@1371
 19104
+        mov     r11, lr /*Get correct sign*/
mgl@1371
 19105
+        andh    r11, 0x8000, COH
mgl@1371
 19106
+        mov     r10, 0
mgl@1371
 19107
+        ldm     sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
mgl@1371
 19108
+	 
mgl@1371
 19109
+16:     /* Return NaN. */
mgl@1371
 19110
+        mov     r11, -1
mgl@1371
 19111
+        mov     r10, -1
mgl@1371
 19112
+        ldm     sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
mgl@1371
 19113
+        
mgl@1371
 19114
+17:     /* Return INF. */
mgl@1371
 19115
+        mov     r11, lr /*Get correct sign*/
mgl@1371
 19116
+        andh    r11, 0x8000, COH
mgl@1371
 19117
+        orh     r11, 0x7ff0
mgl@1371
 19118
+        mov     r10, 0
mgl@1371
 19119
+        ldm     sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
mgl@1371
 19120
+
mgl@1371
 19121
+__avr32_f64_div_op1_zero:
mgl@1371
 19122
+        or      r5, r8, r9 << 1
mgl@1371
 19123
+        breq    16b             /* 0.0/0.0 -> NaN */
mgl@1371
 19124
+        bfextu  r4, r9, 20, 11
mgl@1371
 19125
+        cp      r4, 0x7ff
mgl@1371
 19126
+        brne    15b             /* Return zero */
mgl@1371
 19127
+        /* Check if divisor is Inf or NaN */
mgl@1371
 19128
+        or      r5, r8, r9 << 12
mgl@1371
 19129
+        breq    15b             /* Divisor is inf -> return zero */
mgl@1371
 19130
+        rjmp    16b             /* Return NaN */                
mgl@1371
 19131
+        
mgl@1371
 19132
+        
mgl@1371
 19133
+        
mgl@1371
 19134
+
mgl@1371
 19135
+#endif  
mgl@1371
 19136
+                
mgl@1371
 19137
+#if defined(L_avr32_f32_addsub) || defined(L_avr32_f32_addsub_fast)
mgl@1371
 19138
+
mgl@1371
 19139
+        .align  2
mgl@1371
 19140
+__avr32_f32_sub_from_add:
mgl@1371
 19141
+        /* Switch sign on op2 */
mgl@1371
 19142
+        eorh    r11, 0x8000
mgl@1371
 19143
+
mgl@1371
 19144
+#if defined(L_avr32_f32_addsub_fast)
mgl@1371
 19145
+        .global __avr32_f32_sub_fast
mgl@1371
 19146
+        .type  __avr32_f32_sub_fast,@function
mgl@1371
 19147
+__avr32_f32_sub_fast:
mgl@1371
 19148
+#else
mgl@1371
 19149
+        .global __avr32_f32_sub
mgl@1371
 19150
+        .type  __avr32_f32_sub,@function
mgl@1371
 19151
+__avr32_f32_sub:
mgl@1371
 19152
+#endif 
mgl@1371
 19153
+ 
mgl@1371
 19154
+        /* Check signs */
mgl@1371
 19155
+        eor     r8, r11, r12
mgl@1371
 19156
+        /* Different signs, use subtraction. */
mgl@1371
 19157
+        brmi    __avr32_f32_add_from_sub
mgl@1371
 19158
+ 
mgl@1371
 19159
+        /* Get sign of op1 */
mgl@1371
 19160
+        mov     r8, r12
mgl@1371
 19161
+        andh    r12, 0x8000, COH                
mgl@1371
 19162
+ 
mgl@1371
 19163
+        /* Remove sign from operands */
mgl@1371
 19164
+        cbr     r11, 31
mgl@1371
 19165
+#if defined(L_avr32_f32_addsub_fast)
mgl@1371
 19166
+        reteq   r8      /* If op2 is zero return op1 */
mgl@1371
 19167
+#endif
mgl@1371
 19168
+        cbr     r8, 31
mgl@1371
 19169
+ 
mgl@1371
 19170
+        /* Put the number with the largest exponent in r10
mgl@1371
 19171
+           and the number with the smallest exponent in r9 */
mgl@1371
 19172
+        max     r10, r8, r11
mgl@1371
 19173
+        min     r9, r8, r11
mgl@1371
 19174
+        cp      r10, r8 /*If largest operand (in R10) is not equal to op1*/
mgl@1371
 19175
+        subne   r12, 1 /* Subtract 1 from sign, which will invert MSB of r12*/
mgl@1371
 19176
+        andh    r12, 0x8000, COH /*Mask all but MSB*/
mgl@1371
 19177
+ 
mgl@1371
 19178
+        /* Unpack exponent and mantissa of op1 */
mgl@1371
 19179
+        lsl     r8, r10, 8
mgl@1371
 19180
+        sbr     r8, 31  /* Set implicit bit. */
mgl@1371
 19181
+        lsr     r10, 23 
mgl@1371
 19182
+                
mgl@1371
 19183
+        /* op1 is NaN or Inf. */
mgl@1371
 19184
+        cp.w    r10, 0xff
mgl@1371
 19185
+        breq    __avr32_f32_sub_op1_nan_or_inf
mgl@1371
 19186
+        
mgl@1371
 19187
+        /* Unpack exponent and mantissa of op2 */
mgl@1371
 19188
+        lsl     r11, r9, 8
mgl@1371
 19189
+        sbr     r11, 31  /* Set implicit bit. */
mgl@1371
 19190
+        lsr     r9, 23  
mgl@1371
 19191
+ 
mgl@1371
 19192
+#if defined(L_avr32_f32_addsub)
mgl@1371
 19193
+        /* Keep sticky bit for correct IEEE rounding */
mgl@1371
 19194
+        st.w    --sp, r12
mgl@1371
 19195
+ 
mgl@1371
 19196
+        /* op2 is either zero or subnormal. */
mgl@1371
 19197
+        breq    __avr32_f32_sub_op2_subnormal
mgl@1371
 19198
+0:      
mgl@1371
 19199
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 19200
+        sub     r12, r10, r9                 
mgl@1371
 19201
+
mgl@1371
 19202
+	breq	__avr32_f32_sub_shift_done
mgl@1371
 19203
+ 
mgl@1371
 19204
+        /* Saturate the shift amount to 31. If the amount
mgl@1371
 19205
+           is any larger op2 is insignificant. */
mgl@1371
 19206
+        satu    r12 >> 0, 5      
mgl@1371
 19207
+
mgl@1371
 19208
+        /* Put the remaining bits into r9.*/
mgl@1371
 19209
+        rsub    r9, r12, 32
mgl@1371
 19210
+        lsl     r9, r11, r9
mgl@1371
 19211
+	
mgl@1371
 19212
+	/* If the remaining bits are non-zero then we must subtract one
mgl@1371
 19213
+	   more from opL.  */
mgl@1371
 19214
+	subne	r8, 1
mgl@1371
 19215
+	srne	r9	/* LSB of r9 represents sticky bits. */
mgl@1371
 19216
+
mgl@1371
 19217
+        /* Shift mantissa of op2 to same decimal point as the mantissa
mgl@1371
 19218
+           of op1. */
mgl@1371
 19219
+        lsr     r11, r11, r12
mgl@1371
 19220
+ 
mgl@1371
 19221
+
mgl@1371
 19222
+__avr32_f32_sub_shift_done:	
mgl@1371
 19223
+        /* Now subtract the mantissas. */
mgl@1371
 19224
+        sub     r8, r11
mgl@1371
 19225
+ 
mgl@1371
 19226
+        ld.w    r12, sp++
mgl@1371
 19227
+ 
mgl@1371
 19228
+        /* Normalize resulting mantissa. */
mgl@1371
 19229
+        clz     r11, r8
mgl@1371
 19230
+
mgl@1371
 19231
+	retcs	0
mgl@1371
 19232
+        lsl     r8, r8, r11
mgl@1371
 19233
+        sub     r10, r11
mgl@1371
 19234
+        brle    __avr32_f32_sub_subnormal_result
mgl@1371
 19235
+
mgl@1371
 19236
+        /* Insert the bits we will remove from the mantissa into r9[31:24] */
mgl@1371
 19237
+	or	r9, r9, r8 << 24
mgl@1371
 19238
+#else
mgl@1371
 19239
+        /* Ignore sticky bit to simplify and speed up rounding */
mgl@1371
 19240
+        /* op2 is either zero or subnormal. */
mgl@1371
 19241
+        breq    __avr32_f32_sub_op2_subnormal
mgl@1371
 19242
+0:      
mgl@1371
 19243
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 19244
+        rsub    r9, r10                 
mgl@1371
 19245
+ 
mgl@1371
 19246
+        /* Saturate the shift amount to 31. If the amount
mgl@1371
 19247
+           is any larger op2 is insignificant. */
mgl@1371
 19248
+        satu    r9 >> 0, 5      
mgl@1371
 19249
+ 
mgl@1371
 19250
+        /* Shift mantissa of op2 to same decimal point as the mantissa
mgl@1371
 19251
+           of op1. */
mgl@1371
 19252
+        lsr     r11, r11, r9
mgl@1371
 19253
+ 
mgl@1371
 19254
+        /* Now subtract the mantissas. */
mgl@1371
 19255
+        sub     r8, r11
mgl@1371
 19256
+ 
mgl@1371
 19257
+        /* Normalize resulting mantissa. */
mgl@1371
 19258
+        clz     r9, r8
mgl@1371
 19259
+	retcs	0
mgl@1371
 19260
+        lsl     r8, r8, r9
mgl@1371
 19261
+        sub     r10, r9
mgl@1371
 19262
+        brle    __avr32_f32_sub_subnormal_result        
mgl@1371
 19263
+#endif
mgl@1371
 19264
+        
mgl@1371
 19265
+        /* Pack result. */
mgl@1371
 19266
+        or      r12, r12, r8 >> 8
mgl@1371
 19267
+        bfins   r12, r10, 23, 8         
mgl@1371
 19268
+ 
mgl@1371
 19269
+        /* Round */     
mgl@1371
 19270
+__avr32_f32_sub_round:
mgl@1371
 19271
+#if defined(L_avr32_f32_addsub)
mgl@1371
 19272
+	mov_imm	r10, 0x80000000
mgl@1371
 19273
+        bld     r12, 0
mgl@1371
 19274
+        subne   r10, -1 
mgl@1371
 19275
+        cp.w    r9, r10
mgl@1371
 19276
+        subhs   r12, -1
mgl@1371
 19277
+#else
mgl@1371
 19278
+        bld     r8, 7 
mgl@1371
 19279
+        acr     r12
mgl@1371
 19280
+#endif  
mgl@1371
 19281
+        
mgl@1371
 19282
+        ret     r12     
mgl@1371
 19283
+ 
mgl@1371
 19284
+ 
mgl@1371
 19285
+__avr32_f32_sub_op2_subnormal:
mgl@1371
 19286
+        /* Fix implicit bit and adjust exponent of subnormals. */
mgl@1371
 19287
+        cbr     r11, 31
mgl@1371
 19288
+        /* Set exponent to 1 if we do not have a zero. */
mgl@1371
 19289
+        movne   r9,1
mgl@1371
 19290
+ 
mgl@1371
 19291
+        /* Check if op1 is also subnormal. */
mgl@1371
 19292
+        cp.w    r10, 0
mgl@1371
 19293
+        brne    0b
mgl@1371
 19294
+ 
mgl@1371
 19295
+        cbr     r8, 31
mgl@1371
 19296
+         /* If op1 is not zero set exponent to 1. */
mgl@1371
 19297
+        movne   r10,1
mgl@1371
 19298
+                
mgl@1371
 19299
+        rjmp    0b
mgl@1371
 19300
+ 
mgl@1371
 19301
+__avr32_f32_sub_op1_nan_or_inf: 
mgl@1371
 19302
+        /* Check if op1 is NaN, if so return NaN */
mgl@1371
 19303
+        lsl     r11, r8, 1
mgl@1371
 19304
+        retne   -1
mgl@1371
 19305
+ 
mgl@1371
 19306
+        /* op1 is Inf. */
mgl@1371
 19307
+        bfins   r12, r10, 23, 8 /* Generate Inf in r12 */
mgl@1371
 19308
+ 
mgl@1371
 19309
+        /* Check if op2 is Inf. or NaN */
mgl@1371
 19310
+        lsr     r11, r9, 23
mgl@1371
 19311
+        cp.w    r11, 0xff
mgl@1371
 19312
+        retne   r12             /* op2 not Inf or NaN, return op1 */
mgl@1371
 19313
+ 
mgl@1371
 19314
+        ret     -1              /* op2 Inf or NaN, return NaN */
mgl@1371
 19315
+ 
mgl@1371
 19316
+__avr32_f32_sub_subnormal_result:
mgl@1371
 19317
+        /* Check if the number is so small that
mgl@1371
 19318
+           it will be represented with zero. */
mgl@1371
 19319
+        rsub    r10, r10, 9
mgl@1371
 19320
+        rsub    r11, r10, 32
mgl@1371
 19321
+        retcs   0
mgl@1371
 19322
+ 
mgl@1371
 19323
+        /* Shift the mantissa into the correct position.*/
mgl@1371
 19324
+        lsr     r10, r8, r10
mgl@1371
 19325
+        /* Add sign bit. */
mgl@1371
 19326
+        or      r12, r10
mgl@1371
 19327
+
mgl@1371
 19328
+        /* Put the shifted out bits in the most significant part
mgl@1371
 19329
+           of r8. */
mgl@1371
 19330
+        lsl     r8, r8, r11
mgl@1371
 19331
+ 
mgl@1371
 19332
+#if defined(L_avr32_f32_addsub)
mgl@1371
 19333
+        /* Add all the remainder bits used for rounding into r9 */
mgl@1371
 19334
+        or      r9, r8
mgl@1371
 19335
+#else
mgl@1371
 19336
+        lsr     r8, 24 
mgl@1371
 19337
+#endif
mgl@1371
 19338
+        rjmp    __avr32_f32_sub_round
mgl@1371
 19339
+ 
mgl@1371
 19340
+                                
mgl@1371
 19341
+        .align  2
mgl@1371
 19342
+
mgl@1371
 19343
+__avr32_f32_add_from_sub:
mgl@1371
 19344
+        /* Switch sign on op2 */
mgl@1371
 19345
+        eorh    r11, 0x8000
mgl@1371
 19346
+
mgl@1371
 19347
+#if defined(L_avr32_f32_addsub_fast)
mgl@1371
 19348
+        .global __avr32_f32_add_fast
mgl@1371
 19349
+        .type  __avr32_f32_add_fast,@function
mgl@1371
 19350
+__avr32_f32_add_fast:
mgl@1371
 19351
+#else
mgl@1371
 19352
+        .global __avr32_f32_add
mgl@1371
 19353
+        .type  __avr32_f32_add,@function
mgl@1371
 19354
+__avr32_f32_add:
mgl@1371
 19355
+#endif 
mgl@1371
 19356
+	
mgl@1371
 19357
+        /* Check signs */
mgl@1371
 19358
+        eor     r8, r11, r12
mgl@1371
 19359
+        /* Different signs, use subtraction. */
mgl@1371
 19360
+        brmi    __avr32_f32_sub_from_add
mgl@1371
 19361
+ 
mgl@1371
 19362
+        /* Get sign of op1 */
mgl@1371
 19363
+        mov     r8, r12
mgl@1371
 19364
+        andh    r12, 0x8000, COH                
mgl@1371
 19365
+ 
mgl@1371
 19366
+        /* Remove sign from operands */
mgl@1371
 19367
+        cbr     r11, 31
mgl@1371
 19368
+#if defined(L_avr32_f32_addsub_fast)
mgl@1371
 19369
+        reteq   r8      /* If op2 is zero return op1 */
mgl@1371
 19370
+#endif
mgl@1371
 19371
+        cbr     r8, 31
mgl@1371
 19372
+ 
mgl@1371
 19373
+        /* Put the number with the largest exponent in r10
mgl@1371
 19374
+           and the number with the smallest exponent in r9 */
mgl@1371
 19375
+        max     r10, r8, r11
mgl@1371
 19376
+        min     r9, r8, r11
mgl@1371
 19377
+ 
mgl@1371
 19378
+        /* Unpack exponent and mantissa of op1 */
mgl@1371
 19379
+        lsl     r8, r10, 8
mgl@1371
 19380
+        sbr     r8, 31  /* Set implicit bit. */
mgl@1371
 19381
+        lsr     r10, 23 
mgl@1371
 19382
+                
mgl@1371
 19383
+        /* op1 is NaN or Inf. */
mgl@1371
 19384
+        cp.w    r10, 0xff
mgl@1371
 19385
+        breq    __avr32_f32_add_op1_nan_or_inf
mgl@1371
 19386
+        
mgl@1371
 19387
+        /* Unpack exponent and mantissa of op2 */
mgl@1371
 19388
+        lsl     r11, r9, 8
mgl@1371
 19389
+        sbr     r11, 31  /* Set implicit bit. */
mgl@1371
 19390
+        lsr     r9, 23  
mgl@1371
 19391
+ 
mgl@1371
 19392
+#if defined(L_avr32_f32_addsub)
mgl@1371
 19393
+        /* op2 is either zero or subnormal. */
mgl@1371
 19394
+        breq    __avr32_f32_add_op2_subnormal
mgl@1371
 19395
+0:      
mgl@1371
 19396
+        /* Keep sticky bit for correct IEEE rounding */
mgl@1371
 19397
+        st.w    --sp, r12
mgl@1371
 19398
+ 
mgl@1371
 19399
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 19400
+        rsub    r9, r10                 
mgl@1371
 19401
+ 
mgl@1371
 19402
+        /* Saturate the shift amount to 31. If the amount
mgl@1371
 19403
+           is any larger op2 is insignificant. */
mgl@1371
 19404
+        satu    r9 >> 0, 5      
mgl@1371
 19405
+ 
mgl@1371
 19406
+        /* Shift mantissa of op2 to same decimal point as the mantissa
mgl@1371
 19407
+           of op1. */
mgl@1371
 19408
+        lsr     r12, r11, r9
mgl@1371
 19409
+ 
mgl@1371
 19410
+        /* Put the remainding bits into r11[23:..].*/
mgl@1371
 19411
+        rsub    r9, r9, (32-8)
mgl@1371
 19412
+        lsl     r11, r11, r9
mgl@1371
 19413
+        /* Insert the bits we will remove from the mantissa into r11[31:24] */
mgl@1371
 19414
+        bfins   r11, r12, 24, 8
mgl@1371
 19415
+ 
mgl@1371
 19416
+        /* Now add the mantissas. */
mgl@1371
 19417
+        add     r8, r12
mgl@1371
 19418
+ 
mgl@1371
 19419
+        ld.w    r12, sp++
mgl@1371
 19420
+#else
mgl@1371
 19421
+        /* Ignore sticky bit to simplify and speed up rounding */
mgl@1371
 19422
+        /* op2 is either zero or subnormal. */
mgl@1371
 19423
+        breq    __avr32_f32_add_op2_subnormal
mgl@1371
 19424
+0:      
mgl@1371
 19425
+        /* Get shift amount to scale mantissa of op2. */
mgl@1371
 19426
+        rsub    r9, r10                 
mgl@1371
 19427
+ 
mgl@1371
 19428
+        /* Saturate the shift amount to 31. If the amount
mgl@1371
 19429
+           is any larger op2 is insignificant. */
mgl@1371
 19430
+        satu    r9 >> 0, 5      
mgl@1371
 19431
+ 
mgl@1371
 19432
+        /* Shift mantissa of op2 to same decimal point as the mantissa
mgl@1371
 19433
+           of op1. */
mgl@1371
 19434
+        lsr     r11, r11, r9
mgl@1371
 19435
+ 
mgl@1371
 19436
+        /* Now add the mantissas. */
mgl@1371
 19437
+        add     r8, r11
mgl@1371
 19438
+        
mgl@1371
 19439
+#endif
mgl@1371
 19440
+        /* Check if we overflowed. */
mgl@1371
 19441
+        brcs    __avr32_f32_add_res_of
mgl@1371
 19442
+1:      
mgl@1371
 19443
+        /* Pack result. */
mgl@1371
 19444
+        or      r12, r12, r8 >> 8
mgl@1371
 19445
+        bfins   r12, r10, 23, 8         
mgl@1371
 19446
+ 
mgl@1371
 19447
+        /* Round */     
mgl@1371
 19448
+#if defined(L_avr32_f32_addsub)
mgl@1371
 19449
+	mov_imm	r10, 0x80000000
mgl@1371
 19450
+        bld     r12, 0
mgl@1371
 19451
+        subne   r10, -1 
mgl@1371
 19452
+        cp.w    r11, r10
mgl@1371
 19453
+        subhs   r12, -1
mgl@1371
 19454
+#else
mgl@1371
 19455
+        bld     r8, 7 
mgl@1371
 19456
+        acr     r12
mgl@1371
 19457
+#endif  
mgl@1371
 19458
+
mgl@1371
 19459
+        ret     r12     
mgl@1371
 19460
+ 
mgl@1371
 19461
+__avr32_f32_add_op2_subnormal:
mgl@1371
 19462
+        /* Fix implicit bit and adjust exponent of subnormals. */
mgl@1371
 19463
+        cbr     r11, 31
mgl@1371
 19464
+        /* Set exponent to 1 if we do not have a zero. */
mgl@1371
 19465
+        movne   r9,1
mgl@1371
 19466
+ 
mgl@1371
 19467
+        /* Check if op1 is also subnormal. */
mgl@1371
 19468
+        cp.w    r10, 0
mgl@1371
 19469
+        brne    0b
mgl@1371
 19470
+	/* Both operands subnormal, just add the mantissas and 
mgl@1371
 19471
+	   pack. If the addition of the subnormal numbers results
mgl@1371
 19472
+	   in a normal number then the exponent will automatically
mgl@1371
 19473
+	   be set to 1 by the addition. */
mgl@1371
 19474
+        cbr     r8, 31
mgl@1371
 19475
+	add	r11, r8
mgl@1371
 19476
+	or	r12, r12, r11 >> 8
mgl@1371
 19477
+	ret	r12
mgl@1371
 19478
+ 
mgl@1371
 19479
+__avr32_f32_add_op1_nan_or_inf: 
mgl@1371
 19480
+        /* Check if op1 is NaN, if so return NaN */
mgl@1371
 19481
+        lsl     r11, r8, 1
mgl@1371
 19482
+        retne   -1
mgl@1371
 19483
+ 
mgl@1371
 19484
+        /* op1 is Inf. */
mgl@1371
 19485
+        bfins   r12, r10, 23, 8 /* Generate Inf in r12 */
mgl@1371
 19486
+ 
mgl@1371
 19487
+        /* Check if op2 is Inf. or NaN */
mgl@1371
 19488
+        lsr     r11, r9, 23
mgl@1371
 19489
+        cp.w    r11, 0xff
mgl@1371
 19490
+        retne   r12             /* op2 not Inf or NaN, return op1 */
mgl@1371
 19491
+ 
mgl@1371
 19492
+        lsl     r9, 9
mgl@1371
 19493
+        reteq   r12             /* op2 Inf return op1 */
mgl@1371
 19494
+        ret     -1              /* op2 is NaN, return NaN */ 
mgl@1371
 19495
+ 
mgl@1371
 19496
+__avr32_f32_add_res_of:
mgl@1371
 19497
+        /* We overflowed. Increase exponent and shift mantissa.*/
mgl@1371
 19498
+        lsr     r8, 1
mgl@1371
 19499
+        sub     r10, -1
mgl@1371
 19500
+ 
mgl@1371
 19501
+        /* Clear mantissa to set result to Inf if the exponent is 255. */
mgl@1371
 19502
+        cp.w    r10, 255
mgl@1371
 19503
+        moveq   r8, 0
mgl@1371
 19504
+        moveq   r11, 0
mgl@1371
 19505
+        rjmp    1b      
mgl@1371
 19506
+        
mgl@1371
 19507
+        
mgl@1371
 19508
+#endif
mgl@1371
 19509
+
mgl@1371
 19510
+	
mgl@1371
 19511
+#if defined(L_avr32_f32_div) || defined(L_avr32_f32_div_fast)
mgl@1371
 19512
+	.align	2
mgl@1371
 19513
+
mgl@1371
 19514
+#if defined(L_avr32_f32_div_fast)
mgl@1371
 19515
+        .global __avr32_f32_div_fast
mgl@1371
 19516
+        .type  __avr32_f32_div_fast,@function
mgl@1371
 19517
+__avr32_f32_div_fast:
mgl@1371
 19518
+#else
mgl@1371
 19519
+        .global __avr32_f32_div
mgl@1371
 19520
+        .type  __avr32_f32_div,@function
mgl@1371
 19521
+__avr32_f32_div:
mgl@1371
 19522
+#endif
mgl@1371
 19523
+	 
mgl@1371
 19524
+        eor     r8, r11, r12            /* MSB(r8) = Sign(op1) ^ Sign(op2) */
mgl@1371
 19525
+ 
mgl@1371
 19526
+        /* Unpack */
mgl@1371
 19527
+        lsl     r12,1
mgl@1371
 19528
+        reteq   0                       /* Return zero if op1 is zero */
mgl@1371
 19529
+        lsl     r11,1
mgl@1371
 19530
+        breq    4f                      /* Check op2 for zero */
mgl@1371
 19531
+        
mgl@1371
 19532
+        /* Unpack op1*/ 
mgl@1371
 19533
+        /* exp: r9 */
mgl@1371
 19534
+        /* sf:  r12 */
mgl@1371
 19535
+        lsr     r9, r12, 24
mgl@1371
 19536
+        breq    11f /*If number is subnormal*/
mgl@1371
 19537
+        cp      r9, 0xff
mgl@1371
 19538
+        brhs    2f  /* Check op1 for NaN or Inf */      
mgl@1371
 19539
+        lsl     r12, 7
mgl@1371
 19540
+        sbr     r12, 31 /*Implicit bit*/
mgl@1371
 19541
+12:                     
mgl@1371
 19542
+ 
mgl@1371
 19543
+        /* Unpack op2*/
mgl@1371
 19544
+        /* exp: r10 */
mgl@1371
 19545
+        /* sf:  r11 */
mgl@1371
 19546
+        lsr     r10, r11, 24
mgl@1371
 19547
+        breq    13f /*If number is subnormal*/
mgl@1371
 19548
+        cp      r10, 0xff
mgl@1371
 19549
+        brhs    3f  /* Check op2 for NaN or Inf */      
mgl@1371
 19550
+        
mgl@1371
 19551
+        lsl     r11,7
mgl@1371
 19552
+        sbr     r11, 31 /*Implicit bit*/
mgl@1371
 19553
+14:     
mgl@1371
 19554
+ 
mgl@1371
 19555
+        /* For UC3, store with predecrement is faster than stm */
mgl@1371
 19556
+        st.w    --sp, r5
mgl@1371
 19557
+        st.d    --sp, r6
mgl@1371
 19558
+ 
mgl@1371
 19559
+        /* Calculate new exponent */
mgl@1371
 19560
+        sub     r9, r10
mgl@1371
 19561
+        sub     r9,-127
mgl@1371
 19562
+ 
mgl@1371
 19563
+        /* Divide */
mgl@1371
 19564
+        /* Approximating 1/d with the following recurrence: */
mgl@1371
 19565
+        /* R[j+1] = R[j]*(2-R[j]*d) */
mgl@1371
 19566
+        /* Using 2.30 format */
mgl@1371
 19567
+        /* TWO:  r10 */
mgl@1371
 19568
+        /* d:    r5 */
mgl@1371
 19569
+        /* Multiply result :     r6, r7 */
mgl@1371
 19570
+        /* Initial guess :       r11 */
mgl@1371
 19571
+        /* New approximations :  r11 */
mgl@1371
 19572
+        /* Dividend :            r12 */
mgl@1371
 19573
+
mgl@1371
 19574
+	/* Load TWO */
mgl@1371
 19575
+	mov_imm	r10, 0x80000000 
mgl@1371
 19576
+         
mgl@1371
 19577
+        lsr     r12, 2     /* Get significand of Op1 in 2.30 format */
mgl@1371
 19578
+        lsr     r5, r11, 2 /* Get significand of Op2 (=d) in 2.30 format */
mgl@1371
 19579
+ 
mgl@1371
 19580
+        /* Load initial guess, using look-up table */
mgl@1371
 19581
+        /* Initial guess is of format 01.XY, where XY is constructed as follows: */
mgl@1371
 19582
+        /* Let d be of following format: 00.1xy....., then XY=~xy */
mgl@1371
 19583
+        /* For d=00.100 = 0,5   -> initial guess=01.11 = 1,75 */
mgl@1371
 19584
+        /* For d=00.101 = 0,625 -> initial guess=01.11 = 1,5  */
mgl@1371
 19585
+        /* For d=00.110 = 0,75  -> initial guess=01.11 = 1,25 */
mgl@1371
 19586
+        /* For d=00.111 = 0,875 -> initial guess=01.11 = 1,0  */
mgl@1371
 19587
+ 
mgl@1371
 19588
+        lsr     r11, r10, 1
mgl@1371
 19589
+        bfextu  r6, r5, 27, 2
mgl@1371
 19590
+        com     r6
mgl@1371
 19591
+        bfins   r11, r6, 28, 2
mgl@1371
 19592
+ 
mgl@1371
 19593
+        /* First approximation */
mgl@1371
 19594
+        /* r7 = R[j]*d */
mgl@1371
 19595
+        mulu.d  r6, r11, r5
mgl@1371
 19596
+        /* r7 = 2-R[j]*d */
mgl@1371
 19597
+        sub    r7, r10, r7<<2
mgl@1371
 19598
+        /* r11 = R[j]*(2-R[j]*d) */
mgl@1371
 19599
+        mulu.d  r6, r11, r7
mgl@1371
 19600
+        lsl     r11, r7, 2
mgl@1371
 19601
+         
mgl@1371
 19602
+        /* Second approximation */
mgl@1371
 19603
+        /* r7 = R[j]*d */
mgl@1371
 19604
+        mulu.d  r6, r11, r5
mgl@1371
 19605
+        /* r7 = 2-R[j]*d */
mgl@1371
 19606
+        sub    r7, r10, r7<<2
mgl@1371
 19607
+        /* r11 = R[j]*(2-R[j]*d) */
mgl@1371
 19608
+        mulu.d  r6, r11, r7
mgl@1371
 19609
+        lsl     r11, r7, 2
mgl@1371
 19610
+         
mgl@1371
 19611
+        /* Third approximation */
mgl@1371
 19612
+        /* r7 = R[j]*d */
mgl@1371
 19613
+        mulu.d  r6, r11, r5
mgl@1371
 19614
+        /* r7 = 2-R[j]*d */
mgl@1371
 19615
+        sub    r7, r10, r7<<2
mgl@1371
 19616
+        /* r11 = R[j]*(2-R[j]*d) */
mgl@1371
 19617
+        mulu.d  r6, r11, r7
mgl@1371
 19618
+        lsl     r11, r7, 2
mgl@1371
 19619
+ 
mgl@1371
 19620
+        /* Fourth approximation */
mgl@1371
 19621
+        /* r7 = R[j]*d */
mgl@1371
 19622
+        mulu.d  r6, r11, r5
mgl@1371
 19623
+        /* r7 = 2-R[j]*d */
mgl@1371
 19624
+        sub    r7, r10, r7<<2
mgl@1371
 19625
+        /* r11 = R[j]*(2-R[j]*d) */
mgl@1371
 19626
+        mulu.d  r6, r11, r7
mgl@1371
 19627
+        lsl     r11, r7, 2
mgl@1371
 19628
+ 
mgl@1371
 19629
+ 
mgl@1371
 19630
+        /* Multiply with dividend to get quotient, r7 = sf(op1)/sf(op2) */
mgl@1371
 19631
+        mulu.d  r6, r11, r12
mgl@1371
 19632
+ 
mgl@1371
 19633
+        /* Shift by 3 to get result in 1.31 format, as required by the exponent. */
mgl@1371
 19634
+        /* Note that 1.31 format is already used by the exponent in r9, since */
mgl@1371
 19635
+        /* a bias of 127 was added to the result exponent, even though the implicit */
mgl@1371
 19636
+        /* bit was inserted. This gives the exponent an additional bias of 1, which */
mgl@1371
 19637
+        /* supports 1.31 format. */
mgl@1371
 19638
+	//lsl     r10, r7, 3
mgl@1371
 19639
+
mgl@1371
 19640
+	/* Adjust exponent and mantissa in case the result is of format
mgl@1371
 19641
+	   0000.1xxx to 0001.xxx*/	
mgl@1371
 19642
+#if defined(L_avr32_f32_div)
mgl@1371
 19643
+	lsr	r12, 4	/* Scale dividend to 6.26 format to match the
mgl@1371
 19644
+			   result of the multiplication of the divisor and 
mgl@1371
 19645
+			   quotient to get the remainder. */
mgl@1371
 19646
+#endif
mgl@1371
 19647
+	bld	r7, 31-3
mgl@1371
 19648
+	breq	0f
mgl@1371
 19649
+	lsl	r7, 1	
mgl@1371
 19650
+	sub	r9, 1
mgl@1371
 19651
+#if defined(L_avr32_f32_div)
mgl@1371
 19652
+	lsl	r12, 1	/* Scale dividend to 5.27 format to match the
mgl@1371
 19653
+			   result of the multiplication of the divisor and 
mgl@1371
 19654
+			   quotient to get the remainder. */
mgl@1371
 19655
+#endif
mgl@1371
 19656
+0:		
mgl@1371
 19657
+        cp      r9, 0   
mgl@1371
 19658
+        brle    __avr32_f32_div_res_subnormal /* Result was subnormal. */
mgl@1371
 19659
+
mgl@1371
 19660
+		
mgl@1371
 19661
+#if defined(L_avr32_f32_div)
mgl@1371
 19662
+	/* In order to round correctly we calculate the remainder:	
mgl@1371
 19663
+	   Remainder = dividend[r12] - divisor[r5]*quotient[r7] 
mgl@1371
 19664
+	   for the case when the quotient is halfway between the round-up
mgl@1371
 19665
+	   value and the round down value. If the remainder then is negative
mgl@1371
 19666
+	   it means that the quotient was to big and that it should not be
mgl@1371
 19667
+           rounded up, if the remainder is positive the quotient was to small
mgl@1371
 19668
+	   and we need to round up. If the remainder is zero it means that the
mgl@1371
 19669
+	   quotient is exact but since we need to remove the guard bit we should
mgl@1371
 19670
+	   round to even. */
mgl@1371
 19671
+	andl	r7, 0xffe0
mgl@1371
 19672
+	orl	r7, 0x0010
mgl@1371
 19673
+
mgl@1371
 19674
+	/* Now do the multiplication. The quotient has the format 4.28
mgl@1371
 19675
+	   while the divisor has the format 2.30 which gives a result
mgl@1371
 19676
+	   of 6.26 */
mgl@1371
 19677
+	mulu.d	r10, r5, r7
mgl@1371
 19678
+
mgl@1371
 19679
+	/* Check if remainder is positive, negative or equal. */
mgl@1371
 19680
+	bfextu	r5, r7, 5, 1  /* Get parity bit into bit 0 of r5 */ 
mgl@1371
 19681
+	cp	r10, 0
mgl@1371
 19682
+__avr32_f32_div_round_subnormal:	
mgl@1371
 19683
+	cpc	r11, r12
mgl@1371
 19684
+	srlo	r11	/* Remainder positive:	 we need to round up.*/
mgl@1371
 19685
+	moveq	r11, r5  /* Remainder zero:	 round up if mantissa odd. */
mgl@1371
 19686
+#else
mgl@1371
 19687
+	bfextu	r11, r7, 4, 1  /* Get guard bit */ 	
mgl@1371
 19688
+#endif
mgl@1371
 19689
+                               
mgl@1371
 19690
+        /* Pack final result*/
mgl@1371
 19691
+        lsr     r12, r7, 5
mgl@1371
 19692
+        bfins   r12, r9, 23, 8
mgl@1371
 19693
+        /* For UC3, load with postincrement is faster than ldm */
mgl@1371
 19694
+        ld.d    r6, sp++
mgl@1371
 19695
+        ld.w    r5, sp++
mgl@1371
 19696
+        bld     r8, 31
mgl@1371
 19697
+        bst     r12, 31
mgl@1371
 19698
+	/* Rounding add. */
mgl@1371
 19699
+	add	r12, r11
mgl@1371
 19700
+        ret     r12
mgl@1371
 19701
+
mgl@1371
 19702
+__divsf_return_op1:     
mgl@1371
 19703
+        lsl     r8, 1
mgl@1371
 19704
+        ror     r12
mgl@1371
 19705
+        ret     r12
mgl@1371
 19706
+ 
mgl@1371
 19707
+ 
mgl@1371
 19708
+2:
mgl@1371
 19709
+        /* Op1 is NaN or inf */
mgl@1371
 19710
+        retne   -1      /* Return NaN if op1 is NaN */
mgl@1371
 19711
+        /* Op1 is inf check op2 */
mgl@1371
 19712
+	mov_imm	r9, 0xff000000
mgl@1371
 19713
+        cp      r11, r9
mgl@1371
 19714
+        brlo    __divsf_return_op1 /* inf/number gives inf */
mgl@1371
 19715
+        ret     -1      /* The rest gives NaN*/
mgl@1371
 19716
+3:      
mgl@1371
 19717
+        /* Op2 is NaN or inf */
mgl@1371
 19718
+        reteq   0       /* Return zero if number/inf*/
mgl@1371
 19719
+        ret     -1      /* Return NaN*/
mgl@1371
 19720
+4:
mgl@1371
 19721
+        /* Op2 is zero ? */
mgl@1371
 19722
+        tst     r12,r12
mgl@1371
 19723
+        reteq   -1      /* 0.0/0.0 is NaN */
mgl@1371
 19724
+        /* Nonzero/0.0 is Inf. Sign bit will be shifted in before returning*/
mgl@1371
 19725
+	mov_imm	r12, 0xff000000
mgl@1371
 19726
+        rjmp    __divsf_return_op1
mgl@1371
 19727
+                
mgl@1371
 19728
+11:     /* Op1 was denormal. Fix it. */
mgl@1371
 19729
+        lsl     r12,7
mgl@1371
 19730
+        clz     r9,r12
mgl@1371
 19731
+        lsl     r12,r12,r9
mgl@1371
 19732
+        rsub    r9,r9,1
mgl@1371
 19733
+        rjmp    12b
mgl@1371
 19734
+ 
mgl@1371
 19735
+13:     /* Op2 was denormal. Fix it. */ 
mgl@1371
 19736
+        lsl     r11,7
mgl@1371
 19737
+        clz     r10,r11
mgl@1371
 19738
+        lsl     r11,r11,r10
mgl@1371
 19739
+        rsub    r10,r10,1
mgl@1371
 19740
+        rjmp    14b
mgl@1371
 19741
+        
mgl@1371
 19742
+ 
mgl@1371
 19743
+__avr32_f32_div_res_subnormal:     /* Divide result was subnormal */
mgl@1371
 19744
+#if defined(L_avr32_f32_div)
mgl@1371
 19745
+	/* Check how much we must scale down the mantissa. */
mgl@1371
 19746
+	neg	r9
mgl@1371
 19747
+	sub	r9, -1     /* We do no longer have an implicit bit. */
mgl@1371
 19748
+	satu	r9 >> 0, 5 /* Saturate shift amount to max 32. */
mgl@1371
 19749
+	/* Scale down quotient */
mgl@1371
 19750
+	rsub	r10, r9, 32
mgl@1371
 19751
+	lsr	r7, r7, r9
mgl@1371
 19752
+	/* Scale down the dividend to match the scaling of the quotient. */
mgl@1371
 19753
+	lsl	r6, r12, r10	/* Make the divident 64-bit and put the lsw in r6 */
mgl@1371
 19754
+	lsr	r12, r12, r9
mgl@1371
 19755
+
mgl@1371
 19756
+	/* Start performing the same rounding as done for normal numbers
mgl@1371
 19757
+	   but this time we have scaled the quotient and dividend and hence
mgl@1371
 19758
+	   need a little different comparison. */
mgl@1371
 19759
+	andl	r7, 0xffe0
mgl@1371
 19760
+	orl	r7, 0x0010
mgl@1371
 19761
+
mgl@1371
 19762
+	/* Now do the multiplication. The quotient has the format 4.28
mgl@1371
 19763
+	   while the divisor has the format 2.30 which gives a result
mgl@1371
 19764
+	   of 6.26 */
mgl@1371
 19765
+	mulu.d	r10, r5, r7
mgl@1371
 19766
+
mgl@1371
 19767
+	/* Set exponent to 0 */
mgl@1371
 19768
+	mov	r9, 0	
mgl@1371
 19769
+
mgl@1371
 19770
+	/* Check if remainder is positive, negative or equal. */
mgl@1371
 19771
+	bfextu	r5, r7, 5, 1  /* Get parity bit into bit 0 of r5 */ 
mgl@1371
 19772
+	cp	r10, r6
mgl@1371
 19773
+	rjmp	__avr32_f32_div_round_subnormal
mgl@1371
 19774
+
mgl@1371
 19775
+#else
mgl@1371
 19776
+        ld.d    r6, sp++
mgl@1371
 19777
+        ld.w    r5, sp++
mgl@1371
 19778
+        /*Flush to zero*/
mgl@1371
 19779
+	ret	0
mgl@1371
 19780
+#endif
mgl@1371
 19781
+#endif
mgl@1371
 19782
+ 
mgl@1371
 19783
+#ifdef L_avr32_f32_mul
mgl@1371
 19784
+        .global __avr32_f32_mul
mgl@1371
 19785
+        .type  __avr32_f32_mul,@function
mgl@1371
 19786
+ 
mgl@1371
 19787
+                
mgl@1371
 19788
+__avr32_f32_mul:
mgl@1371
 19789
+        mov     r8, r12
mgl@1371
 19790
+        eor     r12, r11                /* MSB(r8) = Sign(op1) ^ Sign(op2) */
mgl@1371
 19791
+        andh    r12, 0x8000, COH
mgl@1371
 19792
+        
mgl@1371
 19793
+        /* arrange operands so that that op1 >= op2 */
mgl@1371
 19794
+        cbr     r8, 31
mgl@1371
 19795
+        breq    __avr32_f32_mul_op1_zero
mgl@1371
 19796
+        cbr     r11, 31
mgl@1371
 19797
+ 
mgl@1371
 19798
+        /* Put the number with the largest exponent in r10
mgl@1371
 19799
+           and the number with the smallest exponent in r9 */
mgl@1371
 19800
+        max     r10, r8, r11
mgl@1371
 19801
+        min     r9, r8, r11
mgl@1371
 19802
+ 
mgl@1371
 19803
+        /* Unpack exponent and mantissa of op1 */
mgl@1371
 19804
+        lsl     r8, r10, 8
mgl@1371
 19805
+        sbr     r8, 31  /* Set implicit bit. */
mgl@1371
 19806
+        lsr     r10, 23 
mgl@1371
 19807
+                
mgl@1371
 19808
+        /* op1 is NaN or Inf. */
mgl@1371
 19809
+        cp.w    r10, 0xff
mgl@1371
 19810
+        breq    __avr32_f32_mul_op1_nan_or_inf
mgl@1371
 19811
+        
mgl@1371
 19812
+        /* Unpack exponent and mantissa of op2 */
mgl@1371
 19813
+        lsl     r11, r9, 8
mgl@1371
 19814
+        sbr     r11, 31  /* Set implicit bit. */
mgl@1371
 19815
+        lsr     r9, 23  
mgl@1371
 19816
+ 
mgl@1371
 19817
+        /* op2 is either zero or subnormal. */
mgl@1371
 19818
+        breq    __avr32_f32_mul_op2_subnormal
mgl@1371
 19819
+0:      
mgl@1371
 19820
+        /* Calculate new exponent */
mgl@1371
 19821
+        add     r9,r10
mgl@1371
 19822
+ 
mgl@1371
 19823
+        /* Do the multiplication */
mgl@1371
 19824
+        mulu.d  r10,r8,r11
mgl@1371
 19825
+ 
mgl@1371
 19826
+        /* We might need to scale up by two if the MSB of the result is
mgl@1371
 19827
+           zero. */
mgl@1371
 19828
+        lsl     r8, r11, 1
mgl@1371
 19829
+        movcc   r11, r8
mgl@1371
 19830
+        subcc   r9, 1
mgl@1371
 19831
+ 
mgl@1371
 19832
+        /* Put the shifted out bits of the mantissa into r10 */
mgl@1371
 19833
+        lsr     r10, 8
mgl@1371
 19834
+        bfins   r10, r11, 24, 8
mgl@1371
 19835
+                
mgl@1371
 19836
+        sub     r9,(127-1)              /* remove extra exponent bias */
mgl@1371
 19837
+        brle    __avr32_f32_mul_res_subnormal
mgl@1371
 19838
+ 
mgl@1371
 19839
+        /* Check for Inf. */
mgl@1371
 19840
+        cp.w    r9, 0xff
mgl@1371
 19841
+        brge    1f
mgl@1371
 19842
+ 
mgl@1371
 19843
+        /* Pack result. */
mgl@1371
 19844
+        or      r12, r12, r11 >> 8
mgl@1371
 19845
+        bfins   r12, r9, 23, 8          
mgl@1371
 19846
+ 
mgl@1371
 19847
+        /* Round */     
mgl@1371
 19848
+__avr32_f32_mul_round:
mgl@1371
 19849
+	mov_imm	r8, 0x80000000
mgl@1371
 19850
+        bld     r12, 0
mgl@1371
 19851
+        subne   r8, -1  
mgl@1371
 19852
+ 
mgl@1371
 19853
+        cp.w    r10, r8
mgl@1371
 19854
+        subhs   r12, -1
mgl@1371
 19855
+        
mgl@1371
 19856
+        ret     r12     
mgl@1371
 19857
+ 
mgl@1371
 19858
+1:      
mgl@1371
 19859
+        /* Return Inf */        
mgl@1371
 19860
+        orh     r12, 0x7f80
mgl@1371
 19861
+        ret     r12
mgl@1371
 19862
+ 
mgl@1371
 19863
+__avr32_f32_mul_op2_subnormal:
mgl@1371
 19864
+        cbr     r11, 31
mgl@1371
 19865
+        clz     r9, r11
mgl@1371
 19866
+        retcs   0       /* op2 is zero. Return 0 */
mgl@1371
 19867
+        lsl     r11, r11, r9
mgl@1371
 19868
+        rsub    r9, r9, 1
mgl@1371
 19869
+                
mgl@1371
 19870
+        /* Check if op2 is subnormal. */
mgl@1371
 19871
+        tst     r10, r10
mgl@1371
 19872
+        brne    0b
mgl@1371
 19873
+ 
mgl@1371
 19874
+        /* op2 is subnormal */  
mgl@1371
 19875
+        cbr     r8, 31
mgl@1371
 19876
+        clz     r10, r11
mgl@1371
 19877
+        retcs   0       /* op1 is zero. Return 0 */
mgl@1371
 19878
+        lsl     r8, r8, r10
mgl@1371
 19879
+        rsub    r10, r10, 1
mgl@1371
 19880
+                        
mgl@1371
 19881
+        rjmp    0b
mgl@1371
 19882
+                
mgl@1371
 19883
+ 
mgl@1371
 19884
+__avr32_f32_mul_op1_nan_or_inf:
mgl@1371
 19885
+        /* Check if op1 is NaN, if so return NaN */
mgl@1371
 19886
+        lsl     r11, r8, 1
mgl@1371
 19887
+        retne   -1
mgl@1371
 19888
+ 
mgl@1371
 19889
+        /* op1 is Inf. */
mgl@1371
 19890
+        tst     r9, r9
mgl@1371
 19891
+        reteq   -1      /* Inf * 0 -> NaN */
mgl@1371
 19892
+ 
mgl@1371
 19893
+        bfins   r12, r10, 23, 8 /* Generate Inf in r12 */
mgl@1371
 19894
+ 
mgl@1371
 19895
+        /* Check if op2 is Inf. or NaN */
mgl@1371
 19896
+        lsr     r11, r9, 23
mgl@1371
 19897
+        cp.w    r11, 0xff
mgl@1371
 19898
+        retne   r12             /* op2 not Inf or NaN, return Info */
mgl@1371
 19899
+ 
mgl@1371
 19900
+        lsl     r9, 9
mgl@1371
 19901
+        reteq   r12             /* op2 Inf return Inf */
mgl@1371
 19902
+        ret     -1              /* op2 is NaN, return NaN */ 
mgl@1371
 19903
+        
mgl@1371
 19904
+__avr32_f32_mul_res_subnormal:
mgl@1371
 19905
+        /* Check if the number is so small that
mgl@1371
 19906
+           it will be represented with zero. */
mgl@1371
 19907
+        rsub    r9, r9, 9
mgl@1371
 19908
+        rsub    r8, r9, 32
mgl@1371
 19909
+        retcs   0
mgl@1371
 19910
+ 
mgl@1371
 19911
+        /* Shift the mantissa into the correct position.*/
mgl@1371
 19912
+        lsr     r9, r11, r9
mgl@1371
 19913
+        /* Add sign bit. */
mgl@1371
 19914
+        or      r12, r9
mgl@1371
 19915
+        /* Put the shifted out bits in the most significant part
mgl@1371
 19916
+           of r8. */
mgl@1371
 19917
+        lsl     r11, r11, r8
mgl@1371
 19918
+ 
mgl@1371
 19919
+        /* Add all the remainder bits used for rounding into r11 */
mgl@1371
 19920
+        andh    r10, 0x00FF     
mgl@1371
 19921
+        or      r10, r11
mgl@1371
 19922
+        rjmp    __avr32_f32_mul_round
mgl@1371
 19923
+
mgl@1371
 19924
+__avr32_f32_mul_op1_zero:
mgl@1371
 19925
+        bfextu  r10, r11, 23, 8
mgl@1371
 19926
+        cp.w    r10, 0xff
mgl@1371
 19927
+        retne   r12
mgl@1371
 19928
+        reteq   -1        
mgl@1371
 19929
+ 
mgl@1371
 19930
+#endif  
mgl@1371
 19931
+ 
mgl@1371
 19932
+        
mgl@1371
 19933
+#ifdef L_avr32_s32_to_f32
mgl@1371
 19934
+        .global __avr32_s32_to_f32
mgl@1371
 19935
+        .type  __avr32_s32_to_f32,@function
mgl@1371
 19936
+__avr32_s32_to_f32:
mgl@1371
 19937
+        cp      r12, 0
mgl@1371
 19938
+        reteq   r12     /* If zero then return zero float */
mgl@1371
 19939
+        mov     r11, r12 /* Keep the sign */
mgl@1371
 19940
+        abs     r12     /* Compute the absolute value */
mgl@1371
 19941
+        mov     r10, 31 + 127   /* Set the correct exponent */
mgl@1371
 19942
+        
mgl@1371
 19943
+        /* Normalize */
mgl@1371
 19944
+        normalize_sf    r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/       
mgl@1371
 19945
+ 
mgl@1371
 19946
+        /* Check for subnormal result */
mgl@1371
 19947
+        cp.w    r10, 0
mgl@1371
 19948
+        brle    __avr32_s32_to_f32_subnormal
mgl@1371
 19949
+ 
mgl@1371
 19950
+        round_sf        r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/       
mgl@1371
 19951
+        pack_sf         r12 /*sf*/, r10 /*exp*/, r12 /*mant*/
mgl@1371
 19952
+        lsl     r11, 1
mgl@1371
 19953
+        ror     r12
mgl@1371
 19954
+        ret     r12             
mgl@1371
 19955
+ 
mgl@1371
 19956
+__avr32_s32_to_f32_subnormal:
mgl@1371
 19957
+        /* Adjust a subnormal result */
mgl@1371
 19958
+        adjust_subnormal_sf     r12/*sf*/, r10 /*exp*/, r12 /*mant*/, r11/*sign*/, r9 /*scratch*/
mgl@1371
 19959
+        ret     r12
mgl@1371
 19960
+        
mgl@1371
 19961
+#endif
mgl@1371
 19962
+ 
mgl@1371
 19963
+#ifdef L_avr32_u32_to_f32
mgl@1371
 19964
+        .global __avr32_u32_to_f32
mgl@1371
 19965
+        .type  __avr32_u32_to_f32,@function
mgl@1371
 19966
+__avr32_u32_to_f32:
mgl@1371
 19967
+        cp      r12, 0
mgl@1371
 19968
+        reteq   r12     /* If zero then return zero float */
mgl@1371
 19969
+        mov     r10, 31 + 127   /* Set the correct exponent */
mgl@1371
 19970
+        
mgl@1371
 19971
+        /* Normalize */
mgl@1371
 19972
+        normalize_sf    r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/       
mgl@1371
 19973
+ 
mgl@1371
 19974
+        /* Check for subnormal result */
mgl@1371
 19975
+        cp.w    r10, 0
mgl@1371
 19976
+        brle    __avr32_u32_to_f32_subnormal
mgl@1371
 19977
+ 
mgl@1371
 19978
+        round_sf        r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/       
mgl@1371
 19979
+        pack_sf         r12 /*sf*/, r10 /*exp*/, r12 /*mant*/
mgl@1371
 19980
+        lsr     r12,1   /* Sign bit is 0 for unsigned int */
mgl@1371
 19981
+        ret     r12             
mgl@1371
 19982
+ 
mgl@1371
 19983
+__avr32_u32_to_f32_subnormal:
mgl@1371
 19984
+        /* Adjust a subnormal result */
mgl@1371
 19985
+        mov     r8, 0
mgl@1371
 19986
+        adjust_subnormal_sf     r12/*sf*/,r10 /*exp*/, r12 /*mant*/,r8/*sign*/, r9 /*scratch*/
mgl@1371
 19987
+        ret     r12
mgl@1371
 19988
+        
mgl@1371
 19989
+        
mgl@1371
 19990
+#endif
mgl@1371
 19991
+        
mgl@1371
 19992
+ 
mgl@1371
 19993
+#ifdef L_avr32_f32_to_s32
mgl@1371
 19994
+        .global __avr32_f32_to_s32
mgl@1371
 19995
+        .type  __avr32_f32_to_s32,@function
mgl@1371
 19996
+__avr32_f32_to_s32:
mgl@1371
 19997
+        bfextu  r11, r12, 23, 8
mgl@1371
 19998
+        sub     r11,127                 /* Fix bias */
mgl@1371
 19999
+        retlo   0                       /* Negative exponent yields zero integer */
mgl@1371
 20000
+ 
mgl@1371
 20001
+        /* Shift mantissa into correct position */
mgl@1371
 20002
+        rsub    r11,r11,31      /* Shift amount */
mgl@1371
 20003
+        lsl     r10,r12,8       /* Get mantissa */
mgl@1371
 20004
+        sbr     r10,31          /* Add implicit bit */
mgl@1371
 20005
+        lsr     r10,r10,r11     /* Perform shift */
mgl@1371
 20006
+        lsl     r12,1           /* Check sign */
mgl@1371
 20007
+        retcc   r10             /* if positive, we are done */
mgl@1371
 20008
+        neg     r10             /* if negative float, negate result */
mgl@1371
 20009
+        ret     r10
mgl@1371
 20010
+ 
mgl@1371
 20011
+#endif  
mgl@1371
 20012
+        
mgl@1371
 20013
+#ifdef L_avr32_f32_to_u32
mgl@1371
 20014
+        .global __avr32_f32_to_u32
mgl@1371
 20015
+        .type  __avr32_f32_to_u32,@function
mgl@1371
 20016
+__avr32_f32_to_u32:
mgl@1371
 20017
+        cp      r12,0
mgl@1371
 20018
+        retmi   0                       /* Negative numbers gives 0 */
mgl@1371
 20019
+        bfextu  r11, r12, 23, 8         /* Extract exponent */
mgl@1371
 20020
+        sub     r11,127                 /* Fix bias */
mgl@1371
 20021
+        retlo   0                       /* Negative exponent yields zero integer */
mgl@1371
 20022
+ 
mgl@1371
 20023
+        /* Shift mantissa into correct position */
mgl@1371
 20024
+        rsub    r11,r11,31      /* Shift amount */
mgl@1371
 20025
+        lsl     r12,8           /* Get mantissa */
mgl@1371
 20026
+        sbr     r12,31          /* Add implicit bit */
mgl@1371
 20027
+        lsr     r12,r12,r11     /* Perform shift */
mgl@1371
 20028
+        ret     r12
mgl@1371
 20029
+ 
mgl@1371
 20030
+#endif  
mgl@1371
 20031
+ 
mgl@1371
 20032
+#ifdef L_avr32_f32_to_f64
mgl@1371
 20033
+        .global __avr32_f32_to_f64
mgl@1371
 20034
+        .type  __avr32_f32_to_f64,@function
mgl@1371
 20035
+ 
mgl@1371
 20036
+__avr32_f32_to_f64:
mgl@1371
 20037
+        lsl     r11,r12,1               /* Remove sign bit, keep original value in r12*/
mgl@1371
 20038
+        moveq   r10, 0
mgl@1371
 20039
+        reteq   r11                     /* Return zero if input is zero */
mgl@1371
 20040
+ 
mgl@1371
 20041
+        bfextu  r9,r11,24,8              /* Get exponent */
mgl@1371
 20042
+        cp.w    r9,0xff                 /* check for NaN or inf */
mgl@1371
 20043
+        breq    0f
mgl@1371
 20044
+ 
mgl@1371
 20045
+        lsl     r11,7                   /* Convert sf mantissa to df format */
mgl@1371
 20046
+        mov     r10,0
mgl@1371
 20047
+ 
mgl@1371
 20048
+        /* Check if implicit bit should be set */
mgl@1371
 20049
+        cp.w    r9, 0
mgl@1371
 20050
+        subeq   r9,-1                    /* Adjust exponent if it was 0 */
mgl@1371
 20051
+        srne    r8
mgl@1371
 20052
+        or      r11, r11, r8 << 31      /* Set implicit bit if needed */
mgl@1371
 20053
+        sub     r9,(127-0x3ff)          /* Convert exponent to df format exponent */
mgl@1371
 20054
+ 
mgl@1371
 20055
+        /*We know that low register of mantissa is 0, and will be unaffected by normalization.*/
mgl@1371
 20056
+        /*We can therefore use the faster normalize_sf function instead of normalize_df.*/
mgl@1371
 20057
+        normalize_sf    r9 /*exp*/, r11 /*mantissa*/, r8 /*scratch*/
mgl@1371
 20058
+        pack_df         r9 /*exp*/, r10, r11 /*mantissa*/, r10, r11 /*df*/
mgl@1371
 20059
+ 
mgl@1371
 20060
+__extendsfdf_return_op1:        
mgl@1371
 20061
+        /* Rotate in sign bit */
mgl@1371
 20062
+        lsl     r12, 1
mgl@1371
 20063
+        ror     r11
mgl@1371
 20064
+        ret     r11
mgl@1371
 20065
+                        
mgl@1371
 20066
+0:
mgl@1371
 20067
+        /* Inf or NaN*/
mgl@1371
 20068
+	mov_imm	r10, 0xffe00000
mgl@1371
 20069
+        lsl     r11,8                   /* check mantissa */
mgl@1371
 20070
+        movne   r11, -1                 /* Return NaN */
mgl@1371
 20071
+        moveq   r11, r10                /* Return inf */
mgl@1371
 20072
+        rjmp    __extendsfdf_return_op1
mgl@1371
 20073
+#endif                  
mgl@1371
 20074
+ 
mgl@1371
 20075
+ 
mgl@1371
 20076
+#ifdef L_avr32_f64_to_f32
mgl@1371
 20077
+        .global __avr32_f64_to_f32
mgl@1371
 20078
+        .type  __avr32_f64_to_f32,@function
mgl@1371
 20079
+ 
mgl@1371
 20080
+__avr32_f64_to_f32:
mgl@1371
 20081
+        /* Unpack */
mgl@1371
 20082
+        lsl     r9,r11,1                /* Unpack exponent */
mgl@1371
 20083
+        lsr     r9,21
mgl@1371
 20084
+ 
mgl@1371
 20085
+        reteq   0                       /* If exponent is 0 the number is so small
mgl@1371
 20086
+                                           that the conversion to single float gives
mgl@1371
 20087
+                                           zero */
mgl@1371
 20088
+ 
mgl@1371
 20089
+        lsl     r8,r11,10                  /* Adjust mantissa */
mgl@1371
 20090
+        or      r12,r8,r10>>22
mgl@1371
 20091
+ 
mgl@1371
 20092
+        lsl     r10,10                  /* Check if there are any remaining bits
mgl@1371
 20093
+                                           in the low part of the mantissa.*/
mgl@1371
 20094
+        neg     r10
mgl@1371
 20095
+        rol     r12                     /* If there were remaining bits then set lsb
mgl@1371
 20096
+                                           of mantissa to 1 */
mgl@1371
 20097
+ 
mgl@1371
 20098
+        cp      r9,0x7ff
mgl@1371
 20099
+        breq    2f                      /* Check for NaN or inf */
mgl@1371
 20100
+ 
mgl@1371
 20101
+        sub     r9,(0x3ff-127)          /* Adjust bias of exponent */
mgl@1371
 20102
+        sbr     r12,31                  /* set the implicit bit.*/
mgl@1371
 20103
+ 
mgl@1371
 20104
+        cp.w    r9, 0                   /* Check for subnormal number */
mgl@1371
 20105
+        brle    3f
mgl@1371
 20106
+ 
mgl@1371
 20107
+        round_sf        r9 /*exp*/, r12 /*mant*/, r10 /*scratch*/       
mgl@1371
 20108
+        pack_sf         r12 /*sf*/, r9 /*exp*/, r12 /*mant*/
mgl@1371
 20109
+__truncdfsf_return_op1: 
mgl@1371
 20110
+        /* Rotate in sign bit */
mgl@1371
 20111
+        lsl     r11, 1
mgl@1371
 20112
+        ror     r12
mgl@1371
 20113
+        ret     r12             
mgl@1371
 20114
+        
mgl@1371
 20115
+2:
mgl@1371
 20116
+        /* NaN or inf */
mgl@1371
 20117
+        cbr     r12,31                  /* clear implicit bit */
mgl@1371
 20118
+        retne   -1                      /* Return NaN if mantissa not zero */
mgl@1371
 20119
+	mov_imm	r12, 0xff000000
mgl@1371
 20120
+        ret     r12                     /* Return inf */
mgl@1371
 20121
+ 
mgl@1371
 20122
+3:      /* Result is subnormal. Adjust it.*/
mgl@1371
 20123
+        adjust_subnormal_sf     r12/*sf*/,r9 /*exp*/, r12 /*mant*/, r11/*sign*/, r10 /*scratch*/
mgl@1371
 20124
+        ret     r12
mgl@1371
 20125
+        
mgl@1371
 20126
+                
mgl@1371
 20127
+#endif
mgl@1371
 20128
+ 
mgl@1371
 20129
+#if defined(L_mulsi3) && (__AVR32_UC__ == 3)
mgl@1371
 20130
+	.global __mulsi3
mgl@1371
 20131
+	.type __mulsi3,@function
mgl@1371
 20132
+
mgl@1371
 20133
+__mulsi3:
mgl@1371
 20134
+	mov r9, 0
mgl@1371
 20135
+0:
mgl@1371
 20136
+	lsr r11, 1
mgl@1371
 20137
+	addcs r9, r9, r12
mgl@1371
 20138
+	breq 1f
mgl@1371
 20139
+	lsl r12, 1
mgl@1371
 20140
+	rjmp 0b
mgl@1371
 20141
+1:
mgl@1371
 20142
+	ret r9
mgl@1371
 20143
+#endif
mgl@1371
 20144
--- /dev/null
mgl@1371
 20145
+++ b/gcc/config/avr32/lib2funcs.S
mgl@1371
 20146
@@ -0,0 +1,21 @@
mgl@1371
 20147
+	.align	4
mgl@1371
 20148
+	.global __nonlocal_goto
mgl@1371
 20149
+	.type  __nonlocal_goto,@function
mgl@1371
 20150
+
mgl@1371
 20151
+/* __nonlocal_goto:	This function handles nonlocal_goto's in gcc.
mgl@1371
 20152
+
mgl@1371
 20153
+	parameter 0 (r12) = New Frame Pointer
mgl@1371
 20154
+	parameter 1 (r11) = Address to goto
mgl@1371
 20155
+	parameter 2 (r10) = New Stack Pointer
mgl@1371
 20156
+
mgl@1371
 20157
+	This function invalidates the return stack, since it returns from a
mgl@1371
 20158
+	function without using a return instruction.
mgl@1371
 20159
+*/
mgl@1371
 20160
+__nonlocal_goto:
mgl@1371
 20161
+	mov	r7, r12
mgl@1371
 20162
+	mov	sp, r10
mgl@1371
 20163
+	frs			# Flush return stack
mgl@1371
 20164
+	mov	pc, r11
mgl@1371
 20165
+
mgl@1371
 20166
+
mgl@1371
 20167
+		
mgl@1371
 20168
--- /dev/null
mgl@1371
 20169
+++ b/gcc/config/avr32/linux-elf.h
mgl@1371
 20170
@@ -0,0 +1,151 @@
mgl@1371
 20171
+/*
mgl@1371
 20172
+   Linux/Elf specific definitions.
mgl@1371
 20173
+   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 20174
+
mgl@1371
 20175
+   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 20176
+   and H�vard Skinnemoen, Atmel Norway, <hskinnemoen@atmel.com>
mgl@1371
 20177
+
mgl@1371
 20178
+   This file is part of GCC.
mgl@1371
 20179
+
mgl@1371
 20180
+   This program is free software; you can redistribute it and/or modify
mgl@1371
 20181
+   it under the terms of the GNU General Public License as published by
mgl@1371
 20182
+   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 20183
+   (at your option) any later version.
mgl@1371
 20184
+
mgl@1371
 20185
+   This program is distributed in the hope that it will be useful,
mgl@1371
 20186
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 20187
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 20188
+   GNU General Public License for more details.
mgl@1371
 20189
+
mgl@1371
 20190
+   You should have received a copy of the GNU General Public License
mgl@1371
 20191
+   along with this program; if not, write to the Free Software
mgl@1371
 20192
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mgl@1371
 20193
+
mgl@1371
 20194
+
mgl@1371
 20195
+
mgl@1371
 20196
+/* elfos.h should have already been included.  Now just override
mgl@1371
 20197
+   any conflicting definitions and add any extras.  */
mgl@1371
 20198
+
mgl@1371
 20199
+/* Run-time Target Specification.  */
mgl@1371
 20200
+#undef  TARGET_VERSION
mgl@1371
 20201
+#define TARGET_VERSION  fputs (" (AVR32 GNU/Linux with ELF)", stderr);
mgl@1371
 20202
+
mgl@1371
 20203
+/* Do not assume anything about header files.  */
mgl@1371
 20204
+#define NO_IMPLICIT_EXTERN_C
mgl@1371
 20205
+
mgl@1371
 20206
+/* The GNU C++ standard library requires that these macros be defined.  */
mgl@1371
 20207
+#undef CPLUSPLUS_CPP_SPEC
mgl@1371
 20208
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
mgl@1371
 20209
+
mgl@1371
 20210
+/* Now we define the strings used to build the spec file.  */
mgl@1371
 20211
+#undef  LIB_SPEC
mgl@1371
 20212
+#define LIB_SPEC \
mgl@1371
 20213
+  "%{pthread:-lpthread} \
mgl@1371
 20214
+   %{shared:-lc} \
mgl@1371
 20215
+   %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
mgl@1371
 20216
+
mgl@1371
 20217
+/* Provide a STARTFILE_SPEC appropriate for GNU/Linux.  Here we add
mgl@1371
 20218
+   the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
mgl@1371
 20219
+   provides part of the support for getting C++ file-scope static
mgl@1371
 20220
+   object constructed before entering `main'.  */
mgl@1371
 20221
+
mgl@1371
 20222
+#undef  STARTFILE_SPEC
mgl@1371
 20223
+#define STARTFILE_SPEC \
mgl@1371
 20224
+  "%{!shared: \
mgl@1371
 20225
+     %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
mgl@1371
 20226
+		       %{!p:%{profile:gcrt1.o%s} \
mgl@1371
 20227
+			 %{!profile:crt1.o%s}}}} \
mgl@1371
 20228
+   crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
mgl@1371
 20229
+
mgl@1371
 20230
+/* Provide a ENDFILE_SPEC appropriate for GNU/Linux.  Here we tack on
mgl@1371
 20231
+   the GNU/Linux magical crtend.o file (see crtstuff.c) which
mgl@1371
 20232
+   provides part of the support for getting C++ file-scope static
mgl@1371
 20233
+   object constructed before entering `main', followed by a normal
mgl@1371
 20234
+   GNU/Linux "finalizer" file, `crtn.o'.  */
mgl@1371
 20235
+
mgl@1371
 20236
+#undef  ENDFILE_SPEC
mgl@1371
 20237
+#define ENDFILE_SPEC \
mgl@1371
 20238
+  "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
mgl@1371
 20239
+
mgl@1371
 20240
+#undef ASM_SPEC
mgl@1371
 20241
+#define ASM_SPEC "%{!mno-pic:%{!fno-pic:--pic}} %{mrelax|O*:%{mno-relax|O0|O1: ;:--linkrelax}} %{mcpu=*:-mcpu=%*}"
mgl@1371
 20242
+ 
mgl@1371
 20243
+#undef  LINK_SPEC
mgl@1371
 20244
+#define LINK_SPEC "%{version:-v} \
mgl@1371
 20245
+   %{static:-Bstatic} \
mgl@1371
 20246
+   %{shared:-shared} \
mgl@1371
 20247
+   %{symbolic:-Bsymbolic} \
mgl@1371
 20248
+   %{rdynamic:-export-dynamic} \
mgl@1371
 20249
+   %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
mgl@1371
 20250
+   %{mrelax|O*:%{mno-relax|O0|O1: ;:--relax}}"
mgl@1371
 20251
+
mgl@1371
 20252
+#define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
mgl@1371
 20253
+
mgl@1371
 20254
+/* This is how we tell the assembler that two symbols have the same value.  */
mgl@1371
 20255
+#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
mgl@1371
 20256
+  do					   \
mgl@1371
 20257
+    {					   \
mgl@1371
 20258
+      assemble_name (FILE, NAME1); 	   \
mgl@1371
 20259
+      fputs (" = ", FILE);		   \
mgl@1371
 20260
+      assemble_name (FILE, NAME2);	   \
mgl@1371
 20261
+      fputc ('\n', FILE);		   \
mgl@1371
 20262
+    }					   \
mgl@1371
 20263
+  while (0)
mgl@1371
 20264
+
mgl@1371
 20265
+
mgl@1371
 20266
+
mgl@1371
 20267
+#undef  CC1_SPEC
mgl@1371
 20268
+#define CC1_SPEC "%{profile:-p}"
mgl@1371
 20269
+
mgl@1371
 20270
+/* Target CPU builtins.  */
mgl@1371
 20271
+#define TARGET_CPU_CPP_BUILTINS()				\
mgl@1371
 20272
+  do								\
mgl@1371
 20273
+    {								\
mgl@1371
 20274
+      builtin_define ("__avr32__");				\
mgl@1371
 20275
+      builtin_define ("__AVR32__");				\
mgl@1371
 20276
+      builtin_define ("__AVR32_LINUX__");			\
mgl@1371
 20277
+      builtin_define (avr32_part->macro);			\
mgl@1371
 20278
+      builtin_define (avr32_arch->macro);			\
mgl@1371
 20279
+      if (avr32_arch->uarch_type == UARCH_TYPE_AVR32A)		\
mgl@1371
 20280
+	builtin_define ("__AVR32_AVR32A__");			\
mgl@1371
 20281
+      else							\
mgl@1371
 20282
+	builtin_define ("__AVR32_AVR32B__");			\
mgl@1371
 20283
+      if (TARGET_UNALIGNED_WORD)				\
mgl@1371
 20284
+	builtin_define ("__AVR32_HAS_UNALIGNED_WORD__");	\
mgl@1371
 20285
+      if (TARGET_SIMD)						\
mgl@1371
 20286
+	builtin_define ("__AVR32_HAS_SIMD__");			\
mgl@1371
 20287
+      if (TARGET_DSP)						\
mgl@1371
 20288
+	builtin_define ("__AVR32_HAS_DSP__");			\
mgl@1371
 20289
+      if (TARGET_RMW)						\
mgl@1371
 20290
+	builtin_define ("__AVR32_HAS_RMW__");			\
mgl@1371
 20291
+      if (TARGET_BRANCH_PRED)					\
mgl@1371
 20292
+	builtin_define ("__AVR32_HAS_BRANCH_PRED__");		\
mgl@1371
 20293
+      if (TARGET_FAST_FLOAT)                                    \
mgl@1371
 20294
+        builtin_define ("__AVR32_FAST_FLOAT__");                \
mgl@1371
 20295
+    }								\
mgl@1371
 20296
+  while (0)
mgl@1371
 20297
+
mgl@1371
 20298
+
mgl@1371
 20299
+
mgl@1371
 20300
+/* Call the function profiler with a given profile label.  */
mgl@1371
 20301
+#undef  FUNCTION_PROFILER
mgl@1371
 20302
+#define FUNCTION_PROFILER(STREAM, LABELNO)				\
mgl@1371
 20303
+  do									\
mgl@1371
 20304
+    {									\
mgl@1371
 20305
+      fprintf (STREAM, "\tmov\tlr, lo(mcount)\n\torh\tlr, hi(mcount)\n"); \
mgl@1371
 20306
+      fprintf (STREAM, "\ticall lr\n");					\
mgl@1371
 20307
+    }									\
mgl@1371
 20308
+  while (0)
mgl@1371
 20309
+
mgl@1371
 20310
+#define NO_PROFILE_COUNTERS 1
mgl@1371
 20311
+
mgl@1371
 20312
+/* For dynamic libraries to work */
mgl@1371
 20313
+/* #define PLT_REG_CALL_CLOBBERED 1 */
mgl@1371
 20314
+#define AVR32_ALWAYS_PIC 1
mgl@1371
 20315
+
mgl@1371
 20316
+/* uclibc does not implement sinf, cosf etc. */
mgl@1371
 20317
+#undef TARGET_C99_FUNCTIONS
mgl@1371
 20318
+#define TARGET_C99_FUNCTIONS 0
mgl@1371
 20319
+
mgl@1371
 20320
+#define LINK_GCC_C_SEQUENCE_SPEC \
mgl@1371
 20321
+  "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
mgl@1371
 20322
--- /dev/null
mgl@1371
 20323
+++ b/gcc/config/avr32/predicates.md
mgl@1371
 20324
@@ -0,0 +1,419 @@
mgl@1371
 20325
+;;   AVR32 predicates file.
mgl@1371
 20326
+;;   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 20327
+;;
mgl@1371
 20328
+;;   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 20329
+;;
mgl@1371
 20330
+;;   This file is part of GCC.
mgl@1371
 20331
+;;
mgl@1371
 20332
+;;   This program is free software; you can redistribute it and/or modify
mgl@1371
 20333
+;;   it under the terms of the GNU General Public License as published by
mgl@1371
 20334
+;;   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 20335
+;;   (at your option) any later version.
mgl@1371
 20336
+;;
mgl@1371
 20337
+;;   This program is distributed in the hope that it will be useful,
mgl@1371
 20338
+;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 20339
+;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 20340
+;;   GNU General Public License for more details.
mgl@1371
 20341
+;;
mgl@1371
 20342
+;;   You should have received a copy of the GNU General Public License
mgl@1371
 20343
+;;   along with this program; if not, write to the Free Software
mgl@1371
 20344
+;;   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
mgl@1371
 20345
+
mgl@1371
 20346
+
mgl@1371
 20347
+;; True if the operand is a memory reference which contains an
mgl@1371
 20348
+;; Address consisting of a single pointer register
mgl@1371
 20349
+(define_predicate "avr32_indirect_register_operand"
mgl@1371
 20350
+  (and (match_code "mem")
mgl@1371
 20351
+       (match_test "register_operand(XEXP(op, 0), SImode)")))
mgl@1371
 20352
+
mgl@1371
 20353
+
mgl@1371
 20354
+
mgl@1371
 20355
+;; Address expression with a base pointer offset with
mgl@1371
 20356
+;; a register displacement
mgl@1371
 20357
+(define_predicate "avr32_indexed_memory_operand"
mgl@1371
 20358
+  (and (match_code "mem")
mgl@1371
 20359
+       (match_test "GET_CODE(XEXP(op, 0)) == PLUS"))
mgl@1371
 20360
+  {
mgl@1371
 20361
+
mgl@1371
 20362
+   rtx op0 = XEXP(XEXP(op, 0), 0);
mgl@1371
 20363
+   rtx op1 = XEXP(XEXP(op, 0), 1);
mgl@1371
 20364
+
mgl@1371
 20365
+   return ((avr32_address_register_rtx_p (op0, 0)
mgl@1371
 20366
+            && avr32_legitimate_index_p (GET_MODE(op), op1, 0))
mgl@1371
 20367
+	   || (avr32_address_register_rtx_p (op1, 0)
mgl@1371
 20368
+            && avr32_legitimate_index_p (GET_MODE(op), op0, 0)));
mgl@1371
 20369
+
mgl@1371
 20370
+ })
mgl@1371
 20371
+
mgl@1371
 20372
+;; Operand suitable for the ld.sb instruction
mgl@1371
 20373
+(define_predicate "load_sb_memory_operand"
mgl@1371
 20374
+  (ior (match_operand 0 "avr32_indirect_register_operand")
mgl@1371
 20375
+       (match_operand 0 "avr32_indexed_memory_operand")))
mgl@1371
 20376
+
mgl@1371
 20377
+
mgl@1371
 20378
+;; Operand suitable as operand to insns sign extending QI values
mgl@1371
 20379
+(define_predicate "extendqi_operand"
mgl@1371
 20380
+  (ior (match_operand 0 "load_sb_memory_operand")
mgl@1371
 20381
+       (match_operand 0 "register_operand")))
mgl@1371
 20382
+
mgl@1371
 20383
+(define_predicate "post_inc_memory_operand"
mgl@1371
 20384
+  (and (match_code "mem")
mgl@1371
 20385
+       (match_test "(GET_CODE(XEXP(op, 0)) == POST_INC)
mgl@1371
 20386
+                     && REG_P(XEXP(XEXP(op, 0), 0))")))
mgl@1371
 20387
+
mgl@1371
 20388
+(define_predicate "pre_dec_memory_operand"
mgl@1371
 20389
+  (and (match_code "mem")
mgl@1371
 20390
+       (match_test "(GET_CODE(XEXP(op, 0)) == PRE_DEC)
mgl@1371
 20391
+                     && REG_P(XEXP(XEXP(op, 0), 0))")))
mgl@1371
 20392
+
mgl@1371
 20393
+;; Operand suitable for add instructions
mgl@1371
 20394
+(define_predicate "avr32_add_operand"
mgl@1371
 20395
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20396
+       (and (match_operand 0 "immediate_operand")
mgl@1371
 20397
+            (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'I', \"Is21\")"))))
mgl@1371
 20398
+
mgl@1371
 20399
+;; Operand is a power of two immediate
mgl@1371
 20400
+(define_predicate "power_of_two_operand"
mgl@1371
 20401
+  (match_code "const_int")
mgl@1371
 20402
+{
mgl@1371
 20403
+  HOST_WIDE_INT value = INTVAL (op);
mgl@1371
 20404
+
mgl@1371
 20405
+  return value != 0 && (value & (value - 1)) == 0;
mgl@1371
 20406
+})
mgl@1371
 20407
+
mgl@1371
 20408
+;; Operand is a multiple of 8 immediate
mgl@1371
 20409
+(define_predicate "multiple_of_8_operand"
mgl@1371
 20410
+  (match_code "const_int")
mgl@1371
 20411
+{
mgl@1371
 20412
+  HOST_WIDE_INT value = INTVAL (op);
mgl@1371
 20413
+
mgl@1371
 20414
+  return (value & 0x7) == 0 ;
mgl@1371
 20415
+})
mgl@1371
 20416
+
mgl@1371
 20417
+;; Operand is a multiple of 16 immediate
mgl@1371
 20418
+(define_predicate "multiple_of_16_operand"
mgl@1371
 20419
+  (match_code "const_int")
mgl@1371
 20420
+{
mgl@1371
 20421
+  HOST_WIDE_INT value = INTVAL (op);
mgl@1371
 20422
+
mgl@1371
 20423
+  return (value & 0xf) == 0 ;
mgl@1371
 20424
+})
mgl@1371
 20425
+
mgl@1371
 20426
+;; Operand is a mask used for masking away upper bits of a reg
mgl@1371
 20427
+(define_predicate "avr32_mask_upper_bits_operand"
mgl@1371
 20428
+  (match_code "const_int")
mgl@1371
 20429
+{
mgl@1371
 20430
+  HOST_WIDE_INT value = INTVAL (op) + 1;
mgl@1371
 20431
+
mgl@1371
 20432
+  return value != 1 && value != 0 && (value & (value - 1)) == 0;
mgl@1371
 20433
+})
mgl@1371
 20434
+
mgl@1371
 20435
+
mgl@1371
 20436
+;; Operand suitable for mul instructions
mgl@1371
 20437
+(define_predicate "avr32_mul_operand"
mgl@1371
 20438
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20439
+       (and (match_operand 0 "immediate_operand")
mgl@1371
 20440
+            (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")"))))
mgl@1371
 20441
+
mgl@1371
 20442
+;; True for logical binary operators.
mgl@1371
 20443
+(define_predicate "logical_binary_operator"
mgl@1371
 20444
+  (match_code "ior,xor,and"))
mgl@1371
 20445
+
mgl@1371
 20446
+;; True for logical shift operators
mgl@1371
 20447
+(define_predicate "logical_shift_operator"
mgl@1371
 20448
+  (match_code "ashift,lshiftrt"))
mgl@1371
 20449
+
mgl@1371
 20450
+;; True for shift operand for logical and, or and eor insns
mgl@1371
 20451
+(define_predicate "avr32_logical_shift_operand"
mgl@1371
 20452
+  (and (match_code "ashift,lshiftrt")
mgl@1371
 20453
+       (ior (and (match_test "GET_CODE(XEXP(op, 1)) == CONST_INT")
mgl@1371
 20454
+                 (match_test "register_operand(XEXP(op, 0), GET_MODE(XEXP(op, 0)))"))
mgl@1371
 20455
+            (and (match_test "GET_CODE(XEXP(op, 0)) == CONST_INT")
mgl@1371
 20456
+                 (match_test "register_operand(XEXP(op, 1), GET_MODE(XEXP(op, 1)))"))))
mgl@1371
 20457
+  )
mgl@1371
 20458
+
mgl@1371
 20459
+
mgl@1371
 20460
+;; Predicate for second operand to and, ior and xor insn patterns
mgl@1371
 20461
+(define_predicate "avr32_logical_insn_operand"
mgl@1371
 20462
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20463
+       (match_operand 0 "avr32_logical_shift_operand"))
mgl@1371
 20464
+)
mgl@1371
 20465
+
mgl@1371
 20466
+
mgl@1371
 20467
+;; True for avr32 comparison operators
mgl@1371
 20468
+(define_predicate "avr32_comparison_operator"
mgl@1371
 20469
+  (ior (match_code "eq, ne, gt, ge, lt, le, gtu, geu, ltu, leu")
mgl@1371
 20470
+       (and (match_code "unspec")
mgl@1371
 20471
+            (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
mgl@1371
 20472
+                         || (XINT(op, 1) == UNSPEC_COND_PL)"))))
mgl@1371
 20473
+
mgl@1371
 20474
+(define_predicate "avr32_cond3_comparison_operator"
mgl@1371
 20475
+  (ior (match_code "eq, ne, ge, lt, geu, ltu")
mgl@1371
 20476
+       (and (match_code "unspec")
mgl@1371
 20477
+            (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
mgl@1371
 20478
+                         || (XINT(op, 1) == UNSPEC_COND_PL)"))))
mgl@1371
 20479
+
mgl@1371
 20480
+;; True for avr32 comparison operand
mgl@1371
 20481
+(define_predicate "avr32_comparison_operand"
mgl@1371
 20482
+  (ior (and (match_code "eq, ne, gt, ge, lt, le, gtu, geu, ltu, leu")
mgl@1371
 20483
+            (match_test "(CC0_P (XEXP(op,0)) && rtx_equal_p (XEXP(op,1), const0_rtx))"))
mgl@1371
 20484
+       (and (match_code "unspec")
mgl@1371
 20485
+            (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
mgl@1371
 20486
+                         || (XINT(op, 1) == UNSPEC_COND_PL)"))))
mgl@1371
 20487
+
mgl@1371
 20488
+;; True if this is a const_int with one bit set
mgl@1371
 20489
+(define_predicate "one_bit_set_operand"
mgl@1371
 20490
+  (match_code "const_int")
mgl@1371
 20491
+  {
mgl@1371
 20492
+   int i;
mgl@1371
 20493
+   int value;
mgl@1371
 20494
+   int ones = 0;
mgl@1371
 20495
+
mgl@1371
 20496
+   value = INTVAL(op);
mgl@1371
 20497
+   for ( i = 0 ; i < 32; i++ ){
mgl@1371
 20498
+     if ( value & ( 1 << i ) ){
mgl@1371
 20499
+        ones++;
mgl@1371
 20500
+      }
mgl@1371
 20501
+   }
mgl@1371
 20502
+
mgl@1371
 20503
+   return ( ones == 1 );
mgl@1371
 20504
+  })
mgl@1371
 20505
+
mgl@1371
 20506
+
mgl@1371
 20507
+;; True if this is a const_int with one bit cleared
mgl@1371
 20508
+(define_predicate "one_bit_cleared_operand"
mgl@1371
 20509
+  (match_code "const_int")
mgl@1371
 20510
+  {
mgl@1371
 20511
+   int i;
mgl@1371
 20512
+   int value;
mgl@1371
 20513
+   int zeroes = 0;
mgl@1371
 20514
+
mgl@1371
 20515
+   value = INTVAL(op);
mgl@1371
 20516
+   for ( i = 0 ; i < 32; i++ ){
mgl@1371
 20517
+     if ( !(value & ( 1 << i )) ){
mgl@1371
 20518
+        zeroes++;
mgl@1371
 20519
+      }
mgl@1371
 20520
+   }
mgl@1371
 20521
+
mgl@1371
 20522
+   return ( zeroes == 1 );
mgl@1371
 20523
+  })
mgl@1371
 20524
+
mgl@1371
 20525
+
mgl@1371
 20526
+;; Immediate all the low 16-bits cleared
mgl@1371
 20527
+(define_predicate "avr32_hi16_immediate_operand"
mgl@1371
 20528
+  (match_code "const_int")
mgl@1371
 20529
+  {
mgl@1371
 20530
+   /* If the low 16-bits are zero then this
mgl@1371
 20531
+      is a hi16 immediate. */
mgl@1371
 20532
+   return ((INTVAL(op) & 0xffff) == 0);
mgl@1371
 20533
+   }
mgl@1371
 20534
+)
mgl@1371
 20535
+
mgl@1371
 20536
+;; True if this is a register or immediate operand
mgl@1371
 20537
+(define_predicate "register_immediate_operand"
mgl@1371
 20538
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20539
+       (match_operand 0 "immediate_operand")))
mgl@1371
 20540
+
mgl@1371
 20541
+;; True if this is a register or const_int operand
mgl@1371
 20542
+(define_predicate "register_const_int_operand"
mgl@1371
 20543
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20544
+       (and (match_operand 0 "const_int_operand")
mgl@1371
 20545
+            (match_operand 0 "immediate_operand"))))
mgl@1371
 20546
+
mgl@1371
 20547
+;; True if this is a register or const_double operand
mgl@1371
 20548
+(define_predicate "register_const_double_operand"
mgl@1371
 20549
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20550
+       (match_operand 0 "const_double_operand")))
mgl@1371
 20551
+
mgl@1371
 20552
+;; True is this is an operand containing a label_ref
mgl@1371
 20553
+(define_predicate "avr32_label_ref_operand"
mgl@1371
 20554
+  (and (match_code "mem")
mgl@1371
 20555
+       (match_test "avr32_find_symbol(op)
mgl@1371
 20556
+                    && (GET_CODE(avr32_find_symbol(op)) == LABEL_REF)")))
mgl@1371
 20557
+
mgl@1371
 20558
+;; True is this is a valid symbol pointing to the constant pool
mgl@1371
 20559
+(define_predicate "avr32_const_pool_operand"
mgl@1371
 20560
+  (and (match_code "symbol_ref")
mgl@1371
 20561
+       (match_test "CONSTANT_POOL_ADDRESS_P(op)"))
mgl@1371
 20562
+  {
mgl@1371
 20563
+        return (flag_pic ? (!(symbol_mentioned_p (get_pool_constant (op))
mgl@1371
 20564
+                        || label_mentioned_p (get_pool_constant (op)))
mgl@1371
 20565
+                       || avr32_got_mentioned_p(get_pool_constant (op)))
mgl@1371
 20566
+                    : true);
mgl@1371
 20567
+  }
mgl@1371
 20568
+)
mgl@1371
 20569
+
mgl@1371
 20570
+;; True is this is a memory reference to the constant or mini pool
mgl@1371
 20571
+(define_predicate "avr32_const_pool_ref_operand"
mgl@1371
 20572
+  (ior (match_operand 0 "avr32_label_ref_operand")
mgl@1371
 20573
+       (and (match_code "mem")
mgl@1371
 20574
+            (match_test "avr32_const_pool_operand(XEXP(op,0), GET_MODE(XEXP(op,0)))"))))
mgl@1371
 20575
+
mgl@1371
 20576
+
mgl@1371
 20577
+;; Legal source operand for movti insns
mgl@1371
 20578
+(define_predicate "avr32_movti_src_operand"
mgl@1371
 20579
+  (ior (match_operand 0 "avr32_const_pool_ref_operand")
mgl@1371
 20580
+       (ior (ior (match_operand 0 "register_immediate_operand")
mgl@1371
 20581
+                 (match_operand 0 "avr32_indirect_register_operand"))
mgl@1371
 20582
+            (match_operand 0 "post_inc_memory_operand"))))
mgl@1371
 20583
+  
mgl@1371
 20584
+;; Legal destination operand for movti insns
mgl@1371
 20585
+(define_predicate "avr32_movti_dst_operand"
mgl@1371
 20586
+  (ior (ior (match_operand 0 "register_operand")
mgl@1371
 20587
+            (match_operand 0 "avr32_indirect_register_operand"))
mgl@1371
 20588
+       (match_operand 0 "pre_dec_memory_operand")))
mgl@1371
 20589
+
mgl@1371
 20590
+
mgl@1371
 20591
+;; True is this is a k12 offseted memory operand
mgl@1371
 20592
+(define_predicate "avr32_k12_memory_operand"
mgl@1371
 20593
+  (and (match_code "mem")
mgl@1371
 20594
+       (ior (match_test "REG_P(XEXP(op, 0))")
mgl@1371
 20595
+            (match_test "GET_CODE(XEXP(op, 0)) == PLUS
mgl@1371
 20596
+                         && REG_P(XEXP(XEXP(op, 0), 0))
mgl@1371
 20597
+                         && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)
mgl@1371
 20598
+                         && (CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(XEXP(op, 0), 0)),
mgl@1371
 20599
+                                'K', (mode == SImode) ? \"Ks14\" : ((mode == HImode) ? \"Ks13\" : \"Ks12\")))"))))
mgl@1371
 20600
+
mgl@1371
 20601
+;; True is this is a memory operand with an immediate displacement
mgl@1371
 20602
+(define_predicate "avr32_imm_disp_memory_operand"
mgl@1371
 20603
+  (and (match_code "mem")
mgl@1371
 20604
+       (match_test "GET_CODE(XEXP(op, 0)) == PLUS
mgl@1371
 20605
+                    && REG_P(XEXP(XEXP(op, 0), 0))
mgl@1371
 20606
+                    && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)")))
mgl@1371
 20607
+
mgl@1371
 20608
+;; True is this is a bswap operand
mgl@1371
 20609
+(define_predicate "avr32_bswap_operand"
mgl@1371
 20610
+  (ior (match_operand 0 "avr32_k12_memory_operand")
mgl@1371
 20611
+       (match_operand 0 "register_operand")))
mgl@1371
 20612
+
mgl@1371
 20613
+;; True is this is a valid coprocessor insn memory operand
mgl@1371
 20614
+(define_predicate "avr32_cop_memory_operand"
mgl@1371
 20615
+  (and (match_operand 0 "memory_operand")
mgl@1371
 20616
+       (not (match_test "GET_CODE(XEXP(op, 0)) == PLUS
mgl@1371
 20617
+                         && REG_P(XEXP(XEXP(op, 0), 0))
mgl@1371
 20618
+                         && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)
mgl@1371
 20619
+                         && !(CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(XEXP(op, 0), 0)), 'K', \"Ku10\"))"))))
mgl@1371
 20620
+
mgl@1371
 20621
+;; True is this is a valid source/destination operand
mgl@1371
 20622
+;; for moving values to/from a coprocessor
mgl@1371
 20623
+(define_predicate "avr32_cop_move_operand"
mgl@1371
 20624
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20625
+       (match_operand 0 "avr32_cop_memory_operand")))
mgl@1371
 20626
+
mgl@1371
 20627
+
mgl@1371
 20628
+;; True is this is a valid extract byte offset for use in
mgl@1371
 20629
+;; load extracted index insns
mgl@1371
 20630
+(define_predicate "avr32_extract_shift_operand"
mgl@1371
 20631
+  (and (match_operand 0 "const_int_operand")
mgl@1371
 20632
+       (match_test "(INTVAL(op) == 0) || (INTVAL(op) == 8)
mgl@1371
 20633
+                    || (INTVAL(op) == 16) || (INTVAL(op) == 24)")))
mgl@1371
 20634
+
mgl@1371
 20635
+;; True is this is a floating-point register
mgl@1371
 20636
+(define_predicate "avr32_fp_register_operand"
mgl@1371
 20637
+  (and (match_operand 0 "register_operand")
mgl@1371
 20638
+       (match_test "REGNO_REG_CLASS(REGNO(op)) == FP_REGS")))
mgl@1371
 20639
+
mgl@1371
 20640
+;; True is this is valid avr32 symbol operand
mgl@1371
 20641
+(define_predicate "avr32_symbol_operand"
mgl@1371
 20642
+  (and (match_code "label_ref, symbol_ref, const")
mgl@1371
 20643
+       (match_test "avr32_find_symbol(op)")))
mgl@1371
 20644
+
mgl@1371
 20645
+;; True is this is valid operand for the lda.w and call pseudo insns
mgl@1371
 20646
+(define_predicate "avr32_address_operand"
mgl@1371
 20647
+  (and (and (match_code "label_ref, symbol_ref")
mgl@1371
 20648
+            (match_test "avr32_find_symbol(op)"))
mgl@1371
 20649
+       (ior (match_test "TARGET_HAS_ASM_ADDR_PSEUDOS")
mgl@1371
 20650
+            (match_test "flag_pic")) ))
mgl@1371
 20651
+
mgl@1371
 20652
+;; An immediate k16 address operand
mgl@1371
 20653
+(define_predicate "avr32_ks16_address_operand"
mgl@1371
 20654
+  (and (match_operand 0 "address_operand")
mgl@1371
 20655
+       (ior (match_test "REG_P(op)")
mgl@1371
 20656
+            (match_test "GET_CODE(op) == PLUS
mgl@1371
 20657
+                         && ((GET_CODE(XEXP(op,0)) == CONST_INT)
mgl@1371
 20658
+                             || (GET_CODE(XEXP(op,1)) == CONST_INT))")) ))
mgl@1371
 20659
+
mgl@1371
 20660
+;; An offset k16 memory operand
mgl@1371
 20661
+(define_predicate "avr32_ks16_memory_operand"
mgl@1371
 20662
+  (and (match_code "mem")
mgl@1371
 20663
+       (match_test "avr32_ks16_address_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))")))
mgl@1371
 20664
+
mgl@1371
 20665
+;; An immediate k11 address operand
mgl@1371
 20666
+(define_predicate "avr32_ks11_address_operand"
mgl@1371
 20667
+  (and (match_operand 0 "address_operand")
mgl@1371
 20668
+       (ior (match_test "REG_P(op)")
mgl@1371
 20669
+            (match_test "GET_CODE(op) == PLUS
mgl@1371
 20670
+                         && (((GET_CODE(XEXP(op,0)) == CONST_INT)
mgl@1371
 20671
+                              && avr32_const_ok_for_constraint_p(INTVAL(XEXP(op,0)), 'K', \"Ks11\"))
mgl@1371
 20672
+                             || ((GET_CODE(XEXP(op,1)) == CONST_INT)
mgl@1371
 20673
+                                 && avr32_const_ok_for_constraint_p(INTVAL(XEXP(op,1)), 'K', \"Ks11\")))")) ))
mgl@1371
 20674
+
mgl@1371
 20675
+;; True if this is a avr32 call operand
mgl@1371
 20676
+(define_predicate "avr32_call_operand"
mgl@1371
 20677
+  (ior (ior (match_operand 0 "register_operand")
mgl@1371
 20678
+            (ior (match_operand 0 "avr32_const_pool_ref_operand")
mgl@1371
 20679
+                 (match_operand 0 "avr32_address_operand")))
mgl@1371
 20680
+       (match_test "SYMBOL_REF_RCALL_FUNCTION_P(op)")))
mgl@1371
 20681
+
mgl@1371
 20682
+;; Return true for operators performing ALU operations
mgl@1371
 20683
+
mgl@1371
 20684
+(define_predicate "alu_operator"
mgl@1371
 20685
+  (match_code "ior, xor, and, plus, minus, ashift, lshiftrt, ashiftrt"))
mgl@1371
 20686
+
mgl@1371
 20687
+(define_predicate "avr32_add_shift_immediate_operand"
mgl@1371
 20688
+  (and (match_operand 0 "immediate_operand")
mgl@1371
 20689
+       (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ku02\")")))
mgl@1371
 20690
+
mgl@1371
 20691
+(define_predicate "avr32_cond_register_immediate_operand"
mgl@1371
 20692
+  (ior (match_operand 0 "register_operand")
mgl@1371
 20693
+       (and (match_operand 0 "immediate_operand")
mgl@1371
 20694
+            (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")"))))
mgl@1371
 20695
+
mgl@1371
 20696
+(define_predicate "avr32_cond_immediate_operand"
mgl@1371
 20697
+  (and (match_operand 0 "immediate_operand")
mgl@1371
 20698
+       (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'I', \"Is08\")")))
mgl@1371
 20699
+
mgl@1371
 20700
+
mgl@1371
 20701
+(define_predicate "avr32_cond_move_operand"
mgl@1371
 20702
+  (ior (ior (match_operand 0 "register_operand")
mgl@1371
 20703
+            (and (match_operand 0 "immediate_operand")
mgl@1371
 20704
+                 (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")")))
mgl@1371
 20705
+       (and (match_test "TARGET_V2_INSNS")
mgl@1371
 20706
+            (match_operand 0 "memory_operand"))))
mgl@1371
 20707
+
mgl@1371
 20708
+(define_predicate "avr32_mov_immediate_operand"
mgl@1371
 20709
+  (and (match_operand 0 "immediate_operand")
mgl@1371
 20710
+       (match_test "avr32_const_ok_for_move(INTVAL(op))")))
mgl@1371
 20711
+
mgl@1371
 20712
+
mgl@1371
 20713
+(define_predicate "avr32_rmw_address_operand"
mgl@1371
 20714
+  (ior (and (match_code "symbol_ref") 
mgl@1371
 20715
+            (match_test "({rtx symbol = avr32_find_symbol(op); \
mgl@1371
 20716
+                                symbol && (GET_CODE (symbol) == SYMBOL_REF) && SYMBOL_REF_RMW_ADDR(symbol);})"))
mgl@1371
 20717
+       (and (match_operand 0 "immediate_operand")
mgl@1371
 20718
+            (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks17\")")))
mgl@1371
 20719
+  {
mgl@1371
 20720
+   return TARGET_RMW && !flag_pic;
mgl@1371
 20721
+  }
mgl@1371
 20722
+)
mgl@1371
 20723
+ 
mgl@1371
 20724
+(define_predicate "avr32_rmw_memory_operand"
mgl@1371
 20725
+  (and (match_code "mem")
mgl@1371
 20726
+       (match_test "(GET_MODE(op) == SImode) && 
mgl@1371
 20727
+                    avr32_rmw_address_operand(XEXP(op, 0), GET_MODE(XEXP(op, 0)))")))
mgl@1371
 20728
+
mgl@1371
 20729
+(define_predicate "avr32_rmw_memory_or_register_operand"
mgl@1371
 20730
+  (ior (match_operand 0 "avr32_rmw_memory_operand")
mgl@1371
 20731
+       (match_operand 0 "register_operand")))
mgl@1371
 20732
+
mgl@1371
 20733
+(define_predicate "avr32_non_rmw_memory_operand"
mgl@1371
 20734
+  (and (not (match_operand 0 "avr32_rmw_memory_operand"))
mgl@1371
 20735
+       (match_operand 0 "memory_operand")))
mgl@1371
 20736
+
mgl@1371
 20737
+(define_predicate "avr32_non_rmw_general_operand"
mgl@1371
 20738
+  (and (not (match_operand 0 "avr32_rmw_memory_operand"))
mgl@1371
 20739
+       (match_operand 0 "general_operand")))
mgl@1371
 20740
+
mgl@1371
 20741
+(define_predicate "avr32_non_rmw_nonimmediate_operand"
mgl@1371
 20742
+  (and (not (match_operand 0 "avr32_rmw_memory_operand"))
mgl@1371
 20743
+       (match_operand 0 "nonimmediate_operand")))
mgl@1371
 20744
--- /dev/null
mgl@1371
 20745
+++ b/gcc/config/avr32/simd.md
mgl@1371
 20746
@@ -0,0 +1,145 @@
mgl@1371
 20747
+;;   AVR32 machine description file for SIMD instructions.
mgl@1371
 20748
+;;   Copyright 2003-2006 Atmel Corporation.
mgl@1371
 20749
+;;
mgl@1371
 20750
+;;   Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
mgl@1371
 20751
+;;
mgl@1371
 20752
+;;   This file is part of GCC.
mgl@1371
 20753
+;;
mgl@1371
 20754
+;;   This program is free software; you can redistribute it and/or modify
mgl@1371
 20755
+;;   it under the terms of the GNU General Public License as published by
mgl@1371
 20756
+;;   the Free Software Foundation; either version 2 of the License, or
mgl@1371
 20757
+;;   (at your option) any later version.
mgl@1371
 20758
+;;
mgl@1371
 20759
+;;   This program is distributed in the hope that it will be useful,
mgl@1371
 20760
+;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
mgl@1371
 20761
+;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mgl@1371
 20762
+;;   GNU General Public License for more details.
mgl@1371
 20763
+;;
mgl@1371
 20764
+;;   You should have received a copy of the GNU General Public License
mgl@1371
 20765
+;;   along with this program; if not, write to the Free Software
mgl@1371
 20766
+;;   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
mgl@1371
 20767
+
mgl@1371
 20768
+;; -*- Mode: Scheme -*-
mgl@1371
 20769
+
mgl@1371
 20770
+
mgl@1371
 20771
+;; Vector modes
mgl@1371
 20772
+(define_mode_macro VECM [V2HI V4QI])
mgl@1371
 20773
+(define_mode_attr  size [(V2HI "h") (V4QI "b")])
mgl@1371
 20774
+
mgl@1371
 20775
+(define_insn "add<mode>3"
mgl@1371
 20776
+  [(set (match_operand:VECM 0 "register_operand" "=r")
mgl@1371
 20777
+	(plus:VECM (match_operand:VECM 1 "register_operand" "r")
mgl@1371
 20778
+                   (match_operand:VECM 2 "register_operand" "r")))]
mgl@1371
 20779
+  "TARGET_SIMD"
mgl@1371
 20780
+  "padd.<size>\t%0, %1, %2"
mgl@1371
 20781
+  [(set_attr "length" "4")
mgl@1371
 20782
+   (set_attr "type" "alu")])
mgl@1371
 20783
+
mgl@1371
 20784
+
mgl@1371
 20785
+(define_insn "sub<mode>3"
mgl@1371
 20786
+  [(set (match_operand:VECM 0 "register_operand" "=r")
mgl@1371
 20787
+	(minus:VECM (match_operand:VECM 1 "register_operand" "r")
mgl@1371
 20788
+                    (match_operand:VECM 2 "register_operand" "r")))]
mgl@1371
 20789
+  "TARGET_SIMD"
mgl@1371
 20790
+  "psub.<size>\t%0, %1, %2"
mgl@1371
 20791
+  [(set_attr "length" "4")
mgl@1371
 20792
+   (set_attr "type" "alu")])
mgl@1371
 20793
+
mgl@1371
 20794
+
mgl@1371
 20795
+(define_insn "abs<mode>2"
mgl@1371
 20796
+  [(set (match_operand:VECM 0 "register_operand" "=r")
mgl@1371
 20797
+	(abs:VECM (match_operand:VECM 1 "register_operand" "r")))]
mgl@1371
 20798
+  "TARGET_SIMD"
mgl@1371
 20799
+  "pabs.s<size>\t%0, %1"
mgl@1371
 20800
+  [(set_attr "length" "4")
mgl@1371
 20801
+   (set_attr "type" "alu")])
mgl@1371
 20802
+
mgl@1371
 20803
+(define_insn "ashl<mode>3"
mgl@1371
 20804
+  [(set (match_operand:VECM 0 "register_operand"           "=r")
mgl@1371
 20805
+	(ashift:VECM (match_operand:VECM 1 "register_operand" "r")
mgl@1371
 20806
+                     (match_operand:SI 2 "immediate_operand" "Ku04")))]
mgl@1371
 20807
+  "TARGET_SIMD"
mgl@1371
 20808
+  "plsl.<size>\t%0, %1, %2"
mgl@1371
 20809
+  [(set_attr "length" "4")
mgl@1371
 20810
+   (set_attr "type" "alu")])
mgl@1371
 20811
+
mgl@1371
 20812
+(define_insn "ashr<mode>3"
mgl@1371
 20813
+  [(set (match_operand:VECM 0 "register_operand"           "=r")
mgl@1371
 20814
+	(ashiftrt:VECM (match_operand:VECM 1 "register_operand" "r")
mgl@1371
 20815
+                       (match_operand:SI 2 "immediate_operand" "Ku04")))]
mgl@1371
 20816
+  "TARGET_SIMD"
mgl@1371
 20817
+  "pasr.<size>\t%0, %1, %2"
mgl@1371
 20818
+  [(set_attr "length" "4")
mgl@1371
 20819
+   (set_attr "type" "alu")])
mgl@1371
 20820
+
mgl@1371
 20821
+(define_insn "lshr<mode>3"
mgl@1371
 20822
+  [(set (match_operand:VECM 0 "register_operand"           "=r")
mgl@1371
 20823
+	(lshiftrt:VECM (match_operand:VECM 1 "register_operand" "r")
mgl@1371
 20824
+                       (match_operand:SI 2 "immediate_operand" "Ku04")))]
mgl@1371
 20825
+  "TARGET_SIMD"
mgl@1371
 20826
+  "plsr.<size>\t%0, %1, %2"
mgl@1371
 20827
+  [(set_attr "length" "4")
mgl@1371
 20828
+   (set_attr "type" "alu")])
mgl@1371
 20829
+
mgl@1371
 20830
+(define_insn "smaxv2hi3"
mgl@1371
 20831
+  [(set (match_operand:V2HI 0 "register_operand" "=r")
mgl@1371
 20832
+	(smax:V2HI (match_operand:V2HI 1 "register_operand" "r")
mgl@1371
 20833
+                        (match_operand:V2HI 2 "register_operand" "r")))]
mgl@1371
 20834
+
mgl@1371
 20835
+  "TARGET_SIMD"
mgl@1371
 20836
+  "pmax.sh\t%0, %1, %2"
mgl@1371
 20837
+  [(set_attr "length" "4")
mgl@1371
 20838
+   (set_attr "type" "alu")])
mgl@1371
 20839
+
mgl@1371
 20840
+(define_insn "sminv2hi3"
mgl@1371
 20841
+  [(set (match_operand:V2HI 0 "register_operand" "=r")
mgl@1371
 20842
+	(smin:V2HI (match_operand:V2HI 1 "register_operand" "r")
mgl@1371
 20843
+                        (match_operand:V2HI 2 "register_operand" "r")))]
mgl@1371
 20844
+
mgl@1371
 20845
+  "TARGET_SIMD"
mgl@1371
 20846
+  "pmin.sh\t%0, %1, %2"
mgl@1371
 20847
+  [(set_attr "length" "4")
mgl@1371
 20848
+   (set_attr "type" "alu")])
mgl@1371
 20849
+
mgl@1371
 20850
+(define_insn "umaxv4qi3"
mgl@1371
 20851
+  [(set (match_operand:V4QI 0 "register_operand" "=r")
mgl@1371
 20852
+	(umax:V4QI (match_operand:V4QI 1 "register_operand" "r")
mgl@1371
 20853
+                   (match_operand:V4QI 2 "register_operand" "r")))]
mgl@1371
 20854
+
mgl@1371
 20855
+  "TARGET_SIMD"
mgl@1371
 20856
+  "pmax.ub\t%0, %1, %2"
mgl@1371
 20857
+  [(set_attr "length" "4")
mgl@1371
 20858
+   (set_attr "type" "alu")])
mgl@1371
 20859
+
mgl@1371
 20860
+(define_insn "uminv4qi3"
mgl@1371
 20861
+  [(set (match_operand:V4QI 0 "register_operand" "=r")
mgl@1371
 20862
+	(umin:V4QI (match_operand:V4QI 1 "register_operand" "r")
mgl@1371
 20863
+                   (match_operand:V4QI 2 "register_operand" "r")))]
mgl@1371
 20864
+
mgl@1371
 20865
+  "TARGET_SIMD"
mgl@1371
 20866
+  "pmin.ub\t%0, %1, %2"
mgl@1371
 20867
+  [(set_attr "length" "4")
mgl@1371
 20868
+   (set_attr "type" "alu")])
mgl@1371
 20869
+
mgl@1371
 20870
+
mgl@1371
 20871
+(define_insn "addsubv2hi"
mgl@1371
 20872
+  [(set (match_operand:V2HI 0 "register_operand" "=r")
mgl@1371
 20873
+        (vec_concat:V2HI
mgl@1371
 20874
+         (plus:HI (match_operand:HI 1 "register_operand" "r")
mgl@1371
 20875
+                  (match_operand:HI 2 "register_operand" "r"))
mgl@1371
 20876
+         (minus:HI (match_dup 1) (match_dup 2))))]
mgl@1371
 20877
+  "TARGET_SIMD"
mgl@1371
 20878
+  "paddsub.h\t%0, %1:b, %2:b"
mgl@1371
 20879
+  [(set_attr "length" "4")
mgl@1371
 20880
+   (set_attr "type" "alu")])
mgl@1371
 20881
+
mgl@1371
 20882
+(define_insn "subaddv2hi"
mgl@1371
 20883
+  [(set (match_operand:V2HI 0 "register_operand" "=r")
mgl@1371
 20884
+        (vec_concat:V2HI
mgl@1371
 20885
+         (minus:HI (match_operand:HI 1 "register_operand" "r")
mgl@1371
 20886
+                  (match_operand:HI 2 "register_operand" "r"))
mgl@1371
 20887
+         (plus:HI (match_dup 1) (match_dup 2))))]
mgl@1371
 20888
+  "TARGET_SIMD"
mgl@1371
 20889
+  "psubadd.h\t%0, %1:b, %2:b"
mgl@1371
 20890
+  [(set_attr "length" "4")
mgl@1371
 20891
+   (set_attr "type" "alu")])
mgl@1371
 20892
--- /dev/null
mgl@1371
 20893
+++ b/gcc/config/avr32/sync.md
mgl@1371
 20894
@@ -0,0 +1,244 @@
mgl@1371
 20895
+;;=================================================================
mgl@1371
 20896
+;; Atomic operations
mgl@1371
 20897
+;;=================================================================
mgl@1371
 20898
+
mgl@1371
 20899
+
mgl@1371
 20900
+(define_insn "sync_compare_and_swapsi"
mgl@1371
 20901
+  [(set (match_operand:SI 0 "register_operand" "=&r,&r")
mgl@1371
 20902
+	(match_operand:SI 1 "memory_operand" "+RKs16,+RKs16"))
mgl@1371
 20903
+   (set (match_dup 1)
mgl@1371
 20904
+	(unspec_volatile:SI
mgl@1371
 20905
+	  [(match_dup 1)
mgl@1371
 20906
+	   (match_operand:SI 2 "register_immediate_operand" "r,Ks21")
mgl@1371
 20907
+	   (match_operand:SI 3 "register_operand" "r,r")]
mgl@1371
 20908
+	  VUNSPEC_SYNC_CMPXCHG))   ]
mgl@1371
 20909
+  ""
mgl@1371
 20910
+  "0:
mgl@1371
 20911
+   ssrf\t5
mgl@1371
 20912
+   ld.w\t%0,%1
mgl@1371
 20913
+   cp.w\t%0,%2
mgl@1371
 20914
+   brne\t0f
mgl@1371
 20915
+   stcond\t%1, %3
mgl@1371
 20916
+   brne\t0b
mgl@1371
 20917
+   0:
mgl@1371
 20918
+  "
mgl@1371
 20919
+  [(set_attr "length" "16,18")
mgl@1371
 20920
+   (set_attr "cc" "clobber")]
mgl@1371
 20921
+  )
mgl@1371
 20922
+ 
mgl@1371
 20923
+
mgl@1371
 20924
+(define_code_macro atomic_op [plus minus and ior xor])
mgl@1371
 20925
+(define_code_attr  atomic_asm_insn [(plus "add") (minus "sub") (and "and") (ior "or") (xor "eor")])
mgl@1371
 20926
+(define_code_attr  atomic_insn [(plus "add") (minus "sub") (and "and") (ior "ior") (xor "xor")])
mgl@1371
 20927
+
mgl@1371
 20928
+(define_insn "sync_loadsi"
mgl@1371
 20929
+  ; NB! Put an early clobber on the destination operand to 
mgl@1371
 20930
+  ; avoid gcc using the same register in the source and 
mgl@1371
 20931
+  ; destination. This is done in order to avoid gcc to 
mgl@1371
 20932
+  ; clobber the source operand since these instructions
mgl@1371
 20933
+  ; are actually inside a "loop".
mgl@1371
 20934
+  [(set (match_operand:SI 0 "register_operand" "=&r")
mgl@1371
 20935
+	(unspec_volatile:SI
mgl@1371
 20936
+         [(match_operand:SI 1 "avr32_ks16_memory_operand" "RKs16")
mgl@1371
 20937
+          (label_ref (match_operand 2 "" ""))]
mgl@1371
 20938
+         VUNSPEC_SYNC_SET_LOCK_AND_LOAD) )]
mgl@1371
 20939
+  ""
mgl@1371
 20940
+  "%2:
mgl@1371
 20941
+   ssrf\t5
mgl@1371
 20942
+   ld.w\t%0,%1"
mgl@1371
 20943
+  [(set_attr "length" "6")
mgl@1371
 20944
+   (set_attr "cc" "clobber")]
mgl@1371
 20945
+  )
mgl@1371
 20946
+  
mgl@1371
 20947
+(define_insn "sync_store_if_lock"
mgl@1371
 20948
+  [(set (match_operand:SI 0 "avr32_ks16_memory_operand" "=RKs16")
mgl@1371
 20949
+        (unspec_volatile:SI
mgl@1371
 20950
+         [(match_operand:SI 1 "register_operand" "r")
mgl@1371
 20951
+          (label_ref (match_operand 2 "" ""))]
mgl@1371
 20952
+         VUNSPEC_SYNC_STORE_IF_LOCK) )]
mgl@1371
 20953
+  ""
mgl@1371
 20954
+  "stcond\t%0, %1
mgl@1371
 20955
+   brne\t%2"
mgl@1371
 20956
+  [(set_attr "length" "6")
mgl@1371
 20957
+   (set_attr "cc" "clobber")]
mgl@1371
 20958
+  )
mgl@1371
 20959
+
mgl@1371
 20960
+
mgl@1371
 20961
+(define_expand "sync_<atomic_insn>si"
mgl@1371
 20962
+  [(set (match_dup 2)
mgl@1371
 20963
+	(unspec_volatile:SI
mgl@1371
 20964
+         [(match_operand:SI 0 "avr32_ks16_memory_operand" "")
mgl@1371
 20965
+          (match_dup 3)]
mgl@1371
 20966
+         VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
mgl@1371
 20967
+   (set (match_dup 2) 
mgl@1371
 20968
+        (atomic_op:SI (match_dup 2)
mgl@1371
 20969
+                      (match_operand:SI 1 "register_immediate_operand" "")))
mgl@1371
 20970
+   (set (match_dup 0)
mgl@1371
 20971
+        (unspec_volatile:SI
mgl@1371
 20972
+         [(match_dup 2)
mgl@1371
 20973
+          (match_dup 3)]
mgl@1371
 20974
+         VUNSPEC_SYNC_STORE_IF_LOCK) )
mgl@1371
 20975
+   (use (match_dup 1))
mgl@1371
 20976
+   (use (match_dup 4))]
mgl@1371
 20977
+  ""
mgl@1371
 20978
+  {
mgl@1371
 20979
+   rtx *mem_expr = &operands[0];
mgl@1371
 20980
+   rtx ptr_reg;
mgl@1371
 20981
+   if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
mgl@1371
 20982
+    {
mgl@1371
 20983
+      ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
mgl@1371
 20984
+      XEXP (*mem_expr, 0) = ptr_reg;
mgl@1371
 20985
+    } 
mgl@1371
 20986
+   else 
mgl@1371
 20987
+    {
mgl@1371
 20988
+      rtx address = XEXP (*mem_expr, 0);
mgl@1371
 20989
+      if ( REG_P (address) )
mgl@1371
 20990
+         ptr_reg = address;
mgl@1371
 20991
+      else if ( REG_P (XEXP (address, 0)) ) 
mgl@1371
 20992
+         ptr_reg = XEXP (address, 0);
mgl@1371
 20993
+      else 
mgl@1371
 20994
+         ptr_reg = XEXP (address, 1);
mgl@1371
 20995
+    }
mgl@1371
 20996
+
mgl@1371
 20997
+   operands[2] = gen_reg_rtx (SImode);
mgl@1371
 20998
+   operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
mgl@1371
 20999
+   operands[4] = ptr_reg;   
mgl@1371
 21000
+
mgl@1371
 21001
+  }
mgl@1371
 21002
+  )
mgl@1371
 21003
+
mgl@1371
 21004
+
mgl@1371
 21005
+
mgl@1371
 21006
+(define_expand "sync_old_<atomic_insn>si"
mgl@1371
 21007
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 21008
+	(unspec_volatile:SI
mgl@1371
 21009
+         [(match_operand:SI 1 "avr32_ks16_memory_operand" "")
mgl@1371
 21010
+          (match_dup 4)]
mgl@1371
 21011
+         VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
mgl@1371
 21012
+   (set (match_dup 3) 
mgl@1371
 21013
+        (atomic_op:SI (match_dup 0)
mgl@1371
 21014
+                      (match_operand:SI 2 "register_immediate_operand" "")))
mgl@1371
 21015
+   (set (match_dup 1)
mgl@1371
 21016
+        (unspec_volatile:SI
mgl@1371
 21017
+         [(match_dup 3)
mgl@1371
 21018
+          (match_dup 4)]
mgl@1371
 21019
+         VUNSPEC_SYNC_STORE_IF_LOCK) )
mgl@1371
 21020
+   (use (match_dup 2))
mgl@1371
 21021
+   (use (match_dup 5))]
mgl@1371
 21022
+  ""
mgl@1371
 21023
+  {
mgl@1371
 21024
+   rtx *mem_expr = &operands[1];
mgl@1371
 21025
+   rtx ptr_reg;
mgl@1371
 21026
+   if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
mgl@1371
 21027
+    {
mgl@1371
 21028
+      ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
mgl@1371
 21029
+      XEXP (*mem_expr, 0) = ptr_reg;
mgl@1371
 21030
+    } 
mgl@1371
 21031
+   else 
mgl@1371
 21032
+    {
mgl@1371
 21033
+      rtx address = XEXP (*mem_expr, 0);
mgl@1371
 21034
+      if ( REG_P (address) )
mgl@1371
 21035
+         ptr_reg = address;
mgl@1371
 21036
+      else if ( REG_P (XEXP (address, 0)) ) 
mgl@1371
 21037
+         ptr_reg = XEXP (address, 0);
mgl@1371
 21038
+      else 
mgl@1371
 21039
+         ptr_reg = XEXP (address, 1);
mgl@1371
 21040
+    }
mgl@1371
 21041
+
mgl@1371
 21042
+   operands[3] = gen_reg_rtx (SImode);
mgl@1371
 21043
+   operands[4] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
mgl@1371
 21044
+   operands[5] = ptr_reg;
mgl@1371
 21045
+  }
mgl@1371
 21046
+  )
mgl@1371
 21047
+
mgl@1371
 21048
+(define_expand "sync_new_<atomic_insn>si"
mgl@1371
 21049
+  [(set (match_operand:SI 0 "register_operand" "")
mgl@1371
 21050
+	(unspec_volatile:SI
mgl@1371
 21051
+         [(match_operand:SI 1 "avr32_ks16_memory_operand" "")
mgl@1371
 21052
+          (match_dup 3)]
mgl@1371
 21053
+         VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
mgl@1371
 21054
+   (set (match_dup 0) 
mgl@1371
 21055
+        (atomic_op:SI (match_dup 0)
mgl@1371
 21056
+                      (match_operand:SI 2 "register_immediate_operand" "")))
mgl@1371
 21057
+   (set (match_dup 1)
mgl@1371
 21058
+        (unspec_volatile:SI
mgl@1371
 21059
+         [(match_dup 0)
mgl@1371
 21060
+          (match_dup 3)]
mgl@1371
 21061
+         VUNSPEC_SYNC_STORE_IF_LOCK) )
mgl@1371
 21062
+   (use (match_dup 2))
mgl@1371
 21063
+   (use (match_dup 4))]
mgl@1371
 21064
+  ""
mgl@1371
 21065
+  {
mgl@1371
 21066
+   rtx *mem_expr = &operands[1];
mgl@1371
 21067
+   rtx ptr_reg;
mgl@1371
 21068
+   if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
mgl@1371
 21069
+    {
mgl@1371
 21070
+      ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
mgl@1371
 21071
+      XEXP (*mem_expr, 0) = ptr_reg;
mgl@1371
 21072
+    } 
mgl@1371
 21073
+   else 
mgl@1371
 21074
+    {
mgl@1371
 21075
+      rtx address = XEXP (*mem_expr, 0);
mgl@1371
 21076
+      if ( REG_P (address) )
mgl@1371
 21077
+         ptr_reg = address;
mgl@1371
 21078
+      else if ( REG_P (XEXP (address, 0)) ) 
mgl@1371
 21079
+         ptr_reg = XEXP (address, 0);
mgl@1371
 21080
+      else 
mgl@1371
 21081
+         ptr_reg = XEXP (address, 1);
mgl@1371
 21082
+    }
mgl@1371
 21083
+
mgl@1371
 21084
+   operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
mgl@1371
 21085
+   operands[4] = ptr_reg;
mgl@1371
 21086
+  }
mgl@1371
 21087
+  )
mgl@1371
 21088
+
mgl@1371
 21089
+
mgl@1371
 21090
+;(define_insn "sync_<atomic_insn>si"
mgl@1371
 21091
+;  [(set (match_operand:SI 0 "memory_operand" "+RKs16")
mgl@1371
 21092
+;	(unspec_volatile:SI
mgl@1371
 21093
+;         [(atomic_op:SI (match_dup 0)
mgl@1371
 21094
+;                        (match_operand:SI 1 "register_operand" "r"))]
mgl@1371
 21095
+;         VUNSPEC_SYNC_CMPXCHG))
mgl@1371
 21096
+;   (clobber (match_scratch:SI 2 "=&r"))]
mgl@1371
 21097
+;  ""
mgl@1371
 21098
+;  "0:
mgl@1371
 21099
+;   ssrf\t5
mgl@1371
 21100
+;   ld.w\t%2,%0
mgl@1371
 21101
+;   <atomic_asm_insn>\t%2,%1
mgl@1371
 21102
+;   stcond\t%0, %2
mgl@1371
 21103
+;   brne\t0b
mgl@1371
 21104
+;  "
mgl@1371
 21105
+;  [(set_attr "length" "14")
mgl@1371
 21106
+;   (set_attr "cc" "clobber")]
mgl@1371
 21107
+;  )
mgl@1371
 21108
+;
mgl@1371
 21109
+;(define_insn "sync_new_<atomic_insn>si"
mgl@1371
 21110
+;  [(set (match_operand:SI 1 "memory_operand" "+RKs16")
mgl@1371
 21111
+;	(unspec_volatile:SI
mgl@1371
 21112
+;         [(atomic_op:SI (match_dup 1)
mgl@1371
 21113
+;                        (match_operand:SI 2 "register_operand" "r"))]
mgl@1371
 21114
+;         VUNSPEC_SYNC_CMPXCHG))
mgl@1371
 21115
+;   (set (match_operand:SI 0 "register_operand" "=&r")
mgl@1371
 21116
+;	(atomic_op:SI (match_dup 1)
mgl@1371
 21117
+;                      (match_dup 2)))]
mgl@1371
 21118
+;  ""
mgl@1371
 21119
+;  "0:
mgl@1371
 21120
+;   ssrf\t5
mgl@1371
 21121
+;   ld.w\t%0,%1
mgl@1371
 21122
+;   <atomic_asm_insn>\t%0,%2
mgl@1371
 21123
+;   stcond\t%1, %0
mgl@1371
 21124
+;   brne\t0b
mgl@1371
 21125
+;  "
mgl@1371
 21126
+;  [(set_attr "length" "14")
mgl@1371
 21127
+;   (set_attr "cc" "clobber")]
mgl@1371
 21128
+;  )
mgl@1371
 21129
+
mgl@1371
 21130
+(define_insn "sync_lock_test_and_setsi"
mgl@1371
 21131
+  [ (set (match_operand:SI 0 "register_operand" "=&r")
mgl@1371
 21132
+         (match_operand:SI 1 "memory_operand" "+RKu00"))
mgl@1371
 21133
+    (set (match_dup 1)
mgl@1371
 21134
+         (match_operand:SI 2 "register_operand" "r")) ]
mgl@1371
 21135
+  ""
mgl@1371
 21136
+  "xchg\t%0, %p1, %2"
mgl@1371
 21137
+  [(set_attr "length" "4")]
mgl@1371
 21138
+  )
mgl@1371
 21139
--- /dev/null
mgl@1371
 21140
+++ b/gcc/config/avr32/t-avr32
mgl@1371
 21141
@@ -0,0 +1,77 @@
mgl@1371
 21142
+
mgl@1371
 21143
+MD_INCLUDES= 	$(srcdir)/config/avr32/avr32.md \
mgl@1371
 21144
+		$(srcdir)/config/avr32/sync.md \
mgl@1371
 21145
+		$(srcdir)/config/avr32/fpcp.md \
mgl@1371
 21146
+		$(srcdir)/config/avr32/simd.md \
mgl@1371
 21147
+        $(srcdir)/config/avr32/predicates.md
mgl@1371
 21148
+
mgl@1371
 21149
+s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
mgl@1371
 21150
+	s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
mgl@1371
 21151
+
mgl@1371
 21152
+# We want fine grained libraries, so use the new code
mgl@1371
 21153
+# to build the floating point emulation libraries.
mgl@1371
 21154
+FPBIT = fp-bit.c
mgl@1371
 21155
+DPBIT = dp-bit.c
mgl@1371
 21156
+
mgl@1371
 21157
+LIB1ASMSRC = avr32/lib1funcs.S
mgl@1371
 21158
+LIB1ASMFUNCS =  _avr32_f64_mul _avr32_f64_mul_fast _avr32_f64_addsub _avr32_f64_addsub_fast  _avr32_f64_to_u32 \
mgl@1371
 21159
+                _avr32_f64_to_s32 _avr32_f64_to_u64 _avr32_f64_to_s64 _avr32_u32_to_f64 \
mgl@1371
 21160
+                _avr32_s32_to_f64 _avr32_f64_cmp_eq _avr32_f64_cmp_ge _avr32_f64_cmp_lt \
mgl@1371
 21161
+                _avr32_f32_cmp_eq _avr32_f32_cmp_ge _avr32_f32_cmp_lt _avr32_f64_div _avr32_f64_div_fast \
mgl@1371
 21162
+                _avr32_f32_div _avr32_f32_div_fast _avr32_f32_addsub _avr32_f32_addsub_fast \
mgl@1371
 21163
+                _avr32_f32_mul _avr32_s32_to_f32 _avr32_u32_to_f32 _avr32_f32_to_s32 \
mgl@1371
 21164
+                _avr32_f32_to_u32 _avr32_f32_to_f64 _avr32_f64_to_f32 _mulsi3
mgl@1371
 21165
+
mgl@1371
 21166
+#LIB2FUNCS_EXTRA += $(srcdir)/config/avr32/lib2funcs.S
mgl@1371
 21167
+
mgl@1371
 21168
+MULTILIB_OPTIONS     = march=ap/march=ucr1/march=ucr2/march=ucr2nomul
mgl@1371
 21169
+MULTILIB_DIRNAMES    = ap ucr1 ucr2 ucr2nomul
mgl@1371
 21170
+MULTILIB_EXCEPTIONS  =
mgl@1371
 21171
+MULTILIB_MATCHES     += march?ap=mpart?ap7000
mgl@1371
 21172
+MULTILIB_MATCHES     += march?ap=mpart?ap7001
mgl@1371
 21173
+MULTILIB_MATCHES     += march?ap=mpart?ap7002
mgl@1371
 21174
+MULTILIB_MATCHES     += march?ap=mpart?ap7200
mgl@1371
 21175
+MULTILIB_MATCHES     += march?ucr1=march?uc
mgl@1371
 21176
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3a0512es
mgl@1371
 21177
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a0128
mgl@1371
 21178
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a0256
mgl@1371
 21179
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a0512
mgl@1371
 21180
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a1128
mgl@1371
 21181
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a1256
mgl@1371
 21182
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3a1512es
mgl@1371
 21183
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a1512
mgl@1371
 21184
+MULTILIB_MATCHES     += march?ucr2nomul=mpart?uc3a3revd
mgl@1371
 21185
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a364
mgl@1371
 21186
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a364s
mgl@1371
 21187
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a3128
mgl@1371
 21188
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a3128s
mgl@1371
 21189
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a3256
mgl@1371
 21190
+MULTILIB_MATCHES     += march?ucr2=mpart?uc3a3256s
mgl@1371
 21191
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b064
mgl@1371
 21192
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b0128
mgl@1371
 21193
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b0256es
mgl@1371
 21194
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b0256
mgl@1371
 21195
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b164
mgl@1371
 21196
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b1128
mgl@1371
 21197
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b1256es
mgl@1371
 21198
+MULTILIB_MATCHES     += march?ucr1=mpart?uc3b1256
mgl@1371
 21199
+
mgl@1371
 21200
+
mgl@1371
 21201
+EXTRA_MULTILIB_PARTS = crtbegin.o crtbeginS.o crtend.o crtendS.o crti.o crtn.o
mgl@1371
 21202
+
mgl@1371
 21203
+CRTSTUFF_T_CFLAGS = -mrelax
mgl@1371
 21204
+CRTSTUFF_T_CFLAGS_S = -mrelax -fPIC
mgl@1371
 21205
+TARGET_LIBGCC2_CFLAGS += -mrelax
mgl@1371
 21206
+
mgl@1371
 21207
+LIBGCC = stmp-multilib
mgl@1371
 21208
+INSTALL_LIBGCC = install-multilib
mgl@1371
 21209
+
mgl@1371
 21210
+fp-bit.c: $(srcdir)/config/fp-bit.c
mgl@1371
 21211
+	echo '#define FLOAT' > fp-bit.c
mgl@1371
 21212
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
mgl@1371
 21213
+
mgl@1371
 21214
+dp-bit.c: $(srcdir)/config/fp-bit.c
mgl@1371
 21215
+	cat $(srcdir)/config/fp-bit.c > dp-bit.c
mgl@1371
 21216
+
mgl@1371
 21217
+
mgl@1371
 21218
+
mgl@1371
 21219
--- /dev/null
mgl@1371
 21220
+++ b/gcc/config/avr32/t-elf
mgl@1371
 21221
@@ -0,0 +1,16 @@
mgl@1371
 21222
+
mgl@1371
 21223
+# Assemble startup files.
mgl@1371
 21224
+$(T)crti.o: $(srcdir)/config/avr32/crti.asm $(GCC_PASSES)
mgl@1371
 21225
+	$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) $(INCLUDES) \
mgl@1371
 21226
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/avr32/crti.asm
mgl@1371
 21227
+
mgl@1371
 21228
+$(T)crtn.o: $(srcdir)/config/avr32/crtn.asm $(GCC_PASSES)
mgl@1371
 21229
+	$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) $(INCLUDES) \
mgl@1371
 21230
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/avr32/crtn.asm
mgl@1371
 21231
+
mgl@1371
 21232
+
mgl@1371
 21233
+# Build the libraries for both hard and soft floating point
mgl@1371
 21234
+EXTRA_MULTILIB_PARTS = crtbegin.o crtbeginS.o crtend.o crtendS.o crti.o crtn.o
mgl@1371
 21235
+
mgl@1371
 21236
+LIBGCC = stmp-multilib
mgl@1371
 21237
+INSTALL_LIBGCC = install-multilib
mgl@1371
 21238
--- /dev/null
mgl@1371
 21239
+++ b/gcc/config/avr32/uclinux-elf.h
mgl@1371
 21240
@@ -0,0 +1,20 @@
mgl@1371
 21241
+
mgl@1371
 21242
+/* Run-time Target Specification.  */
mgl@1371
 21243
+#undef  TARGET_VERSION
mgl@1371
 21244
+#define TARGET_VERSION  fputs (" (AVR32 uClinux with ELF)", stderr)
mgl@1371
 21245
+
mgl@1371
 21246
+/* We don't want a .jcr section on uClinux. As if this makes a difference... */
mgl@1371
 21247
+#define TARGET_USE_JCR_SECTION 0
mgl@1371
 21248
+
mgl@1371
 21249
+/* Here we go. Drop the crtbegin/crtend stuff completely. */
mgl@1371
 21250
+#undef STARTFILE_SPEC
mgl@1371
 21251
+#define STARTFILE_SPEC							\
mgl@1371
 21252
+  "%{!shared: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s}"			\
mgl@1371
 21253
+  " %{!p:%{profile:gcrt1.o%s}"						\
mgl@1371
 21254
+  " %{!profile:crt1.o%s}}}} crti.o%s"
mgl@1371
 21255
+
mgl@1371
 21256
+#undef ENDFILE_SPEC
mgl@1371
 21257
+#define ENDFILE_SPEC "crtn.o%s"
mgl@1371
 21258
+
mgl@1371
 21259
+#undef TARGET_DEFAULT
mgl@1371
 21260
+#define TARGET_DEFAULT (AVR32_FLAG_NO_INIT_GOT)
mgl@1371
 21261
--- a/gcc/config/host-linux.c
mgl@1371
 21262
+++ b/gcc/config/host-linux.c
mgl@1371
 21263
@@ -25,6 +25,9 @@
mgl@1371
 21264
 #include "hosthooks.h"
mgl@1371
 21265
 #include "hosthooks-def.h"
mgl@1371
 21266
 
mgl@1371
 21267
+#ifndef SSIZE_MAX
mgl@1371
 21268
+#define SSIZE_MAX LONG_MAX
mgl@1371
 21269
+#endif
mgl@1371
 21270
 
mgl@1371
 21271
 /* Linux has a feature called exec-shield-randomize that perturbs the
mgl@1371
 21272
    address of non-fixed mapped segments by a (relatively) small amount.
mgl@1371
 21273
--- a/gcc/config.gcc
mgl@1371
 21274
+++ b/gcc/config.gcc
mgl@1371
 21275
@@ -781,6 +781,24 @@ avr-*-*)
mgl@1371
 21276
 	tm_file="avr/avr.h dbxelf.h"
mgl@1371
 21277
 	use_fixproto=yes
mgl@1371
 21278
 	;;
mgl@1371
 21279
+avr32*-*-linux*)
mgl@1371
 21280
+    tm_file="dbxelf.h elfos.h linux.h avr32/linux-elf.h avr32/avr32.h "
mgl@1371
 21281
+    tmake_file="t-linux avr32/t-avr32 avr32/t-elf"
mgl@1371
 21282
+	extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
mgl@1371
 21283
+	extra_modes=avr32/avr32-modes.def
mgl@1371
 21284
+	gnu_ld=yes
mgl@1371
 21285
+	;;
mgl@1371
 21286
+avr32*-*-uclinux*)
mgl@1371
 21287
+	tm_file="dbxelf.h elfos.h linux.h avr32/linux-elf.h avr32/uclinux-elf.h avr32/avr32.h"
mgl@1371
 21288
+	tmake_file="t-linux avr32/t-avr32 avr32/t-elf"
mgl@1371
 21289
+	extra_modes=avr32/avr32-modes.def
mgl@1371
 21290
+	gnu_ld=yes
mgl@1371
 21291
+	;;
mgl@1371
 21292
+avr32-*-*)
mgl@1371
 21293
+    tm_file="dbxelf.h elfos.h avr32/avr32.h avr32/avr32-elf.h"
mgl@1371
 21294
+    tmake_file="avr32/t-avr32 avr32/t-elf"
mgl@1371
 21295
+	extra_modes=avr32/avr32-modes.def
mgl@1371
 21296
+	;;
mgl@1371
 21297
 bfin*-elf*)
mgl@1371
 21298
 	tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h"
mgl@1371
 21299
         tmake_file=bfin/t-bfin-elf
mgl@1371
 21300
@@ -1681,6 +1699,9 @@ pdp11-*-bsd)
mgl@1371
 21301
 pdp11-*-*)
mgl@1371
 21302
 	use_fixproto=yes
mgl@1371
 21303
 	;;
mgl@1371
 21304
+avr-*-*)
mgl@1371
 21305
+	use_fixproto=yes
mgl@1371
 21306
+	;;
mgl@1371
 21307
 # port not yet contributed
mgl@1371
 21308
 #powerpc-*-openbsd*)
mgl@1371
 21309
 #	tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-fprules-fpbit "
mgl@1371
 21310
@@ -2717,6 +2738,32 @@ case "${target}" in
mgl@1371
 21311
 		fi
mgl@1371
 21312
 		;;
mgl@1371
 21313
 
mgl@1371
 21314
+	avr32*-*-*)
mgl@1371
 21315
+		supported_defaults="part arch"
mgl@1371
 21316
+
mgl@1371
 21317
+		case "$with_part" in
mgl@1371
 21318
+		"" \
mgl@1371
 21319
+		| "ap7000" | "ap7010" | "ap7020" | "uc3a0256" | "uc3a0512" | "uc3a1128" | "uc3a1256" | "uc3a1512" )
mgl@1371
 21320
+			# OK
mgl@1371
 21321
+			;;
mgl@1371
 21322
+		*)
mgl@1371
 21323
+			echo "Unknown part used in --with-part=$with_part" 1>&2
mgl@1371
 21324
+			exit 1
mgl@1371
 21325
+			;;
mgl@1371
 21326
+		esac
mgl@1371
 21327
+
mgl@1371
 21328
+		case "$with_arch" in
mgl@1371
 21329
+		"" \
mgl@1371
 21330
+		| "ap" | "uc")
mgl@1371
 21331
+			# OK
mgl@1371
 21332
+			;;
mgl@1371
 21333
+		*)
mgl@1371
 21334
+			echo "Unknown arch used in --with-arch=$with_arch" 1>&2
mgl@1371
 21335
+			exit 1
mgl@1371
 21336
+			;;
mgl@1371
 21337
+		esac
mgl@1371
 21338
+                ;;
mgl@1371
 21339
+
mgl@1371
 21340
 	fr*-*-*linux*)
mgl@1371
 21341
 		supported_defaults=cpu
mgl@1371
 21342
 		case "$with_cpu" in
mgl@1371
 21343
--- a/gcc/doc/extend.texi
mgl@1371
 21344
+++ b/gcc/doc/extend.texi
mgl@1371
 21345
@@ -1981,7 +1981,7 @@ this attribute to work correctly.
mgl@1371
 21346
 
mgl@1371
 21347
 @item interrupt
mgl@1371
 21348
 @cindex interrupt handler functions
mgl@1371
 21349
-Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
mgl@1371
 21350
+Use this attribute on the ARM, AVR, AVR32, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
mgl@1371
 21351
 ports to indicate that the specified function is an interrupt handler.
mgl@1371
 21352
 The compiler will generate function entry and exit sequences suitable
mgl@1371
 21353
 for use in an interrupt handler when this attribute is present.
mgl@1371
 21354
@@ -2000,6 +2000,15 @@ void f () __attribute__ ((interrupt ("IR
mgl@1371
 21355
 
mgl@1371
 21356
 Permissible values for this parameter are: IRQ, FIQ, SWI, ABORT and UNDEF@.
mgl@1371
 21357
 
mgl@1371
 21358
+Note, for the AVR32, you can specify which banking scheme is used for
mgl@1371
 21359
+the interrupt mode this interrupt handler is used in like this:
mgl@1371
 21360
+
mgl@1371
 21361
+@smallexample
mgl@1371
 21362
+void f () __attribute__ ((interrupt ("FULL")));
mgl@1371
 21363
+@end smallexample
mgl@1371
 21364
+
mgl@1371
 21365
+Permissible values for this parameter are: FULL, HALF, NONE and UNDEF.
mgl@1371
 21366
+
mgl@1371
 21367
 @item interrupt_handler
mgl@1371
 21368
 @cindex interrupt handler functions on the Blackfin, m68k, H8/300 and SH processors
mgl@1371
 21369
 Use this attribute on the Blackfin, m68k, H8/300, H8/300H, H8S, and SH to
mgl@1371
 21370
@@ -3460,6 +3469,23 @@ placed in either the @code{.bss_below100
mgl@1371
 21371
 
mgl@1371
 21372
 @end table
mgl@1371
 21373
 
mgl@1371
 21374
+@subsection AVR32 Variable Attributes
mgl@1371
 21375
+
mgl@1371
 21376
+One attribute is currently defined for AVR32 configurations:
mgl@1371
 21377
+@code{rmw_addressable}
mgl@1371
 21378
+
mgl@1371
 21379
+@table @code
mgl@1371
 21380
+@item rmw_addressable
mgl@1371
 21381
+@cindex @code{rmw_addressable} attribute
mgl@1371
 21382
+
mgl@1371
 21383
+This attribute can be used to signal that a variable can be accessed 
mgl@1371
 21384
+with the addressing mode of the AVR32 Atomic Read-Modify-Write memory
mgl@1371
 21385
+instructions and hence make it possible for gcc to generate these 
mgl@1371
 21386
+instructions without using built-in functions or inline assembly statements. 
mgl@1371
 21387
+Variables used within the AVR32 Atomic Read-Modify-Write built-in
mgl@1371
 21388
+functions will automatically get the @code{rmw_addressable} attribute.
mgl@1371
 21389
+@end table
mgl@1371
 21390
+
mgl@1371
 21391
 @node Type Attributes
mgl@1371
 21392
 @section Specifying Attributes of Types
mgl@1371
 21393
 @cindex attribute of types
mgl@1371
 21394
@@ -6167,6 +6193,7 @@ instructions, but allow the compiler to 
mgl@1371
 21395
 @menu
mgl@1371
 21396
 * Alpha Built-in Functions::
mgl@1371
 21397
 * ARM Built-in Functions::
mgl@1371
 21398
+* AVR32 Built-in Functions::
mgl@1371
 21399
 * Blackfin Built-in Functions::
mgl@1371
 21400
 * FR-V Built-in Functions::
mgl@1371
 21401
 * X86 Built-in Functions::
mgl@1371
 21402
@@ -6405,6 +6432,76 @@ long long __builtin_arm_wxor (long long,
mgl@1371
 21403
 long long __builtin_arm_wzero ()
mgl@1371
 21404
 @end smallexample
mgl@1371
 21405
 
mgl@1371
 21406
+@node AVR32 Built-in Functions
mgl@1371
 21407
+@subsection AVR32 Built-in Functions
mgl@1371
 21408
+
mgl@1371
 21409
+
mgl@1371
 21410
+
mgl@1371
 21411
+Built-in functions for atomic memory (RMW) instructions. Note that these
mgl@1371
 21412
+built-ins will fail for targets where the RMW instructions are not
mgl@1371
 21413
+implemented. Also note that these instructions only that a Ks15 << 2
mgl@1371
 21414
+memory address and will therefor not work with any runtime computed 
mgl@1371
 21415
+memory addresses. The user is responsible for making sure that any
mgl@1371
 21416
+pointers used within these functions points to a valid memory address.
mgl@1371
 21417
+ 
mgl@1371
 21418
+@smallexample
mgl@1371
 21419
+void __builtin_mems(int */*ptr*/, int /*bit*/)
mgl@1371
 21420
+void __builtin_memc(int */*ptr*/, int /*bit*/)
mgl@1371
 21421
+void __builtin_memt(int */*ptr*/, int /*bit*/)
mgl@1371
 21422
+@end smallexample
mgl@1371
 21423
+
mgl@1371
 21424
+Built-in functions for DSP instructions. Note that these built-ins will
mgl@1371
 21425
+fail for targets where the DSP instructions are not implemented.
mgl@1371
 21426
+
mgl@1371
 21427
+@smallexample
mgl@1371
 21428
+int __builtin_sats (int /*Rd*/,int /*sa*/, int /*bn*/)
mgl@1371
 21429
+int __builtin_satu (int /*Rd*/,int /*sa*/, int /*bn*/)
mgl@1371
 21430
+int __builtin_satrnds (int /*Rd*/,int /*sa*/, int /*bn*/)
mgl@1371
 21431
+int __builtin_satrndu (int /*Rd*/,int /*sa*/, int /*bn*/)
mgl@1371
 21432
+short __builtin_mulsathh_h (short, short)
mgl@1371
 21433
+int __builtin_mulsathh_w (short, short)
mgl@1371
 21434
+short __builtin_mulsatrndhh_h (short, short)
mgl@1371
 21435
+int __builtin_mulsatrndwh_w (int, short)
mgl@1371
 21436
+int __builtin_mulsatwh_w (int, short)
mgl@1371
 21437
+int __builtin_macsathh_w (int, short, short)
mgl@1371
 21438
+short __builtin_satadd_h (short, short)
mgl@1371
 21439
+short __builtin_satsub_h (short, short)
mgl@1371
 21440
+int __builtin_satadd_w (int, int)
mgl@1371
 21441
+int __builtin_satsub_w (int, int)
mgl@1371
 21442
+long long __builtin_mulwh_d(int, short)
mgl@1371
 21443
+long long __builtin_mulnwh_d(int, short)
mgl@1371
 21444
+long long __builtin_macwh_d(long long, int, short)
mgl@1371
 21445
+long long __builtin_machh_d(long long, short, short)
mgl@1371
 21446
+@end smallexample
mgl@1371
 21447
+
mgl@1371
 21448
+Other built-in functions for instructions that cannot easily be
mgl@1371
 21449
+generated by the compiler. 
mgl@1371
 21450
+
mgl@1371
 21451
+@smallexample
mgl@1371
 21452
+void __builtin_ssrf(int);
mgl@1371
 21453
+void __builtin_csrf(int);
mgl@1371
 21454
+void __builtin_musfr(int);
mgl@1371
 21455
+int __builtin_mustr(void);
mgl@1371
 21456
+int __builtin_mfsr(int /*Status Register Address*/)
mgl@1371
 21457
+void __builtin_mtsr(int /*Status Register Address*/, int /*Value*/)
mgl@1371
 21458
+int __builtin_mfdr(int /*Debug Register Address*/)
mgl@1371
 21459
+void __builtin_mtdr(int /*Debug Register Address*/, int /*Value*/)
mgl@1371
 21460
+void __builtin_cache(void * /*Address*/, int /*Cache Operation*/)
mgl@1371
 21461
+void __builtin_sync(int /*Sync Operation*/)
mgl@1371
 21462
+void __builtin_tlbr(void)
mgl@1371
 21463
+void __builtin_tlbs(void)
mgl@1371
 21464
+void __builtin_tlbw(void)
mgl@1371
 21465
+void __builtin_breakpoint(void)
mgl@1371
 21466
+int __builtin_xchg(void * /*Address*/, int /*Value*/ )
mgl@1371
 21467
+short __builtin_bswap_16(short)
mgl@1371
 21468
+int __builtin_bswap_32(int)
mgl@1371
 21469
+void __builtin_cop(int/*cpnr*/, int/*crd*/, int/*crx*/, int/*cry*/, int/*op*/)
mgl@1371
 21470
+int __builtin_mvcr_w(int/*cpnr*/, int/*crs*/)
mgl@1371
 21471
+void __builtin_mvrc_w(int/*cpnr*/, int/*crd*/, int/*value*/)
mgl@1371
 21472
+long long __builtin_mvcr_d(int/*cpnr*/, int/*crs*/)
mgl@1371
 21473
+void __builtin_mvrc_d(int/*cpnr*/, int/*crd*/, long long/*value*/)
mgl@1371
 21474
+@end smallexample
mgl@1371
 21475
+
mgl@1371
 21476
 @node Blackfin Built-in Functions
mgl@1371
 21477
 @subsection Blackfin Built-in Functions
mgl@1371
 21478
 
mgl@1371
 21479
--- a/gcc/doc/invoke.texi
mgl@1371
 21480
+++ b/gcc/doc/invoke.texi
mgl@1371
 21481
@@ -190,7 +190,7 @@ in the following sections.
mgl@1371
 21482
 -fno-default-inline  -fvisibility-inlines-hidden @gol
mgl@1371
 21483
 -Wabi  -Wctor-dtor-privacy @gol
mgl@1371
 21484
 -Wnon-virtual-dtor  -Wreorder @gol
mgl@1371
 21485
--Weffc++  -Wno-deprecated  -Wstrict-null-sentinel @gol
mgl@1371
 21486
+-Weffc++  -Wno-deprecated @gol
mgl@1371
 21487
 -Wno-non-template-friend  -Wold-style-cast @gol
mgl@1371
 21488
 -Woverloaded-virtual  -Wno-pmf-conversions @gol
mgl@1371
 21489
 -Wsign-promo}
mgl@1371
 21490
@@ -588,6 +588,12 @@ Objective-C and Objective-C++ Dialects}.
mgl@1371
 21491
 -mauto-incdec  -minmax  -mlong-calls  -mshort @gol
mgl@1371
 21492
 -msoft-reg-count=@var{count}}
mgl@1371
 21493
 
mgl@1371
 21494
+@emph{AVR32 Options}
mgl@1371
 21495
+@gccoptlist{-muse-rodata-section -mhard-float -msoft-float -mrelax @gol
mgl@1371
 21496
+-mforce-double-align -mno-init-got -mrelax -mmd-reorg-opt -masm-addr-pseudos @gol
mgl@1371
 21497
+-mpart=@var{part} -mcpu=@var{cpu} -march=@var{arch} @gol  
mgl@1371
 21498
+-mfast-float -mimm-in-const-pool}
mgl@1371
 21499
+
mgl@1371
 21500
 @emph{MCore Options}
mgl@1371
 21501
 @gccoptlist{-mhardlit  -mno-hardlit  -mdiv  -mno-div  -mrelax-immediates @gol
mgl@1371
 21502
 -mno-relax-immediates  -mwide-bitfields  -mno-wide-bitfields @gol
mgl@1371
 21503
@@ -1868,14 +1874,6 @@ to filter out those warnings.
mgl@1371
 21504
 @opindex Wno-deprecated
mgl@1371
 21505
 Do not warn about usage of deprecated features.  @xref{Deprecated Features}.
mgl@1371
 21506
 
mgl@1371
 21507
-@item -Wstrict-null-sentinel @r{(C++ only)}
mgl@1371
 21508
-@opindex Wstrict-null-sentinel
mgl@1371
 21509
-Warn also about the use of an uncasted @code{NULL} as sentinel.  When
mgl@1371
 21510
-compiling only with GCC this is a valid sentinel, as @code{NULL} is defined
mgl@1371
 21511
-to @code{__null}.  Although it is a null pointer constant not a null pointer,
mgl@1371
 21512
-it is guaranteed to of the same size as a pointer.  But this use is
mgl@1371
 21513
-not portable across different compilers.
mgl@1371
 21514
-
mgl@1371
 21515
 @item -Wno-non-template-friend @r{(C++ only)}
mgl@1371
 21516
 @opindex Wno-non-template-friend
mgl@1371
 21517
 Disable warnings when non-templatized friend functions are declared
mgl@1371
 21518
@@ -2732,13 +2730,11 @@ requiring @option{-O}.
mgl@1371
 21519
 If you want to warn about code which uses the uninitialized value of the
mgl@1371
 21520
 variable in its own initializer, use the @option{-Winit-self} option.
mgl@1371
 21521
 
mgl@1371
 21522
-These warnings occur for individual uninitialized or clobbered
mgl@1371
 21523
-elements of structure, union or array variables as well as for
mgl@1371
 21524
-variables which are uninitialized or clobbered as a whole.  They do
mgl@1371
 21525
-not occur for variables or elements declared @code{volatile}.  Because
mgl@1371
 21526
-these warnings depend on optimization, the exact variables or elements
mgl@1371
 21527
-for which there are warnings will depend on the precise optimization
mgl@1371
 21528
-options and version of GCC used.
mgl@1371
 21529
+These warnings occur only for variables that are candidates for
mgl@1371
 21530
+register allocation.  Therefore, they do not occur for a variable that
mgl@1371
 21531
+is declared @code{volatile}, or whose address is taken, or whose size
mgl@1371
 21532
+is other than 1, 2, 4 or 8 bytes.  Also, they do not occur for
mgl@1371
 21533
+structures, unions or arrays, even when they are in registers.
mgl@1371
 21534
 
mgl@1371
 21535
 Note that there may be no warning about a variable that is used only
mgl@1371
 21536
 to compute a value that itself is never used, because such
mgl@1371
 21537
@@ -6201,10 +6197,6 @@ If number of candidates in the set is sm
mgl@1371
 21538
 we always try to remove unnecessary ivs from the set during its
mgl@1371
 21539
 optimization when a new iv is added to the set.
mgl@1371
 21540
 
mgl@1371
 21541
-@item scev-max-expr-size
mgl@1371
 21542
-Bound on size of expressions used in the scalar evolutions analyzer.
mgl@1371
 21543
-Large expressions slow the analyzer.
mgl@1371
 21544
-
mgl@1371
 21545
 @item vect-max-version-checks
mgl@1371
 21546
 The maximum number of runtime checks that can be performed when doing
mgl@1371
 21547
 loop versioning in the vectorizer.  See option ftree-vect-loop-version
mgl@1371
 21548
@@ -7402,7 +7394,7 @@ platform.
mgl@1371
 21549
 * ARC Options::
mgl@1371
 21550
 * ARM Options::
mgl@1371
 21551
 * AVR Options::
mgl@1371
 21552
-* Blackfin Options::
mgl@1371
 21553
+* AVR32 Options::
mgl@1371
 21554
 * CRIS Options::
mgl@1371
 21555
 * CRX Options::
mgl@1371
 21556
 * Darwin Options::
mgl@1371
 21557
@@ -7867,81 +7859,80 @@ comply to the C standards, but it will p
mgl@1371
 21558
 size.
mgl@1371
 21559
 @end table
mgl@1371
 21560
 
mgl@1371
 21561
-@node Blackfin Options
mgl@1371
 21562
-@subsection Blackfin Options
mgl@1371
 21563
-@cindex Blackfin Options
mgl@1371
 21564
+@node AVR32 Options
mgl@1371
 21565
+@subsection AVR32 Options
mgl@1371
 21566
+@cindex AVR32 Options
mgl@1371
 21567
+
mgl@1371
 21568
+These options are defined for AVR32 implementations:
mgl@1371
 21569
 
mgl@1371
 21570
 @table @gcctabopt
mgl@1371
 21571
-@item -momit-leaf-frame-pointer
mgl@1371
 21572
-@opindex momit-leaf-frame-pointer
mgl@1371
 21573
-Don't keep the frame pointer in a register for leaf functions.  This
mgl@1371
 21574
-avoids the instructions to save, set up and restore frame pointers and
mgl@1371
 21575
-makes an extra register available in leaf functions.  The option
mgl@1371
 21576
-@option{-fomit-frame-pointer} removes the frame pointer for all functions
mgl@1371
 21577
-which might make debugging harder.
mgl@1371
 21578
+@item -muse-rodata-section
mgl@1371
 21579
+@opindex muse-rodata-section
mgl@1371
 21580
+Use section @samp{.rodata} for read-only data instead of @samp{.text}.
mgl@1371
 21581
 
mgl@1371
 21582
-@item -mspecld-anomaly
mgl@1371
 21583
-@opindex mspecld-anomaly
mgl@1371
 21584
-When enabled, the compiler will ensure that the generated code does not
mgl@1371
 21585
-contain speculative loads after jump instructions.  This option is enabled
mgl@1371
 21586
-by default.
mgl@1371
 21587
-
mgl@1371
 21588
-@item -mno-specld-anomaly
mgl@1371
 21589
-@opindex mno-specld-anomaly
mgl@1371
 21590
-Don't generate extra code to prevent speculative loads from occurring.
mgl@1371
 21591
-
mgl@1371
 21592
-@item -mcsync-anomaly
mgl@1371
 21593
-@opindex mcsync-anomaly
mgl@1371
 21594
-When enabled, the compiler will ensure that the generated code does not
mgl@1371
 21595
-contain CSYNC or SSYNC instructions too soon after conditional branches.
mgl@1371
 21596
-This option is enabled by default.
mgl@1371
 21597
-
mgl@1371
 21598
-@item -mno-csync-anomaly
mgl@1371
 21599
-@opindex mno-csync-anomaly
mgl@1371
 21600
-Don't generate extra code to prevent CSYNC or SSYNC instructions from
mgl@1371
 21601
-occurring too soon after a conditional branch.
mgl@1371
 21602
-
mgl@1371
 21603
-@item -mlow-64k
mgl@1371
 21604
-@opindex mlow-64k
mgl@1371
 21605
-When enabled, the compiler is free to take advantage of the knowledge that
mgl@1371
 21606
-the entire program fits into the low 64k of memory.
mgl@1371
 21607
-
mgl@1371
 21608
-@item -mno-low-64k
mgl@1371
 21609
-@opindex mno-low-64k
mgl@1371
 21610
-Assume that the program is arbitrarily large.  This is the default.
mgl@1371
 21611
+@item -mhard-float
mgl@1371
 21612
+@opindex mhard-float
mgl@1371
 21613
+Use floating point coprocessor instructions.
mgl@1371
 21614
 
mgl@1371
 21615
-@item -mid-shared-library
mgl@1371
 21616
-@opindex mid-shared-library
mgl@1371
 21617
-Generate code that supports shared libraries via the library ID method.
mgl@1371
 21618
-This allows for execute in place and shared libraries in an environment
mgl@1371
 21619
-without virtual memory management.  This option implies @option{-fPIC}.
mgl@1371
 21620
+@item -msoft-float
mgl@1371
 21621
+@opindex msoft-float
mgl@1371
 21622
+Use software floating-point library for floating-point operations.
mgl@1371
 21623
 
mgl@1371
 21624
-@item -mno-id-shared-library
mgl@1371
 21625
-@opindex mno-id-shared-library
mgl@1371
 21626
-Generate code that doesn't assume ID based shared libraries are being used.
mgl@1371
 21627
-This is the default.
mgl@1371
 21628
+@item -mforce-double-align
mgl@1371
 21629
+@opindex mforce-double-align
mgl@1371
 21630
+Force double-word alignment for double-word memory accesses.
mgl@1371
 21631
+
mgl@1371
 21632
+@item -mno-init-got
mgl@1371
 21633
+@opindex mno-init-got
mgl@1371
 21634
+Do not initialize the GOT register before using it when compiling PIC
mgl@1371
 21635
+code.
mgl@1371
 21636
 
mgl@1371
 21637
-@item -mshared-library-id=n
mgl@1371
 21638
-@opindex mshared-library-id
mgl@1371
 21639
-Specified the identification number of the ID based shared library being
mgl@1371
 21640
-compiled.  Specifying a value of 0 will generate more compact code, specifying
mgl@1371
 21641
-other values will force the allocation of that number to the current
mgl@1371
 21642
-library but is no more space or time efficient than omitting this option.
mgl@1371
 21643
+@item -mrelax
mgl@1371
 21644
+@opindex mrelax
mgl@1371
 21645
+Let invoked assembler and linker do relaxing 
mgl@1371
 21646
+(Enabled by default when optimization level is >1).
mgl@1371
 21647
+This means that when the address of symbols are known at link time,
mgl@1371
 21648
+the linker can optimize @samp{icall} and @samp{mcall}
mgl@1371
 21649
+instructions into a @samp{rcall} instruction if possible. 
mgl@1371
 21650
+Loading the address of a symbol can also be optimized.  
mgl@1371
 21651
+
mgl@1371
 21652
+@item -mmd-reorg-opt
mgl@1371
 21653
+@opindex mmd-reorg-opt
mgl@1371
 21654
+Perform machine dependent optimizations in reorg stage.
mgl@1371
 21655
+
mgl@1371
 21656
+@item -masm-addr-pseudos
mgl@1371
 21657
+@opindex masm-addr-pseudos
mgl@1371
 21658
+Use assembler pseudo-instructions lda.w and call for handling direct
mgl@1371
 21659
+addresses. (Enabled by default)
mgl@1371
 21660
+
mgl@1371
 21661
+@item -mpart=@var{part}
mgl@1371
 21662
+@opindex mpart
mgl@1371
 21663
+Generate code for the specified part. Permissible parts are: 
mgl@1371
 21664
+@samp{ap7000}, @samp{ap7010},@samp{ap7020},
mgl@1371
 21665
+@samp{uc3a0128}, @samp{uc3a0256}, @samp{uc3a0512},
mgl@1371
 21666
+@samp{uc3a1128}, @samp{uc3a1256}, @samp{uc3a1512},
mgl@1371
 21667
+@samp{uc3b064}, @samp{uc3b0128}, @samp{uc3b0256},
mgl@1371
 21668
+@samp{uc3b164}, @samp{uc3b1128}, @samp{uc3b1256}.
mgl@1371
 21669
 
mgl@1371
 21670
-@item -mlong-calls
mgl@1371
 21671
-@itemx -mno-long-calls
mgl@1371
 21672
-@opindex mlong-calls
mgl@1371
 21673
-@opindex mno-long-calls
mgl@1371
 21674
-Tells the compiler to perform function calls by first loading the
mgl@1371
 21675
-address of the function into a register and then performing a subroutine
mgl@1371
 21676
-call on this register.  This switch is needed if the target function
mgl@1371
 21677
-will lie outside of the 24 bit addressing range of the offset based
mgl@1371
 21678
-version of subroutine call instruction.
mgl@1371
 21679
+@item -mcpu=@var{cpu-type}
mgl@1371
 21680
+@opindex mcpu
mgl@1371
 21681
+Same as -mpart. Obsolete.
mgl@1371
 21682
+
mgl@1371
 21683
+@item -march=@var{arch}
mgl@1371
 21684
+@opindex march
mgl@1371
 21685
+Generate code for the specified architecture. Permissible architectures are:
mgl@1371
 21686
+@samp{ap} and @samp{uc}. 
mgl@1371
 21687
+
mgl@1371
 21688
+@item -mfast-float
mgl@1371
 21689
+@opindex mfast-float
mgl@1371
 21690
+Enable fast floating-point library that does not conform to ieee but is still good enough
mgl@1371
 21691
+for most applications. The fast floating-point library does not round to the nearest even
mgl@1371
 21692
+but away from zero. Enabled by default if the -funsafe-math-optimizations switch is specified. 
mgl@1371
 21693
+
mgl@1371
 21694
+@item -mimm-in-const-pool
mgl@1371
 21695
+@opindex mimm-in-const-pool
mgl@1371
 21696
+Put large immediates in constant pool. This is enabled by default for archs with insn-cache.
mgl@1371
 21697
 
mgl@1371
 21698
-This feature is not enabled by default.  Specifying
mgl@1371
 21699
-@option{-mno-long-calls} will restore the default behavior.  Note these
mgl@1371
 21700
-switches have no effect on how the compiler generates code to handle
mgl@1371
 21701
-function calls via function pointers.
mgl@1371
 21702
 @end table
mgl@1371
 21703
 
mgl@1371
 21704
 @node CRIS Options
mgl@1371
 21705
--- a/gcc/doc/md.texi
mgl@1371
 21706
+++ b/gcc/doc/md.texi
mgl@1371
 21707
@@ -1681,6 +1681,80 @@ A memory reference suitable for iWMMXt l
mgl@1371
 21708
 A memory reference suitable for the ARMv4 ldrsb instruction.
mgl@1371
 21709
 @end table
mgl@1371
 21710
 
mgl@1371
 21711
+@item AVR32 family---@file{avr32.h}
mgl@1371
 21712
+@table @code
mgl@1371
 21713
+@item f
mgl@1371
 21714
+Floating-point registers (f0 to f15) (Reserved for future use)
mgl@1371
 21715
+
mgl@1371
 21716
+@item Ku@var{bits}
mgl@1371
 21717
+Unsigned constant representable with @var{bits} number of bits (Must be
mgl@1371
 21718
+two digits). I.e: An unsigned 8-bit constant is written as @samp{Ku08}  
mgl@1371
 21719
+ 
mgl@1371
 21720
+@item Ks@var{bits}
mgl@1371
 21721
+Signed constant representable with @var{bits} number of bits (Must be
mgl@1371
 21722
+two digits). I.e: A signed 12-bit constant is written as @samp{Ks12}  
mgl@1371
 21723
+
mgl@1371
 21724
+@item Is@var{bits}
mgl@1371
 21725
+The negated range of a signed constant representable with  @var{bits} 
mgl@1371
 21726
+number of bits. The same as @samp{Ks@var{bits}} with a negated range. 
mgl@1371
 21727
+This means that the constant must be in the range @math{-2^{bits-1}-1} to @math{2^{bits-1}}
mgl@1371
 21728
+
mgl@1371
 21729
+@item G
mgl@1371
 21730
+A single/double precision floating-point immediate or 64-bit integer 
mgl@1371
 21731
+immediate where the least and most significant words both can be
mgl@1371
 21732
+loaded with a move instruction. That is the the integer form of the 
mgl@1371
 21733
+values in the least and most significant words both are in the range 
mgl@1371
 21734
+@math{-2^{20}} to @math{2^{20}-1}.
mgl@1371
 21735
+         
mgl@1371
 21736
+@item M
mgl@1371
 21737
+Any 32-bit immediate with the most significant bits set to zero and the
mgl@1371
 21738
+remaining least significant bits set to one. 
mgl@1371
 21739
+
mgl@1371
 21740
+@item J
mgl@1371
 21741
+A 32-bit immediate where all the lower 16-bits are zero. 
mgl@1371
 21742
+
mgl@1371
 21743
+@item O
mgl@1371
 21744
+A 32-bit immediate with one bit set and the rest of the bits cleared. 
mgl@1371
 21745
+
mgl@1371
 21746
+@item N
mgl@1371
 21747
+A 32-bit immediate with one bit cleared and the rest of the bits set. 
mgl@1371
 21748
+
mgl@1371
 21749
+@item L
mgl@1371
 21750
+A 32-bit immediate where all the lower 16-bits are set. 
mgl@1371
 21751
+
mgl@1371
 21752
+@item Q
mgl@1371
 21753
+Any AVR32 memory reference except for reference used for the atomic memory (RMW) instructions.
mgl@1371
 21754
+
mgl@1371
 21755
+@item RKs@var{bits}
mgl@1371
 21756
+A memory reference where the address consists of a base register
mgl@1371
 21757
+plus a signed immediate displacement with range given by @samp{Ks@var{bits}}
mgl@1371
 21758
+which has the same format as for the signed immediate integer constraint
mgl@1371
 21759
+given above.  
mgl@1371
 21760
+
mgl@1371
 21761
+@item RKu@var{bits}
mgl@1371
 21762
+A memory reference where the address consists of a base register
mgl@1371
 21763
+plus an unsigned immediate displacement with range given by @samp{Ku@var{bits}}
mgl@1371
 21764
+which has the same format as for the unsigned immediate integer constraint
mgl@1371
 21765
+given above.  
mgl@1371
 21766
+
mgl@1371
 21767
+@item S
mgl@1371
 21768
+A memory reference with an immediate or register offset
mgl@1371
 21769
+
mgl@1371
 21770
+@item T
mgl@1371
 21771
+A memory reference to a constant pool entry
mgl@1371
 21772
+
mgl@1371
 21773
+@item W
mgl@1371
 21774
+A valid operand for use in the @samp{lda.w} instruction macro when
mgl@1371
 21775
+relaxing is enabled
mgl@1371
 21776
+
mgl@1371
 21777
+@item Y
mgl@1371
 21778
+A memory reference suitable for the atomic memory (RMW) instructions.
mgl@1371
 21779
+
mgl@1371
 21780
+@item Z
mgl@1371
 21781
+A memory reference valid for coprocessor memory instructions
mgl@1371
 21782
+
mgl@1371
 21783
+@end table
mgl@1371
 21784
+
mgl@1371
 21785
 @item AVR family---@file{config/avr/constraints.md}
mgl@1371
 21786
 @table @code
mgl@1371
 21787
 @item l
mgl@1371
 21788
--- a/gcc/expmed.c
mgl@1371
 21789
+++ b/gcc/expmed.c
mgl@1371
 21790
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  
mgl@1371
 21791
 #include "real.h"
mgl@1371
 21792
 #include "recog.h"
mgl@1371
 21793
 #include "langhooks.h"
mgl@1371
 21794
+#include "target.h"
mgl@1371
 21795
 
mgl@1371
 21796
 static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
mgl@1371
 21797
 				   unsigned HOST_WIDE_INT,
mgl@1371
 21798
@@ -454,9 +455,19 @@ store_bit_field (rtx str_rtx, unsigned H
mgl@1371
 21799
 	  ? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
mgl@1371
 21800
 	     || GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
mgl@1371
 21801
 	     && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
mgl@1371
 21802
-	  : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
mgl@1371
 21803
-	     || (offset * BITS_PER_UNIT % bitsize == 0
mgl@1371
 21804
-		 && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
mgl@1371
 21805
+         : ( 
mgl@1371
 21806
+
mgl@1371
 21807
+             /* NB! Added for AVR32, and I think this should be true for
mgl@1371
 21808
+                all targets not using narrow volatile bitfields. If the
mgl@1371
 21809
+                bitfield is volatile then we need to perform an access
mgl@1371
 21810
+                consistent with the container type. */
mgl@1371
 21811
+             !(MEM_VOLATILE_P (op0) 
mgl@1371
 21812
+               && GET_MODE_BITSIZE (GET_MODE (op0)) != bitsize
mgl@1371
 21813
+               && bitsize < BITS_PER_WORD
mgl@1371
 21814
+               && !targetm.narrow_volatile_bitfield ())
mgl@1371
 21815
+             && (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
mgl@1371
 21816
+                 || (offset * BITS_PER_UNIT % bitsize == 0
mgl@1371
 21817
+                     && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0)))))
mgl@1371
 21818
     {
mgl@1371
 21819
       if (MEM_P (op0))
mgl@1371
 21820
 	op0 = adjust_address (op0, fieldmode, offset);
mgl@1371
 21821
@@ -1256,6 +1267,13 @@ extract_bit_field (rtx str_rtx, unsigned
mgl@1371
 21822
 	   && GET_MODE_SIZE (mode1) != 0
mgl@1371
 21823
 	   && byte_offset % GET_MODE_SIZE (mode1) == 0)
mgl@1371
 21824
 	  || (MEM_P (op0)
mgl@1371
 21825
+             /* NB! Added for AVR32, and I think this should be true for
mgl@1371
 21826
+                all targets not using narrow volatile bitfields. If the
mgl@1371
 21827
+                bitfield is volatile then we need to perform an access
mgl@1371
 21828
+                consistent with the container type. */
mgl@1371
 21829
+              && !(MEM_VOLATILE_P (op0)
mgl@1371
 21830
+                   && GET_MODE_BITSIZE (GET_MODE (op0)) != bitsize
mgl@1371
 21831
+                   && !targetm.narrow_volatile_bitfield ())
mgl@1371
 21832
 	      && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
mgl@1371
 21833
 		  || (offset * BITS_PER_UNIT % bitsize == 0
mgl@1371
 21834
 		      && MEM_ALIGN (op0) % bitsize == 0)))))
mgl@1371
 21835
--- a/gcc/expr.c
mgl@1371
 21836
+++ b/gcc/expr.c
mgl@1371
 21837
@@ -3519,18 +3519,19 @@ emit_single_push_insn (enum machine_mode
mgl@1371
 21838
     }
mgl@1371
 21839
   else
mgl@1371
 21840
     {
mgl@1371
 21841
+      emit_move_insn (stack_pointer_rtx,
mgl@1371
 21842
+		      expand_binop (Pmode,
mgl@1371
 21843
 #ifdef STACK_GROWS_DOWNWARD
mgl@1371
 21844
-      /* ??? This seems wrong if STACK_PUSH_CODE == POST_DEC.  */
mgl@1371
 21845
-      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
mgl@1371
 21846
-				GEN_INT (-(HOST_WIDE_INT) rounded_size));
mgl@1371
 21847
+				    sub_optab,
mgl@1371
 21848
 #else
mgl@1371
 21849
-      /* ??? This seems wrong if STACK_PUSH_CODE == POST_INC.  */
mgl@1371
 21850
-      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
mgl@1371
 21851
-				GEN_INT (rounded_size));
mgl@1371
 21852
+				    add_optab,
mgl@1371
 21853
 #endif
mgl@1371
 21854
-      dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
mgl@1371
 21855
+				    stack_pointer_rtx,
mgl@1371
 21856
+				    GEN_INT (rounded_size),
mgl@1371
 21857
+				    NULL_RTX, 0, OPTAB_LIB_WIDEN));
mgl@1371
 21858
+      dest_addr = stack_pointer_rtx;
mgl@1371
 21859
     }
mgl@1371
 21860
-
mgl@1371
 21861
+  
mgl@1371
 21862
   dest = gen_rtx_MEM (mode, dest_addr);
mgl@1371
 21863
 
mgl@1371
 21864
   if (type != 0)
mgl@1371
 21865
@@ -5509,7 +5510,21 @@ store_field (rtx target, HOST_WIDE_INT b
mgl@1371
 21866
      is a bit field, we cannot use addressing to access it.
mgl@1371
 21867
      Use bit-field techniques or SUBREG to store in it.  */
mgl@1371
 21868
 
mgl@1371
 21869
-  if (mode == VOIDmode
mgl@1371
 21870
+  if (
mgl@1371
 21871
+      /* NB! Added for AVR32, and I think this should be true for
mgl@1371
 21872
+         all targets not using narrow volatile bitfields. If the
mgl@1371
 21873
+         bitfield is volatile then we need to perform an access
mgl@1371
 21874
+         consistent with the container type. */
mgl@1371
 21875
+      (MEM_P (target) 
mgl@1371
 21876
+       && MEM_VOLATILE_P (target) 
mgl@1371
 21877
+       && ((GET_MODE (target) != BLKmode
mgl@1371
 21878
+            && GET_MODE_BITSIZE (GET_MODE (target)) > bitsize )
mgl@1371
 21879
+           /* If BLKmode, check if this is a record. Do not know 
mgl@1371
 21880
+              if this is really necesarry though...*/
mgl@1371
 21881
+           || (GET_MODE (target) == BLKmode
mgl@1371
 21882
+               && TREE_CODE (type) == RECORD_TYPE))
mgl@1371
 21883
+       && !targetm.narrow_volatile_bitfield ())
mgl@1371
 21884
+      || mode == VOIDmode
mgl@1371
 21885
       || (mode != BLKmode && ! direct_store[(int) mode]
mgl@1371
 21886
 	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
mgl@1371
 21887
 	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
mgl@1371
 21888
@@ -7560,7 +7575,21 @@ expand_expr_real_1 (tree exp, rtx target
mgl@1371
 21889
 	   by doing the extract into an object as wide as the field
mgl@1371
 21890
 	   (which we know to be the width of a basic mode), then
mgl@1371
 21891
 	   storing into memory, and changing the mode to BLKmode.  */
mgl@1371
 21892
-	if (mode1 == VOIDmode
mgl@1371
 21893
+       if (      
mgl@1371
 21894
+            /* NB! Added for AVR32, and I think this should be true for
mgl@1371
 21895
+               all targets not using narrow volatile bitfields. If the
mgl@1371
 21896
+               bitfield is volatile then we need to perform an access
mgl@1371
 21897
+               consistent with the container type. */
mgl@1371
 21898
+            (MEM_P (op0) 
mgl@1371
 21899
+             && MEM_VOLATILE_P (op0) 
mgl@1371
 21900
+             && ((GET_MODE (op0) != BLKmode
mgl@1371
 21901
+                  && GET_MODE_BITSIZE (GET_MODE (op0)) > bitsize )
mgl@1371
 21902
+                 /* If BLKmode, check if this is a record. Do not know 
mgl@1371
 21903
+                    if this is really necesarry though...*/
mgl@1371
 21904
+                 || (GET_MODE (op0) == BLKmode
mgl@1371
 21905
+                     && TREE_CODE (type) == RECORD_TYPE))
mgl@1371
 21906
+             && !targetm.narrow_volatile_bitfield ())
mgl@1371
 21907
+            || mode1 == VOIDmode
mgl@1371
 21908
 	    || REG_P (op0) || GET_CODE (op0) == SUBREG
mgl@1371
 21909
 	    || (mode1 != BLKmode && ! direct_load[(int) mode1]
mgl@1371
 21910
 		&& GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
mgl@1371
 21911
--- a/gcc/flow.c
mgl@1371
 21912
+++ b/gcc/flow.c
mgl@1371
 21913
@@ -3327,12 +3327,12 @@ not_reg_cond (rtx x)
mgl@1371
 21914
   if (GET_CODE (x) == NOT)
mgl@1371
 21915
     return XEXP (x, 0);
mgl@1371
 21916
   if (COMPARISON_P (x)
mgl@1371
 21917
-      && REG_P (XEXP (x, 0)))
mgl@1371
 21918
+      /* && REG_P (XEXP (x, 0))*/)
mgl@1371
 21919
     {
mgl@1371
 21920
-      gcc_assert (XEXP (x, 1) == const0_rtx);
mgl@1371
 21921
+      /*gcc_assert (XEXP (x, 1) == const0_rtx);*/
mgl@1371
 21922
 
mgl@1371
 21923
       return gen_rtx_fmt_ee (reversed_comparison_code (x, NULL),
mgl@1371
 21924
-			     VOIDmode, XEXP (x, 0), const0_rtx);
mgl@1371
 21925
+			     VOIDmode, XEXP (x, 0), XEXP (x, 0) /*const0_rtx*/);
mgl@1371
 21926
     }
mgl@1371
 21927
   return gen_rtx_NOT (0, x);
mgl@1371
 21928
 }
mgl@1371
 21929
--- a/gcc/function.c
mgl@1371
 21930
+++ b/gcc/function.c
mgl@1371
 21931
@@ -2676,8 +2676,12 @@ assign_parm_setup_reg (struct assign_par
mgl@1371
 21932
     SET_DECL_RTL (parm, parmreg);
mgl@1371
 21933
 
mgl@1371
 21934
   /* Copy the value into the register.  */
mgl@1371
 21935
-  if (data->nominal_mode != data->passed_mode
mgl@1371
 21936
-      || promoted_nominal_mode != data->promoted_mode)
mgl@1371
 21937
+  if ( (data->nominal_mode != data->passed_mode
mgl@1371
 21938
+        /* Added for AVR32: If passed_mode is equal
mgl@1371
 21939
+           to promoted nominal mode why should be convert?
mgl@1371
 21940
+           The conversion should make no difference. */
mgl@1371
 21941
+        && data->passed_mode != promoted_nominal_mode)
mgl@1371
 21942
+       || promoted_nominal_mode != data->promoted_mode)
mgl@1371
 21943
     {
mgl@1371
 21944
       int save_tree_used;
mgl@1371
 21945
 
mgl@1371
 21946
--- a/gcc/genemit.c
mgl@1371
 21947
+++ b/gcc/genemit.c
mgl@1371
 21948
@@ -121,6 +121,24 @@ max_operand_vec (rtx insn, int arg)
mgl@1371
 21949
 }
mgl@1371
 21950
 
mgl@1371
 21951
 static void
mgl@1371
 21952
+gen_vararg_prologue(int operands)
mgl@1371
 21953
+{
mgl@1371
 21954
+  int i;
mgl@1371
 21955
+
mgl@1371
 21956
+  if (operands > 1)
mgl@1371
 21957
+    {
mgl@1371
 21958
+      for (i = 1; i < operands; i++)
mgl@1371
 21959
+	printf("  rtx operand%d ATTRIBUTE_UNUSED;\n", i);
mgl@1371
 21960
+
mgl@1371
 21961
+      printf("  va_list args;\n\n");
mgl@1371
 21962
+      printf("  va_start(args, operand0);\n");
mgl@1371
 21963
+      for (i = 1; i < operands; i++)
mgl@1371
 21964
+	printf("  operand%d = va_arg(args, rtx);\n", i);
mgl@1371
 21965
+      printf("  va_end(args);\n\n");
mgl@1371
 21966
+    }
mgl@1371
 21967
+}
mgl@1371
 21968
+
mgl@1371
 21969
+static void
mgl@1371
 21970
 print_code (RTX_CODE code)
mgl@1371
 21971
 {
mgl@1371
 21972
   const char *p1;
mgl@1371
 21973
@@ -405,18 +423,16 @@ gen_insn (rtx insn, int lineno)
mgl@1371
 21974
     fatal ("match_dup operand number has no match_operand");
mgl@1371
 21975
 
mgl@1371
 21976
   /* Output the function name and argument declarations.  */
mgl@1371
 21977
-  printf ("rtx\ngen_%s (", XSTR (insn, 0));
mgl@1371
 21978
+  printf ("rtx\ngen_%s ", XSTR (insn, 0));
mgl@1371
 21979
+
mgl@1371
 21980
   if (operands)
mgl@1371
 21981
-    for (i = 0; i < operands; i++)
mgl@1371
 21982
-      if (i)
mgl@1371
 21983
-	printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
mgl@1371
 21984
-      else
mgl@1371
 21985
-	printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
mgl@1371
 21986
+    printf("(rtx operand0 ATTRIBUTE_UNUSED, ...)\n");
mgl@1371
 21987
   else
mgl@1371
 21988
-    printf ("void");
mgl@1371
 21989
-  printf (")\n");
mgl@1371
 21990
+    printf("(void)\n");
mgl@1371
 21991
   printf ("{\n");
mgl@1371
 21992
 
mgl@1371
 21993
+  gen_vararg_prologue(operands);
mgl@1371
 21994
+
mgl@1371
 21995
   /* Output code to construct and return the rtl for the instruction body.  */
mgl@1371
 21996
 
mgl@1371
 21997
   if (XVECLEN (insn, 1) == 1)
mgl@1371
 21998
@@ -456,16 +472,12 @@ gen_expand (rtx expand)
mgl@1371
 21999
   operands = max_operand_vec (expand, 1);
mgl@1371
 22000
 
mgl@1371
 22001
   /* Output the function name and argument declarations.  */
mgl@1371
 22002
-  printf ("rtx\ngen_%s (", XSTR (expand, 0));
mgl@1371
 22003
+  printf ("rtx\ngen_%s ", XSTR (expand, 0));
mgl@1371
 22004
   if (operands)
mgl@1371
 22005
-    for (i = 0; i < operands; i++)
mgl@1371
 22006
-      if (i)
mgl@1371
 22007
-	printf (",\n\trtx operand%d", i);
mgl@1371
 22008
-      else
mgl@1371
 22009
-	printf ("rtx operand%d", i);
mgl@1371
 22010
+    printf("(rtx operand0 ATTRIBUTE_UNUSED, ...)\n");
mgl@1371
 22011
   else
mgl@1371
 22012
-    printf ("void");
mgl@1371
 22013
-  printf (")\n");
mgl@1371
 22014
+    printf("(void)\n");
mgl@1371
 22015
+
mgl@1371
 22016
   printf ("{\n");
mgl@1371
 22017
 
mgl@1371
 22018
   /* If we don't have any C code to write, only one insn is being written,
mgl@1371
 22019
@@ -475,6 +487,8 @@ gen_expand (rtx expand)
mgl@1371
 22020
       && operands > max_dup_opno
mgl@1371
 22021
       && XVECLEN (expand, 1) == 1)
mgl@1371
 22022
     {
mgl@1371
 22023
+      gen_vararg_prologue(operands);
mgl@1371
 22024
+
mgl@1371
 22025
       printf ("  return ");
mgl@1371
 22026
       gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
mgl@1371
 22027
       printf (";\n}\n\n");
mgl@1371
 22028
@@ -488,6 +502,7 @@ gen_expand (rtx expand)
mgl@1371
 22029
   for (; i <= max_scratch_opno; i++)
mgl@1371
 22030
     printf ("  rtx operand%d ATTRIBUTE_UNUSED;\n", i);
mgl@1371
 22031
   printf ("  rtx _val = 0;\n");
mgl@1371
 22032
+  gen_vararg_prologue(operands);
mgl@1371
 22033
   printf ("  start_sequence ();\n");
mgl@1371
 22034
 
mgl@1371
 22035
   /* The fourth operand of DEFINE_EXPAND is some code to be executed
mgl@1371
 22036
--- a/gcc/genflags.c
mgl@1371
 22037
+++ b/gcc/genflags.c
mgl@1371
 22038
@@ -127,7 +127,6 @@ static void
mgl@1371
 22039
 gen_proto (rtx insn)
mgl@1371
 22040
 {
mgl@1371
 22041
   int num = num_operands (insn);
mgl@1371
 22042
-  int i;
mgl@1371
 22043
   const char *name = XSTR (insn, 0);
mgl@1371
 22044
   int truth = maybe_eval_c_test (XSTR (insn, 2));
mgl@1371
 22045
 
mgl@1371
 22046
@@ -158,12 +157,7 @@ gen_proto (rtx insn)
mgl@1371
 22047
   if (num == 0)
mgl@1371
 22048
     fputs ("void", stdout);
mgl@1371
 22049
   else
mgl@1371
 22050
-    {
mgl@1371
 22051
-      for (i = 1; i < num; i++)
mgl@1371
 22052
-	fputs ("rtx, ", stdout);
mgl@1371
 22053
-
mgl@1371
 22054
-      fputs ("rtx", stdout);
mgl@1371
 22055
-    }
mgl@1371
 22056
+    fputs("rtx, ...", stdout);
mgl@1371
 22057
 
mgl@1371
 22058
   puts (");");
mgl@1371
 22059
 
mgl@1371
 22060
@@ -173,12 +167,7 @@ gen_proto (rtx insn)
mgl@1371
 22061
     {
mgl@1371
 22062
       printf ("static inline rtx\ngen_%s", name);
mgl@1371
 22063
       if (num > 0)
mgl@1371
 22064
-	{
mgl@1371
 22065
-	  putchar ('(');
mgl@1371
 22066
-	  for (i = 0; i < num-1; i++)
mgl@1371
 22067
-	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
mgl@1371
 22068
-	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
mgl@1371
 22069
-	}
mgl@1371
 22070
+	puts("(rtx ARG_UNUSED(a), ...)");
mgl@1371
 22071
       else
mgl@1371
 22072
 	puts ("(void)");
mgl@1371
 22073
       puts ("{\n  return 0;\n}");
mgl@1371
 22074
--- a/gcc/genoutput.c
mgl@1371
 22075
+++ b/gcc/genoutput.c
mgl@1371
 22076
@@ -386,7 +386,7 @@ output_insn_data (void)
mgl@1371
 22077
 	}
mgl@1371
 22078
 
mgl@1371
 22079
       if (d->name && d->name[0] != '*')
mgl@1371
 22080
-	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
mgl@1371
 22081
+	printf ("    gen_%s,\n", d->name);
mgl@1371
 22082
       else
mgl@1371
 22083
 	printf ("    0,\n");
mgl@1371
 22084
 
mgl@1371
 22085
--- a/gcc/ifcvt.c
mgl@1371
 22086
+++ b/gcc/ifcvt.c
mgl@1371
 22087
@@ -77,7 +77,7 @@ static int num_possible_if_blocks;
mgl@1371
 22088
 static int num_updated_if_blocks;
mgl@1371
 22089
 
mgl@1371
 22090
 /* # of changes made which require life information to be updated.  */
mgl@1371
 22091
-static int num_true_changes;
mgl@1371
 22092
+int num_true_changes;
mgl@1371
 22093
 
mgl@1371
 22094
 /* Whether conditional execution changes were made.  */
mgl@1371
 22095
 static int cond_exec_changed_p;
mgl@1371
 22096
@@ -287,12 +287,15 @@ cond_exec_process_insns (ce_if_block_t *
mgl@1371
 22097
       if (must_be_last)
mgl@1371
 22098
 	return FALSE;
mgl@1371
 22099
 
mgl@1371
 22100
-      if (modified_in_p (test, insn))
mgl@1371
 22101
-	{
mgl@1371
 22102
-	  if (!mod_ok)
mgl@1371
 22103
-	    return FALSE;
mgl@1371
 22104
-	  must_be_last = TRUE;
mgl@1371
 22105
-	}
mgl@1371
 22106
+#ifdef IFCVT_ALLOW_MODIFY_TEST_IN_INSN       
mgl@1371
 22107
+      if ( !IFCVT_ALLOW_MODIFY_TEST_IN_INSN )
mgl@1371
 22108
+#endif
mgl@1371
 22109
+        if (modified_in_p (test, insn))
mgl@1371
 22110
+          {
mgl@1371
 22111
+            if (!mod_ok)
mgl@1371
 22112
+              return FALSE;
mgl@1371
 22113
+            must_be_last = TRUE;
mgl@1371
 22114
+          }
mgl@1371
 22115
 
mgl@1371
 22116
       /* Now build the conditional form of the instruction.  */
mgl@1371
 22117
       pattern = PATTERN (insn);
mgl@1371
 22118
@@ -566,16 +569,19 @@ cond_exec_process_if_block (ce_if_block_
mgl@1371
 22119
   /* Do any machine dependent final modifications.  */
mgl@1371
 22120
   IFCVT_MODIFY_FINAL (ce_info);
mgl@1371
 22121
 #endif
mgl@1371
 22122
-
mgl@1371
 22123
-  /* Conversion succeeded.  */
mgl@1371
 22124
-  if (dump_file)
mgl@1371
 22125
-    fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
mgl@1371
 22126
-	     n_insns, (n_insns == 1) ? " was" : "s were");
mgl@1371
 22127
-
mgl@1371
 22128
+  
mgl@1371
 22129
   /* Merge the blocks!  */
mgl@1371
 22130
-  merge_if_block (ce_info);
mgl@1371
 22131
-  cond_exec_changed_p = TRUE;
mgl@1371
 22132
-  return TRUE;
mgl@1371
 22133
+  if ( reload_completed ){
mgl@1371
 22134
+    /* Conversion succeeded.  */
mgl@1371
 22135
+    if (dump_file)
mgl@1371
 22136
+      fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
mgl@1371
 22137
+               n_insns, (n_insns == 1) ? " was" : "s were");
mgl@1371
 22138
+    
mgl@1371
 22139
+    merge_if_block (ce_info);
mgl@1371
 22140
+    cond_exec_changed_p = TRUE;
mgl@1371
 22141
+    return TRUE;
mgl@1371
 22142
+  }
mgl@1371
 22143
+  return FALSE;
mgl@1371
 22144
 
mgl@1371
 22145
  fail:
mgl@1371
 22146
 #ifdef IFCVT_MODIFY_CANCEL
mgl@1371
 22147
@@ -1050,7 +1056,11 @@ noce_try_addcc (struct noce_if_info *if_
mgl@1371
 22148
 	  != UNKNOWN))
mgl@1371
 22149
     {
mgl@1371
 22150
       rtx cond = if_info->cond;
mgl@1371
 22151
-      enum rtx_code code = reversed_comparison_code (cond, if_info->jump);
mgl@1371
 22152
+      /* This generates wrong code for AVR32. The cond code need not be reversed
mgl@1371
 22153
+         since the addmodecc patterns add if the condition is NOT met. */
mgl@1371
 22154
+      /*   enum rtx_code code = reversed_comparison_code (cond, if_info->jump);*/
mgl@1371
 22155
+      enum rtx_code code = GET_CODE(cond);
mgl@1371
 22156
+
mgl@1371
 22157
 
mgl@1371
 22158
       /* First try to use addcc pattern.  */
mgl@1371
 22159
       if (general_operand (XEXP (cond, 0), VOIDmode)
mgl@1371
 22160
@@ -2651,7 +2661,12 @@ process_if_block (struct ce_if_block * c
mgl@1371
 22161
       && cond_move_process_if_block (ce_info))
mgl@1371
 22162
     return TRUE;
mgl@1371
 22163
 
mgl@1371
 22164
-  if (HAVE_conditional_execution && reload_completed)
mgl@1371
 22165
+  if (HAVE_conditional_execution && 
mgl@1371
 22166
+#ifdef IFCVT_COND_EXEC_BEFORE_RELOAD
mgl@1371
 22167
+      (reload_completed || IFCVT_COND_EXEC_BEFORE_RELOAD))
mgl@1371
 22168
+#else
mgl@1371
 22169
+      reload_completed)
mgl@1371
 22170
+#endif
mgl@1371
 22171
     {
mgl@1371
 22172
       /* If we have && and || tests, try to first handle combining the && and
mgl@1371
 22173
          || tests into the conditional code, and if that fails, go back and
mgl@1371
 22174
@@ -4036,6 +4051,15 @@ rest_of_handle_if_after_reload (void)
mgl@1371
 22175
   cleanup_cfg (CLEANUP_EXPENSIVE
mgl@1371
 22176
                | CLEANUP_UPDATE_LIFE
mgl@1371
 22177
                | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
mgl@1371
 22178
+  
mgl@1371
 22179
+  /* Hack for the AVR32 experimental ifcvt processing before reload.
mgl@1371
 22180
+     The AVR32 specific ifcvt code needs to know when ifcvt after reload 
mgl@1371
 22181
+     has begun. */
mgl@1371
 22182
+#ifdef IFCVT_COND_EXEC_BEFORE_RELOAD
mgl@1371
 22183
+  if ( IFCVT_COND_EXEC_BEFORE_RELOAD )
mgl@1371
 22184
+    cfun->machine->ifcvt_after_reload = 1;
mgl@1371
 22185
+#endif
mgl@1371
 22186
+  
mgl@1371
 22187
   if (flag_if_conversion2)
mgl@1371
 22188
     if_convert (1);
mgl@1371
 22189
   return 0;
mgl@1371
 22190
--- a/gcc/longlong.h
mgl@1371
 22191
+++ b/gcc/longlong.h
mgl@1371
 22192
@@ -226,6 +226,41 @@ UDItype __umulsidi3 (USItype, USItype);
mgl@1371
 22193
 #define UDIV_TIME 100
mgl@1371
 22194
 #endif /* __arm__ */
mgl@1371
 22195
 
mgl@1371
 22196
+#if defined (__avr32__) && W_TYPE_SIZE == 32
mgl@1371
 22197
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
mgl@1371
 22198
+  __asm__ ("add\t%1, %4, %5\n\tadc\t%0, %2, %3"		\
mgl@1371
 22199
+	   : "=r" ((USItype) (sh)),					\
mgl@1371
 22200
+	     "=&r" ((USItype) (sl))					\
mgl@1371
 22201
+	   : "r" ((USItype) (ah)),					\
mgl@1371
 22202
+	     "r" ((USItype) (bh)),					\
mgl@1371
 22203
+	     "r" ((USItype) (al)),					\
mgl@1371
 22204
+	     "r" ((USItype) (bl)) __CLOBBER_CC)
mgl@1371
 22205
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
mgl@1371
 22206
+  __asm__ ("sub\t%1, %4, %5\n\tsbc\t%0, %2, %3"		\
mgl@1371
 22207
+	   : "=r" ((USItype) (sh)),					\
mgl@1371
 22208
+	     "=&r" ((USItype) (sl))					\
mgl@1371
 22209
+	   : "r" ((USItype) (ah)),					\
mgl@1371
 22210
+	     "r" ((USItype) (bh)),					\
mgl@1371
 22211
+	     "r" ((USItype) (al)),					\
mgl@1371
 22212
+	     "r" ((USItype) (bl)) __CLOBBER_CC)
mgl@1371
 22213
+
mgl@1371
 22214
+#if !defined (__AVR32_UC__) || __AVR32_UC__ != 3
mgl@1371
 22215
+#define __umulsidi3(a,b) ((UDItype)(a) * (UDItype)(b))
mgl@1371
 22216
+
mgl@1371
 22217
+#define umul_ppmm(w1, w0, u, v) \
mgl@1371
 22218
+{									\
mgl@1371
 22219
+  DWunion __w;								\
mgl@1371
 22220
+  __w.ll = __umulsidi3 (u, v);						\
mgl@1371
 22221
+  w1 = __w.s.high;							\
mgl@1371
 22222
+  w0 = __w.s.low;							\
mgl@1371
 22223
+}
mgl@1371
 22224
+#endif
mgl@1371
 22225
+
mgl@1371
 22226
+#define count_leading_zeros(COUNT,X)	((COUNT) = __builtin_clz (X))
mgl@1371
 22227
+#define count_trailing_zeros(COUNT,X)	((COUNT) = __builtin_ctz (X))
mgl@1371
 22228
+#define COUNT_LEADING_ZEROS_0 32
mgl@1371
 22229
+#endif
mgl@1371
 22230
+
mgl@1371
 22231
 #if defined (__hppa) && W_TYPE_SIZE == 32
mgl@1371
 22232
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
mgl@1371
 22233
   __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0"				\
mgl@1371
 22234
--- a/gcc/optabs.h
mgl@1371
 22235
+++ b/gcc/optabs.h
mgl@1371
 22236
@@ -431,7 +431,7 @@ extern enum insn_code reload_out_optab[N
mgl@1371
 22237
 extern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
mgl@1371
 22238
 
mgl@1371
 22239
 
mgl@1371
 22240
-typedef rtx (*rtxfun) (rtx);
mgl@1371
 22241
+typedef rtx (*rtxfun) (rtx, ...);
mgl@1371
 22242
 
mgl@1371
 22243
 /* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...)
mgl@1371
 22244
    gives the gen_function to make a branch to test that condition.  */
mgl@1371
 22245
--- a/gcc/regrename.c
mgl@1371
 22246
+++ b/gcc/regrename.c
mgl@1371
 22247
@@ -1592,6 +1592,9 @@ copyprop_hardreg_forward_1 (basic_block 
mgl@1371
 22248
   bool changed = false;
mgl@1371
 22249
   rtx insn;
mgl@1371
 22250
 
mgl@1371
 22251
+  rtx prev_pred_test;
mgl@1371
 22252
+  int prev_pred_insn_skipped = 0;
mgl@1371
 22253
+
mgl@1371
 22254
   for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
mgl@1371
 22255
     {
mgl@1371
 22256
       int n_ops, i, alt, predicated;
mgl@1371
 22257
@@ -1630,7 +1633,60 @@ copyprop_hardreg_forward_1 (basic_block 
mgl@1371
 22258
 	      || (predicated && recog_data.operand_type[i] == OP_OUT))
mgl@1371
 22259
 	    recog_data.operand_type[i] = OP_INOUT;
mgl@1371
 22260
 	}
mgl@1371
 22261
+      
mgl@1371
 22262
 
mgl@1371
 22263
+      /* Added for targets (AVR32) which supports test operands to be modified
mgl@1371
 22264
+         in cond_exec instruction. For these targets we cannot make a change to
mgl@1371
 22265
+         the test operands if one of the test operands is an output operand This beacuse
mgl@1371
 22266
+         changing the test operands might cause the need for inserting a new test
mgl@1371
 22267
+         insns in the middle of a sequence of cond_exec insns and if the test operands
mgl@1371
 22268
+         are modified these tests will fail.
mgl@1371
 22269
+      */
mgl@1371
 22270
+      
mgl@1371
 22271
+      if ( IFCVT_ALLOW_MODIFY_TEST_IN_INSN
mgl@1371
 22272
+           && predicated )
mgl@1371
 22273
+        { 
mgl@1371
 22274
+          int insn_skipped = 0;
mgl@1371
 22275
+          rtx test = COND_EXEC_TEST (PATTERN (insn));
mgl@1371
 22276
+
mgl@1371
 22277
+          /* Check if the previous insn was a skipped predicated insn with the same
mgl@1371
 22278
+             test as this predicated insns. If so we cannot do any modification to
mgl@1371
 22279
+             this insn either since we cannot emit the test insn because the operands
mgl@1371
 22280
+             are clobbered. */
mgl@1371
 22281
+          if ( prev_pred_insn_skipped 
mgl@1371
 22282
+               && (rtx_equal_p (test, prev_pred_test) 
mgl@1371
 22283
+                   || rtx_equal_p (test, reversed_condition (prev_pred_test))) )
mgl@1371
 22284
+            { 
mgl@1371
 22285
+              insn_skipped = 1;
mgl@1371
 22286
+            }
mgl@1371
 22287
+          else
mgl@1371
 22288
+            {
mgl@1371
 22289
+              /* Check if the output operand is used in the test expression. */
mgl@1371
 22290
+              for (i = 0; i < n_ops; ++i)
mgl@1371
 22291
+                if ( recog_data.operand_type[i] == OP_INOUT 
mgl@1371
 22292
+                     && reg_mentioned_p (recog_data.operand[i], test) )
mgl@1371
 22293
+                  {
mgl@1371
 22294
+                    insn_skipped = 1;
mgl@1371
 22295
+                    break;
mgl@1371
 22296
+                  }
mgl@1371
 22297
+              
mgl@1371
 22298
+            }
mgl@1371
 22299
+          
mgl@1371
 22300
+          prev_pred_test = test;
mgl@1371
 22301
+          prev_pred_insn_skipped = insn_skipped;
mgl@1371
 22302
+          if ( insn_skipped )
mgl@1371
 22303
+            {
mgl@1371
 22304
+              if (insn == BB_END (bb))
mgl@1371
 22305
+                break;
mgl@1371
 22306
+              else
mgl@1371
 22307
+                continue;
mgl@1371
 22308
+            }
mgl@1371
 22309
+        } 
mgl@1371
 22310
+      else 
mgl@1371
 22311
+        {
mgl@1371
 22312
+          prev_pred_insn_skipped = 0;
mgl@1371
 22313
+        }
mgl@1371
 22314
+      
mgl@1371
 22315
       /* For each earlyclobber operand, zap the value data.  */
mgl@1371
 22316
       for (i = 0; i < n_ops; i++)
mgl@1371
 22317
 	if (recog_op_alt[i][alt].earlyclobber)
mgl@1371
 22318
--- a/gcc/reload.c
mgl@1371
 22319
+++ b/gcc/reload.c
mgl@1371
 22320
@@ -4574,7 +4574,7 @@ find_reloads_toplev (rtx x, int opnum, e
mgl@1371
 22321
 	      x = mem;
mgl@1371
 22322
 	      i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
mgl@1371
 22323
 					opnum, type, ind_levels, insn);
mgl@1371
 22324
-	      if (x != mem)
mgl@1371
 22325
+         if (!rtx_equal_p (x, mem))
mgl@1371
 22326
 		push_reg_equiv_alt_mem (regno, x);
mgl@1371
 22327
 	      if (address_reloaded)
mgl@1371
 22328
 		*address_reloaded = i;
mgl@1371
 22329
--- a/gcc/sched-deps.c
mgl@1371
 22330
+++ b/gcc/sched-deps.c
mgl@1371
 22331
@@ -649,7 +649,14 @@ fixup_sched_groups (rtx insn)
mgl@1371
 22332
 
mgl@1371
 22333
   prev_nonnote = prev_nonnote_insn (insn);
mgl@1371
 22334
   if (BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (prev_nonnote)
mgl@1371
 22335
-      && ! sched_insns_conditions_mutex_p (insn, prev_nonnote))
mgl@1371
 22336
+      /* Modification for AVR32 by RP: Why is this here, this will
mgl@1371
 22337
+         cause instruction to be without any dependencies which might
mgl@1371
 22338
+         cause it to be moved anywhere. For the AVR32 we try to keep
mgl@1371
 22339
+         a group of conditionals together even if they are mutual exclusive.
mgl@1371
 22340
+      */
mgl@1371
 22341
+      && (! sched_insns_conditions_mutex_p (insn, prev_nonnote)
mgl@1371
 22342
+          || GET_CODE (PATTERN (insn)) == COND_EXEC )
mgl@1371
 22343
+      )
mgl@1371
 22344
     add_dependence (insn, prev_nonnote, REG_DEP_ANTI);
mgl@1371
 22345
 }
mgl@1371
 22346
 
mgl@1371
 22347
@@ -1123,8 +1130,29 @@ sched_analyze_insn (struct deps *deps, r
mgl@1371
 22348
 
mgl@1371
 22349
   if (code == COND_EXEC)
mgl@1371
 22350
     {
mgl@1371
 22351
+#ifdef IFCVT_ALLOW_MODIFY_TEST_IN_INSN
mgl@1371
 22352
+      if (IFCVT_ALLOW_MODIFY_TEST_IN_INSN)
mgl@1371
 22353
+        {
mgl@1371
 22354
+          /* Check if we have a group og conditional instructions with the same test. 
mgl@1371
 22355
+             If so we must make sure that they are not scheduled apart in order to
mgl@1371
 22356
+             avoid unnecesarry tests and if one of the registers in the test is modified
mgl@1371
 22357
+             in the instruction this is needed to ensure correct code. */
mgl@1371
 22358
+          if ( prev_nonnote_insn (insn)
mgl@1371
 22359
+               && INSN_P (prev_nonnote_insn (insn))
mgl@1371
 22360
+               && GET_CODE (PATTERN (prev_nonnote_insn (insn))) == COND_EXEC 
mgl@1371
 22361
+               && rtx_equal_p (XEXP(COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn))), 0), XEXP (COND_EXEC_TEST (x), 0))
mgl@1371
 22362
+               && rtx_equal_p (XEXP(COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn))), 1), XEXP (COND_EXEC_TEST (x), 1))
mgl@1371
 22363
+               && ( GET_CODE (COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn)))) == GET_CODE (COND_EXEC_TEST (x))
mgl@1371
 22364
+                    || GET_CODE (COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn)))) == reversed_comparison_code (COND_EXEC_TEST (x), insn)))
mgl@1371
 22365
+            {
mgl@1371
 22366
+              SCHED_GROUP_P (insn) = 1;
mgl@1371
 22367
+              //CANT_MOVE (prev_nonnote_insn (insn)) = 1;
mgl@1371
 22368
+            }
mgl@1371
 22369
+        }
mgl@1371
 22370
+#endif      
mgl@1371
 22371
       sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
mgl@1371
 22372
 
mgl@1371
 22373
+
mgl@1371
 22374
       /* ??? Should be recording conditions so we reduce the number of
mgl@1371
 22375
 	 false dependencies.  */
mgl@1371
 22376
       x = COND_EXEC_CODE (x);
mgl@1371
 22377
--- a/gcc/testsuite/gcc.dg/sibcall-3.c
mgl@1371
 22378
+++ b/gcc/testsuite/gcc.dg/sibcall-3.c
mgl@1371
 22379
@@ -5,7 +5,7 @@
mgl@1371
 22380
    Copyright (C) 2002 Free Software Foundation Inc.
mgl@1371
 22381
    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
mgl@1371
 22382
 
mgl@1371
 22383
-/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
mgl@1371
 22384
+/* { dg-do run { xfail arc-*-* avr-*-* avr32-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
mgl@1371
 22385
 /* { dg-options "-O2 -foptimize-sibling-calls" } */
mgl@1371
 22386
 
mgl@1371
 22387
 /* The option -foptimize-sibling-calls is the default, but serves as
mgl@1371
 22388
--- a/gcc/testsuite/gcc.dg/sibcall-4.c
mgl@1371
 22389
+++ b/gcc/testsuite/gcc.dg/sibcall-4.c
mgl@1371
 22390
@@ -5,7 +5,7 @@
mgl@1371
 22391
    Copyright (C) 2002 Free Software Foundation Inc.
mgl@1371
 22392
    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
mgl@1371
 22393
 
mgl@1371
 22394
-/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
mgl@1371
 22395
+/* { dg-do run { xfail arc-*-* avr-*-* avr32-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
mgl@1371
 22396
 /* { dg-options "-O2 -foptimize-sibling-calls" } */
mgl@1371
 22397
 
mgl@1371
 22398
 /* The option -foptimize-sibling-calls is the default, but serves as
mgl@1371
 22399
--- a/gcc/testsuite/gcc.dg/trampoline-1.c
mgl@1371
 22400
+++ b/gcc/testsuite/gcc.dg/trampoline-1.c
mgl@1371
 22401
@@ -46,6 +46,8 @@ void foo (void)
mgl@1371
 22402
 
mgl@1371
 22403
 int main (void)
mgl@1371
 22404
 {
mgl@1371
 22405
+#ifndef NO_TRAMPOLINES
mgl@1371
 22406
   foo ();
mgl@1371
 22407
+#endif
mgl@1371
 22408
   return 0;
mgl@1371
 22409
 }
mgl@1371
 22410
--- a/gcc/testsuite/g++.old-deja/g++.pt/static11.C
mgl@1371
 22411
+++ b/gcc/testsuite/g++.old-deja/g++.pt/static11.C
mgl@1371
 22412
@@ -2,7 +2,7 @@
mgl@1371
 22413
 // in their dejagnu baseboard description) require that the status is
mgl@1371
 22414
 // final when exit is entered (or main returns), and not "overruled" by a
mgl@1371
 22415
 // destructor calling _exit.  It's not really worth it to handle that.
mgl@1371
 22416
-// { dg-do run { xfail mmix-knuth-mmixware xtensa-*-elf* arm*-*-elf arm*-*-eabi m68k-*-elf } }
mgl@1371
 22417
+// { dg-do run { xfail mmix-knuth-mmixware xtensa-*-elf* avr32-*-elf arm*-*-elf arm*-*-eabi m68k-*-elf } }
mgl@1371
 22418
 
mgl@1371
 22419
 // Bug: g++ was failing to destroy C<int>::a because it was using two
mgl@1371
 22420
 // different sentry variables for construction and destruction.
mgl@1371
 22421
--- a/gcc/version.c
mgl@1371
 22422
+++ b/gcc/version.c
mgl@1371
 22423
@@ -8,7 +8,7 @@
mgl@1371
 22424
    in parentheses.  You may also wish to include a number indicating
mgl@1371
 22425
    the revision of your modified compiler.  */
mgl@1371
 22426
 
mgl@1371
 22427
-#define VERSUFFIX ""
mgl@1371
 22428
+#define VERSUFFIX "-atmel.1.1.3.avr32linux.1"
mgl@1371
 22429
 
mgl@1371
 22430
 /* This is the location of the online document giving instructions for
mgl@1371
 22431
    reporting bugs.  If you distribute a modified version of GCC,
mgl@1371
 22432
@@ -17,9 +17,9 @@
mgl@1371
 22433
    forward us bugs reported to you, if you determine that they are
mgl@1371
 22434
    not bugs in your modifications.)  */
mgl@1371
 22435
 
mgl@1371
 22436
-const char bug_report_url[] = "<URL:http://gcc.gnu.org/bugs.html>";
mgl@1371
 22437
+const char bug_report_url[] = "<URL:http://www.atmel.com/avr32/>";
mgl@1371
 22438
 
mgl@1371
 22439
 /* The complete version string, assembled from several pieces.
mgl@1371
 22440
    BASEVER, DATESTAMP, and DEVPHASE are defined by the Makefile.  */
mgl@1371
 22441
 
mgl@1371
 22442
-const char version_string[] = BASEVER DATESTAMP DEVPHASE VERSUFFIX;
mgl@1371
 22443
+const char version_string[] = BASEVER VERSUFFIX DATESTAMP DEVPHASE;
mgl@1371
 22444
--- a/libstdc++-v3/acinclude.m4
mgl@1371
 22445
+++ b/libstdc++-v3/acinclude.m4
mgl@1371
 22446
@@ -125,15 +125,6 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [
mgl@1371
 22447
   ## other macros from doing the same.  This should be automated.)  -pme
mgl@1371
 22448
   need_libmath=no
mgl@1371
 22449
 
mgl@1371
 22450
-  # Check for uClibc since Linux platforms use different configuration
mgl@1371
 22451
-  # directories depending on the C library in use.
mgl@1371
 22452
-  AC_EGREP_CPP([_using_uclibc], [
mgl@1371
 22453
-  #include <stdio.h>
mgl@1371
 22454
-  #if __UCLIBC__
mgl@1371
 22455
-    _using_uclibc
mgl@1371
 22456
-  #endif
mgl@1371
 22457
-  ], uclibc=yes, uclibc=no)
mgl@1371
 22458
-
mgl@1371
 22459
   # Find platform-specific directories containing configuration info.
mgl@1371
 22460
   # Also possibly modify flags used elsewhere, as needed by the platform.
mgl@1371
 22461
   GLIBCXX_CHECK_HOST
mgl@1371
 22462
@@ -1389,8 +1380,8 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
mgl@1371
 22463
       #endif
mgl@1371
 22464
       int main()
mgl@1371
 22465
       {
mgl@1371
 22466
-	const char __one[] = "Äuglein Augmen";
mgl@1371
 22467
-        const char __two[] = "Äuglein";
mgl@1371
 22468
+	const char __one[] = "Äuglein Augmen";
mgl@1371
 22469
+        const char __two[] = "Äuglein";
mgl@1371
 22470
        	int i;
mgl@1371
 22471
         int j;
mgl@1371
 22472
         __locale_t        loc;
mgl@1371
 22473
--- a/libstdc++-v3/config/os/gnu-linux/ctype_base.h
mgl@1371
 22474
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_base.h
mgl@1371
 22475
@@ -31,6 +31,8 @@
mgl@1371
 22476
 //
mgl@1371
 22477
 // ISO C++ 14882: 22.1  Locales
mgl@1371
 22478
 //
mgl@1371
 22479
+#include <features.h>
mgl@1371
 22480
+#include <ctype.h>
mgl@1371
 22481
   
mgl@1371
 22482
 /** @file ctype_base.h
mgl@1371
 22483
  *  This is an internal header file, included by other library headers.
mgl@1371
 22484
@@ -45,8 +47,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
mgl@1371
 22485
   struct ctype_base
mgl@1371
 22486
   {
mgl@1371
 22487
     // Non-standard typedefs.
mgl@1371
 22488
-    typedef const int* 		__to_type;
mgl@1371
 22489
-
mgl@1371
 22490
+#ifdef __UCLIBC__
mgl@1371
 22491
+    typedef const __ctype_touplow_t*   __to_type;
mgl@1371
 22492
+#else
mgl@1371
 22493
+    typedef const int*         __to_type;
mgl@1371
 22494
+#endif
mgl@1371
 22495
+ 
mgl@1371
 22496
     // NB: Offsets into ctype<char>::_M_table force a particular size
mgl@1371
 22497
     // on the mask type. Because of this, we don't use an enum.
mgl@1371
 22498
     typedef unsigned short 	mask;   
mgl@1371
 22499
--- a/libstdc++-v3/include/Makefile.in
mgl@1371
 22500
+++ b/libstdc++-v3/include/Makefile.in
mgl@1371
 22501
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
mgl@1371
 22502
 build_triplet = @build@
mgl@1371
 22503
 host_triplet = @host@
mgl@1371
 22504
 target_triplet = @target@
mgl@1371
 22505
+LIBOBJDIR =
mgl@1371
 22506
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
mgl@1371
 22507
 	$(top_srcdir)/fragment.am
mgl@1371
 22508
 subdir = include
mgl@1371
 22509
--- a/libstdc++-v3/libmath/Makefile.in
mgl@1371
 22510
+++ b/libstdc++-v3/libmath/Makefile.in
mgl@1371
 22511
@@ -37,6 +37,7 @@ POST_UNINSTALL = :
mgl@1371
 22512
 build_triplet = @build@
mgl@1371
 22513
 host_triplet = @host@
mgl@1371
 22514
 target_triplet = @target@
mgl@1371
 22515
+LIBOBJDIR =
mgl@1371
 22516
 subdir = libmath
mgl@1371
 22517
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
mgl@1371
 22518
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mgl@1371
 22519
--- a/libstdc++-v3/libsupc++/Makefile.in
mgl@1371
 22520
+++ b/libstdc++-v3/libsupc++/Makefile.in
mgl@1371
 22521
@@ -38,6 +38,7 @@ POST_UNINSTALL = :
mgl@1371
 22522
 build_triplet = @build@
mgl@1371
 22523
 host_triplet = @host@
mgl@1371
 22524
 target_triplet = @target@
mgl@1371
 22525
+LIBOBJDIR =
mgl@1371
 22526
 DIST_COMMON = $(glibcxxinstall_HEADERS) $(srcdir)/Makefile.am \
mgl@1371
 22527
 	$(srcdir)/Makefile.in $(top_srcdir)/fragment.am
mgl@1371
 22528
 subdir = libsupc++
mgl@1371
 22529
--- a/libstdc++-v3/Makefile.in
mgl@1371
 22530
+++ b/libstdc++-v3/Makefile.in
mgl@1371
 22531
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
mgl@1371
 22532
 build_triplet = @build@
mgl@1371
 22533
 host_triplet = @host@
mgl@1371
 22534
 target_triplet = @target@
mgl@1371
 22535
+LIBOBJDIR =
mgl@1371
 22536
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \
mgl@1371
 22537
 	$(srcdir)/../config.sub $(srcdir)/../install-sh \
mgl@1371
 22538
 	$(srcdir)/../ltmain.sh $(srcdir)/../missing \
mgl@1371
 22539
--- a/libstdc++-v3/po/Makefile.in
mgl@1371
 22540
+++ b/libstdc++-v3/po/Makefile.in
mgl@1371
 22541
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
mgl@1371
 22542
 build_triplet = @build@
mgl@1371
 22543
 host_triplet = @host@
mgl@1371
 22544
 target_triplet = @target@
mgl@1371
 22545
+LIBOBJDIR =
mgl@1371
 22546
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
mgl@1371
 22547
 	$(top_srcdir)/fragment.am
mgl@1371
 22548
 subdir = po
mgl@1371
 22549
--- a/libstdc++-v3/src/Makefile.in
mgl@1371
 22550
+++ b/libstdc++-v3/src/Makefile.in
mgl@1371
 22551
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
mgl@1371
 22552
 build_triplet = @build@
mgl@1371
 22553
 host_triplet = @host@
mgl@1371
 22554
 target_triplet = @target@
mgl@1371
 22555
+LIBOBJDIR =
mgl@1371
 22556
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
mgl@1371
 22557
 	$(top_srcdir)/fragment.am
mgl@1371
 22558
 subdir = src
mgl@1371
 22559
--- a/Makefile.def
mgl@1371
 22560
+++ b/Makefile.def
mgl@1371
 22561
@@ -481,7 +481,7 @@ lang_env_dependencies = { module=rda; };
mgl@1371
 22562
 lang_env_dependencies = { module=winsup; };
mgl@1371
 22563
 lang_env_dependencies = { module=qthreads; };
mgl@1371
 22564
 
mgl@1371
 22565
-dependencies = { module=all-target-libgloss; on=configure-target-newlib; };
mgl@1371
 22566
+dependencies = { module=all-target-libgloss; on=all-target-newlib; };
mgl@1371
 22567
 dependencies = { module=all-target-winsup; on=all-target-libiberty; };
mgl@1371
 22568
 dependencies = { module=all-target-winsup; on=all-target-libtermcap; };
mgl@1371
 22569
 
mgl@1371
 22570
--- a/Makefile.in
mgl@1371
 22571
+++ b/Makefile.in
mgl@1371
 22572
@@ -43791,7 +43791,7 @@ all-target-libobjc: maybe-all-target-boe
mgl@1371
 22573
 all-target-libstdc++-v3: maybe-all-target-libiberty
mgl@1371
 22574
 install-target-libssp: maybe-install-gcc
mgl@1371
 22575
 install-target-libgomp: maybe-install-gcc
mgl@1371
 22576
-all-target-libgloss: maybe-configure-target-newlib
mgl@1371
 22577
+all-target-libgloss: maybe-all-target-newlib
mgl@1371
 22578
 all-target-winsup: maybe-all-target-libiberty
mgl@1371
 22579
 all-target-winsup: maybe-all-target-libtermcap
mgl@1371
 22580
 
mgl@1371
 22581
--- a/gcc/configure.ac
mgl@1371
 22582
+++ b/gcc/configure.ac
mgl@1371
 22583
@@ -2158,7 +2158,7 @@ L2:],
mgl@1371
 22584
   as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
mgl@1371
 22585
   if echo "$as_ver" | grep GNU > /dev/null; then
mgl@1371
 22586
 changequote(,)dnl
mgl@1371
 22587
-    as_ver=`echo $as_ver | sed -e 's/GNU assembler \([0-9.][0-9.]*\).*/\1/'`
mgl@1371
 22588
+    as_ver=`echo $as_ver | sed -e 's/GNU assembler\( (GNU Binutils)\)\? \([0-9.][0-9.]*\).*/\2/'`
mgl@1371
 22589
     as_major=`echo $as_ver | sed 's/\..*//'`
mgl@1371
 22590
     as_minor=`echo $as_ver | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
mgl@1371
 22591
 changequote([,])dnl
mgl@1371
 22592
@@ -2971,7 +2971,7 @@ esac
mgl@1371
 22593
 case "$target" in
mgl@1371
 22594
   i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
mgl@1371
 22595
   | x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
mgl@1371
 22596
-  | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
mgl@1371
 22597
+  | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-* | avr32-*-*)
mgl@1371
 22598
     insn="nop"
mgl@1371
 22599
     ;;
mgl@1371
 22600
   ia64*-*-* | s390*-*-*)
mgl@1371
 22601
--- a/gcc/configure
mgl@1371
 22602
+++ b/gcc/configure
mgl@1371
 22603
@@ -14023,7 +14023,7 @@ L2:' > conftest.s
mgl@1371
 22604
   # arbitrary sections are supported and try the test.
mgl@1371
 22605
   as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
mgl@1371
 22606
   if echo "$as_ver" | grep GNU > /dev/null; then
mgl@1371
 22607
-    as_ver=`echo $as_ver | sed -e 's/GNU assembler \([0-9.][0-9.]*\).*/\1/'`
mgl@1371
 22608
+    as_ver=`echo $as_ver | sed -e 's/GNU assembler\( (GNU Binutils)\)\? \([0-9.][0-9.]*\).*/\2/'`
mgl@1371
 22609
     as_major=`echo $as_ver | sed 's/\..*//'`
mgl@1371
 22610
     as_minor=`echo $as_ver | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
mgl@1371
 22611
     if test $as_major -eq 2 && test $as_minor -lt 11
mgl@1371
 22612
@@ -15610,7 +15610,7 @@ esac
mgl@1371
 22613
 case "$target" in
mgl@1371
 22614
   i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
mgl@1371
 22615
   | x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
mgl@1371
 22616
-  | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
mgl@1371
 22617
+  | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-* | avr32-*-*)
mgl@1371
 22618
     insn="nop"
mgl@1371
 22619
     ;;
mgl@1371
 22620
   ia64*-*-* | s390*-*-*)