patches/gcc/4.2.2/300-avr32-atmel-v1.1.3.patch
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
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*-*-*)