Add fr450 support.
[deliverable/binutils-gdb.git] / cpu / frv.opc
index e4b96575db631553d8543cda0abe0e541fcecd2a..46985b6110ae05376a980ace6a9b5508610cc1ae 100644 (file)
@@ -90,6 +90,8 @@ static int find_major_in_vliw
   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
 static int fr400_check_insn_major_constraints
   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
+static int fr450_check_insn_major_constraints
+  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
 static int fr500_check_insn_major_constraints
   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
 static int fr550_check_insn_major_constraints
@@ -106,6 +108,10 @@ frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
       if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
        return 1; /* is a branch */
       break;
+    case bfd_mach_fr450:
+      if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
+       return 1; /* is a branch */
+      break;
     default:
       if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
        return 1; /* is a branch */
@@ -121,6 +127,7 @@ frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
   switch (mach)
     {
     case bfd_mach_fr400:
+    case bfd_mach_fr450:
       return 0; /* No float insns */
     default:
       if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
@@ -140,6 +147,10 @@ frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
       if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
        return 1; /* is a media insn */
       break;
+    case bfd_mach_fr450:
+      if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
+       return 1; /* is a media insn */
+      break;
     default:
       if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
        return 1; /* is a media insn */
@@ -155,6 +166,9 @@ frv_is_branch_insn (const CGEN_INSN *insn)
   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                           bfd_mach_fr400))
     return 1;
+  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                          bfd_mach_fr450))
+    return 1;
   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                           bfd_mach_fr500))
     return 1;
@@ -168,6 +182,9 @@ frv_is_float_insn (const CGEN_INSN *insn)
   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
     return 1;
+  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                         bfd_mach_fr450))
+    return 1;
   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
     return 1;
@@ -181,6 +198,9 @@ frv_is_media_insn (const CGEN_INSN *insn)
   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
     return 1;
+  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                         bfd_mach_fr450))
+    return 1;
   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
     return 1;
@@ -291,6 +311,42 @@ static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
 /* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
+/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
+};
+
+/* Some insns are assigned specialized implementation units which map to
+   different actual implementation units on different machines.  These
+   tables perform that mapping.  */
+static CGEN_ATTR_VALUE_TYPE fr450_unit_mapping[] =
+{
+/* unit in insn    actual unit */
+/* NIL      */     UNIT_NIL,
+/* I0       */     UNIT_I0,
+/* I1       */     UNIT_I1,
+/* I01      */     UNIT_I01, 
+/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
+/* I3       */     UNIT_NIL,
+/* IALL     */     UNIT_I01, /* only I0 and I1 units */
+/* FM0      */     UNIT_FM0,
+/* FM1      */     UNIT_FM1,
+/* FM01     */     UNIT_FM01,
+/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
+/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
+/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
+/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
+/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
+/* B1       */     UNIT_B0,
+/* B01      */     UNIT_B0,
+/* C        */     UNIT_C,
+/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
+/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
+/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
+/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
+/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
+/* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
+/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
 };
 
@@ -322,6 +378,7 @@ static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
 /* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
 /* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
 /* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
 };
 
@@ -353,6 +410,7 @@ static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
 /* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
 /* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
 /* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
+/* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
 /* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
 };
 
@@ -370,6 +428,10 @@ frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
       vliw->current_vliw = fr400_allowed_vliw;
       vliw->unit_mapping = fr400_unit_mapping;
       break;
+    case bfd_mach_fr450:
+      vliw->current_vliw = fr400_allowed_vliw;
+      vliw->unit_mapping = fr450_unit_mapping;
+      break;
     case bfd_mach_fr550:
       vliw->current_vliw = fr550_allowed_vliw;
       vliw->unit_mapping = fr550_unit_mapping;
@@ -507,6 +569,43 @@ fr400_check_insn_major_constraints (
   return 1;
 }
 
+static int
+fr450_check_insn_major_constraints (
+  FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
+)
+{
+  CGEN_ATTR_VALUE_TYPE other_major;
+
+  /* Our caller guarantees there's at least one other instruction.  */
+  other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
+
+  /* (M4, M5) and (M4, M6) are allowed.  */
+  if (other_major == FR450_MAJOR_M_4)
+    if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
+      return 1;
+
+  /* Otherwise, instructions in even-numbered media categories cannot be
+     executed in parallel with other media instructions.  */
+  switch (major)
+    {
+    case FR450_MAJOR_M_2:
+    case FR450_MAJOR_M_4:
+    case FR450_MAJOR_M_6:
+      return !(other_major >= FR450_MAJOR_M_1
+              && other_major <= FR450_MAJOR_M_6);
+
+    case FR450_MAJOR_M_1:
+    case FR450_MAJOR_M_3:
+    case FR450_MAJOR_M_5:
+      return !(other_major == FR450_MAJOR_M_2
+              || other_major == FR450_MAJOR_M_4
+              || other_major == FR450_MAJOR_M_6);
+
+    default:
+      return 1;
+    }
+}
+
 static int
 find_unit_in_vliw (
   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit
@@ -744,6 +843,9 @@ check_insn_major_constraints (
     case bfd_mach_fr400:
       rc = fr400_check_insn_major_constraints (vliw, major);
       break;
+    case bfd_mach_fr450:
+      rc = fr450_check_insn_major_constraints (vliw, major);
+      break;
     case bfd_mach_fr550:
       rc = fr550_check_insn_major_constraints (vliw, major, insn);
       break;
@@ -784,6 +886,9 @@ frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
     case bfd_mach_fr400:
       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
       break;
+    case bfd_mach_fr450:
+      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
+      break;
     case bfd_mach_fr550:
       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
       break;
This page took 0.024958 seconds and 4 git commands to generate.