mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.
authorJeffrey A Law <law@cygnus.com>
Thu, 2 Dec 1999 00:21:59 +0000 (00:21 +0000)
committerJeff Law <law@gcc.gnu.org>
Thu, 2 Dec 1999 00:21:59 +0000 (17:21 -0700)
        * mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.
        (asm_file_start): Emit .am33 into assembly file when compiling for
        the AM33.
        (print_operand_address): Handle POST_INC addresses.
        (can_use_return_insn, initial_offset): Check AM33 registers too.
        (expand_prologue): Check & save AM33 registers too.
        (expand_epilogue): Similarly.
        wise.
        (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Likewise.
        (INDEX_REG_CLASS, REG_CLASS_FROM_LETTER): Likewise.
        (REGNO_OK_FOR_INDEX_P, PREFERRED_RELOAD_CLASS): Likewise.
        (PREFERRED_OUTPUT_RELOAD_CLASS, LIMIT_RELOAD_CLASS): Likewise.
        (REGISTER_MOVE_COST, REGISTER_NAMES): Likewise.
        (HAVE_POST_INCREMENT): Define.
        (GO_IF_LEGITIMATE_ADDRESS): Allow POST_INC addresses for the AM33.
        (GO_IF_MODE_DEPENDENT_ADDRESS): POST_INC is a mode dependent address.
        * mn10300.md (movqi, movhi, addsi, subsi): Add AM33 variants.
        (mulsi, andsi, iorsi, xorsi, notsi): Likewise.
        (ashiftsi, lshiftrtsi, ashiftrtsi): Likewise.
        (zero_extend to SI from QI/HI): Likewise.
        (sign_extend to SI from QI/HI): Likewise.
        (mulsidi3, umulsidi3): New patterns for the AM33.
        (tstsi with zero extension from QI/HI): Add AM33 variants.
        (movsi, movsf, movdi, movdf): Generate efficient code for the AM33 too.
        (return_internal_regs, store_movm): Handle new AM33 registers.
        * t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Define.
        (LIBGCC, INSTALL_LIBGCC): Likewise.
        * invoke.texi: Document new flags.

From-SVN: r30748

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

index 5e8f864c8e404c1a712a434bb1708422e99e30b3..18c69171a1cde9bf79bcf9104d56c6fdef7d0f31 100644 (file)
@@ -1,3 +1,42 @@
+Wed Dec  1 16:51:22 1999  Jeffrey A Law  (law@cygnus.com)
+
+       * mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.
+       (asm_file_start): Emit .am33 into assembly file when compiling for
+       the AM33.
+       (print_operand_address): Handle POST_INC addresses.
+       (can_use_return_insn, initial_offset): Check AM33 registers too.
+       (expand_prologue): Check & save AM33 registers too.
+       (expand_epilogue): Similarly.
+       (secondary_reload_class): Handle AM33 specific secondary reloads.
+       (output_tst): Emit efficient code for the AM33 too.
+       * mn10300.h (CPP_SPEC, TARGET_AM33): Define.
+       (TARGET_SWITCHES): Add -mam33 switch.
+       (FIRST_PSEUDO_REGISTER): Handle new AM33 registers.
+       (FIXED_REGISTERS, CALL_USED_REGISTERS): Likewise.
+       (REG_ALLOC_ORDER, CONDITIONAL_REGISTER_USAGE): Likewise.
+       (HARD_REGNO_MODE_OK, MODES_TIEABLE_P): Likewise.
+       (enum reg_class, REG_CLASS_NAMES): Likewise.
+       (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Likewise.
+       (INDEX_REG_CLASS, REG_CLASS_FROM_LETTER): Likewise.
+       (REGNO_OK_FOR_INDEX_P, PREFERRED_RELOAD_CLASS): Likewise.
+       (PREFERRED_OUTPUT_RELOAD_CLASS, LIMIT_RELOAD_CLASS): Likewise.
+       (REGISTER_MOVE_COST, REGISTER_NAMES): Likewise.
+       (HAVE_POST_INCREMENT): Define.
+       (GO_IF_LEGITIMATE_ADDRESS): Allow POST_INC addresses for the AM33.
+       (GO_IF_MODE_DEPENDENT_ADDRESS): POST_INC is a mode dependent address.
+       * mn10300.md (movqi, movhi, addsi, subsi): Add AM33 variants.
+       (mulsi, andsi, iorsi, xorsi, notsi): Likewise.
+       (ashiftsi, lshiftrtsi, ashiftrtsi): Likewise.
+       (zero_extend to SI from QI/HI): Likewise.
+       (sign_extend to SI from QI/HI): Likewise.
+       (mulsidi3, umulsidi3): New patterns for the AM33.
+       (tstsi with zero extension from QI/HI): Add AM33 variants.
+       (movsi, movsf, movdi, movdf): Generate efficient code for the AM33 too.
+       (return_internal_regs, store_movm): Handle new AM33 registers.
+       * t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Define.
+       (LIBGCC, INSTALL_LIBGCC): Likewise.
+       * invoke.texi: Document new flags.
+
 Fri Nov 26 10:59:12 CET 1999  Jan Hubicka  <hubicka@freesoft.cz>
 
        * i386.md (addsi3_cc): Add "binary_operator_ok" to the condition.
index 80236d28177845ed7bc81d8ed92466ae003901ff..2c325bf17bed12717bc5941a8c354bf0ca613889 100644 (file)
@@ -42,8 +42,10 @@ Boston, MA 02111-1307, USA.  */
    speed standpoint, so we want to optimize this sooner or later.  */
 #define REG_SAVE_BYTES (4 * regs_ever_live[2] \
                        + 4 * regs_ever_live[3] \
-                       + 4 * regs_ever_live[6] \
-                       + 4 * regs_ever_live[7])
+                       + 4 * regs_ever_live[6] \
+                       + 4 * regs_ever_live[7] \
+                       + 16 * (regs_ever_live[14] || regs_ever_live[15] \
+                               || regs_ever_live[16] || regs_ever_live[17]))
 
 void
 asm_file_start (file)
@@ -54,6 +56,9 @@ asm_file_start (file)
     fprintf (file, "# -O%d\n", optimize);
   else
     fprintf (file, "\n\n");
+
+  if (TARGET_AM33)
+    fprintf (file, "\t.am33\n");
   output_file_directive (file, main_input_filename);
 }
 \f
@@ -312,6 +317,10 @@ print_operand_address (file, addr)
 {
   switch (GET_CODE (addr))
     {
+    case POST_INC:
+      print_operand_address (file, XEXP (addr, 0));
+      fputc ('+', file);
+      break;
     case REG:
       if (addr == stack_pointer_rtx)
        print_operand_address (file, gen_rtx_PLUS (SImode,
@@ -360,6 +369,10 @@ can_use_return_insn ()
          && !regs_ever_live[3]
          && !regs_ever_live[6]
          && !regs_ever_live[7]
+         && !regs_ever_live[14]
+         && !regs_ever_live[15]
+         && !regs_ever_live[16]
+         && !regs_ever_live[17]
          && !frame_pointer_needed);
 }
 
@@ -388,6 +401,8 @@ expand_prologue ()
      single two byte instruction.  */
   if (regs_ever_live[2] || regs_ever_live[3]
       || regs_ever_live[6] || regs_ever_live[7]
+      || regs_ever_live[14] || regs_ever_live[15]
+      || regs_ever_live[16] || regs_ever_live[17]
       || frame_pointer_needed)
     emit_insn (gen_store_movm ());
 
@@ -432,6 +447,8 @@ expand_epilogue ()
       size = 0;
     }
   else if ((regs_ever_live[2] || regs_ever_live[3]
+           || regs_ever_live[14] || regs_ever_live[15]
+           || regs_ever_live[16] || regs_ever_live[17]
            || regs_ever_live[6] || regs_ever_live[7])
           && size + REG_SAVE_BYTES > 255)
     {
@@ -448,6 +465,8 @@ expand_epilogue ()
      stack requirements and is faster.  */
   if (regs_ever_live[2] || regs_ever_live[3]
       || regs_ever_live[6] || regs_ever_live[7]
+      || regs_ever_live[14] || regs_ever_live[15]
+      || regs_ever_live[16] || regs_ever_live[17]
       || frame_pointer_needed)
     emit_jump_insn (gen_return_internal_regs (GEN_INT (size + REG_SAVE_BYTES)));
   else
@@ -554,6 +573,8 @@ secondary_reload_class (class, mode, in)
       && (mode == QImode || mode == HImode)
       && (class == ADDRESS_REGS || class == SP_REGS))
     {
+      if (TARGET_AM33)
+       return DATA_OR_EXTENDED_REGS;
       return DATA_REGS;
     }
 
@@ -562,6 +583,9 @@ secondary_reload_class (class, mode, in)
   if (class != SP_REGS
       && class != ADDRESS_REGS
       && class != SP_OR_ADDRESS_REGS
+      && class != SP_OR_EXTENDED_REGS
+      && class != ADDRESS_OR_EXTENDED_REGS
+      && class != SP_OR_ADDRESS_OR_EXTENDED_REGS
       && (in == stack_pointer_rtx
          || (GET_CODE (in) == PLUS
              && (XEXP (in, 0) == stack_pointer_rtx
@@ -572,6 +596,8 @@ secondary_reload_class (class, mode, in)
       && (XEXP (in, 0) == stack_pointer_rtx
          || XEXP (in, 1) == stack_pointer_rtx))
     {
+      if (TARGET_AM33)
+       return DATA_OR_EXTENDED_REGS;
       return DATA_REGS;
     }
  
@@ -589,6 +615,8 @@ initial_offset (from, to)
     {
       if (regs_ever_live[2] || regs_ever_live[3]
          || regs_ever_live[6] || regs_ever_live[7]
+         || regs_ever_live[14] || regs_ever_live[15]
+         || regs_ever_live[16] || regs_ever_live[17]
          || frame_pointer_needed)
        return REG_SAVE_BYTES;
       else
@@ -602,6 +630,8 @@ initial_offset (from, to)
     {
       if (regs_ever_live[2] || regs_ever_live[3]
          || regs_ever_live[6] || regs_ever_live[7]
+         || regs_ever_live[14] || regs_ever_live[15]
+         || regs_ever_live[16] || regs_ever_live[17]
          || frame_pointer_needed)
        return (get_frame_size () + REG_SAVE_BYTES
                + (current_function_outgoing_args_size
@@ -855,6 +885,26 @@ output_tst (operand, insn)
          && !reg_set_between_p (SET_DEST (set), temp, insn)
          && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
              == REGNO_REG_CLASS (REGNO (operand)))
+         && REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
+         && REGNO (SET_DEST (set)) != REGNO (operand)
+         && (!past_call 
+             || !call_used_regs[REGNO (SET_DEST (set))]))
+       {
+         rtx xoperands[2];
+         xoperands[0] = operand;
+         xoperands[1] = SET_DEST (set);
+
+         output_asm_insn ("cmp %1,%0", xoperands);
+         return "";
+       }
+
+      if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
+         && REG_P (SET_DEST (set))
+         && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
+         && !reg_set_between_p (SET_DEST (set), temp, insn)
+         && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
+             != REGNO_REG_CLASS (REGNO (operand)))
+         && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
          && REGNO (SET_DEST (set)) != REGNO (operand)
          && (!past_call 
              || !call_used_regs[REGNO (SET_DEST (set))]))
index a7686ca81cb98a4c6d46d908610e3ff8dd7cf431..8e77acc42b11b726e582cb8cada185477e8bcab3 100644 (file)
@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA.  */
 
 #define CPP_PREDEFINES "-D__mn10300__ -D__MN10300__"
 
+#define CPP_SPEC "%{mam33:-D__AM33__}"
+
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
 extern int target_flags;
@@ -46,9 +48,16 @@ extern int target_flags;
 
 /* Generate code to work around mul/mulq bugs on the mn10300.  */
 #define TARGET_MULT_BUG                        (target_flags & 0x1)
+
+/* Generate code for the AM33 processor.  */
+#define TARGET_AM33                    (target_flags & 0x2)
+
 #define TARGET_SWITCHES  \
   {{ "mult-bug",       0x1,  "Work around hardware multiply bug"},     \
    { "no-mult-bug",    -0x1, "Do not work around hardware multiply bug"},\
+   { "am33",           0x2},   \
+   { "am33",           -(0x1)},\
+   { "no-am33",        -0x2},  \
    { "", TARGET_DEFAULT, NULL}}
 
 #ifndef TARGET_DEFAULT
@@ -134,13 +143,13 @@ 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 10
+#define FIRST_PSEUDO_REGISTER 18
 
 /* 1 for registers that have pervasive standard uses
    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, 1, 1, 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
@@ -151,10 +160,19 @@ extern int target_flags;
    like.  */
 
 #define CALL_USED_REGISTERS \
-  { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}
+  { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}
 
 #define REG_ALLOC_ORDER \
-  { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9}
+  { 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9}
+
+#define CONDITIONAL_REGISTER_USAGE \
+{                                              \
+  if (!TARGET_AM33)                            \
+    {                                          \
+      for (i = 10; i < 18; i++)                \
+       fixed_regs[i] = call_used_regs[i] = 1;  \
+    }                                          \
+}
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
@@ -169,7 +187,9 @@ extern int target_flags;
    MODE.  */
 
 #define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (REGNO_REG_CLASS (REGNO) == DATA_REGS                         \
+ ((REGNO_REG_CLASS (REGNO) == DATA_REGS \
+   || (TARGET_AM33 && REGNO_REG_CLASS (REGNO) == ADDRESS_REGS) \
+   || REGNO_REG_CLASS (REGNO) == EXTENDED_REGS) \
   ? ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) <= 4    \
   : ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) == 4)
 
@@ -178,7 +198,9 @@ extern int target_flags;
    If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
    for any hard reg, then this must be 0 for correct output.  */
 #define MODES_TIEABLE_P(MODE1, MODE2) \
-  (MODE1 == MODE2 || (GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4))
+  (TARGET_AM33  \
+   || MODE1 == MODE2 \
+   || (GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4))
 
 /* 4 data, and effectively 3 address registers is small as far as I'm
    concerned.  */
@@ -207,6 +229,8 @@ extern int target_flags;
 enum reg_class {
   NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS,
   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, 
   GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
 };
 
@@ -217,6 +241,9 @@ enum reg_class {
 #define REG_CLASS_NAMES \
 { "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \
   "SP_REGS", "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", \
   "GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
 
 /* Define which registers fit in which classes.
@@ -225,13 +252,18 @@ enum reg_class {
 
 #define REG_CLASS_CONTENTS                     \
 {      0,              /* No regs      */      \
-   0x00f,              /* DATA_REGS */         \
-   0x1f0,              /* ADDRESS_REGS */      \
-   0x200,              /* SP_REGS */           \
-   0x1ff,              /* DATA_OR_ADDRESS_REGS */\
-   0x1f0,              /* SP_OR_ADDRESS_REGS */\
-   0x1ff,              /* GENERAL_REGS */      \
-   0x3ff,              /* ALL_REGS     */      \
+   0x0000f,            /* DATA_REGS */         \
+   0x001f0,            /* ADDRESS_REGS */      \
+   0x00200,            /* SP_REGS */           \
+   0x001ff,            /* DATA_OR_ADDRESS_REGS */\
+   0x003f0,            /* SP_OR_ADDRESS_REGS */\
+   0x2fc00,            /* EXTENDED_REGS */     \
+   0x2fc0f,            /* DATA_OR_EXTENDED_REGS */     \
+   0x2fdf0,            /* ADDRESS_OR_EXTENDED_REGS */  \
+   0x2fe00,            /* SP_OR_EXTENDED_REGS */       \
+   0x2fff0,            /* SP_OR_ADDRESS_OR_EXTENDED_REGS */    \
+   0x2fdff,            /* GENERAL_REGS */      \
+   0x2ffff,            /* ALL_REGS     */      \
 }
 
 /* The same information, inverted:
@@ -242,10 +274,11 @@ enum reg_class {
 #define REGNO_REG_CLASS(REGNO) \
   ((REGNO) < 4 ? DATA_REGS : \
    (REGNO) < 9 ? ADDRESS_REGS : \
-    (REGNO) == 9 ? SP_REGS : 0)
+    (REGNO) == 9 ? SP_REGS : \
+     (REGNO) < 18 ? EXTENDED_REGS : 0)
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS DATA_REGS
+#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS
 #define BASE_REG_CLASS  SP_OR_ADDRESS_REGS
 
 /* Get reg_class from a letter such as appears in the machine description.  */
@@ -253,6 +286,7 @@ enum reg_class {
 #define REG_CLASS_FROM_LETTER(C) \
   ((C) == 'd' ? DATA_REGS : \
    (C) == 'a' ? ADDRESS_REGS : \
+   (C) == 'x' ? EXTENDED_REGS : \
    (C) == 'y' ? SP_REGS : NO_REGS)
 
 /* Macros to check register numbers against specific register classes.  */
@@ -273,6 +307,8 @@ enum reg_class {
 
 #define REGNO_OK_FOR_INDEX_P(regno) \
   (((regno) >= 0 && regno < 4) \
+   || ((regno) >= 10 && regno < 18)    \
+   || (reg_renumber[regno] >= 10 && reg_renumber[regno] < 18) \
    || (reg_renumber[regno] >= 0 && reg_renumber[regno] < 4))
 
 
@@ -282,13 +318,15 @@ enum reg_class {
    in some cases it is preferable to use a more restrictive class.  */
 
 #define PREFERRED_RELOAD_CLASS(X,CLASS) \
-  (X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS)
+  (X == stack_pointer_rtx && CLASS != SP_REGS \
+   ? ADDRESS_OR_EXTENDED_REGS : CLASS)
 
 #define PREFERRED_OUTPUT_RELOAD_CLASS(X,CLASS) \
-  (X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS)
+  (X == stack_pointer_rtx && CLASS != SP_REGS \
+   ? ADDRESS_OR_EXTENDED_REGS : CLASS)
 
 #define LIMIT_RELOAD_CLASS(MODE, CLASS) \
-  ((MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS)
+  (!TARGET_AM33 && (MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS)
 
 #define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
   secondary_reload_class(CLASS,MODE,IN)
@@ -645,6 +683,8 @@ extern struct rtx_def *mn10300_va_arg();
 #endif
 
 \f
+#define HAVE_POST_INCREMENT (TARGET_AM33)
+
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
    that is a valid memory address for an instruction.
    The MODE argument is the machine mode for the MEM expression
@@ -678,6 +718,11 @@ extern struct rtx_def *mn10300_va_arg();
     goto ADDR;                                         \
   if (RTX_OK_FOR_BASE_P (X))                           \
     goto ADDR;                                         \
+  if (TARGET_AM33                                      \
+      && GET_CODE (X) == POST_INC                      \
+      && RTX_OK_FOR_BASE_P (XEXP (X, 0))               \
+      && (MODE == SImode || MODE == SFmode || MODE == HImode))\
+    goto ADDR;                                         \
   if (GET_CODE (X) == PLUS)                            \
     {                                                  \
       rtx base = 0, index = 0;                         \
@@ -719,7 +764,9 @@ extern struct rtx_def *legitimize_address ();
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.  */
 
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)  {}
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)        \
+  if (GET_CODE (ADDR) == POST_INC) \
+    goto LABEL
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
@@ -772,8 +819,9 @@ extern struct rtx_def *legitimize_address ();
   case CONST_DOUBLE:                                                   \
     return 8;
 
-
-#define REGISTER_MOVE_COST(CLASS1, CLASS2)  (CLASS1 != CLASS2 ? 4 : 2)
+#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+  ((CLASS1 == CLASS2 && (CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS)) ? 2 :\
+   CLASS1 == CLASS2 && CLASS1 == EXTENDED_REGS ? 6 : 4)
 
 /* A crude cut at RTX_COSTS for the MN10300.  */
 
@@ -923,7 +971,8 @@ do { char dstr[30];                                 \
    This sequence is indexed by compiler's hard-register-number (see above).  */
 
 #define REGISTER_NAMES \
-{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp" }
+{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp", \
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" }
 
 /* Print an instruction operand X on file FILE.
    look in mn10300.c for details */
index 54cc0dbc4417a10c630b3f4626d9f3ff6a454373..27fdb6810dda9f39fa7eb1afac6a4b04a2d24e39 100644 (file)
     operands[1] = copy_to_mode_reg (QImode, operand1);
 }")
 
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=dx,a,dx,a,dx,a,dx,a,dxa,m")
+       (match_operand:QI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dxa"))]
+  "TARGET_AM33
+   && (register_operand (operands[0], QImode)
+       || register_operand (operands[1], QImode))"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+    case 1:
+      return \"nop\";
+    case 2:
+      return \"clr %0\";
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       {
+         rtx xoperands[2];
+         xoperands[0] = operands[0];
+         xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+         output_asm_insn (\"mov %1,%0\", xoperands);
+         return \"\";
+       }
+
+      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+         && GET_CODE (operands[1]) == CONST_INT)
+       {
+         HOST_WIDE_INT val = INTVAL (operands[1]);
+
+         if (((val & 0x80) && ! (val & 0xffffff00))
+             || ((val & 0x800000) && ! (val & 0xff000000)))
+           return \"movu %1,%0\";
+       }
+      return \"mov %1,%0\";
+    case 8:
+    case 9:
+      return \"movbu %1,%0\";
+    }
+}"
+  [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
+
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=dx,*a,dx,*a,dx,*a,dx,*a,dx,m")
        (match_operand:QI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dx"))]
     operands[1] = copy_to_mode_reg (HImode, operand1);
 }")
 
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=dx,a,dx,a,dx,a,dx,a,dxa,m")
+       (match_operand:HI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dxa"))]
+  "TARGET_AM33
+   && (register_operand (operands[0], HImode)
+       || register_operand (operands[1], HImode))"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+    case 1:
+      return \"nop\";
+    case 2:
+      return \"clr %0\";
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       {
+         rtx xoperands[2];
+         xoperands[0] = operands[0];
+         xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+         output_asm_insn (\"mov %1,%0\", xoperands);
+         return \"\";
+       }
+
+      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+         && GET_CODE (operands[1]) == CONST_INT)
+       {
+         HOST_WIDE_INT val = INTVAL (operands[1]);
+
+         if (((val & 0x80) && ! (val & 0xffffff00))
+             || ((val & 0x800000) && ! (val & 0xff000000)))
+           return \"movu %1,%0\";
+       }
+      return \"mov %1,%0\";
+    case 8:
+    case 9:
+      return \"movhu %1,%0\";
+    }
+}"
+  [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
+
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=dx,*a,dx,*a,dx,*a,dx,*a,dx,m")
        (match_operand:HI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dx"))]
          output_asm_insn (\"mov %1,%0\", xoperands);
          return \"\";
        }
+
+      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+         && GET_CODE (operands[1]) == CONST_INT)
+       {
+         HOST_WIDE_INT val = INTVAL (operands[1]);
+
+         if (((val & 0x80) && ! (val & 0xffffff00))
+             || ((val & 0x800000) && ! (val & 0xff000000)))
+           return \"movu %1,%0\";
+       }
       return \"mov %1,%0\";
     }
 }"
     case 3:
     case 4:
     case 5:
+      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+         && GET_CODE (operands[1]) == CONST_INT)
+       {
+         HOST_WIDE_INT val = INTVAL (operands[1]);
+
+         if (((val & 0x80) && ! (val & 0xffffff00))
+             || ((val & 0x800000) && ! (val & 0xff000000)))
+           return \"movu %1,%0\";
+       }
       return \"mov %1,%0\";
     }
 }"
                else
                  output_asm_insn (\"mov %L1,%L0\", operands);
              }
+           else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+                     == EXTENDED_REGS)
+                    && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
+                        || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
+             output_asm_insn (\"movu %1,%0\", operands);
            else
              output_asm_insn (\"mov %L1,%L0\", operands);
 
                      || GET_CODE (operands[1]) == CONST_DOUBLE)
                     && val[0] == val[1])
              output_asm_insn (\"mov %L0,%H0\", operands);
+           else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+                     == EXTENDED_REGS)
+                    && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
+                        || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
+             output_asm_insn (\"movu %1,%0\", operands);
            else
              output_asm_insn (\"mov %H1,%H0\", operands);
            return \"\";
                else
                  output_asm_insn (\"mov %L1,%L0\", operands);
              }
+           else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+                     == EXTENDED_REGS)
+                    && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
+                        || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
+             output_asm_insn (\"movu %1,%0\", operands);
            else
              output_asm_insn (\"mov %L1,%L0\", operands);
 
                      || GET_CODE (operands[1]) == CONST_DOUBLE)
                     && val[0] == val[1])
              output_asm_insn (\"mov %L0,%H0\", operands);
+           else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+                     == EXTENDED_REGS)
+                    && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
+                        || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
+             output_asm_insn (\"movu %1,%0\", operands);
            else
              output_asm_insn (\"mov %H1,%H0\", operands);
            return \"\";
   "* return output_tst (operands[0], insn);"
   [(set_attr "cc" "set_znv")])
 
+(define_insn ""
+  [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")))]
+  "TARGET_AM33"
+  "* return output_tst (operands[0], insn);"
+  [(set_attr "cc" "set_znv")])
+
 (define_insn ""
   [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")))]
   ""
   "* return output_tst (operands[0], insn);"
   [(set_attr "cc" "set_znv")])
 
+(define_insn ""
+  [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")))]
+  "TARGET_AM33"
+  "* return output_tst (operands[0], insn);"
+  [(set_attr "cc" "set_znv")])
+
 (define_insn ""
   [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")))]
   ""
   "* return output_tst (operands[0], insn);"
   [(set_attr "cc" "set_znv")])
 
-
 (define_insn "cmpsi"
   [(set (cc0)
        (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax")
    }
 }")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,ax,ax,dax,xy,!dax")
+       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax")
+                (match_operand:SI 2 "nonmemory_operand" "J,J,L,daxi,i,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+    case 1:
+      return \"inc %0\";
+    case 2:
+      return \"inc4 %0\";
+    case 3:
+    case 4:
+      return \"add %2,%0\";
+    case 5:
+      {
+       enum reg_class src1_class, src2_class, dst_class;
+
+       src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
+       src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
+       dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
+       
+       /* I'm not sure if this can happen or not.  Might as well be prepared
+         and generate the best possible code if it does happen.  */
+       if (true_regnum (operands[0]) == true_regnum (operands[1]))
+         return \"add %2,%0\";
+       if (true_regnum (operands[0]) == true_regnum (operands[2]))
+         return \"add %1,%0\";
+
+       /* Catch cases where no extended register was used.  These should be
+          handled just like the mn10300.  */
+       if (src1_class != EXTENDED_REGS
+           && src2_class != EXTENDED_REGS
+           && dst_class != EXTENDED_REGS)
+         {
+           /* We have to copy one of the sources into the destination, then
+              add the other source to the destination.
+
+              Carefully select which source to copy to the destination; a naive
+              implementation will waste a byte when the source classes are 
+              different and the destination is an address register.  Selecting
+              the lowest cost register copy will optimize this sequence.  */
+           if (REGNO_REG_CLASS (true_regnum (operands[1]))
+               == REGNO_REG_CLASS (true_regnum (operands[0])))
+             return \"mov %1,%0\;add %2,%0\";
+           return \"mov %2,%0\;add %1,%0\";
+         }
+
+       /* At least one register is an extended register.  */
+
+       /* The three operand add instruction on the am33 is a win iff the
+          output register is an extended register, or if both source
+          registers are extended registers.  */
+       if (dst_class == EXTENDED_REGS
+           || src1_class == src2_class)
+         return \"add %2,%1,%0\";
+
+      /* It is better to copy one of the sources to the destination, then
+        perform a 2 address add.  The destination in this case must be
+        an address or data register and one of the sources must be an
+        extended register and the remaining source must not be an extended
+        register.
+
+        The best code for this case is to copy the extended reg to the
+        destination, then emit a two address add.  */
+      if (src1_class == EXTENDED_REGS)
+       return \"mov %1,%0\;add %2,%0\";
+      return \"mov %2,%0\;add %1,%0\";
+      }
+    }
+}"
+  [(set_attr "cc" "set_zn,none_0hit,none_0hit,set_zn,none_0hit,set_zn")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx,ax,ax,dax,xy,!dax")
        (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax")
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dax,!dax")
+       (minus:SI (match_operand:SI 1 "register_operand" "0,dax")
+                 (match_operand:SI 2 "nonmemory_operand" "daxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (true_regnum (operands[0]) == true_regnum (operands[1]))
+    return \"sub %2,%0\";
+  else
+    {
+      enum reg_class src1_class, src2_class, dst_class;
+
+      src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
+      src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
+      dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
+
+      /* If no extended registers are used, then the best way to handle
+        this is to copy the first source operand into the destination
+        and emit a two address subtraction.  */
+      if (src1_class != EXTENDED_REGS
+         && src2_class != EXTENDED_REGS
+         && dst_class != EXTENDED_REGS
+         && true_regnum (operands[0]) != true_regnum (operands[2]))
+       return \"mov %1,%0\;sub %2,%0\";
+      return \"sub %2,%1,%0\";
+    }
+}"
+  [(set_attr "cc" "set_zn")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dax")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
 ;; MULTIPLY INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
+(define_insn "mulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "=dax")
+        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "dax"))
+                 (sign_extend:DI (match_operand:SI 2 "register_operand" "dax"))))]
+  "TARGET_AM33"
+  "mul %1,%2,%H0,%L0"
+  [(set_attr "cc" "set_zn")])
+
+(define_insn "umulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "=dax")
+        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "dax"))
+                 (zero_extend:DI (match_operand:SI 2 "register_operand" "dax"))))]
+  "TARGET_AM33"
+  "mulu %1,%2,%H0,%L0"
+  [(set_attr "cc" "set_zn")])
+
 (define_expand "mulsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (mult:SI (match_operand:SI 1 "register_operand" "")
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (mult:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "nonmemory_operand" "dx,daxi")))]
+  "TARGET_AM33"
+  "*
+{
+  if (TARGET_MULT_BUG)
+    return \"nop\;nop\;mul %2,%0\";
+  else
+    return \"mul %2,%0\";
+}"
+  [(set_attr "cc" "set_zn")])
+  
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (mult:SI (match_operand:SI 1 "register_operand" "%0")
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax")
+       (and:SI (match_operand:SI 1 "register_operand" "%0,0,dax")
+               (match_operand:SI 2 "nonmemory_operand" "N,dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff)
+    return \"extbu %0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xffff)
+    return \"exthu %0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x7fffffff)
+    return \"add %0,%0\;lsr 1,%0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x3fffffff)
+    return \"asl2 %0\;lsr 2,%0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x1fffffff)
+    return \"add %0,%0\;asl2 %0\;lsr 3,%0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x0fffffff)
+    return \"asl2 %0\;asl2 %0\;lsr 4,%0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffe)
+    return \"lsr 1,%0\;add %0,%0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffc)
+    return \"lsr 2,%0\;asl2 %0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff8)
+    return \"lsr 3,%0\;add %0,%0\;asl2 %0\";
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff0)
+    return \"lsr 4,%0\;asl2 %0\;asl2 %0\";
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2])
+      && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+    return \"mov %1,%0\;and %2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"and %1,%2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[0])
+      && true_regnum (operands[2]) == true_regnum (operands[0]))
+    return \"and %1,%0\";
+  return \"and %2,%0\";
+}"
+  [(set_attr "cc" "none_0hit,set_znv,set_znv")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx,dx")
        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (ior:SI (match_operand:SI 1 "register_operand" "%0,dax")
+               (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2])
+      && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+    return \"mov %1,%0\;or %2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"or %1,%2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[0])
+      && true_regnum (operands[2]) == true_regnum (operands[0]))
+    return \"or %1,%0\";
+  return \"or %2,%0\";
+}"
+  [(set_attr "cc" "set_znv")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (ior:SI (match_operand:SI 1 "register_operand" "%0")
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (xor:SI (match_operand:SI 1 "register_operand" "%0,dax")
+               (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2])
+      && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+    return \"mov %1,%0\;xor %2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[1])
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"xor %1,%2,%0\";
+  if (REG_P (operands[2]) && REG_P (operands[0])
+      && true_regnum (operands[2]) == true_regnum (operands[0]))
+    return \"xor %1,%0\";
+  return \"xor %2,%0\";
+}"
+  [(set_attr "cc" "set_znv")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (xor:SI (match_operand:SI 1 "register_operand" "%0")
        (not:SI (match_operand:SI 1 "register_operand" "")))]
   ""
   "")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (not:SI (match_operand:SI 1 "register_operand" "0,0")))]
+  "TARGET_AM33"
+  "not %0"
+  [(set_attr "cc" "set_znv")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (not:SI (match_operand:SI 1 "register_operand" "0")))]
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx,!dax,!dax,!dax")
+       (zero_extend:SI
+        (match_operand:QI 1 "general_operand" "0,dax,m,0,dax,m")))]
+  "TARGET_AM33"
+  "@
+  extbu %0
+  mov %1,%0\;extbu %0
+  movbu %1,%0
+  extbu %0
+  mov %1,%0\;extbu %0
+  movbu %1,%0"
+  [(set_attr "cc" "none_0hit")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx")
        (zero_extend:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx,!dax,!dax,!dax")
+       (zero_extend:SI
+        (match_operand:HI 1 "general_operand" "0,dax,m,0,dax,m")))]
+  "TARGET_AM33"
+  "@
+  exthu %0
+  mov %1,%0\;exthu %0
+  movhu %1,%0
+  exthu %0
+  mov %1,%0\;exthu %0
+  movhu %1,%0"
+  [(set_attr "cc" "none_0hit")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx")
        (zero_extend:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=dx,dx,!dax,!dax")
+       (sign_extend:SI
+        (match_operand:QI 1 "general_operand" "0,dx,0,dax")))]
+  "TARGET_AM33"
+  "@
+  extb %0
+  mov %1,%0\;extb %0
+  extb %0
+  mov %1,%0\;extb %0"
+  [(set_attr "cc" "none_0hit")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=dx,dx")
        (sign_extend:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=dx,dx,!dax,!dax")
+       (sign_extend:SI
+        (match_operand:HI 1 "general_operand" "0,dax,0,dax")))]
+  "TARGET_AM33"
+  "@
+  exth %0
+  mov %1,%0\;exth %0
+  exth %0
+  mov %1,%0\;exth %0"
+  [(set_attr "cc" "none_0hit")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=dx,dx")
        (sign_extend:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dax,dx,!dax")
+       (ashift:SI
+        (match_operand:SI 1 "register_operand" "0,0,dax")
+        (match_operand:QI 2 "nonmemory_operand" "J,dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1)
+    return \"add %0,%0\";
+
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 2)
+    return \"asl2 %0\";
+
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 3
+      && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+    return \"asl2 %0\;add %0,%0\";
+
+  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 4
+      && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+    return \"asl2 %0\;asl2 %0\";
+
+  if (true_regnum (operands[1]) == true_regnum (operands[0]))
+    return \"asl %S2,%0\";
+
+  if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"mov %1,%0\;asl %S2,%0\";
+  return \"asl %2,%1,%0\";
+}"
+  [(set_attr "cc" "set_zn")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dax,dx,dx,dx,dx")
        (ashift:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (lshiftrt:SI
+        (match_operand:SI 1 "register_operand" "0,dax")
+        (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (true_regnum (operands[1]) == true_regnum (operands[0]))
+    return \"lsr %S2,%0\";
+
+  if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"mov %1,%0\;lsr %S2,%0\";
+  return \"lsr %2,%1,%0\";
+}"
+  [(set_attr "cc" "set_zn")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (lshiftrt:SI
   ""
   "")
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+       (ashiftrt:SI
+        (match_operand:SI 1 "register_operand" "0,dax")
+        (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))]
+  "TARGET_AM33"
+  "*
+{
+  if (true_regnum (operands[1]) == true_regnum (operands[0]))
+    return \"asr %S2,%0\";
+
+  if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+      && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+      && true_regnum (operands[0]) != true_regnum (operands[2]))
+    return \"mov %1,%0\;asr %S2,%0\";
+  return \"asr %2,%1,%0\";
+}"
+  [(set_attr "cc" "set_zn")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=dx")
        (ashiftrt:SI
 {
   int i, need_comma;
   int d2, d3, a2, a3;
+  int exreg1;
 
   need_comma = 0;
   fputs (\"\\tret [\", asm_out_file);
       fputs (\"a3\", asm_out_file);
       need_comma = 1;
     }
+  if (regs_ever_live[14] || regs_ever_live[15]
+      || regs_ever_live[16] || regs_ever_live[17])
+    {
+      if (need_comma)
+       fputc (',', asm_out_file); 
+      fputs (\"exreg1\", asm_out_file);
+      need_comma = 1;
+    }
   fprintf (asm_out_file, \"],%d\\n\", INTVAL (operands[0]));
   return \"\";
 }"
 {
   int i, need_comma;
   int d2, d3, a2, a3;
+  int exreg1;
 
   need_comma = 0;
   fputs (\"\\tmovm [\", asm_out_file);
       fputs (\"a3\", asm_out_file);
       need_comma = 1;
     }
+  if (regs_ever_live[14] || regs_ever_live[15]
+      || regs_ever_live[16] || regs_ever_live[17])
+    {
+      if (need_comma)
+       fputc (',', asm_out_file); 
+      fputs (\"exreg1\", asm_out_file);
+      need_comma = 1;
+    }
   fputs (\"],(sp)\\n\", asm_out_file);
   return \"\";
 }"
index 5dbb46f5cb0dc02fe91f19caa52b7108ab6dbe12..0e3f74bb58aaff38161ffff39d4e644b1fc399f1 100644 (file)
@@ -18,3 +18,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
        echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
        echo '#endif'           >> fp-bit.c
        cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+MULTILIB_OPTIONS = mam33
+MULTILIB_DIRNAMES = am33 
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
index f1b064975c621c424dc20afe38d0974a5001422e..8213cf4d6b4f5e9310320d3da1e01fb762108902 100644 (file)
@@ -291,6 +291,8 @@ in the following sections.
 @emph{MN10300 Options}
 -mmult-bug
 -mno-mult-bug
+-mam33
+-mno-am33
 -mrelax
 
 @emph{M32R/D Options}
@@ -4641,6 +4643,14 @@ processors.  This is the default.
 Do not generate code to avoid bugs in the multiply instructions for the
 MN10300 processors.
 
+@table @code
+@item -mam33
+Generate code which uses features specific to the AM33 processor.
+
+@item -mno-am33
+Do not generate code which uses features specific to the AM33 processor.  This
+is the default.
+
 @item -mrelax
 Indicate to the linker that it should perform a relaxation optimization pass
 to shorten branches, calls and absolute memory addresses.  This option only