-/* tc-m32r.c -- Assembler for the Mitsubishi M32R.
- Copyright (C) 1996, 1997, 1998, 1999, 2000
+/* tc-m32r.c -- Assembler for the Renesas M32R.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
Boston, MA 02111-1307, USA. */
#include <stdio.h>
-#include <ctype.h>
#include "as.h"
+#include "safe-ctype.h"
#include "subsegs.h"
#include "symcat.h"
#include "opcodes/m32r-desc.h"
#include "opcodes/m32r-opc.h"
#include "cgen.h"
+#include "elf/m32r.h"
/* Linked list of symbols that are debugging symbols to be defined as the
beginning of the current instruction. */
shouldn't assume or require it to). */
static int warn_unmatched_high = 0;
-/* Non-zero if -m32rx has been specified, in which case support for the
- extended M32RX instruction set should be enabled. */
-static int enable_m32rx = 0;
+/* 1 if -m32rx has been specified, in which case support for
+ the extended M32RX instruction set should be enabled.
+ 2 if -m32r2 has been specified, in which case support for
+ the extended M32R2 instruction set should be enabled. */
+static int enable_m32rx = 0; /* Default to M32R. */
/* Non-zero if -m32rx -hidden has been specified, in which case support for
the special M32RX instruction set should be enabled. */
static int enable_special = 0;
+/* Non-zero if -bitinst has been specified, in which case support
+ for extended M32R bit-field instruction set should be enabled. */
+static int enable_special_m32r = 0;
+
+/* Non-zero if -float has been specified, in which case support for
+ extended M32R floating point instruction set should be enabled. */
+static int enable_special_float = 0;
+
/* Non-zero if the programmer should be warned when an explicit parallel
instruction might have constraint violations. */
static int warn_explicit_parallel_conflicts = 1;
+/* Non-zero if the programmer should receive an error message when an
+ explicit parallel instruction might have constraint violations. */
+static int error_explicit_parallel_conflicts = 1;
+
/* Non-zero if insns can be made parallel. */
+static int use_parallel = 1;
+
+/* Non-zero if optimizations should be performed. */
static int optimize;
+/* m32r er_flags. */
+static int m32r_flags = 0;
+
/* Stuff for .scomm symbols. */
static segT sbss_section;
static asection scom_section;
const char comment_chars[] = ";";
const char line_comment_chars[] = "#";
-const char line_separator_chars[] = "";
+const char line_separator_chars[] = "!";
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD";
static struct m32r_hi_fixup *m32r_hi_fixup_list;
\f
+struct {
+ enum bfd_architecture bfd_mach;
+ int mach_flags;
+} mach_table[] =
+{
+ { bfd_mach_m32r, (1<<MACH_M32R) },
+ { bfd_mach_m32rx, (1<<MACH_M32RX) },
+ { bfd_mach_m32r2, (1<<MACH_M32R2) }
+};
+
+static void allow_m32rx (int);
+
static void
-allow_m32rx (on)
- int on;
+allow_m32rx (int on)
{
enable_m32rx = on;
if (stdoutput != NULL)
- bfd_set_arch_mach (stdoutput, TARGET_ARCH,
- enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r);
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_table[on].bfd_mach);
+
+ if (gas_cgen_cpu_desc != NULL)
+ gas_cgen_cpu_desc->machs = mach_table[on].mach_flags;
}
\f
#define M32R_SHORTOPTS "O"
struct option md_longopts[] =
{
-#define OPTION_M32R (OPTION_MD_BASE)
-#define OPTION_M32RX (OPTION_M32R + 1)
-#define OPTION_WARN_PARALLEL (OPTION_M32RX + 1)
-#define OPTION_NO_WARN_PARALLEL (OPTION_WARN_PARALLEL + 1)
-#define OPTION_SPECIAL (OPTION_NO_WARN_PARALLEL + 1)
-#define OPTION_WARN_UNMATCHED (OPTION_SPECIAL + 1)
+#define OPTION_M32R (OPTION_MD_BASE)
+#define OPTION_M32RX (OPTION_M32R + 1)
+#define OPTION_M32R2 (OPTION_M32RX + 1)
+#define OPTION_BIG (OPTION_M32R2 + 1)
+#define OPTION_LITTLE (OPTION_BIG + 1)
+#define OPTION_PARALLEL (OPTION_LITTLE + 1)
+#define OPTION_NO_PARALLEL (OPTION_PARALLEL + 1)
+#define OPTION_WARN_PARALLEL (OPTION_NO_PARALLEL + 1)
+#define OPTION_NO_WARN_PARALLEL (OPTION_WARN_PARALLEL + 1)
+#define OPTION_ERROR_PARALLEL (OPTION_NO_WARN_PARALLEL + 1)
+#define OPTION_NO_ERROR_PARALLEL (OPTION_ERROR_PARALLEL + 1)
+#define OPTION_SPECIAL (OPTION_NO_ERROR_PARALLEL + 1)
+#define OPTION_SPECIAL_M32R (OPTION_SPECIAL + 1)
+#define OPTION_SPECIAL_FLOAT (OPTION_SPECIAL_M32R + 1)
+#define OPTION_WARN_UNMATCHED (OPTION_SPECIAL_FLOAT + 1)
#define OPTION_NO_WARN_UNMATCHED (OPTION_WARN_UNMATCHED + 1)
{"m32r", no_argument, NULL, OPTION_M32R},
{"m32rx", no_argument, NULL, OPTION_M32RX},
+ {"m32r2", no_argument, NULL, OPTION_M32R2},
+ {"big", no_argument, NULL, OPTION_BIG},
+ {"little", no_argument, NULL, OPTION_LITTLE},
+ {"EB", no_argument, NULL, OPTION_BIG},
+ {"EL", no_argument, NULL, OPTION_LITTLE},
+ {"parallel", no_argument, NULL, OPTION_PARALLEL},
+ {"no-parallel", no_argument, NULL, OPTION_NO_PARALLEL},
{"warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_WARN_PARALLEL},
{"Wp", no_argument, NULL, OPTION_WARN_PARALLEL},
{"no-warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_WARN_PARALLEL},
{"Wnp", no_argument, NULL, OPTION_NO_WARN_PARALLEL},
+ {"error-explicit-parallel-conflicts", no_argument, NULL, OPTION_ERROR_PARALLEL},
+ {"Ep", no_argument, NULL, OPTION_ERROR_PARALLEL},
+ {"no-error-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_ERROR_PARALLEL},
+ {"Enp", no_argument, NULL, OPTION_NO_ERROR_PARALLEL},
{"hidden", no_argument, NULL, OPTION_SPECIAL},
+ {"bitinst", no_argument, NULL, OPTION_SPECIAL_M32R},
+ {"float", no_argument, NULL, OPTION_SPECIAL_FLOAT},
/* Sigh. I guess all warnings must now have both variants. */
{"warn-unmatched-high", no_argument, NULL, OPTION_WARN_UNMATCHED},
{"Wuh", no_argument, NULL, OPTION_WARN_UNMATCHED},
size_t md_longopts_size = sizeof (md_longopts);
+static void little (int);
+static int parallel (void);
+
+static void
+little (int on)
+{
+ target_big_endian = ! on;
+}
+
+/* Use parallel execution. */
+
+static int
+parallel (void)
+{
+ if (! enable_m32rx)
+ return 0;
+
+ if (use_parallel == 1)
+ return 1;
+
+ return 0;
+}
+
int
md_parse_option (c, arg)
int c;
- char *arg;
+ char *arg ATTRIBUTE_UNUSED;
{
switch (c)
{
case 'O':
optimize = 1;
+ use_parallel = 1;
break;
case OPTION_M32R:
allow_m32rx (1);
break;
+ case OPTION_M32R2:
+ allow_m32rx (2);
+ enable_special = 1;
+ enable_special_m32r = 1;
+ break;
+
+ case OPTION_BIG:
+ target_big_endian = 1;
+ break;
+
+ case OPTION_LITTLE:
+ target_big_endian = 0;
+ break;
+
+ case OPTION_PARALLEL:
+ use_parallel = 1;
+ break;
+
+ case OPTION_NO_PARALLEL:
+ use_parallel = 0;
+ break;
+
case OPTION_WARN_PARALLEL:
warn_explicit_parallel_conflicts = 1;
+ error_explicit_parallel_conflicts = 0;
break;
case OPTION_NO_WARN_PARALLEL:
+ warn_explicit_parallel_conflicts = 0;
+ error_explicit_parallel_conflicts = 0;
+ break;
+
+ case OPTION_ERROR_PARALLEL:
+ warn_explicit_parallel_conflicts = 1;
+ error_explicit_parallel_conflicts = 1;
+ break;
+
+ case OPTION_NO_ERROR_PARALLEL:
+ error_explicit_parallel_conflicts = 0;
warn_explicit_parallel_conflicts = 0;
break;
}
break;
+ case OPTION_SPECIAL_M32R:
+ enable_special_m32r = 1;
+ break;
+
+ case OPTION_SPECIAL_FLOAT:
+ enable_special_float = 1;
+ break;
+
case OPTION_WARN_UNMATCHED:
warn_unmatched_high = 1;
break;
fprintf (stream, _("\
-m32rx support the extended m32rx instruction set\n"));
fprintf (stream, _("\
- -O try to combine instructions in parallel\n"));
+ -m32r2 support the extended m32r2 instruction set\n"));
+ fprintf (stream, _("\
+ -EL,-little produce little endian code and data\n"));
+ fprintf (stream, _("\
+ -EB,-big produce big endian code and data\n"));
+ fprintf (stream, _("\
+ -parallel try to combine instructions in parallel\n"));
+ fprintf (stream, _("\
+ -no-parallel disable -parallel\n"));
+ fprintf (stream, _("\
+ -O try to optimize code. Implies -parallel\n"));
fprintf (stream, _("\
-warn-explicit-parallel-conflicts warn when parallel instructions\n"));
-Wp synonym for -warn-explicit-parallel-conflicts\n"));
fprintf (stream, _("\
-Wnp synonym for -no-warn-explicit-parallel-conflicts\n"));
+ fprintf (stream, _("\
+ -error-explicit-parallel-conflicts error when parallel instructions\n"));
+ fprintf (stream, _("\
+ violate contraints\n"));
+ fprintf (stream, _("\
+ -no-error-explicit-parallel-conflicts do not error when parallel\n"));
+ fprintf (stream, _("\
+ instructions violate contraints\n"));
+ fprintf (stream, _("\
+ -Ep synonym for -error-explicit-parallel-conflicts\n"));
+ fprintf (stream, _("\
+ -Enp synonym for -no-error-explicit-parallel-conflicts\n"));
fprintf (stream, _("\
-warn-unmatched-high warn when an (s)high reloc has no matching low reloc\n"));
{ "fillinsn", fill_insn, 0 },
{ "scomm", m32r_scomm, 0 },
{ "debugsym", debug_sym, 0 },
- /* Not documented as so far there is no need for them.... */
{ "m32r", allow_m32rx, 0 },
{ "m32rx", allow_m32rx, 1 },
+ { "m32r2", allow_m32rx, 2 },
+ { "little", little, 1 },
+ { "big", little, 0 },
{ NULL, NULL, 0 }
};
/* FIXME: Should be machine generated. */
-#define NOP_INSN 0x7000
+#define NOP_INSN 0x7000
#define PAR_NOP_INSN 0xf000 /* Can only be used in 2nd slot. */
/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
void
m32r_handle_align (fragp)
+ fragS *fragp;
{
static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 };
static void
fill_insn (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
frag_align_code (2, 0);
prev_insn.insn = NULL;
static void
debug_sym (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
register char *name;
register char delim;
if (!syms)
return;
- (void) m32r_do_align (align, NULL, 0, 0);
+ (void) frag_align_code (align, 0);
for (; syms != (sym_linkS *) 0; syms = next_syms)
{
symbolS *symbolP = syms->symbol;
input_line_pointer = save_input_line;
}
+void
+m32r_flush_pending_output()
+{
+ if (debug_sym_link)
+ {
+ expand_debug_syms (debug_sym_link, 1);
+ debug_sym_link = (sym_linkS *) 0;
+ }
+}
+
/* 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
current line is a label. */
return 1;
}
\f
+/* The default target format to use. */
+
+const char *
+m32r_target_format ()
+{
+#ifdef TE_LINUX
+ if (target_big_endian)
+ return "elf32-m32r-linux";
+ else
+ return "elf32-m32rle-linux";
+#else
+ if (target_big_endian)
+ return "elf32-m32r";
+ else
+ return "elf32-m32rle";
+#endif
+}
+
void
md_begin ()
{
/* Set the machine number and endian. */
gas_cgen_cpu_desc = m32r_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
CGEN_CPU_OPEN_ENDIAN,
- CGEN_ENDIAN_BIG,
+ (target_big_endian ?
+ CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE),
CGEN_CPU_OPEN_END);
m32r_cgen_init_asm (gas_cgen_cpu_desc);
scom_symbol.section = &scom_section;
allow_m32rx (enable_m32rx);
+
+ gas_cgen_initialize_saved_fixups_array ();
}
#define OPERAND_IS_COND_BIT(operand, indices, index) \
of instruction 'b'. If 'check_outputs' is true then b's outputs are
checked, otherwise its inputs are examined. */
+static int first_writes_to_seconds_operands
+ PARAMS ((m32r_insn *, m32r_insn *, const int));
+
static int
first_writes_to_seconds_operands (a, b, check_outputs)
m32r_insn *a;
/* Returns true if the insn can (potentially) alter the program counter. */
+static int writes_to_pc PARAMS ((m32r_insn *));
+
static int
writes_to_pc (a)
m32r_insn *a;
/* Return NULL if the two 16 bit insns can be executed in parallel.
Otherwise return a pointer to an error message explaining why not. */
+static const char *can_make_parallel PARAMS ((m32r_insn *, m32r_insn *));
+
static const char *
can_make_parallel (a, b)
m32r_insn *a;
|| CGEN_FIELDS_BITSIZE (&b->fields) != 16)
abort ();
- if (first_writes_to_seconds_operands (a, b, true))
+ if (first_writes_to_seconds_operands (a, b, TRUE))
return _("Instructions write to the same destination register.");
a_pipe = CGEN_INSN_ATTR_VALUE (a->insn, CGEN_INSN_PIPE);
go away if the instructions are swapped, and we want to make
sure that any other errors are detected before this happens. */
if (a_pipe == PIPE_S
- || b_pipe == PIPE_O)
+ || b_pipe == PIPE_O
+ || (b_pipe == PIPE_O_OS && (enable_m32rx != 2)))
return _("Instructions share the same execution pipeline");
return NULL;
/* Force the top bit of the second 16-bit insn to be set. */
+static void make_parallel PARAMS ((CGEN_INSN_BYTES_PTR));
+
static void
make_parallel (buffer)
CGEN_INSN_BYTES_PTR buffer;
/* Same as make_parallel except buffer contains the bytes in target order. */
+static void target_make_parallel PARAMS ((char *));
+
static void
target_make_parallel (buffer)
char *buffer;
/* Assemble two instructions with an explicit parallel operation (||) or
sequential operation (->). */
+static void assemble_two_insns PARAMS ((char *, char *, int));
+
static void
assemble_two_insns (str, str2, parallel_p)
char *str;
char *errmsg;
char save_str2 = *str2;
- /* Seperate the two instructions. */
+ /* Separate the two instructions. */
*str2 = 0;
/* Make sure the two insns begin on a 32 bit boundary.
as_bad (_("not a 16 bit instruction '%s'"), str);
return;
}
+#ifdef E_M32R2_ARCH
+ else if ((enable_m32rx == 1)
+ /* FIXME: Need standard macro to perform this test. */
+ && ((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32R2))
+ && !((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32RX)))))
+ {
+ /* xgettext:c-format */
+ as_bad (_("instruction '%s' is for the M32R2 only"), str);
+ return;
+ }
+ else if ((! enable_special
+ && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL))
+ || (! enable_special_m32r
+ && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
else if (! enable_special
&& CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL))
+#endif
{
/* xgettext:c-format */
as_bad (_("unknown instruction '%s'"), str);
{
char *s2 = str;
- while (isspace (*s2++))
+ while (ISSPACE (*s2++))
continue;
--s2;
- while (isalnum (*s2))
+ while (ISALNUM (*s2))
{
- if (isupper ((unsigned char) *s2))
- *s2 = tolower (*s2);
+ *s2 = TOLOWER (*s2);
s2++;
}
}
/* Preserve any fixups that have been generated and reset the list
to empty. */
- gas_cgen_save_fixups ();
+ gas_cgen_save_fixups (0);
/* Get the indices of the operands of the instruction. */
/* FIXME: CGEN_FIELDS is already recorded, but relying on that fact
as_bad (_("not a 16 bit instruction '%s'"), str);
return;
}
+#ifdef E_M32R2_ARCH
+ else if ((enable_m32rx == 1)
+ /* FIXME: Need standard macro to perform this test. */
+ && ((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32R2))
+ && !((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32RX)))))
+ {
+ /* xgettext:c-format */
+ as_bad (_("instruction '%s' is for the M32R2 only"), str);
+ return;
+ }
+ else if ((! enable_special
+ && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+ || (! enable_special_m32r
+ && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
else if (! enable_special
&& CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+#endif
{
/* xgettext:c-format */
as_bad (_("unknown instruction '%s'"), str);
if (parallel_p && warn_explicit_parallel_conflicts)
{
- if (first_writes_to_seconds_operands (&first, &second, false))
+ void (* func)(const char *, ...);
+
+ func = error_explicit_parallel_conflicts ? as_bad : as_warn;
+
+ if (first_writes_to_seconds_operands (&first, &second, FALSE))
/* xgettext:c-format */
- as_warn (_("%s: output of 1st instruction is the same as an input to 2nd instruction - is this intentional ?"), str2);
+ func (_("%s: output of 1st instruction is the same as an input to 2nd instruction - is this intentional ?"), str2);
- if (first_writes_to_seconds_operands (&second, &first, false))
+ if (first_writes_to_seconds_operands (&second, &first, FALSE))
/* xgettext:c-format */
- as_warn (_("%s: output of 2nd instruction is the same as an input to 1st instruction - is this intentional ?"), str2);
+ func (_("%s: output of 2nd instruction is the same as an input to 1st instruction - is this intentional ?"), str2);
}
if (!parallel_p
|| (errmsg = (char *) can_make_parallel (&first, &second)) == NULL)
{
/* Get the fixups for the first instruction. */
- gas_cgen_swap_fixups ();
+ gas_cgen_swap_fixups (0);
/* Write it out. */
expand_debug_syms (first.debug_sym_link, 1);
make_parallel (second.buffer);
/* Get its fixups. */
- gas_cgen_restore_fixups ();
+ gas_cgen_restore_fixups (0);
/* Write it out. */
expand_debug_syms (second.debug_sym_link, 1);
make_parallel (first.buffer);
/* Get the fixups for the first instruction. */
- gas_cgen_restore_fixups ();
+ gas_cgen_restore_fixups (0);
/* Write out the first instruction. */
expand_debug_syms (first.debug_sym_link, 1);
return;
}
+ if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL)
+ || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+ m32r_flags |= E_M32R_HAS_HIDDEN_INST;
+ if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_M32R)
+ || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_M32R))
+ m32r_flags |= E_M32R_HAS_BIT_INST;
+ if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_FLOAT)
+ || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_FLOAT))
+ m32r_flags |= E_M32R_HAS_FLOAT_INST;
+
/* Set these so m32r_fill_insn can use them. */
prev_seg = now_seg;
prev_subseg = now_subseg;
/* Initialize GAS's cgen interface for a new instruction. */
gas_cgen_init_parse ();
- /* Look for a parallel instruction seperator. */
+ /* Look for a parallel instruction separator. */
if ((str2 = strstr (str, "||")) != NULL)
{
assemble_two_insns (str, str2, 1);
+ m32r_flags |= E_M32R_HAS_PARALLEL;
return;
}
- /* Also look for a sequential instruction seperator. */
+ /* Also look for a sequential instruction separator. */
if ((str2 = strstr (str, "->")) != NULL)
{
assemble_two_insns (str, str2, 0);
return;
}
+#ifdef E_M32R2_ARCH
+ if ((enable_m32rx == 1)
+ /* FIXME: Need standard macro to perform this test. */
+ && ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32R2))
+ && !((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MACH)
+ & (1 << MACH_M32RX)))))
+ {
+ /* xgettext:c-format */
+ as_bad (_("instruction '%s' is for the M32R2 only"), str);
+ return;
+ }
+ else if ((! enable_special
+ && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+ || (! enable_special_m32r
+ && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
if (! enable_special
&& CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+#endif
{
/* xgettext:c-format */
as_bad (_("unknown instruction '%s'"), str);
return;
}
+ if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+ m32r_flags |= E_M32R_HAS_HIDDEN_INST;
+ if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_M32R))
+ m32r_flags |= E_M32R_HAS_BIT_INST;
+ if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_FLOAT))
+ m32r_flags |= E_M32R_HAS_FLOAT_INST;
+
if (CGEN_INSN_BITSIZE (insn.insn) == 32)
{
/* 32 bit insns must live on 32 bit boundaries. */
else
{
int on_32bit_boundary_p;
- int swap = false;
+ int swap = FALSE;
if (CGEN_INSN_BITSIZE (insn.insn) != 16)
abort ();
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
+ && parallel ()
&& CGEN_INSN_ATTR_VALUE (insn.orig_insn, CGEN_INSN_RELAXABLE) == 0
&& ! writes_to_pc (&prev_insn)
- && ! first_writes_to_seconds_operands (&prev_insn, &insn, false))
+ && ! 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;
+ swap = TRUE;
}
expand_debug_syms (insn.debug_sym_link, 1);
symbolS *
md_undefined_symbol (name)
- char *name;
+ char *name ATTRIBUTE_UNUSED;
{
return 0;
}
static void
m32r_scomm (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
register char *name;
register char c;
};
long
-m32r_relax_frag (fragP, stretch)
+m32r_relax_frag (segment, fragP, stretch)
+ segT segment;
fragS *fragP;
long stretch;
{
}
else
{
- growth = relax_frag (fragP, stretch);
+ growth = relax_frag (segment, fragP, stretch);
/* Long jump on odd halfword boundary? */
if (fragP->fr_subtype == 2 && (address & 3) != 0)
fragS *fragP;
segT segment;
{
- int old_fr_fix = fragP->fr_fix;
-
/* The only thing we have to handle here are symbols outside of the
current segment. They may be undefined or in a different segment in
which case linker scripts may place them anywhere.
if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
{
+#if 0
+ int old_fr_fix = fragP->fr_fix;
+#endif
+
/* The symbol is undefined in this segment.
Change the relaxation subtype to the max allowable and leave
all further handling to md_convert_frag. */
/* Mark this fragment as finished. */
frag_wane (fragP);
+ return fragP->fr_fix - old_fr_fix;
#else
{
const CGEN_INSN *insn;
if ((strcmp (CGEN_INSN_MNEMONIC (insn),
CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
== 0)
- && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX))
+ && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
break;
}
if (i == 4)
#endif
}
- return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+ return md_relax_table[fragP->fr_subtype].rlx_length;
}
/* *FRAGP has been relaxed to its final size, and now needs to have
void
md_convert_frag (abfd, sec, fragP)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
segT sec;
fragS *fragP;
{
{
/* Address we want to reach in file space. */
target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
- target_address += symbol_get_frag (fragP->fr_symbol)->fr_address;
addend = (target_address - (opcode_address & -4)) >> 2;
}
bfd_reloc_code_real_type
md_cgen_lookup_reloc (insn, operand, fixP)
- const CGEN_INSN *insn;
+ const CGEN_INSN *insn ATTRIBUTE_UNUSED;
const CGEN_OPERAND *operand;
fixS *fixP;
{
/* Record a HI16 reloc for later matching with its LO16 cousin. */
+static void m32r_record_hi16 PARAMS ((int, fixS *, segT));
+
static void
m32r_record_hi16 (reloc_type, fixP, seg)
int reloc_type;
fixS *fixP;
- segT seg;
+ segT seg ATTRIBUTE_UNUSED;
{
struct m32r_hi_fixup *hi_fixup;
#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
/* Sort any unmatched HI16 relocs so that they immediately precede
- the corresponding LO16 reloc. This is called before md_apply_fix and
+ the corresponding LO16 reloc. This is called before md_apply_fix3 and
tc_gen_reloc. */
void
m32r_force_relocation (fix)
fixS *fix;
{
- if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
- || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ if (generic_force_reloc (fix))
return 1;
if (! m32r_relax)
int prec;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
char *t;
- char *atof_ieee ();
switch (type)
{
/* Return true if can adjust the reloc to be relative to its section
(such as .data) instead of relative to some symbol. */
-boolean
+bfd_boolean
m32r_fix_adjustable (fixP)
fixS *fixP;
{
-
bfd_reloc_code_real_type reloc_type;
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
else
reloc_type = fixP->fx_r_type;
- if (fixP->fx_addsy == NULL)
- return 1;
-
- /* Prevent all adjustments to global symbols. */
- if (S_IS_EXTERN (fixP->fx_addsy))
- return 0;
- if (S_IS_WEAK (fixP->fx_addsy))
- return 0;
-
/* We need the symbol name for the VTABLE entries. */
if (reloc_type == BFD_RELOC_VTABLE_INHERIT
|| reloc_type == BFD_RELOC_VTABLE_ENTRY)
return 1;
}
+
+void
+m32r_elf_final_processing ()
+{
+ if (use_parallel)
+ m32r_flags |= E_M32R_HAS_PARALLEL;
+ elf_elfheader (stdoutput)->e_flags |= m32r_flags;
+}