mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 11:39:26 +08:00
* cgen.c: #include symcat.h.
* config/tc-m32r.c: Likewise.
This commit is contained in:
@ -1,3 +1,8 @@
|
|||||||
|
Mon Feb 23 11:29:06 1998 Doug Evans <devans@seba.cygnus.com>
|
||||||
|
|
||||||
|
* cgen.c: #include symcat.h.
|
||||||
|
* config/tc-m32r.c: Likewise.
|
||||||
|
|
||||||
Mon Feb 23 10:27:40 1998 Jeffrey A Law (law@cygnus.com)
|
Mon Feb 23 10:27:40 1998 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
* config/tc-mips.c (mips_ip, case 'P'): Make 'P' arguments be
|
* config/tc-mips.c (mips_ip, case 'P'): Make 'P' arguments be
|
||||||
|
@ -22,12 +22,14 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "as.h"
|
#include "as.h"
|
||||||
#include "subsegs.h"
|
#include "subsegs.h"
|
||||||
|
#include "symcat.h"
|
||||||
#include "cgen-opc.h"
|
#include "cgen-opc.h"
|
||||||
|
|
||||||
/* Structure to hold all of the different components describing an individual instruction. */
|
/* Structure to hold all of the different components describing an individual instruction. */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const CGEN_INSN * insn;
|
const CGEN_INSN * insn;
|
||||||
|
const CGEN_INSN * orig_insn;
|
||||||
CGEN_FIELDS fields;
|
CGEN_FIELDS fields;
|
||||||
#ifdef CGEN_INT_INSN
|
#ifdef CGEN_INT_INSN
|
||||||
cgen_insn_t buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)];
|
cgen_insn_t buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)];
|
||||||
@ -125,8 +127,10 @@ struct option md_longopts[] =
|
|||||||
{"m32rx", no_argument, NULL, OPTION_M32RX},
|
{"m32rx", no_argument, NULL, OPTION_M32RX},
|
||||||
#define OPTION_WARN (OPTION_MD_BASE + 1)
|
#define OPTION_WARN (OPTION_MD_BASE + 1)
|
||||||
{"warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_WARN},
|
{"warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_WARN},
|
||||||
|
{"Wp", no_argument, NULL, OPTION_WARN},
|
||||||
#define OPTION_NO_WARN (OPTION_MD_BASE + 2)
|
#define OPTION_NO_WARN (OPTION_MD_BASE + 2)
|
||||||
{"no-warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_WARN},
|
{"no-warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_WARN},
|
||||||
|
{"Wnp", no_argument, NULL, OPTION_NO_WARN},
|
||||||
/* end-sanitize-m32rx */
|
/* end-sanitize-m32rx */
|
||||||
|
|
||||||
#if 0 /* not supported yet */
|
#if 0 /* not supported yet */
|
||||||
@ -188,6 +192,10 @@ md_show_usage (stream)
|
|||||||
--warn-explicit-parallel-conflicts Warn when parallel instrucitons violate contraints\n");
|
--warn-explicit-parallel-conflicts Warn when parallel instrucitons violate contraints\n");
|
||||||
fprintf (stream, "\
|
fprintf (stream, "\
|
||||||
--no-warn-explicit-parallel-conflicts Do not warn when parallel instrucitons violate contraints\n");
|
--no-warn-explicit-parallel-conflicts Do not warn when parallel instrucitons violate contraints\n");
|
||||||
|
fprintf (stream, "\
|
||||||
|
--Wp Synonym for --warn-explicit-parallel-conflicts\n");
|
||||||
|
fprintf (stream, "\
|
||||||
|
--Wnp Synonym for --no-warn-explicit-parallel-conflicts\n");
|
||||||
/* end-sanitize-m32rx */
|
/* end-sanitize-m32rx */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -387,6 +395,11 @@ md_begin ()
|
|||||||
|
|
||||||
/* start-sanitize-m32rx */
|
/* start-sanitize-m32rx */
|
||||||
|
|
||||||
|
#define OPERAND_IS_COND_BIT(operand, indices, index) \
|
||||||
|
(CGEN_OPERAND_INSTANCE_HW (operand)->type == HW_H_COND \
|
||||||
|
|| (CGEN_OPERAND_INSTANCE_HW (operand)->type == HW_H_CR \
|
||||||
|
&& (indices [index] == 0 || indices [index] == 1)))
|
||||||
|
|
||||||
/* Returns true if an output of instruction 'a' is referenced by an operand
|
/* Returns true if an output of instruction 'a' is referenced by an operand
|
||||||
of instruction 'b'. If 'check_outputs' is true then b's outputs are
|
of instruction 'b'. If 'check_outputs' is true then b's outputs are
|
||||||
checked, otherwise its inputs are examined. */
|
checked, otherwise its inputs are examined. */
|
||||||
@ -414,18 +427,41 @@ first_writes_to_seconds_operands (a, b, check_outputs)
|
|||||||
if (CGEN_OPERAND_INSTANCE_TYPE (a_operands) == CGEN_OPERAND_INSTANCE_OUTPUT)
|
if (CGEN_OPERAND_INSTANCE_TYPE (a_operands) == CGEN_OPERAND_INSTANCE_OUTPUT)
|
||||||
{
|
{
|
||||||
int b_index;
|
int b_index;
|
||||||
|
|
||||||
/* Scan operand list of 'b' looking for an operand that references
|
/* Special Case:
|
||||||
the same hardware element, and which goes in the right direction. */
|
The Condition bit 'C' is a shadow of the CBR register (control
|
||||||
for (b_index = 0;
|
register 1) and also a shadow of bit 31 of the program status
|
||||||
CGEN_OPERAND_INSTANCE_TYPE (b_operands) != CGEN_OPERAND_INSTANCE_END;
|
word (control register 0). For now this is handled here, rather
|
||||||
b_index ++, b_operands ++)
|
than by cgen.... */
|
||||||
|
|
||||||
|
if (OPERAND_IS_COND_BIT (a_operands, a->indices, a_index))
|
||||||
{
|
{
|
||||||
if ((CGEN_OPERAND_INSTANCE_TYPE (b_operands) ==
|
/* Scan operand list of 'b' looking for another reference to the
|
||||||
(check_outputs ? CGEN_OPERAND_INSTANCE_OUTPUT : CGEN_OPERAND_INSTANCE_INPUT))
|
condition bit, which goes in the right direction. */
|
||||||
&& (CGEN_OPERAND_INSTANCE_HW (b_operands) == CGEN_OPERAND_INSTANCE_HW (a_operands))
|
for (b_index = 0;
|
||||||
&& (a->indices [a_index] == b->indices [b_index]))
|
CGEN_OPERAND_INSTANCE_TYPE (b_operands) != CGEN_OPERAND_INSTANCE_END;
|
||||||
return 1;
|
b_index ++, b_operands ++)
|
||||||
|
{
|
||||||
|
if ((CGEN_OPERAND_INSTANCE_TYPE (b_operands) ==
|
||||||
|
(check_outputs ? CGEN_OPERAND_INSTANCE_OUTPUT : CGEN_OPERAND_INSTANCE_INPUT))
|
||||||
|
&& OPERAND_IS_COND_BIT (b_operands, b->indices, b_index))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Scan operand list of 'b' looking for an operand that references
|
||||||
|
the same hardware element, and which goes in the right direction. */
|
||||||
|
for (b_index = 0;
|
||||||
|
CGEN_OPERAND_INSTANCE_TYPE (b_operands) != CGEN_OPERAND_INSTANCE_END;
|
||||||
|
b_index ++, b_operands ++)
|
||||||
|
{
|
||||||
|
if ((CGEN_OPERAND_INSTANCE_TYPE (b_operands) ==
|
||||||
|
(check_outputs ? CGEN_OPERAND_INSTANCE_OUTPUT : CGEN_OPERAND_INSTANCE_INPUT))
|
||||||
|
&& (CGEN_OPERAND_INSTANCE_HW (b_operands) == CGEN_OPERAND_INSTANCE_HW (a_operands))
|
||||||
|
&& (a->indices [a_index] == b->indices [b_index]))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +474,7 @@ static int
|
|||||||
writes_to_pc (a)
|
writes_to_pc (a)
|
||||||
m32r_insn * a;
|
m32r_insn * a;
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0 /* Once PC operands are working.... */
|
||||||
const CGEN_OPERAND_INSTANCE * a_operands == CGEN_INSN_OPERANDS (a->insn);
|
const CGEN_OPERAND_INSTANCE * a_operands == CGEN_INSN_OPERANDS (a->insn);
|
||||||
|
|
||||||
if (a_operands == NULL)
|
if (a_operands == NULL)
|
||||||
@ -569,6 +605,37 @@ assemble_parallel_insn (str, str2)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Temporary Hack:
|
||||||
|
If the instruciton is relaxable, reparse it looking for a non-relaxable variant.
|
||||||
|
(We do not want to relax instructions inside a parallel construction, and if it
|
||||||
|
turns out that the branch is too far for the displacement field available to the
|
||||||
|
non-relaxed instruction, then this is the programmer's fault.
|
||||||
|
A better solution would be to pass attribute requirements to assemble_insn() so
|
||||||
|
that the relaxable variant would not be accepted as a valid parse of the instruction. */
|
||||||
|
|
||||||
|
if (CGEN_INSN_ATTR (first.insn, CGEN_INSN_RELAXABLE) != 0)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
char * p;
|
||||||
|
/* Oh dear - the insn is relaxable, so it might be replaced with a longer,
|
||||||
|
non-parallel version. Try appending ".s" to the instruction and reparsing it. */
|
||||||
|
|
||||||
|
p = strchr (str, ' ');
|
||||||
|
if (p == NULL)
|
||||||
|
abort();
|
||||||
|
* p = 0;
|
||||||
|
sprintf (buf, "%s.s %s", str, p + 1);
|
||||||
|
* p = ' ';
|
||||||
|
|
||||||
|
/* Reset fixup list to empty. */
|
||||||
|
cgen_save_fixups();
|
||||||
|
|
||||||
|
first.insn = CGEN_SYM (assemble_insn) (buf, & first.fields, first.buffer, & errmsg);
|
||||||
|
|
||||||
|
if (first.insn == NULL)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
*str2 = '|'; /* Restore the original assembly text, just in case it is needed. */
|
*str2 = '|'; /* Restore the original assembly text, just in case it is needed. */
|
||||||
str3 = str; /* Save the original string pointer. */
|
str3 = str; /* Save the original string pointer. */
|
||||||
str = str2 + 2; /* Advanced past the parsed string. */
|
str = str2 + 2; /* Advanced past the parsed string. */
|
||||||
@ -582,7 +649,11 @@ assemble_parallel_insn (str, str2)
|
|||||||
doesn't seem right. Perhaps allow passing fields like we do insn. */
|
doesn't seem right. Perhaps allow passing fields like we do insn. */
|
||||||
/* FIXME: ALIAS insns do not have operands, so we use this function
|
/* FIXME: ALIAS insns do not have operands, so we use this function
|
||||||
to find the equivalent insn and overwrite the value stored in our
|
to find the equivalent insn and overwrite the value stored in our
|
||||||
structure. When aliases behave differently this may have to change. */
|
structure. We still need the original insn, however, since this
|
||||||
|
may have certain attributes that are not present in the unaliased
|
||||||
|
version (eg relaxability). When aliases behave differently this
|
||||||
|
may have to change. */
|
||||||
|
first.orig_insn = first.insn;
|
||||||
first.insn = m32r_cgen_get_insn_operands (first.insn, bfd_getb16 ((char *) first.buffer), 16,
|
first.insn = m32r_cgen_get_insn_operands (first.insn, bfd_getb16 ((char *) first.buffer), 16,
|
||||||
first.indices);
|
first.indices);
|
||||||
if (first.insn == NULL)
|
if (first.insn == NULL)
|
||||||
@ -614,7 +685,33 @@ assemble_parallel_insn (str, str2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See comment above. */
|
||||||
|
if (CGEN_INSN_ATTR (second.insn, CGEN_INSN_RELAXABLE) != 0)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
char * p;
|
||||||
|
/* Oh dear - the insn is relaxable, so it might be replaced with a longer,
|
||||||
|
non-parallel version. Try appending ".s" to the instruction and reparsing it. */
|
||||||
|
|
||||||
|
p = strchr (str, ' ');
|
||||||
|
if (p == NULL)
|
||||||
|
abort();
|
||||||
|
* p = 0;
|
||||||
|
sprintf (buf, "%s.s %s", str, p + 1);
|
||||||
|
* p = ' ';
|
||||||
|
|
||||||
|
/* Reset fixup list to empty, preserving saved fixups. */
|
||||||
|
cgen_restore_fixups();
|
||||||
|
cgen_save_fixups();
|
||||||
|
|
||||||
|
second.insn = CGEN_SYM (assemble_insn) (buf, & second.fields, second.buffer, & errmsg);
|
||||||
|
|
||||||
|
if (second.insn == NULL)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the indicies of the operands of the instruction. */
|
/* Get the indicies of the operands of the instruction. */
|
||||||
|
second.orig_insn = second.insn;
|
||||||
second.insn = m32r_cgen_get_insn_operands (second.insn, bfd_getb16 ((char *) second.buffer), 16,
|
second.insn = m32r_cgen_get_insn_operands (second.insn, bfd_getb16 ((char *) second.buffer), 16,
|
||||||
second.indices);
|
second.indices);
|
||||||
if (second.insn == NULL)
|
if (second.insn == NULL)
|
||||||
@ -643,7 +740,7 @@ assemble_parallel_insn (str, str2)
|
|||||||
cgen_swap_fixups ();
|
cgen_swap_fixups ();
|
||||||
|
|
||||||
/* Write it out. */
|
/* Write it out. */
|
||||||
(void) cgen_asm_finish_insn (first.insn, first.buffer,
|
(void) cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||||
CGEN_FIELDS_BITSIZE (& first.fields));
|
CGEN_FIELDS_BITSIZE (& first.fields));
|
||||||
|
|
||||||
/* Force the top bit of the second insn to be set. */
|
/* Force the top bit of the second insn to be set. */
|
||||||
@ -653,14 +750,14 @@ assemble_parallel_insn (str, str2)
|
|||||||
cgen_restore_fixups ();
|
cgen_restore_fixups ();
|
||||||
|
|
||||||
/* Write it out. */
|
/* Write it out. */
|
||||||
(void) cgen_asm_finish_insn (second.insn, second.buffer,
|
(void) cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||||
CGEN_FIELDS_BITSIZE (& second.fields));
|
CGEN_FIELDS_BITSIZE (& second.fields));
|
||||||
}
|
}
|
||||||
/* Try swapping the instructions to see if they work that way. */
|
/* Try swapping the instructions to see if they work that way. */
|
||||||
else if (can_make_parallel (& second, & first) == NULL)
|
else if (can_make_parallel (& second, & first) == NULL)
|
||||||
{
|
{
|
||||||
/* Write out the second instruction first. */
|
/* Write out the second instruction first. */
|
||||||
(void) cgen_asm_finish_insn (second.insn, second.buffer,
|
(void) cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||||
CGEN_FIELDS_BITSIZE (& second.fields));
|
CGEN_FIELDS_BITSIZE (& second.fields));
|
||||||
|
|
||||||
/* Force the top bit of the first instruction to be set. */
|
/* Force the top bit of the first instruction to be set. */
|
||||||
@ -670,7 +767,7 @@ assemble_parallel_insn (str, str2)
|
|||||||
cgen_restore_fixups ();
|
cgen_restore_fixups ();
|
||||||
|
|
||||||
/* Write out the first instruction. */
|
/* Write out the first instruction. */
|
||||||
(void) cgen_asm_finish_insn (first.insn, first.buffer,
|
(void) cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||||
CGEN_FIELDS_BITSIZE (& first.fields));
|
CGEN_FIELDS_BITSIZE (& first.fields));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user