* config/tc-mips.c (mips_5400): New variable.

(md_begin, md_parse_option): Handle 5400 options/names.
(macro_build, mips_ip): Check for 5400-specific instructions.
(md_longopts, OPTION_M5400, OPTION_NO_M5400): More command-line support for
5400.

* config/tc-mips.c (validate_mips_insn): New function, checks match versus mask
bits, and also verifies that all bits to be output are actually specified
somewhere.
(md_begin): Call it for 32-bit instructions, instead of doing match/mask check
here.  In case of failure, print a message, but check the rest of the opcode
table before exiting.
This commit is contained in:
Ken Raeburn 1997-10-31 23:21:44 +00:00
parent fcc86d82f7
commit aa2e0460a0
4 changed files with 246 additions and 11 deletions

View File

@ -175,6 +175,34 @@ else
done
fi
vr5400_files="ChangeLog"
if ( echo $* | grep keep\-vr5400 > /dev/null ) ; then
for i in $vr5400_files ; do
if test ! -d $i && (grep sanitize-vr5400 $i > /dev/null) ; then
if [ -n "${verbose}" ] ; then
echo Keeping vr5400 stuff in $i
fi
fi
done
else
for i in $vr5400_files ; do
if test ! -d $i && (grep sanitize-vr5400 $i > /dev/null) ; then
if [ -n "${verbose}" ] ; then
echo Removing traces of \"vr5400\" from $i...
fi
cp $i new
sed '/start\-sanitize\-vr5400/,/end-\sanitize\-vr5400/d' < $i > new
if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
if [ -n "${verbose}" ] ; then
echo Caching $i in .Recover...
fi
mv $i .Recover
fi
mv new $i
fi
done
fi
tx19_files="ChangeLog"
if ( echo $* | grep keep\-tx19 > /dev/null ) ; then
for i in $tx19_files ; do

View File

@ -1,3 +1,20 @@
Fri Oct 31 18:19:55 1997 Ken Raeburn <raeburn@cygnus.com>
start-sanitize-vr5400
* config/tc-mips.c (mips_5400): New variable.
(md_begin, md_parse_option): Handle 5400 options/names.
(macro_build, mips_ip): Check for 5400-specific instructions.
(md_longopts, OPTION_M5400, OPTION_NO_M5400): More command-line
support for 5400.
end-sanitize-vr5400
* config/tc-mips.c (validate_mips_insn): New function, checks
match versus mask bits, and also verifies that all bits to be
output are actually specified somewhere.
(md_begin): Call it for 32-bit instructions, instead of doing
match/mask check here. In case of failure, print a message, but
check the rest of the opcode table before exiting.
Thu Oct 30 13:46:20 1997 Nick Clifton <nickc@cygnus.com>
* config/tc-arm.c (md_apply_fix3): Fix thumb ADR pseudo op. Patch

View File

@ -201,6 +201,34 @@ else
done
fi
vr5400_files="tc-mips.c"
if ( echo $* | grep keep\-vr5400 > /dev/null ) ; then
for i in $vr5400_files ; do
if test ! -d $i && (grep sanitize-vr5400 $i > /dev/null) ; then
if [ -n "${verbose}" ] ; then
echo Keeping vr5400 stuff in $i
fi
fi
done
else
for i in * ; do
if test ! -d $i && (grep sanitize-vr5400 $i > /dev/null) ; then
if [ -n "${verbose}" ] ; then
echo Removing traces of \"vr5400\" from $i...
fi
cp $i new
sed '/start\-sanitize\-vr5400/,/end\-sanitize\-vr5400/d' < $i > new
if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
if [ -n "${verbose}" ] ; then
echo Caching $i in .Recover...
fi
mv $i .Recover
fi
mv new $i
fi
done
fi
tx19_files="tc-mips.c"
if ( echo $* | grep keep\-tx19 > /dev/null ) ; then

View File

@ -203,11 +203,16 @@ static int mips_4010 = -1;
/* Whether the 4100 MADD16 and DMADD16 are permitted. */
static int mips_4100 = -1;
/* start-sanitize-vr5400 */
/* Whether NEC vr5400 instructions are permitted. */
static int mips_5400 = -1;
/* end-sanitize-vr5400 */
/* start-sanitize-r5900 */
/* Whether Toshiba r5900 instructions are permitted. */
static int mips_5900 = -1;
/* end-sanitize-r5900 */
/* end-sanitize-r5900 */
/* Whether Toshiba r3900 instructions are permitted. */
static int mips_3900 = -1;
@ -642,6 +647,8 @@ static void s_mipsend PARAMS ((int));
static void s_file PARAMS ((int));
static void s_mips_stab PARAMS ((int));
static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
static int validate_mips_insn PARAMS ((const struct mips_opcode *));
/* Pseudo-op table.
@ -788,6 +795,7 @@ md_begin ()
boolean ok = false;
register const char *retval = NULL;
register unsigned int i = 0;
int broken = 0;
if (mips_opts.isa == -1)
{
@ -896,6 +904,18 @@ md_begin ()
if (mips_cpu == -1)
mips_cpu = 5000;
}
/* start-sanitize-vr5400 */
else if (strcmp (cpu, "r5400") == 0
|| strcmp (cpu, "mips64r5400") == 0
|| strcmp (cpu, "mips64r5400el") == 0)
{
mips_opts.isa = 4;
if (mips_cpu == -1)
mips_cpu = 5400;
if (mips_5400 == -1)
mips_5400 = 1;
}
/* end-sanitize-vr5400 */
/* start-sanitize-r5900 */
else if (strcmp (cpu, "r5900") == 0
|| strcmp (cpu, "mips64r5900") == 0
@ -955,11 +975,16 @@ md_begin ()
if (mips_4100 < 0)
mips_4100 = 0;
/* start-sanitize-vr5400 */
if (mips_5400 < 0)
mips_5400 = 0;
/* end-sanitize-vr5400 */
/* start-sanitize-r5900 */
if (mips_5900 < 0)
mips_5900 = 0;
/* end-sanitize-r5900 */
/* end-sanitize-r5900 */
if (mips_3900 < 0)
mips_3900 = 0;
@ -997,17 +1022,15 @@ md_begin ()
{
fprintf (stderr, "internal error: can't hash `%s': %s\n",
mips_opcodes[i].name, retval);
/* Probably a memory allocation problem? Give up now. */
as_fatal ("Broken assembler. No assembly attempted.");
}
do
{
if (mips_opcodes[i].pinfo != INSN_MACRO
&& ((mips_opcodes[i].match & mips_opcodes[i].mask)
!= mips_opcodes[i].match))
if (mips_opcodes[i].pinfo != INSN_MACRO)
{
fprintf (stderr, "internal error: bad opcode: `%s' \"%s\"\n",
mips_opcodes[i].name, mips_opcodes[i].args);
as_fatal ("Broken assembler. No assembly attempted.");
if (!validate_mips_insn (&mips_opcodes[i]))
broken = 1;
}
++i;
}
@ -1023,21 +1046,27 @@ md_begin ()
retval = hash_insert (mips16_op_hash, name, (PTR) &mips16_opcodes[i]);
if (retval != NULL)
as_fatal ("internal error: can't hash `%s': %s\n",
as_fatal ("internal: can't hash `%s': %s",
mips16_opcodes[i].name, retval);
do
{
if (mips16_opcodes[i].pinfo != INSN_MACRO
&& ((mips16_opcodes[i].match & mips16_opcodes[i].mask)
!= mips16_opcodes[i].match))
as_fatal ("internal error: bad opcode: `%s' \"%s\"\n",
mips16_opcodes[i].name, mips16_opcodes[i].args);
{
fprintf (stderr, "internal error: bad mips16 opcode: %s %s\n",
mips16_opcodes[i].name, mips16_opcodes[i].args);
broken = 1;
}
++i;
}
while (i < bfd_mips16_num_opcodes
&& strcmp (mips16_opcodes[i].name, name) == 0);
}
if (broken)
as_fatal ("Broken assembler. No assembly attempted.");
/* We add all the general register names to the symbol table. This
helps us detect invalid uses of them. */
for (i = 0; i < 32; i++)
@ -2392,6 +2421,10 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|| (mips_5900
&& (insn.insn_mo->membership & INSN_5900) != 0)
/* end-sanitize-r5900 */
/* start-sanitize-vr5400 */
|| (mips_5400
&& (insn.insn_mo->membership & INSN_5400) != 0)
/* end-sanitize-vr5400 */
|| (mips_3900
&& (insn.insn_mo->membership & INSN_3900) != 0))
/* start-sanitize-r5900 */
@ -6568,6 +6601,107 @@ mips16_macro (ip)
}
}
/* For consistency checking, verify that all bits are specified either
by the match/mask part of the instruction definition, or by the
operand list. */
static int
validate_mips_insn (opc)
const struct mips_opcode *opc;
{
const char *p = opc->args;
char c;
unsigned long used_bits = opc->mask;
if ((used_bits & opc->match) != opc->match)
{
as_bad ("internal: bad mips opcode (mask error): %s %s",
opc->name, opc->args);
return 0;
}
#define USE_BITS(mask,shift) (used_bits |= ((mask) << (shift)))
while (*p)
switch (c = *p++)
{
case ',': break;
case '(': break;
case ')': break;
case '<': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case 'A': break;
case 'B': USE_BITS (OP_MASK_SYSCALL, OP_SH_SYSCALL); break;
case 'C': USE_BITS (OP_MASK_COPZ, OP_SH_COPZ); break;
case 'D': USE_BITS (OP_MASK_FD, OP_SH_FD); break;
case 'E': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
case 'F': break;
case 'G': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
case 'I': break;
case 'L': break;
case 'M': USE_BITS (OP_MASK_CCC, OP_SH_CCC); break;
case 'N': USE_BITS (OP_MASK_BCC, OP_SH_BCC); break;
case 'R': USE_BITS (OP_MASK_FR, OP_SH_FR); break;
case 'S': USE_BITS (OP_MASK_FS, OP_SH_FS); break;
case 'T': USE_BITS (OP_MASK_FT, OP_SH_FT); break;
case 'V': USE_BITS (OP_MASK_FS, OP_SH_FS); break;
case 'W': USE_BITS (OP_MASK_FT, OP_SH_FT); break;
case 'a': USE_BITS (OP_MASK_TARGET, OP_SH_TARGET); break;
case 'b': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
case 'c': USE_BITS (OP_MASK_CODE, OP_SH_CODE); break;
case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
case 'f': break;
case 'h': USE_BITS (OP_MASK_PREFX, OP_SH_PREFX); break;
case 'i': USE_BITS (OP_MASK_IMMEDIATE, OP_SH_IMMEDIATE); break;
case 'j': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'k': USE_BITS (OP_MASK_CACHE, OP_SH_CACHE); break;
case 'l': break;
case 'o': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'p': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'r': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
case 's': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
case 't': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
case 'u': USE_BITS (OP_MASK_IMMEDIATE, OP_SH_IMMEDIATE); break;
case 'v': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
case 'w': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
case 'x': break;
case 'z': break;
/* start-sanitize-vr5400 */
case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break;
case 'e': USE_BITS (OP_MASK_VECBYTE, OP_SH_VECBYTE); break;
case '%': USE_BITS (OP_MASK_VECALIGN, OP_SH_VECALIGN); break;
case '[': break;
case ']': break;
/* end-sanitize-vr5400 */
default:
as_bad ("internal: bad mips opcode (unknown operand type `%c'): %s %s",
c, opc->name, opc->args);
return 0;
}
#undef USE_BITS
/* Some of the trapping instructions (break, t*, sdbbp) have "code"
fields that cannot currently be set by assembly code. Ignore them
for now. */
if (opc->pinfo & INSN_TRAP)
{
static const char *const trap_insns[] = {
"break", "sdbbp",
"teq", "tge", "tgeu", "tlt", "tltu", "tne",
};
int i;
for (i = sizeof(trap_insns)/sizeof(trap_insns[0]) - 1; i >= 0; i--)
if (!strcmp (trap_insns[i], opc->name))
{
used_bits |= 0xffc0;
break;
}
}
if (used_bits != 0xffffffff)
{
as_bad ("internal: bad mips opcode (bits 0x%lx undefined): %s %s",
~used_bits & 0xffffffff, opc->name, opc->args);
return 0;
}
return 1;
}
/* This routine assembles an instruction into its binary format. As a
side effect, it sets one of the global variables imm_reloc or
offset_reloc to the type of relocation to do if one of the operands
@ -6630,6 +6764,9 @@ mips_ip (str, ip)
/* start-sanitize-r5900 */
|| (mips_5900 && (insn->membership & INSN_5900) != 0)
/* end-sanitize-r5900 */
/* start-sanitize-vr5400 */
|| (mips_5400 && (insn->membership & INSN_5400) != 0)
/* end-sanitize-vr5400 */
|| (mips_3900 && (insn->membership & INSN_3900) != 0))
{
ok = true;
@ -6710,6 +6847,10 @@ mips_ip (str, ip)
return;
case ')': /* these must match exactly */
/* start-sanitize-vr5400 */
case '[':
case ']':
/* end-sanitize-vr5400 */
if (*s++ == *args)
continue;
break;
@ -8393,6 +8534,13 @@ struct option md_longopts[] = {
{"no-m1900", no_argument, NULL, OPTION_NO_M3900},
/* end-sanitize-tx19 */
/* start-sanitize-vr5400 */
#define OPTION_M5400 (OPTION_MD_BASE + 28)
{"m5400", no_argument, NULL, OPTION_M5400},
#define OPTION_NO_M5400 (OPTION_MD_BASE + 29)
{"no-m5400", no_argument, NULL, OPTION_NO_M5400},
/* end-sanitize-vr5400 */
#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
#define OPTION_XGOT (OPTION_MD_BASE + 19)
@ -8571,6 +8719,10 @@ md_parse_option (c, arg)
|| strcmp (p, "5k") == 0
|| strcmp (p, "5K") == 0)
mips_cpu = 5000;
/* start-sanitize-vr5400 */
else if (strcmp (p, "5400") == 0)
mips_cpu = 5400;
/* end-sanitize-vr5400 */
/* start-sanitize-r5900 */
else if (strcmp (p, "5900") == 0)
mips_cpu = 5900;
@ -8646,6 +8798,16 @@ md_parse_option (c, arg)
break;
/* end-sanitize-r5900 */
/* start-sanitize-vr5400 */
case OPTION_M5400:
mips_5400 = 1;
break;
case OPTION_NO_M5400:
mips_5400 = 0;
break;
/* end-sanitize-vr5400 */
case OPTION_M3900:
mips_3900 = 1;
break;