/* tc-frv.c -- Assembler for the Fujitsu FRV.
- Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation. Inc.
+ Copyright (C) 2002-2021 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
Boston, MA 02110-1301, USA. */
#include "as.h"
-#include "subsegs.h"
+#include "subsegs.h"
#include "symcat.h"
#include "opcodes/frv-desc.h"
#include "opcodes/frv-opc.h"
#include "cgen.h"
-#include "libbfd.h"
#include "elf/common.h"
#include "elf/frv.h"
#include "dwarf2dbg.h"
VLIW_BRANCH_HAS_NOPS /* A Branch that requires NOPS. */
};
-/* We're going to use these in the fr_subtype field to mark
+/* We're going to use these in the fr_subtype field to mark
whether to keep inserted nops. */
#define NOP_KEEP 1 /* Keep these NOPS. */
#define NOP_DELETE 2 /* Delete these NOPS. */
-#define DO_COUNT TRUE
-#define DONT_COUNT FALSE
+#define DO_COUNT true
+#define DONT_COUNT false
/* A list of insns within a VLIW insn. */
struct vliw_insn_list
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";
#endif
static unsigned long frv_mach = bfd_mach_frv;
-static bfd_boolean fr400_audio;
+static bool fr400_audio;
/* Flags to set in the elf header */
static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
static int g_switch_value = 8;
int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
{
switch (c)
{
case OPTION_CPU:
{
- char *p;
+ const char *p;
int cpu_flags = EF_FRV_CPU_GENERIC;
/* Identify the processor type */
{
cpu_flags = EF_FRV_CPU_FR405;
frv_mach = bfd_mach_fr400;
- fr400_audio = TRUE;
+ fr400_audio = true;
}
else if (strcmp (p, "fr400") == 0)
{
cpu_flags = EF_FRV_CPU_FR400;
frv_mach = bfd_mach_fr400;
- fr400_audio = FALSE;
+ fr400_audio = false;
}
else if (strcmp (p, "fr300") == 0)
fprintf (stream, _("-mno-pack Do not allow instructions to be packed\n"));
fprintf (stream, _("-mpic Mark generated file as using small position independent code\n"));
fprintf (stream, _("-mPIC Mark generated file as using large position independent code\n"));
- fprintf (stream, _("-mlibrary-pic Mark generated file as using position indepedent code for libraries\n"));
+ fprintf (stream, _("-mlibrary-pic Mark generated file as using position independent code for libraries\n"));
fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n"));
fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
fprintf (stream, _(" Record the cpu type\n"));
fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
-}
+}
\f
void
md_begin (void)
{
/* Initialize the `cgen' interface. */
-
+
/* Set the machine number and endian. */
gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
CGEN_CPU_OPEN_ENDIAN,
frv_vliw_reset (& vliw, frv_mach, frv_flags);
}
-bfd_boolean
+bool
frv_md_fdpic_enabled (void)
{
return (frv_flags & EF_FRV_FDPIC) != 0;
int chain_num = 0;
static struct vliw_insn_list *
-frv_insert_vliw_insn (bfd_boolean count)
+frv_insert_vliw_insn (bool count)
{
struct vliw_insn_list *vliw_insn_list_entry;
struct vliw_chain *vliw_chain_entry;
if (current_vliw_chain == NULL)
{
- vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+ vliw_chain_entry = XNEW (struct vliw_chain);
vliw_chain_entry->insn_count = 0;
vliw_chain_entry->insn_list = NULL;
vliw_chain_entry->next = NULL;
previous_vliw_chain->next = vliw_chain_entry;
}
- vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
+ vliw_insn_list_entry = XNEW (struct vliw_insn_list);
vliw_insn_list_entry->type = VLIW_GENERIC_TYPE;
vliw_insn_list_entry->insn = NULL;
vliw_insn_list_entry->sym = NULL;
}
/* Identify the following cases:
-
+
1) A VLIW insn that contains both a branch and the branch destination.
This requires the insertion of two vliw instructions before the
branch. The first consists of two nops. The second consists of
a single nop.
-
+
2) A single instruction VLIW insn which is the destination of a branch
that is in the next VLIW insn. This requires the insertion of a vliw
insn containing two nops before the branch.
-
+
3) A double instruction VLIW insn which contains the destination of a
branch that is in the next VLIW insn. This requires the insertion of
a VLIW insn containing a single nop before the branch.
-
+
4) A single instruction VLIW insn which contains branch destination (x),
followed by a single instruction VLIW insn which does not contain
the branch to (x), followed by a VLIW insn which does contain the branch
to (x). This requires the insertion of a VLIW insn containing a single
nop before the VLIW instruction containing the branch.
-
+
*/
#define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
#define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
{
/* A Vliw insn containing a single nop insn. */
VLIW_SINGLE_NOP,
-
+
/* A Vliw insn containing two nop insns. */
VLIW_DOUBLE_NOP,
- /* Two vliw insns. The first containing two nop insns.
+ /* Two vliw insns. The first containing two nop insns.
The second contain a single nop insn. */
VLIW_DOUBLE_THEN_SINGLE_NOP
};
struct vliw_insn_list *insert_before_insn)
{
- bfd_boolean pack_prev = FALSE;
+ bool pack_prev = false;
struct vliw_chain *return_me = NULL;
struct vliw_insn_list *prev_insn = NULL;
struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
- struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
- struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
- struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+ struct vliw_chain *double_nop = XNEW (struct vliw_chain);
+ struct vliw_chain *single_nop = XNEW (struct vliw_chain);
+ struct vliw_chain *second_part = XNEW (struct vliw_chain);
struct vliw_chain *curr_vliw = vliw_chain_top;
struct vliw_chain *prev_vliw = NULL;
Then don't set pack bit later. */
if (curr_insn->type != VLIW_LABEL_TYPE)
- pack_prev = TRUE;
+ pack_prev = true;
prev_insn = curr_insn;
curr_insn = curr_insn->next;
- }
+ }
while (curr_vliw && curr_vliw != vliw_to_split)
{
buffer[0] |= 0x80;
}
/* The branch is in the middle. Split this vliw insn into first
- and second parts. Insert the NOP inbetween. */
+ and second parts. Insert the NOP between. */
second_part->insn_list = insert_before_insn;
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
frv_adjust_vliw_count (second_part);
single_nop->next = second_part;
-
+
vliw_to_split->next = single_nop;
prev_insn->next = NULL;
-
+
return_me = second_part;
frv_adjust_vliw_count (vliw_to_split);
}
}
/* The branch is in the middle. Split this vliw insn into first
- and second parts. Insert the NOP inbetween. */
+ and second parts. Insert the NOP in between. */
second_part->insn_list = insert_before_insn;
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
second_part->next = vliw_to_split->next;
frv_adjust_vliw_count (second_part);
-
+
double_nop->next = second_part;
-
+
vliw_to_split->next = single_nop;
prev_insn->next = NULL;
frv_adjust_vliw_count (vliw_to_split);
-
+
return_me = second_part;
}
break;
prev_vliw->next = double_nop;
else
vliw_chain_top = double_nop;
-
+
single_nop->next = vliw_to_split;
return_me = vliw_to_split;
vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
}
/* The branch is in the middle of this vliw insn. Split into first and
- second parts. Insert the nop vliws in between. */
+ second parts. Insert the nop vliws in between. */
second_part->insn_list = insert_before_insn;
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
second_part->next = vliw_to_split->next;
vliw1 = vliw_chain_top;
-workaround_top:
+ workaround_top:
FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
tomcat_doubles++;
goto workaround_top;
}
- else if (vliw2
+ else if (vliw2
&& vliw2->insn_count == 1
&& (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
{
if (vliw1->insn_count == 2)
{
- struct vliw_insn_list *this_insn;
-
- /* check vliw1 for a label. */
+ /* Check vliw1 for a label. */
for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
{
if (this_insn->type == VLIW_LABEL_TYPE)
case FRV_INSN_CMQMULHU:
case FRV_INSN_MMACHS:
case FRV_INSN_MMRDHS:
- case FRV_INSN_CMMACHS:
+ case FRV_INSN_CMMACHS:
case FRV_INSN_MQMACHS:
case FRV_INSN_CMQMACHS:
case FRV_INSN_MQXMACHS:
}
static int
-fr550_check_acc_range (FRV_VLIW *vliw, frv_insn *insn)
+fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
{
- switch ((*vliw->current_vliw)[vliw->next_slot - 1])
+ switch ((*vlw->current_vliw)[vlw->next_slot - 1])
{
case UNIT_FM0:
case UNIT_FM2:
/* Return true if the target implements instruction INSN. */
-static bfd_boolean
+static bool
target_implements_insn_p (const CGEN_INSN *insn)
{
switch (frv_mach)
{
default:
/* bfd_mach_frv or generic. */
- return TRUE;
+ return true;
case bfd_mach_fr300:
case bfd_mach_frvsimple:
insn.insn = frv_cgen_assemble_insn
(gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
-
+
if (!insn.insn)
{
as_bad ("%s", errmsg);
return;
}
-
+
/* If the cpu is tomcat, then we need to insert nops to workaround
hardware limitations. We need to keep track of each vliw unit
and examine the length of the unit and the individual insns
{
/* If we've just finished a VLIW insn OR this is a branch,
then start up a new frag. Fill it with nops. We will get rid
- of those that are not required after we've seen all of the
+ of those that are not required after we've seen all of the
instructions but before we start resolving fixups. */
if ( !FRV_IS_NOP (insn)
&& (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
previous_vliw_chain = current_vliw_chain;
current_vliw_chain = NULL;
current_vliw_insn = NULL;
- }
+ }
}
}
/* The syntax in the manual says constants begin with '#'.
We just ignore it. */
-void
+void
md_operand (expressionS *expressionP)
{
if (* input_line_pointer == '#')
valueT
md_section_align (segT segment, valueT size)
{
- int align = bfd_get_section_alignment (stdoutput, segment);
- return ((size + (1 << align) - 1) & (-1 << align));
+ int align = bfd_section_alignment (segment);
+ return ((size + (1 << align) - 1) & -(1 << align));
}
symbolS *
default:
case NOP_DELETE:
return 0;
- }
-}
+ }
+}
/* *fragP has been relaxed to its final size, and now needs to have
the bytes inside it modified to conform to the new size.
case NOP_KEEP:
fragP->fr_fix = fragP->fr_var;
fragP->fr_var = 0;
- return;
+ return;
}
}
\f
switch (operand->type)
{
case FRV_OPERAND_LABEL16:
- fixP->fx_pcrel = TRUE;
+ fixP->fx_pcrel = true;
return BFD_RELOC_FRV_LABEL16;
case FRV_OPERAND_LABEL24:
- fixP->fx_pcrel = TRUE;
+ fixP->fx_pcrel = true;
if (fixP->fx_cgen.opinfo != 0)
return fixP->fx_cgen.opinfo;
case FRV_OPERAND_U12:
return BFD_RELOC_FRV_GPRELU12;
- default:
+ default:
break;
}
return BFD_RELOC_NONE;
number_to_chars_bigendian (buf, val, n);
}
-char *
+const char *
md_atof (int type, char *litP, int *sizeP)
{
- return ieee_md_atof (type, litP, sizeP, TRUE);
+ return ieee_md_atof (type, litP, sizeP, true);
}
-bfd_boolean
+bool
frv_fix_adjustable (fixS *fixP)
{
bfd_reloc_code_real_type reloc_type;
do
{
bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
-
+
if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
{
input_line_pointer += 9;
segment_info_type *seginfo = seg_info (sec);
fixS *fixp;
CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
- flagword flags = bfd_get_section_flags (abfd, sec);
+ flagword flags = bfd_section_flags (sec);
/* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
since we can fix those up by hand. */
vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
- vliw_insn_list_entry->sym = this_label;
+ vliw_insn_list_entry->sym = this_label;
}
fixS *
&& current_vliw_insn->type == VLIW_BRANCH_TYPE
&& exp != NULL)
current_vliw_insn->sym = exp->X_add_symbol;
-
+
return fixP;
}