aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <dje.gcc@gmail.com>1996-04-03 18:54:49 +0000
committerDavid Edelsohn <dje.gcc@gmail.com>1996-04-03 18:54:49 +0000
commitd302b5f240683111aa39bf23778705cd88a2a078 (patch)
treee945ffad389b010296efdfc25b5aa8869c0dcdbc
parentd1f74cd2c3a5165946c0152eeedd5515a356a189 (diff)
downloadgdb-d302b5f240683111aa39bf23778705cd88a2a078.zip
gdb-d302b5f240683111aa39bf23778705cd88a2a078.tar.gz
gdb-d302b5f240683111aa39bf23778705cd88a2a078.tar.bz2
* 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.
-rw-r--r--opcodes/ChangeLog19
-rw-r--r--opcodes/sparc-dis.c95
-rw-r--r--opcodes/sparc-opc.c119
3 files changed, 161 insertions, 72 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 34ae975..5bfbf2d 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -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
diff --git a/opcodes/sparc-dis.c b/opcodes/sparc-dis.c
index df2f6f0..1815881 100644
--- a/opcodes/sparc-dis.c
+++ b/opcodes/sparc-dis.c
@@ -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. */
{
diff --git a/opcodes/sparc-opc.c b/opcodes/sparc-opc.c
index 6d4e847..c4e22d4 100644
--- a/opcodes/sparc-opc.c
+++ b/opcodes/sparc-opc.c
@@ -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),