Put the qsort() back in in sparc-pinsn.c

This commit is contained in:
Per Bothner
1992-01-29 01:33:48 +00:00
parent 69bbcf05f4
commit 4a074bea28
2 changed files with 137 additions and 0 deletions

View File

@@ -1,3 +1,7 @@
Tue Jan 28 17:32:13 1992 Per Bothner (bothner at cygnus.com)
* sparc-pinsn.c: Put the qsort() back in.
Mon Jan 27 18:51:03 1992 John Gilmore (gnu at cygnus.com)
* findvar.c (read_register, write_register): Handle machines

View File

@@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "string.h"
#include "target.h"
#define SORT_NEEDED
extern char *reg_names[];
#define freg_names (&reg_names[4 * 8])
@@ -89,6 +91,11 @@ is_delayed_branch (insn)
return 0;
}
#ifdef SORT_NEEDED
static int opcodes_sorted = 0;
extern void qsort ();
#endif
/* Print one instruction from MEMADDR on STREAM. */
int
print_insn (memaddr, stream)
@@ -99,6 +106,16 @@ print_insn (memaddr, stream)
register unsigned int i;
#ifdef SORT_NEEDED
if (!opcodes_sorted)
{
static int compare_opcodes ();
qsort ((char *) sparc_opcodes, NUMOPCODES,
sizeof (sparc_opcodes[0]), compare_opcodes);
opcodes_sorted = 1;
}
#endif
read_memory (memaddr, &insn, sizeof (insn));
for (i = 0; i < NUMOPCODES; ++i)
@@ -178,14 +195,20 @@ print_insn (memaddr, stream)
#define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
case 'e':
case 'v': /* double/even */
case 'V': /* quad/multiple of 4 */
freg (insn.rs1);
break;
case 'f':
case 'B': /* double/even */
case 'R': /* quad/multiple of 4 */
freg (insn.rs2);
break;
case 'g':
case 'H': /* double/even */
case 'J': /* quad/multiple of 4 */
freg (insn.rd);
break;
#undef freg
@@ -346,3 +369,113 @@ print_insn (memaddr, stream)
printf_filtered ("%#8x", insn.code);
return sizeof (insn);
}
#ifdef SORT_NEEDED
/* Compare opcodes A and B. */
static int
compare_opcodes (a, b)
char *a, *b;
{
struct sparc_opcode *op0 = (struct sparc_opcode *) a;
struct sparc_opcode *op1 = (struct sparc_opcode *) b;
unsigned long int match0 = op0->match, match1 = op1->match;
unsigned long int lose0 = op0->lose, lose1 = op1->lose;
register unsigned int i;
/* If a bit is set in both match and lose, there is something
wrong with the opcode table. */
if (match0 & lose0)
{
fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
op0->name, match0, lose0);
op0->lose &= ~op0->match;
lose0 = op0->lose;
}
if (match1 & lose1)
{
fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
op1->name, match1, lose1);
op1->lose &= ~op1->match;
lose1 = op1->lose;
}
/* Because the bits that are variable in one opcode are constant in
another, it is important to order the opcodes in the right order. */
for (i = 0; i < 32; ++i)
{
unsigned long int x = 1 << i;
int x0 = (match0 & x) != 0;
int x1 = (match1 & x) != 0;
if (x0 != x1)
return x1 - x0;
}
for (i = 0; i < 32; ++i)
{
unsigned long int x = 1 << i;
int x0 = (lose0 & x) != 0;
int x1 = (lose1 & x) != 0;
if (x0 != x1)
return x1 - x0;
}
/* They are functionally equal. So as long as the opcode table is
valid, we can put whichever one first we want, on aesthetic grounds. */
/* Our first aesthetic ground is that aliases defer to real insns. */
{
int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
if (alias_diff != 0)
/* Put the one that isn't an alias first. */
return alias_diff;
}
/* Except for aliases, two "identical" instructions had
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;
else
fprintf (stderr,
"Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
op0->name, op1->name);
/* Fewer arguments are preferred. */
{
int length_diff = strlen (op0->args) - strlen (op1->args);
if (length_diff != 0)
/* Put the one with fewer arguments first. */
return length_diff;
}
/* Put 1+i before i+1. */
{
char *p0 = (char *) strchr(op0->args, '+');
char *p1 = (char *) strchr(op1->args, '+');
if (p0 && p1)
{
/* There is a plus in both operands. Note that a plus
sign cannot be the first character in args,
so the following [-1]'s are valid. */
if (p0[-1] == 'i' && p1[1] == 'i')
/* op0 is i+1 and op1 is 1+i, so op1 goes first. */
return 1;
if (p0[1] == 'i' && p1[-1] == 'i')
/* op0 is 1+i and op1 is i+1, so op0 goes first. */
return -1;
}
}
/* They are, as far as we can tell, identical.
Since qsort may have rearranged the table partially, there is
no way to tell which one was first in the opcode table as
written, so just say there are equal. */
return 0;
}
#endif