Add ms2 support
authorNathan Sidwell <nathan@codesourcery.com>
Wed, 9 Nov 2005 09:34:21 +0000 (09:34 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 9 Nov 2005 09:34:21 +0000 (09:34 +0000)
Add ms2 support
* config/ms1/ms1.md (UNSPEC_BLOCKAGE, UNSPEC_EI, UNSPEC_DI): New
constants.
(call,load,store): New insn types.
(mem_access, branch_access): Adjust reservation conditions.
(define_delay): Adjust condition.
(decrement_and_branch_until_zero): Allow for ms2.  Set branch
type.
(*decrement_and_rbanch_until_zero_no_clobber): Allow for ms2.
(*movqi_internal,*movsi_internal,*movsf_internal): Use load,store
insn type.
(call_internal, call_value_internal, return_internal,
return_interrupt_internal, eh_return_internal, indirect_jump,
tablejump): Set call insn type.
(blockage, ei, di): Use appropriate unspec const.
* config/ms1/ms1.c (ms1_flag_delayed_branch): New.
(ms1_get_attr_type): Adjust to give load & store types.
(ms1_final_prescan_insn): Adjust for new insn types.  Don't look
backwards past a barrier.
(ms1_override_options): Accept ms2 arch.  Copy and reset delayed
branch scheduling.
(struct branch_info, struct label_info): New.
(ms1_labels): New.
(ms1_add_branches, ms1_check_delay_slot, ms1_reorg_hazard): New.
(ms1_machine_reorg): New.
(TARGET_MACHINE_DEPENDENT_REORG): Override.
* config/ms1/crtn.asm: Add nop for ms2 JAL hazard.
* config/ms1/ms1.h (processor_type): Add PROCESSOR_MS2.
(ASM_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Add ms2.
(TARGET_MS2): New.

From-SVN: r106680

gcc/ChangeLog
gcc/config/ms1/crtn.asm
gcc/config/ms1/ms1.c
gcc/config/ms1/ms1.h
gcc/config/ms1/ms1.md

index c9836318d76e7c15cf554c9824987561681a27b9..32c9206a6835ac17923c910d7fcd12bfaebeb42d 100644 (file)
@@ -1,3 +1,36 @@
+2005-11-09  Nathan Sidwell  <nathan@codesourcery.com>
+
+       Add ms2 support
+       * config/ms1/ms1.md (UNSPEC_BLOCKAGE, UNSPEC_EI, UNSPEC_DI): New
+       constants.
+       (call,load,store): New insn types.
+       (mem_access, branch_access): Adjust reservation conditions.
+       (define_delay): Adjust condition.
+       (decrement_and_branch_until_zero): Allow for ms2.  Set branch
+       type.
+       (*decrement_and_rbanch_until_zero_no_clobber): Allow for ms2.
+       (*movqi_internal,*movsi_internal,*movsf_internal): Use load,store
+       insn type.
+       (call_internal, call_value_internal, return_internal,
+       return_interrupt_internal, eh_return_internal, indirect_jump,
+       tablejump): Set call insn type.
+       (blockage, ei, di): Use appropriate unspec const.
+       * config/ms1/ms1.c (ms1_flag_delayed_branch): New.
+       (ms1_get_attr_type): Adjust to give load & store types.
+       (ms1_final_prescan_insn): Adjust for new insn types.  Don't look
+       backwards past a barrier.
+       (ms1_override_options): Accept ms2 arch.  Copy and reset delayed
+       branch scheduling.
+       (struct branch_info, struct label_info): New.
+       (ms1_labels): New.
+       (ms1_add_branches, ms1_check_delay_slot, ms1_reorg_hazard): New.
+       (ms1_machine_reorg): New.
+       (TARGET_MACHINE_DEPENDENT_REORG): Override.
+       * config/ms1/crtn.asm: Add nop for ms2 JAL hazard.
+       * config/ms1/ms1.h (processor_type): Add PROCESSOR_MS2.
+       (ASM_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Add ms2.
+       (TARGET_MS2): New.
+
 2005-11-09  Per Bothner  <per@bothner.com>
            Uros Bizjak  <uros@kss-loka.si>
        
index 1fa42ac56a4112d37cb71d7bfb5ffdc9eed803c6..5fbe7ece9695544f2770f7b94afa94d3a07cca8f 100644 (file)
@@ -42,6 +42,7 @@
        .align          4
        ldw     r14, sp, #0
        addi    sp, sp, #4
+       nop
        jal     r0, r14
        or      r0, r0, r0
        
@@ -50,5 +51,6 @@
 
        ldw     r14, sp, #0
        addi    sp, sp, #4
+       nop
        jal     r0, r14
        or      r0, r0, r0
index 25ba78ec40b5c97dc468711b852faa16e19bede0..19f02a1c7469d67a405d583ed02a60ef08a13d47 100644 (file)
@@ -84,6 +84,8 @@ struct ms1_frame_info zero_frame_info;
 /* ms1 doesn't have unsigned compares need a library call for this.  */
 struct rtx_def * ms1_ucmpsi3_libcall;
 
+static int ms1_flag_delayed_branch;
+
 \f
 static rtx
 ms1_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
@@ -125,13 +127,6 @@ ms1_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED, const char *ptr)
   return ptr;
 }
 
-/* Return TRUE if INSN is a memory load.  */
-static bool
-ms1_memory_load (rtx insn)
-{
-  return ((GET_CODE (insn) == SET) && (GET_CODE (XEXP (insn,1)) == MEM));
-}
-
 /* Given an insn, return whether it's a memory operation or a branch
    operation, otherwise return TYPE_ARITH.  */
 static enum attr_type
@@ -139,18 +134,24 @@ ms1_get_attr_type (rtx complete_insn)
 {
   rtx insn = PATTERN (complete_insn);
 
-  if ((GET_CODE (insn) == SET)
-      && ((GET_CODE (XEXP (insn, 0)) == MEM)
-         || (GET_CODE (XEXP (insn, 1)) == MEM)))
-    return TYPE_MEM;
-
-  else if (((GET_CODE (insn) == SET) && (XEXP (insn, 0) == pc_rtx))
-          || (GET_CODE (complete_insn) == JUMP_INSN)
-          || (GET_CODE (complete_insn) == CALL_INSN))
+  if (JUMP_P (complete_insn))
+    return TYPE_BRANCH;
+  if (CALL_P (complete_insn))
     return TYPE_BRANCH;
 
-  else
+  if (GET_CODE (insn) != SET)
     return TYPE_ARITH;
+
+  if (SET_DEST (insn) == pc_rtx)
+    return TYPE_BRANCH;
+
+  if (GET_CODE (SET_DEST (insn)) == MEM)
+    return TYPE_STORE;
+
+  if (GET_CODE (SET_SRC (insn)) == MEM)
+    return TYPE_LOAD;
+  
+  return TYPE_ARITH;
 }
 
 /* A helper routine for insn_dependent_p called through note_stores.  */
@@ -212,35 +213,48 @@ ms1_final_prescan_insn (rtx   insn,
                        int   noperands ATTRIBUTE_UNUSED)
 {
   rtx prev_i;
+  enum attr_type prev_attr;
 
   ms1_nops_required = 0;
   ms1_nop_reasons = "";
 
+  /* ms2 constraints are dealt with in reorg.  */
+  if (ms1_cpu == PROCESSOR_MS2)
+    return;
+  
   /* Only worry about real instructions.  */
   if (! INSN_P (insn))
     return;
 
   /* Find the previous real instructions.  */
-  prev_i = PREV_INSN (insn);
-  while (prev_i != NULL
+  for (prev_i = PREV_INSN (insn);
+       prev_i != NULL
         && (! INSN_P (prev_i)
             || GET_CODE (PATTERN (prev_i)) == USE
-            || GET_CODE (PATTERN (prev_i)) == CLOBBER))
-    prev_i = PREV_INSN (prev_i);
-
+            || GET_CODE (PATTERN (prev_i)) == CLOBBER);
+       prev_i = PREV_INSN (prev_i))
+    {
+      /* If we meet a barrier, there is no flow through here.  */
+      if (BARRIER_P (prev_i))
+       return;
+    }
+  
   /* If there isn't one then there is nothing that we need do.  */
   if (prev_i == NULL || ! INSN_P (prev_i))
     return;
 
+  prev_attr = ms1_get_attr_type (prev_i);
+  
   /* Delayed branch slots already taken care of by delay branch scheduling.  */
-  if (ms1_get_attr_type (prev_i) == TYPE_BRANCH)
+  if (prev_attr == TYPE_BRANCH)
     return;
 
   switch (ms1_get_attr_type (insn))
     {
-    case TYPE_MEM:
+    case TYPE_LOAD:
+    case TYPE_STORE:
       /* Avoid consecutive memory operation.  */
-      if  (ms1_get_attr_type (prev_i) == TYPE_MEM
+      if  ((prev_attr == TYPE_LOAD || prev_attr == TYPE_STORE)
           && ms1_cpu == PROCESSOR_MS1_64_001)
        {
          ms1_nops_required = 1;
@@ -252,7 +266,7 @@ ms1_final_prescan_insn (rtx   insn,
     case TYPE_COMPLEX:
       /* One cycle of delay is required between load
         and the dependent arithmetic instruction.  */
-      if (ms1_memory_load (PATTERN (prev_i))
+      if (prev_attr == TYPE_LOAD
          && insn_true_dependent_p (prev_i, insn))
        {
          ms1_nops_required = 1;
@@ -263,7 +277,7 @@ ms1_final_prescan_insn (rtx   insn,
     case TYPE_BRANCH:
       if (insn_dependent_p (prev_i, insn))
        {
-         if (ms1_get_attr_type (prev_i) == TYPE_ARITH
+         if (prev_attr == TYPE_ARITH
              && ms1_cpu == PROCESSOR_MS1_64_001)
            {
              /* One cycle of delay between arith
@@ -271,7 +285,7 @@ ms1_final_prescan_insn (rtx   insn,
              ms1_nops_required = 1;
              ms1_nop_reasons = "arith->branch dependency delay";
            }
-         else if (ms1_memory_load (PATTERN (prev_i)))
+         else if (prev_attr == TYPE_LOAD)
            {
              /* Two cycles of delay are required
                 between load and dependent branch.  */
@@ -790,10 +804,9 @@ ms1_override_options (void)
       else if (!strcasecmp (ms1_cpu_string, "MS1-16-002"))
        ms1_cpu = PROCESSOR_MS1_16_002;
       else if  (!strcasecmp (ms1_cpu_string, "MS1-16-003"))
-       {
-         ms1_cpu = PROCESSOR_MS1_16_003;
-         target_flags |= MASK_MUL;
-       }
+       ms1_cpu = PROCESSOR_MS1_16_003;
+      else if (!strcasecmp (ms1_cpu_string, "MS2"))
+       ms1_cpu = PROCESSOR_MS2;
       else
        error ("bad value (%s) for -march= switch", ms1_cpu_string);
     }
@@ -806,6 +819,10 @@ ms1_override_options (void)
       flag_gcse = 0;
     }
 
+  /* We do delayed branch filling in machine dependent reorg */
+  ms1_flag_delayed_branch = flag_delayed_branch;
+  flag_delayed_branch = 0;
+
   init_machine_status = ms1_init_machine_status;
 }
 
@@ -1631,6 +1648,315 @@ ms1_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)
               || TREE_ADDRESSABLE (type))));
 }
 \f
+
+/* Structures to hold branch information during reorg.  */
+typedef struct branch_info
+{
+  rtx insn;  /* The branch insn.  */
+  
+  struct branch_info *next;
+} branch_info;
+
+typedef struct label_info
+{
+  rtx label;  /* The label.  */
+  branch_info *branches;  /* branches to this label.  */
+  struct label_info *next;
+} label_info;
+
+/* Chain of labels found in current function, used during reorg.  */
+static label_info *ms1_labels;
+
+/* If *X is a label, add INSN to the list of branches for that
+   label.  */
+
+static int
+ms1_add_branches (rtx *x, void *insn)
+{
+  if (GET_CODE (*x) == LABEL_REF)
+    {
+      branch_info *branch = xmalloc (sizeof (*branch));
+      rtx label = XEXP (*x, 0);
+      label_info *info;
+
+      for (info = ms1_labels; info; info = info->next)
+       if (info->label == label)
+         break;
+
+      if (!info)
+       {
+         info = xmalloc (sizeof (*info));
+         info->next = ms1_labels;
+         ms1_labels = info;
+         
+         info->label = label;
+         info->branches = NULL;
+       }
+
+      branch->next = info->branches;
+      info->branches = branch;
+      branch->insn = insn;
+    }
+  return 0;
+}
+
+/* If BRANCH has a filled delay slot, check if INSN is dependent upon
+   it.  If so, undo the delay slot fill.   Returns the next insn, if
+   we patch out the branch.  Returns the branch insn, if we cannot
+   patch out the branch (due to anti-dependency in the delay slot).
+   In that case, the caller must insert nops at the branch target.  */
+
+static rtx
+ms1_check_delay_slot (rtx branch, rtx insn)
+{
+  rtx slot;
+  rtx tmp;
+  rtx p;
+  rtx jmp;
+  
+  gcc_assert (GET_CODE (PATTERN (branch)) == SEQUENCE);
+  if (INSN_DELETED_P (branch))
+    return NULL_RTX;
+  slot = XVECEXP (PATTERN (branch), 0, 1);
+  
+  tmp = PATTERN (insn);
+  note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
+  if (tmp)
+    /* Not dependent.  */
+    return NULL_RTX;
+  
+  /* Undo the delay slot.  */
+  jmp = XVECEXP (PATTERN (branch), 0, 0);
+  
+  tmp = PATTERN (jmp);
+  note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
+  if (!tmp)
+    /* Anti dependent. */
+    return branch;
+      
+  p = PREV_INSN (branch);
+  NEXT_INSN (p) = slot;
+  PREV_INSN (slot) = p;
+  NEXT_INSN (slot) = jmp;
+  PREV_INSN (jmp) = slot;
+  NEXT_INSN (jmp) = branch;
+  PREV_INSN (branch) = jmp;
+  XVECEXP (PATTERN (branch), 0, 0) = NULL_RTX;
+  XVECEXP (PATTERN (branch), 0, 1) = NULL_RTX;
+  delete_insn (branch);
+  return jmp;
+}
+
+/* Insert nops to satisfy pipeline constraints.  We only deal with ms2
+   constraints here.  Earlier CPUs are dealt with by inserting nops with
+   final_prescan (but that can lead to inferior code, and is
+   impractical with ms2's JAL hazard).
+
+   ms2 dynamic constraints
+   1) a load and a following use must be separated by one insn
+   2) an insn and a following dependent call must be separated by two insns
+   
+   only arith insns are placed in delay slots so #1 cannot happen with
+   a load in a delay slot.  #2 can happen with an arith insn in the
+   delay slot.  */
+
+static void
+ms1_reorg_hazard (void)
+{
+  rtx insn, next;
+
+  /* Find all the branches */
+  for (insn = get_insns ();
+       insn;
+       insn = NEXT_INSN (insn))
+    {
+      rtx jmp;
+
+      if (!INSN_P (insn))
+       continue;
+
+      jmp = PATTERN (insn);
+      
+      if (GET_CODE (jmp) != SEQUENCE)
+       /* If it's not got a filled delay slot, then it can't
+          conflict.  */
+       continue;
+      
+      jmp = XVECEXP (jmp, 0, 0);
+
+      if (recog_memoized (jmp) == CODE_FOR_tablejump)
+       for (jmp = XEXP (XEXP (XVECEXP (PATTERN (jmp), 0, 1), 0), 0);
+            !JUMP_TABLE_DATA_P (jmp);
+            jmp = NEXT_INSN (jmp))
+         continue;
+
+      for_each_rtx (&PATTERN (jmp), ms1_add_branches, insn);
+    }
+
+  /* Now scan for dependencies.  */
+  for (insn = get_insns ();
+       insn && !INSN_P (insn);
+       insn = NEXT_INSN (insn))
+    continue;
+  
+  for (;
+       insn;
+       insn = next)
+    {
+      rtx jmp, tmp;
+      enum attr_type attr;
+      
+      gcc_assert (INSN_P (insn) && !INSN_DELETED_P (insn));
+      for (next = NEXT_INSN (insn);
+          next && !INSN_P (next);
+          next = NEXT_INSN (next))
+       continue;
+
+      jmp = insn;
+      if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+       jmp = XVECEXP (PATTERN (insn), 0, 0);
+      
+      attr = recog_memoized (jmp) >= 0 ? get_attr_type (jmp) : TYPE_UNKNOWN;
+      
+      if (next && attr == TYPE_LOAD)
+       {
+         /* A load.  See if NEXT is dependent, and if so insert a
+            nop.  */
+         
+         tmp = PATTERN (next);
+         if (GET_CODE (tmp) == SEQUENCE)
+           tmp = PATTERN (XVECEXP (tmp, 0, 0));
+         note_stores (PATTERN (insn), insn_dependent_p_1, &tmp);
+         if (!tmp)
+           emit_insn_after (gen_nop (), insn);
+       }
+      
+      if (attr == TYPE_CALL)
+       {
+         /* A call.  Make sure we're not dependent on either of the
+            previous two dynamic instructions.  */
+         int nops = 0;
+         int count;
+         rtx prev = insn;
+         rtx rescan = NULL_RTX;
+
+         for (count = 2; count && !nops;)
+           {
+             int type;
+             
+             prev = PREV_INSN (prev);
+             if (!prev)
+               {
+                 /* If we reach the start of the function, we must
+                    presume the caller set the address in the delay
+                    slot of the call instruction.  */
+                 nops = count;
+                 break;
+               }
+             
+             if (BARRIER_P (prev))
+               break;
+             if (LABEL_P (prev))
+               {
+                 /* Look at branches to this label.  */
+                 label_info *label;
+                 branch_info *branch;
+
+                 for (label = ms1_labels;
+                      label;
+                      label = label->next)
+                   if (label->label == prev)
+                     {
+                       for (branch = label->branches;
+                            branch;
+                            branch = branch->next)
+                         {
+                           tmp = ms1_check_delay_slot (branch->insn, jmp);
+
+                           if (tmp == branch->insn)
+                             {
+                               nops = count;
+                               break;
+                             }
+                           
+                           if (tmp && branch->insn == next)
+                             rescan = tmp;
+                         }
+                       break;
+                     }
+                 continue;
+               }
+             if (!INSN_P (prev))
+               continue;
+             
+             if (GET_CODE (PATTERN (prev)) == SEQUENCE)
+               {
+                 /* Look at the delay slot.  */
+                 tmp = ms1_check_delay_slot (prev, jmp);
+                 if (tmp == prev)
+                   nops = count;
+                 break;
+               }
+             
+             type = (INSN_CODE (prev) >= 0 ? get_attr_type (prev)
+                     : TYPE_COMPLEX);
+             if (type == TYPE_CALL || type == TYPE_BRANCH)
+               break;
+             
+             if (type == TYPE_LOAD
+                 || type == TYPE_ARITH
+                 || type == TYPE_COMPLEX)
+               {
+                 tmp = PATTERN (jmp);
+                 note_stores (PATTERN (prev), insn_dependent_p_1, &tmp);
+                 if (!tmp)
+                   {
+                     nops = count;
+                     break;
+                   }
+               }
+             count -= INSN_CODE (prev) >= 0;
+           }
+
+         if (rescan)
+           for (next = NEXT_INSN (rescan);
+                next && !INSN_P (next);
+                next = NEXT_INSN (next))
+             continue;
+         while (nops--)
+           emit_insn_before (gen_nop (), insn);
+       }
+    }
+
+  /* Free the data structures.  */
+  while (ms1_labels)
+    {
+      label_info *label = ms1_labels;
+      branch_info *branch, *next;
+      
+      ms1_labels = label->next;
+      for (branch = label->branches; branch; branch = next)
+       {
+         next = branch->next;
+         free (branch);
+       }
+      free (label);
+    }
+}
+
+/* Fixup the looping instructions, do delayed branch scheduling, fixup
+   scheduling hazards.  */
+
+static void
+ms1_machine_reorg (void)
+{
+  if (ms1_flag_delayed_branch)
+    dbr_schedule (get_insns (), dump_file);
+  
+  if (ms1_cpu == PROCESSOR_MS2)
+    ms1_reorg_hazard ();
+}
+\f
 /* Initialize the GCC target structure.  */
 const struct attribute_spec ms1_attribute_table[];
 
@@ -1646,6 +1972,8 @@ const struct attribute_spec ms1_attribute_table[];
 #define TARGET_MUST_PASS_IN_STACK       ms1_pass_in_stack
 #undef  TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES       ms1_arg_partial_bytes
+#undef  TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG  ms1_machine_reorg
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
index cf24671a5965a0adcacb74fe7fcc7ba2ec44ba52..aa01831ade4f4fc9f3ea11fcf100a8eaffaeba5a 100644 (file)
@@ -25,7 +25,8 @@ enum processor_type
 {
   PROCESSOR_MS1_64_001,
   PROCESSOR_MS1_16_002,
-  PROCESSOR_MS1_16_003
+  PROCESSOR_MS1_16_003,
+  PROCESSOR_MS2
 };
 
 enum epilogue_type
@@ -40,7 +41,7 @@ extern enum processor_type ms1_cpu;
 /* A C string constant that tells the GCC driver program options to pass to
    the assembler.  */
 #undef  ASM_SPEC
-#define ASM_SPEC "%{march=ms1-16-002: -march=ms1-16-002} %{march=ms1-16-003: -march=ms1-16-003} %{!march=*: -march=ms1-16-002}"
+#define ASM_SPEC "%{march=ms1-16-002: -march=ms1-16-002} %{march=ms1-16-003: -march=ms1-16-003} %{march=ms2: -march=ms2} %{!march=*: -march=ms1-16-002}"
 
 /* A string to pass to at the end of the command given to the linker.  */
 #undef  LIB_SPEC
@@ -51,7 +52,9 @@ march=MS1-64-001:-T 64-001.ld%s; \
 march=ms1-16-002:-T 16-002.ld%s; \
 march=MS1-16-002:-T 16-002.ld%s; \
 march=ms1-16-003:-T 16-003.ld%s; \
-march=MS1-16-003:-T 16-003.ld%s}"
+march=MS1-16-003:-T 16-003.ld%s; \
+march=ms2:-T ms2.ld%s; \
+march=MS2:-T ms2.ld%s}"
 
 /* A string to pass at the very beginning of the command given to the
    linker.  */
@@ -62,7 +65,9 @@ march=MS1-64-001:%{!mno-crt0:crt0-64-001.o%s} startup-64-001.o%s; \
 march=ms1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
 march=MS1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
 march=ms1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
-march=MS1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s} \
+march=MS1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
+march=ms2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s; \
+march=MS2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s} \
 crti.o%s crtbegin.o%s"
 
 /* A string to pass at the end of the command given to the linker.  */
@@ -73,7 +78,9 @@ march=MS1-64-001:exit-64-001.o%s; \
 march=ms1-16-002:exit-16-002.o%s; \
 march=MS1-16-002:exit-16-002.o%s; \
 march=ms1-16-003:exit-16-003.o%s; \
-march=MS1-16-003:exit-16-003.o%s} \
+march=MS1-16-003:exit-16-003.o%s; \
+march=ms2:exit-ms2.o%s; \
+march=MS2:exit-ms2.o%s} \
  crtend.o%s crtn.o%s"
 \f
 /* Run-time target specifications.  */
@@ -89,6 +96,7 @@ march=MS1-16-003:exit-16-003.o%s} \
 #define TARGET_MS1_64_001 (ms1_cpu == PROCESSOR_MS1_64_001)
 #define TARGET_MS1_16_002 (ms1_cpu == PROCESSOR_MS1_16_002)
 #define TARGET_MS1_16_003 (ms1_cpu == PROCESSOR_MS1_16_003)
+#define TARGET_MS2 (ms1_cpu == PROCESSOR_MS2)
 
 #define TARGET_VERSION  fprintf (stderr, " (ms1)");
 
index b96dfc07d60046bf926db057a17f50c97fc674df..1d5ff5266f362e500c0c14b58d265d3b3b2e7ebf 100644 (file)
 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 \f
+;; UNSPECs
+(define_constants
+  [
+    (UNSPEC_BLOCKAGE 0)
+    (UNSPEC_EI 1)
+    (UNSPEC_DI 2)
+  ])
+
 ;; Attributes
-(define_attr "type" "branch,mem,io,arith,complex,unknown"
+(define_attr "type" "branch,call,load,store,io,arith,complex,unknown"
         (const_string "unknown") )
 
 ;; If the attribute takes numeric values, no `enum' type will be defined and
@@ -36,7 +44,7 @@
 (define_cpu_unit "branch_unit" "other")
 
 (define_insn_reservation "mem_access" 2
-  (eq_attr "type" "mem")
+  (ior (eq_attr "type" "load") (eq_attr "type" "store"))
   "decode_unit+memory_unit*2")
 
 (define_insn_reservation "io_access" 2
@@ -44,7 +52,8 @@
   "decode_unit+memory_unit*2")
 
 (define_insn_reservation "branch_access" 2
-  (eq_attr "type" "branch")
+  (ior (eq_attr "type" "branch")
+       (eq_attr "type" "call"))
   "decode_unit+branch_unit*2")
 
 (define_insn_reservation "arith_access" 1
@@ -64,7 +73,8 @@
 ;; the destination of the branch.  Thus, only type that will be acceptable
 ;; (safe) is the arith type.
 
-(define_delay (eq_attr "type" "branch")
+(define_delay (ior (eq_attr "type" "branch")
+                  (eq_attr "type" "call"))
                 [(eq_attr "type" "arith") (nil) (nil)])
 
 \f
@@ -79,7 +89,7 @@
         (plus:SI (match_dup 0)
                  (const_int -1)))
     (clobber (match_scratch:SI 2 "=X,r"))]
-  "TARGET_MS1_16_003"
+  "TARGET_MS1_16_003 || TARGET_MS2"
   "@
    dbnz\t%0, %l1%#
    #"
     (set (match_dup 0)
         (plus:SI (match_dup 0)
                  (const_int -1)))]
-  "TARGET_MS1_16_003"
+  "TARGET_MS1_16_003 || TARGET_MS2"
   "dbnz\t%0, %l1%#"
-  [(set_attr "length" "4")]
+  [(set_attr "length" "4")
+   (set_attr "type" "branch")]
 )
 
 ;; Split the above to handle the case where operand 0 is in memory
         (plus:SI (match_dup 0)
                  (const_int -1)))
     (clobber (match_scratch:SI 2 ""))]
-  "TARGET_MS1_16_003"
+  "TARGET_MS1_16_003 || TARGET_MS2"
   [(set (match_dup 2) (match_dup 0))
    (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
    (set (match_dup 0) (match_dup 2))
                (label_ref (match_operand 2 "" ""))
                (pc)))
    ]
-  "TARGET_MS1_16_003"
+  "TARGET_MS1_16_003 || TARGET_MS2"
   [(parallel [(set (pc)
                   (if_then_else
                      (ne (match_dup 0) (const_int 0))
    stb %1, %0
    addi %0, r0, %1"
   [(set_attr "length" "4,4,4,4")
-   (set_attr "type" "arith,mem,mem,arith")])
+   (set_attr "type" "arith,load,store,arith")])
 
 (define_insn "*movqi_internal_nobyte"
   [(set (match_operand:QI 0 "register_operand" "=r,r")
   nori   %0, r0, %N1
   ldui   %0, %H1\;addui %0, %0, %L1"
   [(set_attr "length" "4,4,4,4,4,4,4,8")
-   (set_attr "type" "arith,mem,mem,arith,arith,arith,arith,complex")]
+   (set_attr "type" "arith,load,store,arith,arith,arith,arith,complex")]
 )
 
 ;; Floating Point Moves
   ldw    %0, %1
   stw    %1, %0"
   [(set_attr "length" "4,4,4")
-   (set_attr "type" "arith,mem,mem")]
+   (set_attr "type" "arith,load,store")]
 )
 
 (define_expand "movdf"
   ""
   "jal r14, %0%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "register_operand" "")
   ""
   "jal r14, %1%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 ;; Subroutine return
 (define_insn "return_internal"
   ""
   "jal r0, r14%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 ;; Interrupt return
 (define_insn "return_interrupt_internal"
   ""
   "reti r15%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 ;; Subroutine return
 (define_insn "eh_return_internal"
   ""
   "jal r0, r11%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 
 ;; Normal unconditional jump
   ""
   "jal r0,%0%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 (define_insn "tablejump"
   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
   ""
   "jal r0, %0%#"
   [(set_attr "length" "4")
-   (set_attr "type" "branch")])
+   (set_attr "type" "call")])
 
 \f
 (define_expand "prologue"
 ;; Pseudo instruction that prevents the scheduler from moving code above this
 ;; point.
 (define_insn "blockage"
-  [(unspec_volatile [(const_int 0)] 0)]
+  [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
   ""
   ""
   [(set_attr "length" "0")])
 
 ;; Enable interrupts template
 (define_insn "ei"
-  [(unspec_volatile [(const_int 0)] 1)]
+  [(unspec_volatile [(const_int 0)] UNSPEC_EI)]
   ""
   "ei"
   [(set_attr "length" "4")])
 
 ;; Enable interrupts template
 (define_insn "di"
-  [(unspec_volatile [(const_int 0)] 2)]
+  [(unspec_volatile [(const_int 0)] UNSPEC_DI)]
   ""
   "di"
   [(set_attr "length" "4")])