* cgen.h: New file.
* cgen.c: Include it. (MAX_FIXUPS): Renamed to CGEN_MAX_FIXUPS. (cgen_asm_finish_insn): Result is now void. New arg `result'. All callers updated. * config/tc-m32r.c: Include cgen.h. (m23r_insn): New members num_fixups,fixups. (assemble_parallel_insn): Initialize debug_sym_link for each insn. (md_assemble): Simplify code to pack two insns in parallel. When swapping two insns, update their fixups.
This commit is contained in:
parent
e2d7426296
commit
defc70bf2b
4 changed files with 263 additions and 118 deletions
|
@ -51,6 +51,7 @@ bignum-copy.c
|
|||
bignum.h
|
||||
bit_fix.h
|
||||
cgen.c
|
||||
cgen.h
|
||||
cond.c
|
||||
config
|
||||
config-gas.com
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
Thu May 7 02:19:14 1998 Doug Evans <devans@charmed.cygnus.com>
|
||||
|
||||
* cgen.h: New file.
|
||||
* cgen.c: Include it.
|
||||
(MAX_FIXUPS): Renamed to CGEN_MAX_FIXUPS.
|
||||
(cgen_asm_finish_insn): Result is now void. New arg `result'.
|
||||
All callers updated.
|
||||
* config/tc-m32r.c: Include cgen.h.
|
||||
(m23r_insn): New members num_fixups,fixups.
|
||||
start-sanitize-m32rx
|
||||
(assemble_parallel_insn): Initialize debug_sym_link for each insn.
|
||||
(md_assemble): Simplify code to pack two insns in parallel.
|
||||
When swapping two insns, update their fixups.
|
||||
end-sanitize-m32rx
|
||||
|
||||
start-sanitize-sky
|
||||
Wed May 6 16:26:57 1998 Doug Evans <devans@canuck.cygnus.com>
|
||||
|
||||
|
|
99
gas/cgen.c
99
gas/cgen.c
|
@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
#include "cgen-opc.h"
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
#include "cgen.h"
|
||||
|
||||
/* Callback to insert a register into the symbol table.
|
||||
A target may choose to let GAS parse the registers.
|
||||
|
@ -32,7 +33,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
void
|
||||
cgen_asm_record_register (name, number)
|
||||
char * name;
|
||||
int number;
|
||||
int number;
|
||||
{
|
||||
/* Use symbol_create here instead of symbol_new so we don't try to
|
||||
output registers into the object file's symbol table. */
|
||||
|
@ -53,15 +54,13 @@ cgen_asm_record_register (name, number)
|
|||
|
||||
struct fixup
|
||||
{
|
||||
int opindex;
|
||||
int opinfo;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
expressionS exp;
|
||||
};
|
||||
|
||||
#define MAX_FIXUPS 5
|
||||
|
||||
static struct fixup fixups [MAX_FIXUPS];
|
||||
static int num_fixups;
|
||||
static struct fixup fixups [CGEN_MAX_FIXUPS];
|
||||
static int num_fixups;
|
||||
|
||||
/* Prepare to parse an instruction.
|
||||
??? May wish to make this static and delete calls in md_assemble. */
|
||||
|
@ -80,7 +79,7 @@ cgen_queue_fixup (opindex, opinfo, expP)
|
|||
expressionS * expP;
|
||||
{
|
||||
/* We need to generate a fixup for this expression. */
|
||||
if (num_fixups >= MAX_FIXUPS)
|
||||
if (num_fixups >= CGEN_MAX_FIXUPS)
|
||||
as_fatal (_("too many fixups"));
|
||||
fixups[num_fixups].exp = * expP;
|
||||
fixups[num_fixups].opindex = opindex;
|
||||
|
@ -92,8 +91,8 @@ cgen_queue_fixup (opindex, opinfo, expP)
|
|||
and to have this backup be swapped with the current chain. This allows
|
||||
certain ports, eg the m32r, to swap two instructions and swap their fixups
|
||||
at the same time. */
|
||||
static struct fixup saved_fixups [MAX_FIXUPS];
|
||||
static int saved_num_fixups;
|
||||
static struct fixup saved_fixups [CGEN_MAX_FIXUPS];
|
||||
static int saved_num_fixups;
|
||||
|
||||
void
|
||||
cgen_save_fixups ()
|
||||
|
@ -118,7 +117,7 @@ cgen_restore_fixups ()
|
|||
void
|
||||
cgen_swap_fixups ()
|
||||
{
|
||||
int tmp;
|
||||
int tmp;
|
||||
struct fixup tmp_fixup;
|
||||
|
||||
if (num_fixups == 0)
|
||||
|
@ -135,7 +134,7 @@ cgen_swap_fixups ()
|
|||
saved_num_fixups = num_fixups;
|
||||
num_fixups = tmp;
|
||||
|
||||
for (tmp = MAX_FIXUPS; tmp--;)
|
||||
for (tmp = CGEN_MAX_FIXUPS; tmp--;)
|
||||
{
|
||||
tmp_fixup = saved_fixups [tmp];
|
||||
saved_fixups [tmp] = fixups [tmp];
|
||||
|
@ -235,23 +234,23 @@ static jmp_buf expr_jmp_buf;
|
|||
|
||||
const char *
|
||||
cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
|
||||
enum cgen_parse_operand_type want;
|
||||
const char ** strP;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
enum cgen_parse_operand_type want;
|
||||
const char ** strP;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
enum cgen_parse_operand_result * resultP;
|
||||
bfd_vma * valueP;
|
||||
bfd_vma * valueP;
|
||||
{
|
||||
#ifdef __STDC__
|
||||
/* These is volatile to survive the setjmp. */
|
||||
char * volatile hold;
|
||||
/* These are volatile to survive the setjmp. */
|
||||
char * volatile hold;
|
||||
enum cgen_parse_operand_result * volatile resultP_1;
|
||||
#else
|
||||
static char * hold;
|
||||
static enum cgen_parse_operand_result * resultP_1;
|
||||
static char * hold;
|
||||
static enum cgen_parse_operand_result * resultP_1;
|
||||
#endif
|
||||
const char * errmsg = NULL;
|
||||
expressionS exp;
|
||||
const char * errmsg = NULL;
|
||||
expressionS exp;
|
||||
|
||||
if (want == CGEN_PARSE_OPERAND_INIT)
|
||||
{
|
||||
|
@ -322,18 +321,23 @@ cgen_md_operand (expressionP)
|
|||
/* Finish assembling instruction INSN.
|
||||
BUF contains what we've built up so far.
|
||||
LENGTH is the size of the insn in bits.
|
||||
RELAX_P is non-zero if relaxable insns should be emitted as such.
|
||||
Otherwise they're emitted in non-relaxable forms.
|
||||
The "result" is stored in RESULT if non-NULL.
|
||||
Returns the address of the buffer containing the assembled instruction,
|
||||
in case the caller needs to modify it for some reason. */
|
||||
|
||||
char *
|
||||
cgen_asm_finish_insn (insn, buf, length)
|
||||
void
|
||||
cgen_asm_finish_insn (insn, buf, length, relax_p, result)
|
||||
const CGEN_INSN * insn;
|
||||
cgen_insn_t * buf;
|
||||
unsigned int length;
|
||||
cgen_insn_t * buf;
|
||||
unsigned int length;
|
||||
int relax_p;
|
||||
finished_insn * result;
|
||||
{
|
||||
int i;
|
||||
int relax_operand;
|
||||
char * f;
|
||||
int i;
|
||||
int relax_operand;
|
||||
char * f;
|
||||
unsigned int byte_len = length / 8;
|
||||
|
||||
/* ??? Target foo issues various warnings here, so one might want to provide
|
||||
|
@ -354,7 +358,7 @@ cgen_asm_finish_insn (insn, buf, length)
|
|||
/* Is there a relaxable insn with the relaxable operand needing a fixup? */
|
||||
|
||||
relax_operand = -1;
|
||||
if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
|
||||
if (relax_p && CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
|
||||
{
|
||||
/* Scan the fixups for the operand affected by relaxing
|
||||
(i.e. the branch address). */
|
||||
|
@ -372,7 +376,7 @@ cgen_asm_finish_insn (insn, buf, length)
|
|||
|
||||
if (relax_operand != -1)
|
||||
{
|
||||
int max_len;
|
||||
int max_len;
|
||||
fragS * old_frag;
|
||||
|
||||
#ifdef TC_CGEN_MAX_RELAX
|
||||
|
@ -405,9 +409,15 @@ cgen_asm_finish_insn (insn, buf, length)
|
|||
old_frag->fr_cgen.insn = insn;
|
||||
old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
|
||||
old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
|
||||
if (result)
|
||||
result->frag = old_frag;
|
||||
}
|
||||
else
|
||||
f = frag_more (byte_len);
|
||||
{
|
||||
f = frag_more (byte_len);
|
||||
if (result)
|
||||
result->frag = frag_now;
|
||||
}
|
||||
|
||||
/* If we're recording insns as numbers (rather than a string of bytes),
|
||||
target byte order handling is deferred until now. */
|
||||
|
@ -436,10 +446,13 @@ cgen_asm_finish_insn (insn, buf, length)
|
|||
/* Create any fixups. */
|
||||
for (i = 0; i < num_fixups; ++i)
|
||||
{
|
||||
fixS * fixP;
|
||||
|
||||
/* Don't create fixups for these. That's done during relaxation.
|
||||
We don't need to test for CGEN_INSN_RELAX as they can't get here
|
||||
(see above). */
|
||||
if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
|
||||
if (relax_p
|
||||
&& CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
|
||||
&& CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
|
||||
CGEN_OPERAND_RELAX) != 0)
|
||||
continue;
|
||||
|
@ -448,14 +461,20 @@ cgen_asm_finish_insn (insn, buf, length)
|
|||
#define md_cgen_record_fixup_exp cgen_record_fixup_exp
|
||||
#endif
|
||||
|
||||
md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
|
||||
insn, length,
|
||||
& CGEN_SYM (operand_table) [fixups[i].opindex],
|
||||
fixups[i].opinfo,
|
||||
& fixups[i].exp);
|
||||
fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
|
||||
insn, length,
|
||||
& CGEN_SYM (operand_table) [fixups[i].opindex],
|
||||
fixups[i].opinfo,
|
||||
& fixups[i].exp);
|
||||
if (result)
|
||||
result->fixups[i] = fixP;
|
||||
}
|
||||
|
||||
return f;
|
||||
if (result)
|
||||
{
|
||||
result->num_fixups = num_fixups;
|
||||
result->addr = f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply a fixup to the object code. This is called for all the
|
||||
|
|
|
@ -24,7 +24,18 @@
|
|||
#include "subsegs.h"
|
||||
#include "symcat.h"
|
||||
#include "cgen-opc.h"
|
||||
#include "cgen.h"
|
||||
|
||||
/* Linked list of symbols that are debugging symbols to be defined as the
|
||||
beginning of the current instruction. */
|
||||
typedef struct sym_link
|
||||
{
|
||||
struct sym_link *next;
|
||||
symbolS *symbol;
|
||||
} sym_linkS;
|
||||
|
||||
static sym_linkS *debug_sym_link = (sym_linkS *)0;
|
||||
|
||||
/* Structure to hold all of the different components describing an individual instruction. */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -38,7 +49,10 @@ typedef struct
|
|||
#endif
|
||||
char * addr;
|
||||
fragS * frag;
|
||||
int num_fixups;
|
||||
fixS * fixups [CGEN_MAX_FIXUPS];
|
||||
int indices [MAX_OPERAND_INSTANCES];
|
||||
sym_linkS *debug_sym_link;
|
||||
}
|
||||
m32r_insn;
|
||||
|
||||
|
@ -69,10 +83,8 @@ static int enable_m32rx = 0;
|
|||
instruction might have constraint violations. */
|
||||
static int warn_explicit_parallel_conflicts = 1;
|
||||
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
/* Non-zero if insns can be made parallel. */
|
||||
static int optimize;
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
/* stuff for .scomm symbols. */
|
||||
|
@ -124,10 +136,10 @@ allow_m32rx (on)
|
|||
/* end-sanitize-m32rx */
|
||||
|
||||
#define M32R_SHORTOPTS ""
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
/* start-sanitize-m32rx */
|
||||
#undef M32R_SHORTOPTS
|
||||
#define M32R_SHORTOPTS "O"
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
/* end-sanitize-m32rx */
|
||||
const char * md_shortopts = M32R_SHORTOPTS;
|
||||
|
||||
struct option md_longopts[] =
|
||||
|
@ -162,11 +174,9 @@ md_parse_option (c, arg)
|
|||
switch (c)
|
||||
{
|
||||
/* start-sanitize-m32rx */
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
case 'O':
|
||||
optimize = 1;
|
||||
break;
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
|
||||
case OPTION_M32RX:
|
||||
allow_m32rx (1);
|
||||
|
@ -204,10 +214,8 @@ md_show_usage (stream)
|
|||
fprintf (stream, _("\
|
||||
--m32rx support the extended m32rx instruction set\n"));
|
||||
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
fprintf (stream, _("\
|
||||
-O try to combine instructions in parallel\n"));
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
|
||||
fprintf (stream, _("\
|
||||
--warn-explicit-parallel-conflicts warn when parallel instrucitons violate contraints\n"));
|
||||
|
@ -229,6 +237,8 @@ md_show_usage (stream)
|
|||
|
||||
static void fill_insn PARAMS ((int));
|
||||
static void m32r_scomm PARAMS ((int));
|
||||
static void debug_sym PARAMS ((int));
|
||||
static void expand_debug_syms PARAMS ((sym_linkS *, int));
|
||||
|
||||
/* Set by md_assemble for use by m32r_fill_insn. */
|
||||
static subsegT prev_subseg;
|
||||
|
@ -237,12 +247,13 @@ static segT prev_seg;
|
|||
/* The target specific pseudo-ops which we support. */
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
{ "word", cons, 4 },
|
||||
{ "fillinsn", fill_insn, 0 },
|
||||
{ "scomm", m32r_scomm, 0 },
|
||||
{ "word", cons, 4 },
|
||||
{ "fillinsn", fill_insn, 0 },
|
||||
{ "scomm", m32r_scomm, 0 },
|
||||
{ "debugsym", debug_sym, 0 },
|
||||
/* start-sanitize-m32rx */
|
||||
{ "m32r", allow_m32rx, 0},
|
||||
{ "m32rx", allow_m32rx, 1},
|
||||
{ "m32r", allow_m32rx, 0 },
|
||||
{ "m32rx", allow_m32rx, 1 },
|
||||
/* end-sanitize-m32rx */
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
@ -324,6 +335,77 @@ fill_insn (ignore)
|
|||
seen_relaxable_p = 0;
|
||||
}
|
||||
|
||||
/* Record the symbol so that when we output the insn, we can create
|
||||
a symbol that is at the start of the instruction. This is used
|
||||
to emit the label for the start of a breakpoint without causing
|
||||
the assembler to emit a NOP if the previous instruction was a
|
||||
16 bit instruction. */
|
||||
|
||||
static void
|
||||
debug_sym (ignore)
|
||||
int ignore;
|
||||
{
|
||||
register char *name;
|
||||
register char delim;
|
||||
register char *end_name;
|
||||
register symbolS *symbolP;
|
||||
register sym_linkS *link;
|
||||
|
||||
name = input_line_pointer;
|
||||
delim = get_symbol_end ();
|
||||
end_name = input_line_pointer;
|
||||
|
||||
if ((symbolP = symbol_find (name)) == NULL
|
||||
&& (symbolP = md_undefined_symbol (name)) == NULL)
|
||||
{
|
||||
symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
|
||||
}
|
||||
|
||||
symbol_table_insert (symbolP);
|
||||
if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section)
|
||||
as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
|
||||
|
||||
else
|
||||
{
|
||||
link = (sym_linkS *) xmalloc (sizeof (sym_linkS));
|
||||
link->symbol = symbolP;
|
||||
link->next = debug_sym_link;
|
||||
debug_sym_link = link;
|
||||
symbolP->local = 1;
|
||||
}
|
||||
|
||||
*end_name = delim;
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Second pass to expanding the debug symbols, go through linked
|
||||
list of symbols and reassign the address. */
|
||||
|
||||
static void
|
||||
expand_debug_syms (syms, align)
|
||||
sym_linkS *syms;
|
||||
int align;
|
||||
{
|
||||
char *save_input_line = input_line_pointer;
|
||||
sym_linkS *next_syms;
|
||||
expressionS exp;
|
||||
|
||||
if (!syms)
|
||||
return;
|
||||
|
||||
(void) m32r_do_align (align, NULL, 0, 0);
|
||||
for (; syms != (sym_linkS *)0; syms = next_syms)
|
||||
{
|
||||
symbolS *symbolP = syms->symbol;
|
||||
next_syms = syms->next;
|
||||
input_line_pointer = ".\n";
|
||||
pseudo_set (symbolP);
|
||||
free ((char *)syms);
|
||||
}
|
||||
|
||||
input_line_pointer = save_input_line;
|
||||
}
|
||||
|
||||
/* Cover function to fill_insn called after a label and at end of assembly.
|
||||
|
||||
The result is always 1: we're called in a conditional to see if the
|
||||
|
@ -608,6 +690,9 @@ assemble_parallel_insn (str, str2)
|
|||
if (prev_insn.insn)
|
||||
fill_insn (0);
|
||||
|
||||
first.debug_sym_link = debug_sym_link;
|
||||
debug_sym_link = (sym_linkS *)0;
|
||||
|
||||
/* Parse the first instruction. */
|
||||
if (! (first.insn = CGEN_SYM (assemble_insn)
|
||||
(str, & first.fields, first.buffer, & errmsg)))
|
||||
|
@ -656,6 +741,8 @@ assemble_parallel_insn (str, str2)
|
|||
if (first.insn == NULL)
|
||||
as_fatal (_("internal error: m32r_cgen_lookup_get_insn_operands failed for first insn"));
|
||||
|
||||
second.debug_sym_link = NULL;
|
||||
|
||||
/* Parse the second instruction. */
|
||||
if (! (second.insn = CGEN_SYM (assemble_insn)
|
||||
(str, & second.fields, second.buffer, & errmsg)))
|
||||
|
@ -721,8 +808,9 @@ assemble_parallel_insn (str, str2)
|
|||
cgen_swap_fixups ();
|
||||
|
||||
/* Write it out. */
|
||||
(void) cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& first.fields), 0);
|
||||
expand_debug_syms (first.debug_sym_link, 1);
|
||||
cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& first.fields), 0, NULL);
|
||||
|
||||
/* Force the top bit of the second insn to be set. */
|
||||
make_parallel (second.buffer);
|
||||
|
@ -731,15 +819,17 @@ assemble_parallel_insn (str, str2)
|
|||
cgen_restore_fixups ();
|
||||
|
||||
/* Write it out. */
|
||||
(void) cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& second.fields), 0);
|
||||
expand_debug_syms (second.debug_sym_link, 1);
|
||||
cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& second.fields), 0, NULL);
|
||||
}
|
||||
/* Try swapping the instructions to see if they work that way. */
|
||||
else if (can_make_parallel (& second, & first) == NULL)
|
||||
{
|
||||
/* Write out the second instruction first. */
|
||||
(void) cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& second.fields), 0);
|
||||
expand_debug_syms (second.debug_sym_link, 1);
|
||||
cgen_asm_finish_insn (second.orig_insn, second.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& second.fields), 0, NULL);
|
||||
|
||||
/* Force the top bit of the first instruction to be set. */
|
||||
make_parallel (first.buffer);
|
||||
|
@ -748,8 +838,9 @@ assemble_parallel_insn (str, str2)
|
|||
cgen_restore_fixups ();
|
||||
|
||||
/* Write out the first instruction. */
|
||||
(void) cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& first.fields), 0);
|
||||
expand_debug_syms (first.debug_sym_link, 1);
|
||||
cgen_asm_finish_insn (first.orig_insn, first.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& first.fields), 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -785,6 +876,9 @@ md_assemble (str)
|
|||
}
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
insn.debug_sym_link = debug_sym_link;
|
||||
debug_sym_link = (sym_linkS *)0;
|
||||
|
||||
insn.insn = CGEN_SYM (assemble_insn) (str, & insn.fields, insn.buffer, & errmsg);
|
||||
if (!insn.insn)
|
||||
{
|
||||
|
@ -810,26 +904,28 @@ md_assemble (str)
|
|||
fill_insn (0);
|
||||
}
|
||||
|
||||
expand_debug_syms (insn.debug_sym_link, 2);
|
||||
|
||||
/* Doesn't really matter what we pass for RELAX_P here. */
|
||||
(void) cgen_asm_finish_insn (insn.insn, insn.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& insn.fields), 1);
|
||||
cgen_asm_finish_insn (insn.insn, insn.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int on_32bit_boundary_p;
|
||||
/* start-sanitize-m32rx */
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
int swap = false;
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
if (CGEN_INSN_BITSIZE (insn.insn) != 16)
|
||||
abort();
|
||||
|
||||
insn.orig_insn = insn.insn;
|
||||
/* start-sanitize-m32rx */
|
||||
if (enable_m32rx)
|
||||
{
|
||||
/* Get the indices of the operands of the instruction.
|
||||
FIXME: See assemble_parallel for notes on orig_insn. */
|
||||
insn.orig_insn = insn.insn;
|
||||
insn.insn = m32r_cgen_lookup_get_insn_operands (NULL,
|
||||
bfd_getb16 ((char *) insn.buffer),
|
||||
16,
|
||||
|
@ -837,58 +933,61 @@ md_assemble (str)
|
|||
if (insn.insn == NULL)
|
||||
as_fatal (_("internal error: m32r_cgen_get_insn_operands failed"));
|
||||
}
|
||||
else
|
||||
insn.orig_insn = insn.insn;
|
||||
|
||||
/* Keep track of whether we've seen a pair of 16 bit insns.
|
||||
prev_insn.insn is NULL when we're on a 32 bit boundary. */
|
||||
if (prev_insn.insn)
|
||||
{
|
||||
/* start-sanitize-m32rx */
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
/* Look to see if this instruction can be combined with the
|
||||
previous instruction to make one, parallel, 32 bit instruction.
|
||||
If the previous instruction (potentially) changed the flow of
|
||||
program control, then it cannot be combined with the current
|
||||
instruction. If the current instruction is relaxable, then it
|
||||
might be replaced with a longer version, so we cannot combine it.
|
||||
Also if the output of the previous instruction is used as an
|
||||
input to the current instruction then it cannot be combined.
|
||||
Otherwise call can_make_parallel() with both orderings of the
|
||||
instructions to see if they can be combined. */
|
||||
if ( enable_m32rx
|
||||
&& optimize
|
||||
&& CGEN_INSN_ATTR (insn.orig_insn, CGEN_INSN_RELAXABLE) == 0
|
||||
&& ! writes_to_pc (& prev_insn)
|
||||
&& ! first_writes_to_seconds_operands (& prev_insn, &insn, false)
|
||||
)
|
||||
{
|
||||
if (can_make_parallel (& prev_insn, & insn) == NULL)
|
||||
make_parallel (insn.buffer);
|
||||
else if (can_make_parallel (& insn, & prev_insn) == NULL)
|
||||
swap = true;
|
||||
}
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
prev_insn.insn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_insn = insn;
|
||||
}
|
||||
|
||||
/* Record the frag that might be used by this insn. */
|
||||
insn.frag = frag_now;
|
||||
insn.addr = cgen_asm_finish_insn (insn.orig_insn, insn.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& insn.fields),
|
||||
1 /*relax_p*/);
|
||||
/* Compute whether we're on a 32 bit boundary or not.
|
||||
prev_insn.insn is NULL when we're on a 32 bit boundary. */
|
||||
on_32bit_boundary_p = prev_insn.insn == NULL;
|
||||
|
||||
/* start-sanitize-m32rx */
|
||||
/* Look to see if this instruction can be combined with the
|
||||
previous instruction to make one, parallel, 32 bit instruction.
|
||||
If the previous instruction (potentially) changed the flow of
|
||||
program control, then it cannot be combined with the current
|
||||
instruction. If the current instruction is relaxable, then it
|
||||
might be replaced with a longer version, so we cannot combine it.
|
||||
Also if the output of the previous instruction is used as an
|
||||
input to the current instruction then it cannot be combined.
|
||||
Otherwise call can_make_parallel() with both orderings of the
|
||||
instructions to see if they can be combined. */
|
||||
if ( ! on_32bit_boundary_p
|
||||
&& enable_m32rx
|
||||
&& optimize
|
||||
&& CGEN_INSN_ATTR (insn.orig_insn, CGEN_INSN_RELAXABLE) == 0
|
||||
&& ! writes_to_pc (& prev_insn)
|
||||
&& ! first_writes_to_seconds_operands (& prev_insn, &insn, false)
|
||||
)
|
||||
{
|
||||
if (can_make_parallel (& prev_insn, & insn) == NULL)
|
||||
make_parallel (insn.buffer);
|
||||
else if (can_make_parallel (& insn, & prev_insn) == NULL)
|
||||
swap = true;
|
||||
}
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
expand_debug_syms (insn.debug_sym_link, 1);
|
||||
|
||||
{
|
||||
int i;
|
||||
finished_insnS fi;
|
||||
|
||||
/* Ensure each pair of 16 bit insns is in the same frag. */
|
||||
frag_grow (4);
|
||||
|
||||
cgen_asm_finish_insn (insn.orig_insn, insn.buffer,
|
||||
CGEN_FIELDS_BITSIZE (& insn.fields),
|
||||
1 /*relax_p*/, &fi);
|
||||
insn.addr = fi.addr;
|
||||
insn.frag = fi.frag;
|
||||
insn.num_fixups = fi.num_fixups;
|
||||
for (i = 0; i < fi.num_fixups; ++i)
|
||||
insn.fixups[i] = fi.fixups[i];
|
||||
}
|
||||
|
||||
/* start-sanitize-m32rx */
|
||||
/* start-sanitize-phase2-m32rx */
|
||||
if (swap)
|
||||
{
|
||||
int tmp;
|
||||
int i,tmp;
|
||||
|
||||
#define SWAP_BYTES(a,b) tmp = a; a = b; b = tmp
|
||||
|
||||
|
@ -899,21 +998,32 @@ md_assemble (str)
|
|||
make_parallel (insn.addr);
|
||||
|
||||
/* Swap any relaxable frags recorded for the two insns. */
|
||||
/* FIXME: Clarify. relaxation precludes parallel insns */
|
||||
if (prev_insn.frag->fr_opcode == prev_insn.addr)
|
||||
prev_insn.frag->fr_opcode = insn.addr;
|
||||
else if (insn.frag->fr_opcode == insn.addr)
|
||||
insn.frag->fr_opcode = prev_insn.addr;
|
||||
}
|
||||
/* end-sanitize-phase2-m32rx */
|
||||
|
||||
/* Record where this instruction was assembled. */
|
||||
prev_insn.addr = insn.addr;
|
||||
prev_insn.frag = insn.frag;
|
||||
/* Update the addresses in any fixups.
|
||||
Note that we don't have to handle the case where each insn is in
|
||||
a different frag as we ensure they're in the same frag above. */
|
||||
for (i = 0; i < prev_insn.num_fixups; ++i)
|
||||
prev_insn.fixups[i]->fx_where += 2;
|
||||
for (i = 0; i < insn.num_fixups; ++i)
|
||||
insn.fixups[i]->fx_where -= 2;
|
||||
}
|
||||
/* end-sanitize-m32rx */
|
||||
|
||||
/* Keep track of whether we've seen a pair of 16 bit insns.
|
||||
prev_insn.insn is NULL when we're on a 32 bit boundary. */
|
||||
if (on_32bit_boundary_p)
|
||||
prev_insn = insn;
|
||||
else
|
||||
prev_insn.insn = NULL;
|
||||
|
||||
/* If the insn needs the following one to be on a 32 bit boundary
|
||||
(e.g. subroutine calls), fill this insn's slot. */
|
||||
if (prev_insn.insn != NULL
|
||||
if (on_32bit_boundary_p
|
||||
&& CGEN_INSN_ATTR (insn.orig_insn, CGEN_INSN_FILL_SLOT) != 0)
|
||||
fill_insn (0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue