/* tc-frv.c -- Assembler for the Fujitsu FRV.
- Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation. Inc.
+ Copyright (C) 2002-2020 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. */
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 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 */
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,
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 *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;
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:
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
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);
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;
}