* cgen.c: #include symcat.h.

* config/tc-m32r.c: Likewise.
This commit is contained in:
Doug Evans
1998-02-23 19:30:18 +00:00
parent a2f256c4e0
commit a15a45e51f
2 changed files with 119 additions and 17 deletions

View File

@ -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

View File

@ -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