mn10300.h (PREDICATE_CODES): Define.
authorAlexandre Oliva <aoliva@redhat.com>
Thu, 10 Jul 2003 02:56:29 +0000 (02:56 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 10 Jul 2003 02:56:29 +0000 (02:56 +0000)
* config/mn10300/mn10300.h (PREDICATE_CODES): Define.
2001-05-01  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (sqrtsf2): flag_fast_math was renamed
to flag_unsafe_math_optimizations.
2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c (expand_prologue): Mark
FP-register-saving insns as frame-related.
2001-02-13  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c
(mn10300_get_live_callee_saved_regs): Don't search past
LAST_EXTENDED_REGNUM.
(mn10300_gen_multiple_store, store_multiple_operation): Likewise.
* config/mn10300/mn10300.md: Remove excessive line breaks from
`@' output patterns that were accounted as additional
alternatives.
* config/mn10300/mn10300.md, config/mn10300/mn10300.c:
Re-introduce changes accidentally removed in Richard Sandiford's
2000-12-05's patch.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
Re-instate am33-2 lost in merge from net GCC.
2000-08-26  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.h (DBX_REGISTER_NUMBER): Added
floating-point registers.
2000-08-07  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (movdf): Revert some am33-specific
pessimizations that had gone in on 2000-05-08.
2000-06-28  Graham Stott  <grahams@cygnus.co.uk>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Fix typo.
2000-06-22  Graham Stott  <grahams@cygnus.co.uk>
* config/mn10300/mn10300.md (movqi): Use nonimmediate_operand for
operand 0.
* (movhi): Likewise.
* (movsi): Likewise.
* (movsf): Likewise.
* (movdi): Likewise.
* (movdf): Likewise.
Wed May 24 13:16:09 2000  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.c (fp_regs_to_save): New function.
(can_use_return_insn, initial_offset): Add fp_regs_to_save.
(expand_prologue, expand_epilogue): Save and restore FP regs.
2000-05-20  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdi, movdf): 64-bit clean-up.
2000-05-13  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2, addsf3,
subsf3, mulsf3, divsf3, fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4):
Do not clobber cc0.
2000-05-12  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2):
Discourage the two-argument, longer opcodes.
(addsf3, subsf3, mulsf3, divsf3): Likewise for three-argument
ones.
* config/mn10300/mn10300.h (struct mn10300_cc_status_mdep): New.
(CC_STATUS_MDEP, CC_STATUS_MDEP_INIT): Define.
* config/mn10300/mn10300.md (cmpsf): New pattern.
(branch): Test mdep.fpCC and output fbCC.
* config/mn10300/mn10300.c (print_operand): Output conditions.
(notice_cc_update): Recognize fcmp and set mdep.fpCC.
2000-05-10  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movsf, movdf, addsf3, subsf3,
mulsf3, divsf3): Use the `F' constraint for FP values.
* config/mn10300/mn10300.c (const_1f_operand): New function.
* config/mn10300/mn10300-protos.h (const_1f_operand): Declare.
* config/mn10300/mn10300.md (sqrtsf2): New expand.
(rsqrtsf2): New insn.
2000-05-09  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdf): Oops, I missed it in my
previous check-in.
2000-05-08  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negdf2): On
TARGET_AM33_2, expand to...
(abssf2_am33_2, negdf2_am33_2): New insns.
(addsf3, subsf3, mulsf3, divsf3): Likewise.
(fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4): Likewise.
* config/mn10300/mn10300.md (movqi, movhi, movsi, movsf,
movdi, movdf): Added FP regs.
* invoke.texi (-mam33-2, -mno-am33-2): Document.
2000-04-29  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (FIRST_FP_REGNUM, LAST_FP_REGNUM):
New macros.
(REGNO_AM33_2_FP_P): Renamed to...
(REGNO_FP_P): Redefine in terms of FIRST_* and LAST_*.
(CONDITIONAL_REGISTER_USAGE, REGNO_REG_CLASS): Likewise.
2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Remove FP
regs from GENERAL_REGS.
2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REGNO_AM33_2_FP_P): New macro.
* config/mn10300/mn10300.c (mn10300_address_cost): Added FP_REGS.
* config/mn10300/mn10300.h (REGISTER_MOVE_COST): Added FP_REGS.
2000-04-23  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (CLASS_CANNOT_CHANGE_SIZE): Defined
as FP_REGS.
2000-04-21  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (OK_FOR_Q): New macro.
(EXTRA_CONSTRAINT): Added OK_FOR_Q.
* config/mn10300/mn10300.c (secondary_reload_class): Adjust.
* config/mn10300/mn10300.c (print_operand): Support `D' for doubles.
* config/mn10300/mn10300.h (FIRST_PSEUDO_REGISTER): Adjust.
(FIXED_REGISTERS, CALL_USED_REGISTERS, REG_ALLOC_ORDER): Added
AM33/2.0 floating-point registers.
(CONDITIONAL_REGISTER_USAGE): Adjust.
(enum reg_class, REG_CLASS_NAMES): Added FP_REGS and FP_ACC_REGS.
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Adjust.
(REG_CLASS_FROM_LETTER): Added `f' and `A'.
(REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Adjust.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS): Added am33-2.
(MULTILIB_DIRNAMES): Likewise.
* config/mn10300/mn10300.h (CPP_SPEC): Define `__AM33__=2' and
`__AM33_2__' when `-mam33-2' is given.
(TARGET_AM33_2): Define.
(TARGET_SWITCHES): Adjust.
* config/mn10300/mn10300.c (asm_file_start): Print `.am33_2'
when appropriate.

From-SVN: r69167

gcc/ChangeLog
gcc/config/mn10300/mn10300.c
gcc/config/mn10300/mn10300.h
gcc/config/mn10300/mn10300.md
gcc/config/mn10300/t-mn10300
gcc/doc/invoke.texi

index 6bf663b85c294e1ea5b3d31b78a35ef7ee12b0e7..d01693a42131f2e805f7d0ede5e3abdff8d3d443 100644 (file)
@@ -1,3 +1,119 @@
+2003-07-09  Alexandre Oliva  <aoliva@redhat.com>
+
+       * config/mn10300/mn10300.h (PREDICATE_CODES): Define.
+       2001-05-01  Alexandre Oliva  <aoliva@redhat.com>
+       * config/mn10300/mn10300.md (sqrtsf2): flag_fast_math was renamed
+       to flag_unsafe_math_optimizations.
+       2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/mn10300/mn10300.c (expand_prologue): Mark
+       FP-register-saving insns as frame-related.
+       2001-02-13  Alexandre Oliva  <aoliva@redhat.com>
+       * config/mn10300/mn10300.c
+       (mn10300_get_live_callee_saved_regs): Don't search past
+       LAST_EXTENDED_REGNUM.
+       (mn10300_gen_multiple_store, store_multiple_operation): Likewise.
+       * config/mn10300/mn10300.md: Remove excessive line breaks from
+       `@' output patterns that were accounted as additional
+       alternatives.
+       * config/mn10300/mn10300.md, config/mn10300/mn10300.c:
+       Re-introduce changes accidentally removed in Richard Sandiford's
+       2000-12-05's patch.
+       * config/mn10300/t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
+       Re-instate am33-2 lost in merge from net GCC.
+       2000-08-26  Alexandre Oliva  <aoliva@redhat.com>
+       * config/mn10300/mn10300.h (DBX_REGISTER_NUMBER): Added
+       floating-point registers.
+       2000-08-07  Alexandre Oliva  <aoliva@redhat.com>
+       * config/mn10300/mn10300.md (movdf): Revert some am33-specific
+       pessimizations that had gone in on 2000-05-08.
+       2000-06-28  Graham Stott  <grahams@cygnus.co.uk>
+       * config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Fix typo.
+       2000-06-22  Graham Stott  <grahams@cygnus.co.uk>
+       * config/mn10300/mn10300.md (movqi): Use nonimmediate_operand for
+       operand 0.
+       * (movhi): Likewise.
+       * (movsi): Likewise.
+       * (movsf): Likewise.
+       * (movdi): Likewise.
+       * (movdf): Likewise.
+       Wed May 24 13:16:09 2000  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.c (fp_regs_to_save): New function.
+       (can_use_return_insn, initial_offset): Add fp_regs_to_save.
+       (expand_prologue, expand_epilogue): Save and restore FP regs.
+       2000-05-20  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (movdi, movdf): 64-bit clean-up.
+       2000-05-13  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2, addsf3,
+       subsf3, mulsf3, divsf3, fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4):
+       Do not clobber cc0.
+       2000-05-12  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2):
+       Discourage the two-argument, longer opcodes.
+       (addsf3, subsf3, mulsf3, divsf3): Likewise for three-argument
+       ones.
+       * config/mn10300/mn10300.h (struct mn10300_cc_status_mdep): New.
+       (CC_STATUS_MDEP, CC_STATUS_MDEP_INIT): Define.
+       * config/mn10300/mn10300.md (cmpsf): New pattern.
+       (branch): Test mdep.fpCC and output fbCC.
+       * config/mn10300/mn10300.c (print_operand): Output conditions.
+       (notice_cc_update): Recognize fcmp and set mdep.fpCC.
+       2000-05-10  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (movsf, movdf, addsf3, subsf3,
+       mulsf3, divsf3): Use the `F' constraint for FP values.
+       * config/mn10300/mn10300.c (const_1f_operand): New function.
+       * config/mn10300/mn10300-protos.h (const_1f_operand): Declare.
+       * config/mn10300/mn10300.md (sqrtsf2): New expand.
+       (rsqrtsf2): New insn.
+       2000-05-09  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (movdf): Oops, I missed it in my
+       previous check-in.
+       2000-05-08  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.md (abssf2, negdf2): On
+       TARGET_AM33_2, expand to...
+       (abssf2_am33_2, negdf2_am33_2): New insns.
+       (addsf3, subsf3, mulsf3, divsf3): Likewise.
+       (fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4): Likewise.
+       * config/mn10300/mn10300.md (movqi, movhi, movsi, movsf,
+       movdi, movdf): Added FP regs.
+       * invoke.texi (-mam33-2, -mno-am33-2): Document.
+       2000-04-29  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.h (FIRST_FP_REGNUM, LAST_FP_REGNUM):
+       New macros.
+       (REGNO_AM33_2_FP_P): Renamed to...
+       (REGNO_FP_P): Redefine in terms of FIRST_* and LAST_*.
+       (CONDITIONAL_REGISTER_USAGE, REGNO_REG_CLASS): Likewise.
+       2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Remove FP
+       regs from GENERAL_REGS.
+       2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.h (REGNO_AM33_2_FP_P): New macro.
+       * config/mn10300/mn10300.c (mn10300_address_cost): Added FP_REGS.
+       * config/mn10300/mn10300.h (REGISTER_MOVE_COST): Added FP_REGS.
+       2000-04-23  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.h (CLASS_CANNOT_CHANGE_SIZE): Defined
+       as FP_REGS.
+       2000-04-21  Alexandre Oliva  <aoliva@cygnus.com>
+       * config/mn10300/mn10300.h (OK_FOR_Q): New macro.
+       (EXTRA_CONSTRAINT): Added OK_FOR_Q.
+       * config/mn10300/mn10300.c (secondary_reload_class): Adjust.
+       * config/mn10300/mn10300.c (print_operand): Support `D' for doubles.
+       * config/mn10300/mn10300.h (FIRST_PSEUDO_REGISTER): Adjust.
+       (FIXED_REGISTERS, CALL_USED_REGISTERS, REG_ALLOC_ORDER): Added
+       AM33/2.0 floating-point registers.
+       (CONDITIONAL_REGISTER_USAGE): Adjust.
+       (enum reg_class, REG_CLASS_NAMES): Added FP_REGS and FP_ACC_REGS.
+       (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Adjust.
+       (REG_CLASS_FROM_LETTER): Added `f' and `A'.
+       (REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Adjust.
+       * config/mn10300/t-mn10300 (MULTILIB_OPTIONS): Added am33-2.
+       (MULTILIB_DIRNAMES): Likewise.
+       * config/mn10300/mn10300.h (CPP_SPEC): Define `__AM33__=2' and
+       `__AM33_2__' when `-mam33-2' is given.
+       (TARGET_AM33_2): Define.
+       (TARGET_SWITCHES): Adjust.
+       * config/mn10300/mn10300.c (asm_file_start): Print `.am33_2'
+       when appropriate.
+
 2003-07-09  Matt Kraai  <kraai@alumni.cmu.edu>
 
        * doc/install.texi: Add missing @.
index df5d35fb7701069134a012ef1098b965569c235c..bb14b4c902383425a6e133e0d458945591b20cbc 100644 (file)
@@ -82,7 +82,9 @@ mn10300_file_start ()
 {
   default_file_start ();
 
-  if (TARGET_AM33)
+  if (TARGET_AM33_2)
+    fprintf (asm_out_file, "\t.am33_2\n");
+  else if (TARGET_AM33)
     fprintf (asm_out_file, "\t.am33\n");
 }
 \f
@@ -100,6 +102,58 @@ print_operand (file, x, code)
     {
       case 'b':
       case 'B':
+       if (cc_status.mdep.fpCC)
+         {
+           switch (code == 'b' ? GET_CODE (x)
+                   : reverse_condition_maybe_unordered (GET_CODE (x)))
+             {
+             case NE:
+               fprintf (file, "ne");
+               break;
+             case EQ:
+               fprintf (file, "eq");
+               break;
+             case GE:
+               fprintf (file, "ge");
+               break;
+             case GT:
+               fprintf (file, "gt");
+               break;
+             case LE:
+               fprintf (file, "le");
+               break;
+             case LT:
+               fprintf (file, "lt");
+               break;
+             case ORDERED:
+               fprintf (file, "lge");
+               break;
+             case UNORDERED:
+               fprintf (file, "uo");
+               break;
+             case LTGT:
+               fprintf (file, "lg");
+               break;
+             case UNEQ:
+               fprintf (file, "ue");
+               break;
+             case UNGE:
+               fprintf (file, "uge");
+               break;
+             case UNGT:
+               fprintf (file, "ug");
+               break;
+             case UNLE:
+               fprintf (file, "ule");
+               break;
+             case UNLT:
+               fprintf (file, "ul");
+               break;
+             default:
+               abort ();
+             }
+           break;
+         }
        /* These are normal and reversed branches.  */
        switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
          {
@@ -151,6 +205,24 @@ print_operand (file, x, code)
          print_operand (file, x, 0);
        break;
      
+      case 'D':
+       switch (GET_CODE (x))
+         {
+         case MEM:
+           fputc ('(', file);
+           output_address (XEXP (x, 0));
+           fputc (')', file);
+           break;
+
+         case REG:
+           fprintf (file, "fd%d", REGNO (x) - 18);
+           break;
+
+         default:
+           abort ();
+         }
+       break;
+
       /* These are the least significant word in a 64bit value.  */
       case 'L':
        switch (GET_CODE (x))
@@ -388,6 +460,22 @@ print_operand_address (file, addr)
     }
 }
 
+/* Count the number of FP registers that have to be saved.  */
+static int
+fp_regs_to_save ()
+{
+  int i, n = 0;
+
+  if (! TARGET_AM33_2)
+    return 0;
+
+  for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
+    if (regs_ever_live[i] && ! call_used_regs[i])
+      ++n;
+
+  return n;
+}
+
 /* Print a set of registers in the format required by "movm" and "ret".
    Register K is saved if bit K of MASK is set.  The data and address
    registers can be stored individually, but the extended registers cannot.
@@ -446,6 +534,7 @@ can_use_return_insn ()
          && !regs_ever_live[15]
          && !regs_ever_live[16]
          && !regs_ever_live[17]
+         && fp_regs_to_save () == 0
          && !frame_pointer_needed);
 }
 
@@ -460,7 +549,7 @@ mn10300_get_live_callee_saved_regs ()
   int i;
 
   mask = 0;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+  for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
     if (regs_ever_live[i] && ! call_used_regs[i])
       mask |= (1 << i);
   if ((mask & 0x3c000) != 0)
@@ -501,7 +590,7 @@ mn10300_gen_multiple_store (mask)
 
       /* Count how many registers need to be saved. */
       count = 0;
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
        if ((mask & (1 << i)) != 0)
          count += 1;
 
@@ -519,7 +608,7 @@ mn10300_gen_multiple_store (mask)
 
       /* Create each store. */
       pari = 1;
-      for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+      for (i = LAST_EXTENDED_REGNUM; i >= 0; i--)
        if ((mask & (1 << i)) != 0)
          {
            rtx address = gen_rtx_PLUS (SImode,
@@ -549,6 +638,240 @@ expand_prologue ()
   /* If we use any of the callee-saved registers, save them now. */
   mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
 
+  if (TARGET_AM33_2 && fp_regs_to_save ())
+    {
+      int num_regs_to_save = fp_regs_to_save (), i;
+      HOST_WIDE_INT xsize;
+      enum { save_sp_merge,
+            save_sp_no_merge,
+            save_sp_partial_merge,
+            save_a0_merge,
+            save_a0_no_merge } strategy;
+      unsigned int strategy_size = (unsigned)-1, this_strategy_size;
+      rtx reg;
+      rtx insn;
+
+      /* We have several different strategies to save FP registers.
+        We can store them using SP offsets, which is beneficial if
+        there are just a few registers to save, or we can use `a0' in
+        post-increment mode (`a0' is the only call-clobbered address
+        register that is never used to pass information to a
+        function).  Furthermore, if we don't need a frame pointer, we
+        can merge the two SP adds into a single one, but this isn't
+        always beneficial; sometimes we can just split the two adds
+        so that we don't exceed a 16-bit constant size.  The code
+        below will select which strategy to use, so as to generate
+        smallest code.  Ties are broken in favor or shorter sequences
+        (in terms of number of instructions).  */
+
+#define SIZE_ADD_AX(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
+                       : (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 2)
+#define SIZE_ADD_SP(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
+                       : (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 3)
+#define SIZE_FMOV_LIMIT(S,N,L,SIZE1,SIZE2,ELSE) \
+  (((S) >= (L)) ? (SIZE1) * (N) \
+   : ((S) + 4 * (N) >= (L)) ? (((L) - (S)) / 4 * (SIZE2) \
+                              + ((S) + 4 * (N) - (L)) / 4 * (SIZE1)) \
+   : (ELSE))
+#define SIZE_FMOV_SP_(S,N) \
+  (SIZE_FMOV_LIMIT ((S), (N), (1 << 24), 7, 6, \
+                   SIZE_FMOV_LIMIT ((S), (N), (1 << 8), 6, 4, \
+                                   (S) ? 4 * (N) : 3 + 4 * ((N) - 1))))
+#define SIZE_FMOV_SP(S,N) (SIZE_FMOV_SP_ ((unsigned HOST_WIDE_INT)(S), (N)))
+
+      /* Consider alternative save_sp_merge only if we don't need the
+        frame pointer and size is non-zero.  */
+      if (! frame_pointer_needed && size)
+       {
+         /* Insn: add -(size + 4 * num_regs_to_save), sp.  */
+         this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
+         /* Insn: fmov fs#, (##, sp), for each fs# to be saved.  */
+         this_strategy_size += SIZE_FMOV_SP (size, num_regs_to_save);
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = save_sp_merge;
+             strategy_size = this_strategy_size;
+           }
+       }
+
+      /* Consider alternative save_sp_no_merge unconditionally.  */
+      /* Insn: add -4 * num_regs_to_save, sp.  */
+      this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
+      /* Insn: fmov fs#, (##, sp), for each fs# to be saved.  */
+      this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
+      if (size)
+       {
+         /* Insn: add -size, sp.  */
+         this_strategy_size += SIZE_ADD_SP (-size);
+       }
+
+      if (this_strategy_size < strategy_size)
+       {
+         strategy = save_sp_no_merge;
+         strategy_size = this_strategy_size;
+       }
+
+      /* Consider alternative save_sp_partial_merge only if we don't
+        need a frame pointer and size is reasonably large.  */
+      if (! frame_pointer_needed && size + 4 * num_regs_to_save > 128)
+       {
+         /* Insn: add -128, sp.  */
+         this_strategy_size = SIZE_ADD_SP (-128);
+         /* Insn: fmov fs#, (##, sp), for each fs# to be saved.  */
+         this_strategy_size += SIZE_FMOV_SP (128 - 4 * num_regs_to_save,
+                                             num_regs_to_save);
+         if (size)
+           {
+             /* Insn: add 128-size, sp.  */
+             this_strategy_size += SIZE_ADD_SP (128 - size);
+           }
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = save_sp_partial_merge;
+             strategy_size = this_strategy_size;
+           }
+       }
+
+      /* Consider alternative save_a0_merge only if we don't need a
+        frame pointer, size is non-zero and the user hasn't
+        changed the calling conventions of a0.  */
+      if (! frame_pointer_needed && size
+         && call_used_regs[FIRST_ADDRESS_REGNUM]
+         && ! fixed_regs[FIRST_ADDRESS_REGNUM])
+       {
+         /* Insn: add -(size + 4 * num_regs_to_save), sp.  */
+         this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
+         /* Insn: mov sp, a0.  */
+         this_strategy_size++;
+         if (size)
+           {
+             /* Insn: add size, a0.  */
+             this_strategy_size += SIZE_ADD_AX (size);
+           }
+         /* Insn: fmov fs#, (a0+), for each fs# to be saved.  */
+         this_strategy_size += 3 * num_regs_to_save;
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = save_a0_merge;
+             strategy_size = this_strategy_size;
+           }
+       }
+
+      /* Consider alternative save_a0_no_merge if the user hasn't
+        changed the calling conventions of a0. */
+      if (call_used_regs[FIRST_ADDRESS_REGNUM]
+         && ! fixed_regs[FIRST_ADDRESS_REGNUM])
+       {
+         /* Insn: add -4 * num_regs_to_save, sp.  */
+         this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
+         /* Insn: mov sp, a0.  */
+         this_strategy_size++;
+         /* Insn: fmov fs#, (a0+), for each fs# to be saved.  */
+         this_strategy_size += 3 * num_regs_to_save;
+         if (size)
+           {
+             /* Insn: add -size, sp.  */
+             this_strategy_size += SIZE_ADD_SP (-size);
+           }
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = save_a0_no_merge;
+             strategy_size = this_strategy_size;
+           }
+       }
+
+      /* Emit the initial SP add, common to all strategies.  */
+      switch (strategy)
+       {
+       case save_sp_no_merge:
+       case save_a0_no_merge:
+         emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                stack_pointer_rtx,
+                                GEN_INT (-4 * num_regs_to_save)));
+         xsize = 0;
+         break;
+
+       case save_sp_partial_merge:
+         emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                stack_pointer_rtx,
+                                GEN_INT (-128)));
+         xsize = 128 - 4 * num_regs_to_save;
+         size -= xsize;
+         break;
+
+       case save_sp_merge:
+       case save_a0_merge:
+         emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                stack_pointer_rtx,
+                                GEN_INT (-(size + 4 * num_regs_to_save))));
+         /* We'll have to adjust FP register saves according to the
+            frame size. */
+         xsize = size;
+         /* Since we've already created the stack frame, don't do it
+            again at the end of the function. */
+         size = 0;
+         break;
+
+       default:
+         abort ();
+       }
+         
+      /* Now prepare register a0, if we have decided to use it.  */
+      switch (strategy)
+       {
+       case save_sp_merge:
+       case save_sp_no_merge:
+       case save_sp_partial_merge:
+         reg = 0;
+         break;
+
+       case save_a0_merge:
+       case save_a0_no_merge:
+         reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM);
+         emit_insn (gen_movsi (reg, stack_pointer_rtx));
+         if (xsize)
+           emit_insn (gen_addsi3 (reg, reg, GEN_INT (xsize)));
+         reg = gen_rtx_POST_INC (SImode, reg);
+         break;
+         
+       default:
+         abort ();
+       }
+      
+      /* Now actually save the FP registers.  */
+      for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
+       if (regs_ever_live[i] && ! call_used_regs[i])
+         {
+           rtx addr;
+
+           if (reg)
+             addr = reg;
+           else
+             {
+               /* If we aren't using `a0', use an SP offset.  */
+               if (xsize)
+                 {
+                   addr = gen_rtx_PLUS (SImode,
+                                        stack_pointer_rtx,
+                                        GEN_INT (xsize));
+                 }
+               else
+                 addr = stack_pointer_rtx;
+               
+               xsize += 4;
+             }
+
+           insn = emit_insn (gen_movsi (gen_rtx_MEM (SImode, addr),
+                                        gen_rtx_REG (SImode, i)));
+
+           RTX_FRAME_RELATED_P (insn) = 1;
+         }
+    }
+
   /* Now put the frame pointer into the frame pointer register.  */
   if (frame_pointer_needed)
     emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
@@ -569,6 +892,193 @@ expand_epilogue ()
   size = get_frame_size () + current_function_outgoing_args_size;
   size += (current_function_outgoing_args_size ? 4 : 0);
 
+  if (TARGET_AM33_2 && fp_regs_to_save ())
+    {
+      int num_regs_to_save = fp_regs_to_save (), i;
+      rtx reg = 0;
+
+      /* We have several options to restore FP registers.  We could
+        load them from SP offsets, but, if there are enough FP
+        registers to restore, we win if we use a post-increment
+        addressing mode.  */
+
+      /* If we have a frame pointer, it's the best option, because we
+        already know it has the value we want.  */
+      if (frame_pointer_needed)
+       reg = gen_rtx_REG (SImode, FRAME_POINTER_REGNUM);
+      /* Otherwise, we may use `a1', since it's call-clobbered and
+        it's never used for return values.  But only do so if it's
+        smaller than using SP offsets.  */
+      else
+       {
+         enum { restore_sp_post_adjust,
+                restore_sp_pre_adjust,
+                restore_sp_partial_adjust,
+                restore_a1 } strategy;
+         unsigned int this_strategy_size, strategy_size = (unsigned)-1;
+
+         /* Consider using sp offsets before adjusting sp.  */
+         /* Insn: fmov (##,sp),fs#, for each fs# to be restored.  */
+         this_strategy_size = SIZE_FMOV_SP (size, num_regs_to_save);
+         /* If size is too large, we'll have to adjust SP with an
+                add.  */
+         if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
+           {
+             /* Insn: add size + 4 * num_regs_to_save, sp.  */
+             this_strategy_size += SIZE_ADD_SP (size + 4 * num_regs_to_save);
+           }
+         /* If we don't have to restore any non-FP registers,
+                we'll be able to save one byte by using rets.  */
+         if (! REG_SAVE_BYTES)
+           this_strategy_size--;
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = restore_sp_post_adjust;
+             strategy_size = this_strategy_size;
+           }
+
+         /* Consider using sp offsets after adjusting sp.  */
+         /* Insn: add size, sp.  */
+         this_strategy_size = SIZE_ADD_SP (size);
+         /* Insn: fmov (##,sp),fs#, for each fs# to be restored.  */
+         this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
+         /* We're going to use ret to release the FP registers
+                save area, so, no savings. */
+
+         if (this_strategy_size < strategy_size)
+           {
+             strategy = restore_sp_pre_adjust;
+             strategy_size = this_strategy_size;
+           }
+
+         /* Consider using sp offsets after partially adjusting sp.
+            When size is close to 32Kb, we may be able to adjust SP
+            with an imm16 add instruction while still using fmov
+            (d8,sp).  */
+         if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
+           {
+             /* Insn: add size + 4 * num_regs_to_save
+                               + REG_SAVE_BYTES - 252,sp.  */
+             this_strategy_size = SIZE_ADD_SP (size + 4 * num_regs_to_save
+                                               + REG_SAVE_BYTES - 252);
+             /* Insn: fmov (##,sp),fs#, fo each fs# to be restored.  */
+             this_strategy_size += SIZE_FMOV_SP (252 - REG_SAVE_BYTES
+                                                 - 4 * num_regs_to_save,
+                                                 num_regs_to_save);
+             /* We're going to use ret to release the FP registers
+                save area, so, no savings. */
+
+             if (this_strategy_size < strategy_size)
+               {
+                 strategy = restore_sp_partial_adjust;
+                 strategy_size = this_strategy_size;
+               }
+           }
+
+         /* Consider using a1 in post-increment mode, as long as the
+            user hasn't changed the calling conventions of a1.  */
+         if (call_used_regs[FIRST_ADDRESS_REGNUM+1]
+             && ! fixed_regs[FIRST_ADDRESS_REGNUM+1])
+           {
+             /* Insn: mov sp,a1.  */
+             this_strategy_size = 1;
+             if (size)
+               {
+                 /* Insn: add size,a1.  */
+                 this_strategy_size += SIZE_ADD_AX (size);
+               }
+             /* Insn: fmov (a1+),fs#, for each fs# to be restored.  */
+             this_strategy_size += 3 * num_regs_to_save;
+             /* If size is large enough, we may be able to save a
+                couple of bytes.  */
+             if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
+               {
+                 /* Insn: mov a1,sp.  */
+                 this_strategy_size += 2;
+               }
+             /* If we don't have to restore any non-FP registers,
+                we'll be able to save one byte by using rets.  */
+             if (! REG_SAVE_BYTES)
+               this_strategy_size--;
+
+             if (this_strategy_size < strategy_size)
+               {
+                 strategy = restore_a1;
+                 strategy_size = this_strategy_size;
+               }
+           }
+
+         switch (strategy)
+           {
+           case restore_sp_post_adjust:
+             break;
+
+           case restore_sp_pre_adjust:
+             emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                    stack_pointer_rtx,
+                                    GEN_INT (size)));
+             size = 0;
+             break;
+
+           case restore_sp_partial_adjust:
+             emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                    stack_pointer_rtx,
+                                    GEN_INT (size + 4 * num_regs_to_save
+                                             + REG_SAVE_BYTES - 252)));
+             size = 252 - REG_SAVE_BYTES - 4 * num_regs_to_save;
+             break;
+             
+           case restore_a1:
+             reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM + 1);
+             emit_insn (gen_movsi (reg, stack_pointer_rtx));
+             if (size)
+               emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
+             break;
+
+           default:
+             abort ();
+           }
+       }
+
+      /* Adjust the selected register, if any, for post-increment.  */
+      if (reg)
+       reg = gen_rtx_POST_INC (SImode, reg);
+
+      for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
+       if (regs_ever_live[i] && ! call_used_regs[i])
+         {
+           rtx addr;
+           
+           if (reg)
+             addr = reg;
+           else if (size)
+             {
+               /* If we aren't using a post-increment register, use an
+                  SP offset. */
+               addr = gen_rtx_PLUS (SImode,
+                                    stack_pointer_rtx,
+                                    GEN_INT (size));
+             }
+           else
+             addr = stack_pointer_rtx;
+
+           size += 4;
+
+           emit_insn (gen_movsi (gen_rtx_REG (SImode, i),
+                                 gen_rtx_MEM (SImode, addr)));
+         }
+
+      /* If we were using the restore_a1 strategy and the number of
+        bytes to be released won't fit in the `ret' byte, copy `a1'
+        to `sp', to avoid having to use `add' to adjust it.  */
+      if (! frame_pointer_needed && reg && size + REG_SAVE_BYTES > 255)
+       {
+         emit_move_insn (stack_pointer_rtx, XEXP (reg, 0));
+         size = 0;
+       }
+    }
+
   /* Maybe cut back the stack, except for the register save area.
 
      If the frame pointer exists, then use the frame pointer to
@@ -649,6 +1159,9 @@ notice_update_cc (body, insn)
       /* The insn is a compare instruction.  */
       CC_STATUS_INIT;
       cc_status.value1 = SET_SRC (body);
+      if (GET_CODE (cc_status.value1) == COMPARE
+         && GET_MODE (XEXP (cc_status.value1, 0)) == SFmode)
+       cc_status.mdep.fpCC = 1;
       break;
 
     case CC_INVERT:
@@ -714,7 +1227,7 @@ store_multiple_operation (op, mode)
 
      LAST keeps track of the smallest-numbered register stored so far.
      MASK is the set of stored registers. */
-  last = FIRST_PSEUDO_REGISTER;
+  last = LAST_EXTENDED_REGNUM + 1;
   mask = 0;
   for (i = 1; i < count; i++)
     {
@@ -810,6 +1323,14 @@ secondary_reload_class (class, mode, in)
       return DATA_REGS;
     }
  
+  if (TARGET_AM33_2 && class == FP_REGS
+      && GET_CODE (in) == MEM && ! OK_FOR_Q (in))
+    {
+      if (TARGET_AM33)
+       return DATA_OR_EXTENDED_REGS;
+      return DATA_REGS;
+    }
+
   /* Otherwise assume no secondary reloads are needed.  */
   return NO_REGS;
 }
@@ -826,8 +1347,10 @@ initial_offset (from, to)
          || regs_ever_live[6] || regs_ever_live[7]
          || regs_ever_live[14] || regs_ever_live[15]
          || regs_ever_live[16] || regs_ever_live[17]
+         || fp_regs_to_save ()
          || frame_pointer_needed)
-       return REG_SAVE_BYTES;
+       return REG_SAVE_BYTES
+         + 4 * fp_regs_to_save ();
       else
        return 0;
     }
@@ -841,8 +1364,10 @@ initial_offset (from, to)
          || regs_ever_live[6] || regs_ever_live[7]
          || regs_ever_live[14] || regs_ever_live[15]
          || regs_ever_live[16] || regs_ever_live[17]
+         || fp_regs_to_save ()
          || frame_pointer_needed)
        return (get_frame_size () + REG_SAVE_BYTES
+               + 4 * fp_regs_to_save ()
                + (current_function_outgoing_args_size
                   ? current_function_outgoing_args_size + 4 : 0)); 
       else
@@ -1155,6 +1680,15 @@ const_8bit_operand (op, mode)
          && INTVAL (op) < 256);
 }
 
+/* Return true if the operand is the 1.0f constant.  */
+int
+const_1f_operand (op, mode)
+    register rtx op;
+    enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return (op == CONST1_RTX (SFmode));
+}
+
 /* Similarly, but when using a zero_extract pattern for a btst where
    the source operand might end up in memory.  */
 int
@@ -1271,6 +1805,7 @@ mn10300_address_cost_1 (x, unsig)
 
        case DATA_REGS:
        case EXTENDED_REGS:
+       case FP_REGS:
          return 3;
 
        case NO_REGS:
index cae8f2a3f819e4cb749b6f0d1212821c0cf6ec09..75d4183af74a44c8d0c4747cf7d0e4e7dd5eb267 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler.
    Matsushita MN10300 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA.  */
     }                                          \
   while (0)
 
-#define CPP_SPEC "%{mam33:-D__AM33__}"
+#define CPP_SPEC "%{mam33:-D__AM33__} %{mam33-2:-D__AM33__=2 -D__AM33_2__}"
 
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
@@ -60,6 +60,9 @@ extern int target_flags;
 /* Generate code for the AM33 processor.  */
 #define TARGET_AM33                    (target_flags & 0x2)
 
+/* Generate code for the AM33/2.0 processor.  */
+#define TARGET_AM33_2                  (target_flags & 0x4)
+
 #define TARGET_SWITCHES  \
   {{ "mult-bug",       0x1,  N_("Work around hardware multiply bug")}, \
    { "no-mult-bug",    -0x1, N_("Do not work around hardware multiply bug")},\
@@ -67,6 +70,9 @@ extern int target_flags;
    { "am33",           -(0x1), ""},\
    { "no-am33",        -0x2, ""},      \
    { "no-crt0",                0,    N_("No default crt0.o") }, \
+   { "am33-2",         0x6,  N_("Target the AM33/2.0 processor")},   \
+   { "am33-2",         -(0x1), ""},\
+   { "no-am33-2",      -0x4,   ""},  \
    { "relax",          0,    N_("Enable linker relaxations") }, \
    { "", TARGET_DEFAULT, NULL}}
 
@@ -131,7 +137,7 @@ extern int target_flags;
    All registers that the compiler knows about must be given numbers,
    even those that are not normally considered general registers.  */
 
-#define FIRST_PSEUDO_REGISTER 18
+#define FIRST_PSEUDO_REGISTER 50
 
 /* Specify machine-specific register numbers.  */
 #define FIRST_DATA_REGNUM 0
@@ -140,6 +146,8 @@ extern int target_flags;
 #define LAST_ADDRESS_REGNUM 8
 #define FIRST_EXTENDED_REGNUM 10
 #define LAST_EXTENDED_REGNUM 17
+#define FIRST_FP_REGNUM 18
+#define LAST_FP_REGNUM 49
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -162,7 +170,10 @@ extern int target_flags;
    and are not available for the register allocator.  */
 
 #define FIXED_REGISTERS \
-  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
+  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 \
+  , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+  , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+  }
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -173,10 +184,16 @@ extern int target_flags;
    like.  */
 
 #define CALL_USED_REGISTERS \
-  { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}
+  { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 \
+  , 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+  , 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
+  }
 
 #define REG_ALLOC_ORDER \
-  { 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9}
+  { 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9 \
+  , 42, 43, 44, 45, 46, 47, 48, 49, 34, 35, 36, 37, 38, 39, 40, 41 \
+  , 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 \
+  }
 
 #define CONDITIONAL_REGISTER_USAGE \
 {                                              \
@@ -188,6 +205,13 @@ extern int target_flags;
           i <= LAST_EXTENDED_REGNUM; i++)      \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
+  if (!TARGET_AM33_2)                          \
+    {                                          \
+      for (i = FIRST_FP_REGNUM;                        \
+          i <= LAST_FP_REGNUM;                 \
+           i++)                                \
+       fixed_regs[i] = call_used_regs[i] = 1;  \
+    }                                          \
 }
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
@@ -247,6 +271,7 @@ enum reg_class {
   DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS, 
   EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
   SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS, 
+  FP_REGS, FP_ACC_REGS,
   GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
 };
 
@@ -260,6 +285,7 @@ enum reg_class {
   "EXTENDED_REGS", \
   "DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \
   "SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \
+  "FP_REGS", "FP_ACC_REGS", \
   "GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
 
 /* Define which registers fit in which classes.
@@ -267,19 +293,21 @@ enum reg_class {
    of length N_REG_CLASSES.  */
 
 #define REG_CLASS_CONTENTS                     \
-{      {0},            /* No regs      */      \
-   {0x0000f},          /* DATA_REGS */         \
-   {0x001f0},          /* ADDRESS_REGS */      \
-   {0x00200},          /* SP_REGS */           \
-   {0x001ff},          /* DATA_OR_ADDRESS_REGS */\
-   {0x003f0},          /* SP_OR_ADDRESS_REGS */\
-   {0x3fc00},          /* EXTENDED_REGS */     \
-   {0x3fc0f},          /* DATA_OR_EXTENDED_REGS */     \
-   {0x3fdf0},          /* ADDRESS_OR_EXTENDED_REGS */  \
-   {0x3fe00},          /* SP_OR_EXTENDED_REGS */       \
-   {0x3fff0},          /* SP_OR_ADDRESS_OR_EXTENDED_REGS */    \
-   {0x3fdff},          /* GENERAL_REGS */      \
-   {0x3ffff},          /* ALL_REGS     */      \
+{  { 0,        0 },            /* No regs      */      \
+ { 0x0000f, 0 },       /* DATA_REGS */         \
+ { 0x001f0, 0 },       /* ADDRESS_REGS */      \
+ { 0x00200, 0 },       /* SP_REGS */           \
+ { 0x001ff, 0 },       /* DATA_OR_ADDRESS_REGS */\
+ { 0x003f0, 0 },       /* SP_OR_ADDRESS_REGS */\
+ { 0x3fc00, 0 },       /* EXTENDED_REGS */     \
+ { 0x3fc0f, 0 },       /* DATA_OR_EXTENDED_REGS */     \
+ { 0x3fdf0, 0 },       /* ADDRESS_OR_EXTENDED_REGS */  \
+ { 0x3fe00, 0 },       /* SP_OR_EXTENDED_REGS */       \
+ { 0x3fff0, 0 },       /* SP_OR_ADDRESS_OR_EXTENDED_REGS */    \
+ { 0xfffc0000, 0x3ffff }, /* FP_REGS */                \
+ { 0x03fc0000, 0 },    /* FP_ACC_REGS */       \
+ { 0x3fdff, 0 },       /* GENERAL_REGS */      \
+ { 0xffffffff, 0x3ffff } /* ALL_REGS   */      \
 }
 
 /* The same information, inverted:
@@ -292,6 +320,7 @@ enum reg_class {
    (REGNO) <= LAST_ADDRESS_REGNUM ? ADDRESS_REGS : \
    (REGNO) == STACK_POINTER_REGNUM ? SP_REGS : \
    (REGNO) <= LAST_EXTENDED_REGNUM ? EXTENDED_REGS : \
+   (REGNO) <= LAST_FP_REGNUM ? FP_REGS : \
    NO_REGS)
 
 /* The class value for index registers, and the one for base regs.  */
@@ -306,6 +335,9 @@ enum reg_class {
    (C) == 'y' ? SP_REGS : \
    ! TARGET_AM33 ? NO_REGS : \
    (C) == 'x' ? EXTENDED_REGS : \
+   ! TARGET_AM33_2 ? NO_REGS : \
+   (C) == 'f' ? FP_REGS : \
+   (C) == 'A' ? FP_ACC_REGS : \
    NO_REGS)
 
 /* Macros to check register numbers against specific register classes.  */
@@ -350,6 +382,8 @@ enum reg_class {
 #define REGNO_AM33_P(regno) \
   (REGNO_DATA_P ((regno)) || REGNO_ADDRESS_P ((regno)) \
    || REGNO_EXTENDED_P ((regno)))
+#define REGNO_FP_P(regno) \
+  REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM)
 
 #define REGNO_OK_FOR_BASE_P(regno) \
   (REGNO_SP_P ((regno)) \
@@ -397,6 +431,11 @@ enum reg_class {
 #define CLASS_MAX_NREGS(CLASS, MODE)   \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
+/* A class that contains registers which the compiler must always
+   access in a mode that is the same size as the mode in which it
+   loaded the register.  */
+#define CLASS_CANNOT_CHANGE_SIZE FP_REGS
+
 /* The letters I, J, K, L, M, N, O, P in a register constraint string
    can be used to stand for particular ranges of immediate operands.
    This macro defines what the ranges are.
@@ -669,6 +708,9 @@ struct cum_arg {int nbytes; };
 
 /* Extra constraints.  */
  
+#define OK_FOR_Q(OP) \
+   (GET_CODE (OP) == MEM && ! CONSTANT_ADDRESS_P (XEXP (OP, 0)))
+
 #define OK_FOR_R(OP) \
    (GET_CODE (OP) == MEM                                       \
     && GET_MODE (OP) == QImode                                 \
@@ -692,6 +734,7 @@ struct cum_arg {int nbytes; };
 
 #define EXTRA_CONSTRAINT(OP, C) \
  ((C) == 'R' ? OK_FOR_R (OP) \
+  : (C) == 'Q' ? OK_FOR_Q (OP) \
   : (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF \
   : (C) == 'T' ? OK_FOR_T (OP) \
   : 0)
@@ -814,6 +857,7 @@ struct cum_arg {int nbytes; };
    ! TARGET_AM33 ? 6 : \
    (CLASS1 == SP_REGS || CLASS2 == SP_REGS) ? 6 : \
    (CLASS1 == CLASS2 && CLASS1 == EXTENDED_REGS) ? 6 : \
+   (CLASS1 == FP_REGS || CLASS2 == FP_REGS) ? 6 : \
    (CLASS1 == EXTENDED_REGS || CLASS2 == EXTENDED_REGS) ? 4 : \
    4)
 
@@ -885,6 +929,10 @@ struct cum_arg {int nbytes; };
 #define REGISTER_NAMES \
 { "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp", \
   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" \
+, "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7" \
+, "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15" \
+, "fs16", "fs17", "fs18", "fs19", "fs20", "fs21", "fs22", "fs23" \
+, "fs24", "fs25", "fs26", "fs27", "fs28", "fs29", "fs30", "fs31" \
 }
 
 #define ADDITIONAL_REGISTER_NAMES \
@@ -892,6 +940,10 @@ struct cum_arg {int nbytes; };
   {"r12", 0}, {"r13", 1}, {"r14", 2}, {"r15", 3}, \
   {"e0", 10}, {"e1", 11}, {"e2", 12}, {"e3", 13}, \
   {"e4", 14}, {"e5", 15}, {"e6", 16}, {"e7", 17} \
+, {"fd0", 18}, {"fd2", 20}, {"fd4", 22}, {"fd6", 24} \
+, {"fd8", 26}, {"fd10", 28}, {"fd12", 30}, {"fd14", 32} \
+, {"fd16", 34}, {"fd18", 36}, {"fd20", 38}, {"fd22", 40} \
+, {"fd24", 42}, {"fd26", 44}, {"fd28", 46}, {"fd30", 48} \
 }
 
 /* Print an instruction operand X on file FILE.
@@ -994,3 +1046,15 @@ struct cum_arg {int nbytes; };
 
 #define FILE_ASM_OP "\t.file\n"
 
+#define PREDICATE_CODES \
+  {"const_1f_operand", {CONST_INT, CONST_DOUBLE}},
+
+typedef struct mn10300_cc_status_mdep
+  {
+    int fpCC;
+  }
+cc_status_mdep;
+
+#define CC_STATUS_MDEP cc_status_mdep
+
+#define CC_STATUS_MDEP_INIT (cc_status.mdep.fpCC = 0)
index f889aa61cdd81450c381c0371630b9d23fd26b79..a615f6b97eaf392f094b396e828e4d1928b79c03 100644 (file)
@@ -57,8 +57,8 @@
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m")
-       (match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a")
+       (match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa,d*xa*f,*f"))]
   "TARGET_AM33
    && (register_operand (operands[0], QImode)
        || register_operand (operands[1], QImode))"
     case 3:
     case 4:
       return \"movbu %1,%0\";
+    case 5:
+    case 6:
+      return \"fmov %1,%0\";
     default:
       abort ();
     }
 }"
-  [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")])
+  [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m")
 }")
 
 (define_insn ""
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m")
-       (match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a")
+       (match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a,d*x*a*f,*f"))]
   "TARGET_AM33
    && (register_operand (operands[0], HImode)
        || register_operand (operands[1], HImode))"
     case 3:
     case 4:
       return \"movhu %1,%0\";
+    case 5:
+    case 6:
+      return \"fmov %1,%0\";
     default:
       abort ();
     }
 }"
-  [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")])
+  [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m")
 
 (define_insn ""
   [(set (match_operand:SI 0 "nonimmediate_operand"
-                               "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y")
+                               "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y,*f,*f,dxaQ")
        (match_operand:SI 1 "general_operand"
-                               "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR"))]
+                               "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR,0,dxaQi*f,*f"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)"
   "*
            return \"movu %1,%0\";
        }
       return \"mov %1,%0\";
+    case 14:
+      return \"nop\";
+    case 15:
+    case 16:
+      return \"fmov %1,%0\";
     default:
       abort ();
     }
 }"
-  [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
+  [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")])
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
 }")
 
 (define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=dx,ax,dx,a,daxm,dax")
-       (match_operand:SF 1 "general_operand" "0,0,G,G,dax,daxFm"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,dx,ax,dx,a,f,dxaQ,daxm,dax")
+       (match_operand:SF 1 "general_operand" "0,0,0,G,G,fdxaQF,f,dax,daxFm"))]
   "register_operand (operands[0], SFmode)
    || register_operand (operands[1], SFmode)"
   "*
     {
     case 0:
     case 1:
-      return \"nop\";
     case 2:
-      return \"clr %0\";
+      return \"nop\";
     case 3:
-    case 4:
+      return \"clr %0\";
+    /* case 4: below */
     case 5:
+    case 6:
+      return \"fmov %1, %0\";
+    case 4:
+    case 7:
+    case 8:
       if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
          && GET_CODE (operands[1]) == CONST_INT)
        {
       abort ();
     }
 }"
-  [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")])
+  [(set_attr "cc" "none,none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
 
 (define_expand "movdi"
   [(set (match_operand:DI 0 "general_operand" "")
 
 (define_insn ""
   [(set (match_operand:DI 0 "nonimmediate_operand"
-                               "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
+                               "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,*f,*f,*f,dxa,*f,Q")
        (match_operand:DI 1 "general_operand"
-                               "0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim"))]
+                               "0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim,0,*f,dxai,*f,Q,*f"))]
   "register_operand (operands[0], DImode)
    || register_operand (operands[1], DImode)"
   "*
              output_asm_insn (\"mov %H1,%H0\", operands);
            return \"\";
          }
+      case 12:
+        return \"nop\";
+      case 13:
+      case 14:
+      case 15:
+        return \"fmov %L1, %L0\;fmov %H1, %H0\";
+      case 16:
+       if (GET_CODE (operands[1]) == MEM
+           && GET_CODE (XEXP (operands[1], 0)) == CONST_INT
+           && (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
+         return \"fmov %D1, %D0\";
+       else
+          return \"fmov %L1, %L0\;fmov %H1, %H0\";
+      case 17:
+       if (GET_CODE (operands[0]) == MEM
+           && GET_CODE (XEXP (operands[0], 0)) == CONST_INT
+           && (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
+         return \"fmov %D1, %D0\";
+       else
+          return \"fmov %L1, %L0\;fmov %H1, %H0\";
     default:
       abort ();
     }
   [(set (attr "cc")
        (cond
         [
-        (lt (symbol_ref "which_alternative") (const_int 2)
-            ) (const_string "none")
+        (ior (lt (symbol_ref "which_alternative") (const_int 2))
+             (eq (symbol_ref "which_alternative") (const_int 12))
+             ) (const_string "none")
         (eq (symbol_ref "which_alternative") (const_int 2)
             ) (const_string "clobber")
         (eq (symbol_ref "which_alternative") (const_int 3)
 
 (define_insn ""
   [(set (match_operand:DF 0 "nonimmediate_operand"
-                               "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
+                               "=f,dx,ax,dx,f,f,dxa,f,Q,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
        (match_operand:DF 1 "general_operand"
-                               "0,0,G,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
+                               "0,0,0,G,f,dxaF,f,Q,f,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
   "register_operand (operands[0], DFmode)
    || register_operand (operands[1], DFmode)"
   "*
     {
       case 0:
       case 1:
+      case 2:
        return \"nop\";
 
-      case 2:
+      case 3:
        return \"clr %L0\;clr %H0\";
 
-      case 3:
-        if (rtx_equal_p (operands[0], operands[1]))
-          return \"sub %L1,%L0\;mov %L0,%H0\";
-        else
-          return \"mov %1,%L0\;mov %L0,%H0\";
       case 4:
       case 5:
       case 6:
+        return \"fmov %L1, %L0\;fmov %H1, %H0\";
+
       case 7:
+       if (GET_CODE (operands[1]) == MEM
+           && GET_CODE (XEXP (operands[1], 0)) == CONST_INT
+           && (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
+         return \"fmov %D1, %D0\";
+       else
+          return \"fmov %L1, %L0\;fmov %H1, %H0\";
+
       case 8:
+       if (GET_CODE (operands[0]) == MEM
+           && GET_CODE (XEXP (operands[0], 0)) == CONST_INT
+           && (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
+         return \"fmov %D1, %D0\";
+       else
+          return \"fmov %L1, %L0\;fmov %H1, %H0\";
+
       case 9:
+        if (rtx_equal_p (operands[0], operands[1]))
+          return \"sub %L1,%L0\;mov %L0,%H0\";
+        else
+          return \"mov %1,%L0\;mov %L0,%H0\";
       case 10:
       case 11:
+      case 12:
+      case 13:
+      case 14:
+      case 15:
+      case 16:
+      case 17:
        if (GET_CODE (operands[1]) == CONST_INT)
          {
            rtx low, high;
   [(set (attr "cc")
        (cond
         [
-        (lt (symbol_ref "which_alternative") (const_int 2)
+        (lt (symbol_ref "which_alternative") (const_int 3)
             ) (const_string "none")
-        (eq (symbol_ref "which_alternative") (const_int 2)
-            ) (const_string "clobber")
         (eq (symbol_ref "which_alternative") (const_int 3)
+            ) (const_string "clobber")
+        (eq (symbol_ref "which_alternative") (const_int 9)
             ) (if_then_else
                (ne (symbol_ref "rtx_equal_p (operands[0], operands[1])")
                    (const_int 0)) (const_string "clobber")
                    (const_string "none_0hit"))
-        (ior (eq (symbol_ref "which_alternative") (const_int 8))
-             (eq (symbol_ref "which_alternative") (const_int 9))
+        (ior (eq (symbol_ref "which_alternative") (const_int 14))
+             (eq (symbol_ref "which_alternative") (const_int 15))
              ) (if_then_else
                 (ne (symbol_ref "mn10300_wide_const_load_uses_clr
                                  (operands)")
   btst 0,d0
   cmp %1,%0"
   [(set_attr "cc" "compare,compare")])
+
+(define_insn "cmpsf"
+  [(set (cc0)
+       (compare (match_operand:SF 0 "register_operand" "f,f")
+                (match_operand:SF 1 "nonmemory_operand" "f,F")))]
+  "TARGET_AM33_2"
+  "fcmp %1,%0"
+  [(set_attr "cc" "compare,compare")])
 \f
 ;; ----------------------------------------------------------------------
 ;; ADD INSTRUCTIONS
   ""
   "*
 {
+  if (cc_status.mdep.fpCC)
+    return \"fb%b1 %0\";
   if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
       && (GET_CODE (operands[1]) == GT
          || GET_CODE (operands[1]) == GE
   ""
   "*
 {
+  if (cc_status.mdep.fpCC)
+    return \"fb%B1 %0\";
   if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
       && (GET_CODE (operands[1]) == GT
          || GET_CODE (operands[1]) == GE
   rtx result;
   rtx target;
 
+  if (TARGET_AM33_2)
+    {
+      emit_insn (gen_abssf2_am33_2 (operands[0], operands[1]));
+      DONE;
+    }
+
   target = operand_subword_force (operands[0], 0, SFmode);
   result = expand_binop (SImode, and_optab,
                         operand_subword_force (operands[1], 0, SFmode),
 }")
 
 
+(define_insn "abssf2_am33_2"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (abs:SF (match_operand:SF 1 "register_operand" "0,?f")))]
+  "TARGET_AM33_2"
+  "@
+   fabs %0
+   fabs %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
 (define_expand "negdf2"
   [(set (match_operand:DF 0 "register_operand" "")
         (neg:DF (match_operand:DF 1 "register_operand" "")))]
   rtx result;
   rtx target;
 
+  if (TARGET_AM33_2)
+    {
+      emit_insn (gen_negsf2_am33_2 (operands[0], operands[1]));
+      DONE;
+    }
+
   target = operand_subword_force (operands[0], 0, SFmode);
   result = expand_binop (SImode, xor_optab,
                         operand_subword_force (operands[1], 0, SFmode),
   DONE;
 }")
 
+(define_insn "negsf2_am33_2"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (neg:SF (match_operand:SF 1 "register_operand" "0,?f")))]
+  "TARGET_AM33_2"
+  "@
+   fneg %0
+   fneg %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_expand "sqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "")
+       (sqrt:SF (match_operand:SF 1 "register_operand" "")))]
+  "TARGET_AM33_2 && flag_unsafe_math_optimizations"
+  "
+{
+  rtx scratch = gen_reg_rtx (SFmode);
+  emit_insn (gen_rsqrtsf2 (scratch, operands[1], CONST1_RTX (SFmode)));
+  emit_insn (gen_divsf3 (operands[0], force_reg (SFmode, CONST1_RTX (SFmode)),
+                        scratch));
+  DONE;
+}")
+
+(define_insn "rsqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (div:SF (match_operand:SF 2 "const_1f_operand" "F,F")
+               (sqrt:SF (match_operand:SF 1 "register_operand" "0,?f"))))]
+  "TARGET_AM33_2"
+  "@
+   frsqrt %0
+   frsqrt %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "addsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (plus:SF (match_operand:SF 1 "register_operand" "%0,f")
+                (match_operand:SF 2 "general_operand" "f,?fF")))]
+  "TARGET_AM33_2"
+  "@
+   fadd %2, %0
+   fadd %2, %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "subsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (minus:SF (match_operand:SF 1 "register_operand" "0,f")
+                 (match_operand:SF 2 "general_operand" "f,?fF")))]
+  "TARGET_AM33_2"
+  "@
+   fsub %2, %0
+   fsub %2, %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "mulsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (mult:SF (match_operand:SF 1 "register_operand" "%0,f")
+                (match_operand:SF 2 "general_operand" "f,?fF")))]
+  "TARGET_AM33_2"
+  "@
+   fmul %2, %0
+   fmul %2, %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "divsf3"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (div:SF (match_operand:SF 1 "register_operand" "0,f")
+               (match_operand:SF 2 "general_operand" "f,?fF")))]
+  "TARGET_AM33_2"
+  "@
+   fdiv %2, %0
+   fdiv %2, %1, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "fmaddsf4"
+  [(set (match_operand:SF 0 "register_operand" "=A")
+       (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
+                         (match_operand:SF 2 "register_operand" "f"))
+                (match_operand:SF 3 "register_operand" "f")))]
+  "TARGET_AM33_2"
+  "fmadd %1, %2, %3, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "fmsubsf4"
+  [(set (match_operand:SF 0 "register_operand" "=A")
+       (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
+                          (match_operand:SF 2 "register_operand" "f"))
+                 (match_operand:SF 3 "register_operand" "f")))]
+  "TARGET_AM33_2"
+  "fmsub %1, %2, %3, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "fnmaddsf4"
+  [(set (match_operand:SF 0 "register_operand" "=A")
+       (minus:SF (match_operand:SF 3 "register_operand" "f")
+                 (mult:SF (match_operand:SF 1 "register_operand" "%f")
+                          (match_operand:SF 2 "register_operand" "f"))))]
+  "TARGET_AM33_2"
+  "fnmadd %1, %2, %3, %0"
+  [(set_attr "cc" "none_0hit")])
+
+(define_insn "fnmsubsf4"
+  [(set (match_operand:SF 0 "register_operand" "=A")
+       (minus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
+                                  (match_operand:SF 2 "register_operand" "f")))
+                 (match_operand:SF 3 "register_operand" "f")))]
+  "TARGET_AM33_2"
+  "fnmsub %1, %2, %3, %0"
+  [(set_attr "cc" "none_0hit")])
+
 
 ;; ----------------------------------------------------------------------
 ;; PROLOGUE/EPILOGUE
index 2e26e229acc62c2d9af28b08dcea6f26b4c858af..a35b2c5018539a60b3f0906378685d25d3932e93 100644 (file)
@@ -10,8 +10,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
        echo '#define FLOAT' > fp-bit.c
        cat $(srcdir)/config/fp-bit.c >> fp-bit.c
 
-MULTILIB_OPTIONS = mam33
-MULTILIB_DIRNAMES = am33
+MULTILIB_OPTIONS = mam33/mam33-2
+MULTILIB_DIRNAMES = am33 am33-2
 
 LIBGCC = stmp-multilib
 INSTALL_LIBGCC = install-multilib
index 79f57af8a7b55a6a0e955e6fb119e02c5071954b..bd49134720387e812ada38347268d982f3240056 100644 (file)
@@ -386,6 +386,7 @@ in the following sections.
 @emph{MN10300 Options}
 @gccoptlist{-mmult-bug  -mno-mult-bug @gol
 -mam33  -mno-am33 @gol
+-mam33-2  -mno-am33-2 @gol
 -mno-crt0  -mrelax}
 
 @emph{M32R/D Options}