]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* sparc-dis.c (opcodes_initialized): Move inside print_insn_sparc.
authorDavid Edelsohn <dje.gcc@gmail.com>
Wed, 3 Apr 1996 18:54:49 +0000 (18:54 +0000)
committerDavid Edelsohn <dje.gcc@gmail.com>
Wed, 3 Apr 1996 18:54:49 +0000 (18:54 +0000)
(current_arch_mask): New static global.
(compute_arch_mask): New static function.
(print_insn_sparc): Delete sparc_v9_p.  New static local
current_mach.  Resort opcode table if current_mach changes.
Generalize "insn not supported" test.
(compare_opcodes): Prefer supported opcodes to nonsupported ones.
Delete test for v9/!v9.
* sparc-opc.c (MASK_*): Use SPARC_OPCODE_ARCH_MASK.
(v6notlet): Define.
(brfc): Split into CBR and FBR for coprocessor/fp branches.
(brfcx): Renamed to FBRX.
(condfc): Renamed to CONDFC.  Pass v6notlet to CBR (standard
coprocessor mnemonics are not supported on the sparclet).
(condf): Renamed to CONDF.
(SLCBCC2): Delete F_ALIAS flag.

opcodes/ChangeLog
opcodes/sparc-dis.c
opcodes/sparc-opc.c

index 34ae975c3cc6698ff4aa8826216b5e286ad12260..5bfbf2d2cb5975d34c99da45e8300073efc4adcb 100644 (file)
@@ -1,3 +1,22 @@
+Wed Apr  3 10:40:45 1996  Doug Evans  <dje@canuck.cygnus.com>
+
+       * sparc-dis.c (opcodes_initialized): Move inside print_insn_sparc.
+       (current_arch_mask): New static global.
+       (compute_arch_mask): New static function.
+       (print_insn_sparc): Delete sparc_v9_p.  New static local
+       current_mach.  Resort opcode table if current_mach changes.
+       Generalize "insn not supported" test.
+       (compare_opcodes): Prefer supported opcodes to nonsupported ones.
+       Delete test for v9/!v9.
+       * sparc-opc.c (MASK_*): Use SPARC_OPCODE_ARCH_MASK.
+       (v6notlet): Define.
+       (brfc): Split into CBR and FBR for coprocessor/fp branches.
+       (brfcx): Renamed to FBRX.
+       (condfc): Renamed to CONDFC.  Pass v6notlet to CBR (standard
+       coprocessor mnemonics are not supported on the sparclet).
+       (condf): Renamed to CONDF.
+       (SLCBCC2): Delete F_ALIAS flag.
+
 Sat Mar 30 21:45:59 1996  Doug Evans  <dje@canuck.cygnus.com>
 
        * sparc-opc.c (sparc_opcodes): rd must be 0 for
index df2f6f0bf2a9da136536d8e69551fbfc7772150c..1815881856040d1d31e5986c3d80ba0867c6a0cc 100644 (file)
@@ -175,12 +175,14 @@ is_delayed_branch (insn)
   return 0;
 }
 
-/* Nonzero of opcode table has been initialized.  */
-static int opcodes_initialized = 0;
-
 /* extern void qsort (); */
 static int compare_opcodes ();
 
+/* Records current mask of SPARC_OPCODE_ARCH_FOO values, used to pass value
+   to compare_opcodes.  */
+static unsigned int current_arch_mask;
+static int compute_arch_mask ();
+
 /* Print one instruction from MEMADDR on INFO->STREAM.
 
    We suffix the instruction with a comment that gives the absolute
@@ -199,13 +201,19 @@ print_insn_sparc (memaddr, info)
   unsigned long insn;
   register unsigned int i;
   register struct opcode_hash *op;
-  int sparc_v9_p = bfd_mach_sparc_v9_p (info->mach);
+  /* Nonzero of opcode table has been initialized.  */
+  static int opcodes_initialized = 0;
+  /* bfd mach number of last call.  */
+  static unsigned long current_mach = 0;
 
-  if (!opcodes_initialized)
+  if (!opcodes_initialized
+      || info->mach != current_mach)
     {
+      current_arch_mask = compute_arch_mask (info->mach);
       qsort ((char *) sparc_opcodes, sparc_num_opcodes,
             sizeof (sparc_opcodes[0]), compare_opcodes);
       build_hash_table (sparc_opcodes, opcode_hash_table, sparc_num_opcodes);
+      current_mach = info->mach;
       opcodes_initialized = 1;
     }
 
@@ -230,16 +238,8 @@ print_insn_sparc (memaddr, info)
     {
       CONST struct sparc_opcode *opcode = op->opcode;
 
-      /* ??? These architecture tests need to be more selective.  */
-
-      /* If the current architecture isn't sparc64, skip sparc64 insns.  */
-      if (!sparc_v9_p
-         && V9_ONLY_P (opcode))
-       continue;
-
-      /* If the current architecture is sparc64, skip sparc32 only insns.  */
-      if (sparc_v9_p
-         && ! V9_P (opcode))
+      /* If the insn isn't supported by the current architecture, skip it.  */
+      if (! (opcode->architecture & current_arch_mask))
        continue;
 
       if ((opcode->match & insn) == opcode->match
@@ -267,6 +267,10 @@ print_insn_sparc (memaddr, info)
              && strchr (opcode->args, 'r') != 0)
              /* Can't do simple format if source and dest are different.  */
              continue;
+         if (X_RS2 (insn) != X_RD (insn)
+             && strchr (opcode->args, 'O') != 0)
+             /* Can't do simple format if source and dest are different.  */
+             continue;
 
          (*info->fprintf_func) (stream, opcode->name);
 
@@ -325,6 +329,7 @@ print_insn_sparc (memaddr, info)
                    break;
 
                  case '2':
+                 case 'O':
                    reg (X_RS2 (insn));
                    break;
 
@@ -691,6 +696,34 @@ print_insn_sparc (memaddr, info)
   return sizeof (buffer);
 }
 
+/* Given BFD mach number, return a mask of SPARC_OPCODE_ARCH_FOO values.  */
+
+static int
+compute_arch_mask (unsigned long mach)
+{
+  switch (mach)
+    {
+    case 0 :
+    case bfd_mach_sparc :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8);
+    case bfd_mach_sparc_sparclet :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET);
+    case bfd_mach_sparc_sparclite :
+      /* sparclites insns are recognized by default (because that's how
+        they've always been treated, for better or worse).  Kludge this by
+        indicating generic v8 is also selected.  */
+      return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
+             | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8));
+    case bfd_mach_sparc_v8plus :
+    case bfd_mach_sparc_v9 :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
+    case bfd_mach_sparc_v8plusa :
+    case bfd_mach_sparc_v9a :
+      return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A);
+    }
+  abort ();
+}
+
 /* Compare opcodes A and B.  */
 
 static int
@@ -703,6 +736,24 @@ compare_opcodes (a, b)
   unsigned long int lose0 = op0->lose, lose1 = op1->lose;
   register unsigned int i;
 
+  /* If one (and only one) insn isn't supported by the current architecture,
+     prefer the one that is.  If neither are supported, but they're both for
+     the same architecture, continue processing.  Otherwise (both unsupported
+     and for different architectures), prefer lower numbered arch's (fudged
+     by comparing the bitmasks).  */
+  if (op0->architecture & current_arch_mask)
+    {
+      if (! (op1->architecture & current_arch_mask))
+       return -1;
+    }
+  else
+    {
+      if (op1->architecture & current_arch_mask)
+       return 1;
+      else if (op0->architecture != op1->architecture)
+       return op0->architecture - op1->architecture;
+    }
+
   /* If a bit is set in both match and lose, there is something
      wrong with the opcode table.  */
   if (match0 & lose0)
@@ -743,10 +794,6 @@ compare_opcodes (a, b)
        return x1 - x0;
     }
 
-  /* Put non-sparc64 insns ahead of sparc64 ones.  */
-  if (V9_ONLY_P (op0) != V9_ONLY_P (op1))
-    return V9_ONLY_P (op0) - V9_ONLY_P (op1);
-
   /* They are functionally equal.  So as long as the opcode table is
      valid, we can put whichever one first we want, on aesthetic grounds.  */
 
@@ -762,12 +809,14 @@ compare_opcodes (a, b)
      better have the same opcode.  This is a sanity check on the table.  */
   i = strcmp (op0->name, op1->name);
   if (i)
+    {
       if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */
-         return i;
+       return i;
       else
-         fprintf (stderr,
-                  "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
-                  op0->name, op1->name);
+       fprintf (stderr,
+                "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
+                op0->name, op1->name);
+    }
 
   /* Fewer arguments are preferred.  */
   {
index 6d4e84706d704616262212a2490fe147ab48923b..c4e22d458d5daf44da29d9352fe5546a53aa5e73 100644 (file)
@@ -29,18 +29,21 @@ Boston, MA 02111-1307, USA. */
 #include "opcode/sparc.h"
 
 /* Some defines to make life easy.  */
-#define MASK_V6                (1 << SPARC_OPCODE_ARCH_V6)
-#define MASK_V7                (1 << SPARC_OPCODE_ARCH_V7)
-#define MASK_V8                (1 << SPARC_OPCODE_ARCH_V8)
-#define MASK_SPARCLET  (1 << SPARC_OPCODE_ARCH_SPARCLET)
-#define MASK_SPARCLITE (1 << SPARC_OPCODE_ARCH_SPARCLITE)
-#define MASK_V9                (1 << SPARC_OPCODE_ARCH_V9)
-#define MASK_V9A       (1 << SPARC_OPCODE_ARCH_V9A)
+#define MASK_V6                SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
+#define MASK_V7                SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7)
+#define MASK_V8                SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
+#define MASK_SPARCLET  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET)
+#define MASK_SPARCLITE SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
+#define MASK_V9                SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9)
+#define MASK_V9A       SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)
 
 /* Bit masks of architectures supporting the insn.  */
 
 #define v6             (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \
                         | MASK_SPARCLITE | MASK_V9 | MASK_V9A)
+/* v6 insns not supported on the sparclet */
+#define v6notlet       (MASK_V6 | MASK_V7 | MASK_V8 \
+                        | MASK_SPARCLITE | MASK_V9 | MASK_V9A)
 #define v7             (MASK_V7 | MASK_V8 | MASK_SPARCLET \
                         | MASK_SPARCLITE | MASK_V9 | MASK_V9A)
 /* Although not all insns are implemented in hardware, sparclite is defined
@@ -59,7 +62,9 @@ Boston, MA 02111-1307, USA.   */
                         | MASK_SPARCLET | MASK_SPARCLITE)
 
 /* Table of opcode architectures.
-   The order is defined in opcode/sparc.h.  */
+   The order is defined in opcode/sparc.h.
+   The names must match the arguments to gas' -A<arch> option in tc-sparc.c.
+*/
 const struct sparc_opcode_arch sparc_opcode_archs[] = {
   { "v6", MASK_V6 },
   { "v7", MASK_V6 | MASK_V7 },
@@ -67,6 +72,7 @@ const struct sparc_opcode_arch sparc_opcode_archs[] = {
   { "sparclet", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET },
   { "sparclite", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLITE },
   /* ??? Don't some v8 priviledged insns conflict with v9?  */
+  /* ??? Will we want v8plus{,a} entries?  */
   { "v9", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 },
   /* v9 with ultrasparc additions */
   { "v9a", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A },
@@ -979,12 +985,12 @@ cond ("bcc",      "tcc",  CONDCC, F_CONDBR),
 cond ("bcs",   "tcs",  CONDCS, F_CONDBR),
 cond ("be",    "te",   CONDE, F_CONDBR),
 cond ("bg",    "tg",   CONDG, F_CONDBR),
-cond ("bgt",   "tgt",   CONDG, F_CONDBR|F_ALIAS),
+cond ("bgt",   "tgt",  CONDG, F_CONDBR|F_ALIAS),
 cond ("bge",   "tge",  CONDGE, F_CONDBR),
 cond ("bgeu",  "tgeu", CONDGEU, F_CONDBR|F_ALIAS), /* for cc */
 cond ("bgu",   "tgu",  CONDGU, F_CONDBR),
 cond ("bl",    "tl",   CONDL, F_CONDBR),
-cond ("blt",   "tlt",   CONDL, F_CONDBR|F_ALIAS),
+cond ("blt",   "tlt",  CONDL, F_CONDBR|F_ALIAS),
 cond ("ble",   "tle",  CONDLE, F_CONDBR),
 cond ("bleu",  "tleu", CONDLEU, F_CONDBR),
 cond ("blu",   "tlu",  CONDLU, F_CONDBR|F_ALIAS), /* for cs */
@@ -1249,11 +1255,18 @@ cond ("bz",     "tz",   CONDZ, F_CONDBR|F_ALIAS), /* for e */
 #undef FM_QF /* v9 */
 #undef FM_SF /* v9 */
 
-#define brfc(opcode, mask, lose, flags) \
+/* Coprocessor branches.  */
+#define CBR(opcode, mask, lose, flags, arch) \
+ { opcode, (mask), ANNUL|(lose), "l",    flags|F_DELAYED, arch }, \
+ { opcode, (mask)|ANNUL, (lose), ",a l", flags|F_DELAYED, arch }
+
+/* Floating point branches.  */
+#define FBR(opcode, mask, lose, flags) \
  { opcode, (mask), ANNUL|(lose), "l",    flags|F_DELAYED, v6 }, \
  { opcode, (mask)|ANNUL, (lose), ",a l", flags|F_DELAYED, v6 }
 
-#define brfcx(opcode, mask, lose, flags) /* v9 */ \
+/* V9 extended floating point branches.  */
+#define FBRX(opcode, mask, lose, flags) /* v9 */ \
  { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), "6,G",      flags|F_DELAYED, v9 }, \
  { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), ",T 6,G",   flags|F_DELAYED, v9 }, \
  { opcode, FBFCC(0)|(mask)|BPRED|ANNUL, FBFCC(~0)|(lose), ",a 6,G",   flags|F_DELAYED, v9 }, \
@@ -1279,43 +1292,51 @@ cond ("bz",     "tz",   CONDZ, F_CONDBR|F_ALIAS), /* for e */
  { opcode, FBFCC(3)|(mask), ANNUL|BPRED|FBFCC(~3)|(lose), ",N 9,G",   flags|F_DELAYED, v9 }, \
  { opcode, FBFCC(3)|(mask)|ANNUL, BPRED|FBFCC(~3)|(lose), ",a,N  9,G", flags|F_DELAYED, v9 }
 
-/* v9: We must put `brfcx' before `brfc', to ensure that we never match
+/* v9: We must put `FBRX' before `FBR', to ensure that we never match
    v9: something against an expression unless it is an expression.  Otherwise,
    v9: we end up with undefined symbol tables entries, because they get added,
    v9: but are not deleted if the pattern fails to match.  */
 
-#define condfc(fop, cop, mask, flags) \
-  brfcx(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \
-  brfc(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \
-  brfc(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags)
-
-#define condf(fop, mask, flags) \
-  brfcx(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \
-  brfc(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags)
-
-condfc("fb",   "cb",    0x8, 0),
-condfc("fba",  "cba",   0x8, F_ALIAS),
-condfc("fbe",  "cb0",   0x9, 0),
-condf("fbz",            0x9, F_ALIAS),
-condfc("fbg",  "cb2",   0x6, 0),
-condfc("fbge", "cb02",  0xb, 0),
-condfc("fbl",  "cb1",   0x4, 0),
-condfc("fble", "cb01",  0xd, 0),
-condfc("fblg", "cb12",  0x2, 0),
-condfc("fbn",  "cbn",   0x0, 0),
-condfc("fbne", "cb123", 0x1, 0),
-condf("fbnz",           0x1, F_ALIAS),
-condfc("fbo",  "cb012", 0xf, 0),
-condfc("fbu",  "cb3",   0x7, 0),
-condfc("fbue", "cb03",  0xa, 0),
-condfc("fbug", "cb23",  0x5, 0),
-condfc("fbuge",        "cb023", 0xc, 0),
-condfc("fbul", "cb13",  0x3, 0),
-condfc("fbule",        "cb013", 0xe, 0),
-
-#undef condfc
-#undef brfc
-#undef brfcx   /* v9 */
+#define CONDFC(fop, cop, mask, flags) \
+  FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \
+  FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \
+  CBR(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags, v6notlet)
+
+#define CONDFCL(fop, cop, mask, flags) \
+  FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \
+  FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \
+  CBR(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags, v6)
+
+#define CONDF(fop, mask, flags) \
+  FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \
+  FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags)
+
+CONDFC  ("fb",    "cb",    0x8, 0),
+CONDFCL ("fba",          "cba",   0x8, F_ALIAS),
+CONDFC  ("fbe",          "cb0",   0x9, 0),
+CONDF   ("fbz",            0x9, F_ALIAS),
+CONDFC  ("fbg",          "cb2",   0x6, 0),
+CONDFC  ("fbge",  "cb02",  0xb, 0),
+CONDFC  ("fbl",          "cb1",   0x4, 0),
+CONDFC  ("fble",  "cb01",  0xd, 0),
+CONDFC  ("fblg",  "cb12",  0x2, 0),
+CONDFCL ("fbn",          "cbn",   0x0, 0),
+CONDFC  ("fbne",  "cb123", 0x1, 0),
+CONDF   ("fbnz",           0x1, F_ALIAS),
+CONDFC  ("fbo",          "cb012", 0xf, 0),
+CONDFC  ("fbu",          "cb3",   0x7, 0),
+CONDFC  ("fbue",  "cb03",  0xa, 0),
+CONDFC  ("fbug",  "cb23",  0x5, 0),
+CONDFC  ("fbuge", "cb023", 0xc, 0),
+CONDFC  ("fbul",  "cb13",  0x3, 0),
+CONDFC  ("fbule", "cb013", 0xe, 0),
+
+#undef CONDFC
+#undef CONDFCL
+#undef CONDF
+#undef CBR
+#undef FBR
+#undef FBRX    /* v9 */
 
 { "jmp",       F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0),        "1+2", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */
 { "jmp",       F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0),    "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */
@@ -1516,14 +1537,14 @@ COMMUTEOP ("smuld", 0x0d, sparclet),
 { "cpull",     F3(2, 0x36, 0)|ASI(2), F3(~2, ~0x36, ~0)|ASI(~2)|RS1(~0)|RS2(~0), "d", 0, sparclet },
 
 /* sparclet coprocessor branch insns */
-/* FIXME: We have to mark these as aliases until we can sort opcodes based
-   on selected cpu.  */
 #define SLCBCC2(opcode, mask, lose) \
- { opcode, (mask), ANNUL|(lose), "l",    F_DELAYED|F_CONDBR|F_ALIAS, sparclet }, \
- { opcode, (mask)|ANNUL, (lose), ",a l", F_DELAYED|F_CONDBR|F_ALIAS, sparclet }
+ { opcode, (mask), ANNUL|(lose), "l",    F_DELAYED|F_CONDBR, sparclet }, \
+ { opcode, (mask)|ANNUL, (lose), ",a l", F_DELAYED|F_CONDBR, sparclet }
 #define SLCBCC(opcode, mask) \
   SLCBCC2(opcode, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)))
 
+/* cbn,cba can't be defined here because they're defined elsewhere and GAS
+   requires all mnemonics of the same name to be consecutive.  */
 /*SLCBCC("cbn", 0), - already defined */
 SLCBCC("cbe", 1),
 SLCBCC("cbf", 2),