/* tc-rx.c -- Assembler for the Renesas RX
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
02110-1301, USA. */
#include "as.h"
-#include "struc-symbol.h"
#include "safe-ctype.h"
#include "dwarf2dbg.h"
#include "elf/common.h"
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD";
\f
-/* ELF flags to set in the output file header. */
+#ifndef TE_LINUX
+bfd_boolean rx_use_conventional_section_names = FALSE;
static int elf_flags = E_FLAG_RX_ABI;
+#else
+bfd_boolean rx_use_conventional_section_names = TRUE;
+static int elf_flags;
+#endif
-bfd_boolean rx_use_conventional_section_names = FALSE;
static bfd_boolean rx_use_small_data_limit = FALSE;
-
static bfd_boolean rx_pid_mode = FALSE;
static int rx_num_int_regs = 0;
int rx_pid_register;
{
const char *cpu_name;
enum rx_cpu_types type;
+ int flag;
};
struct cpu_type cpu_type_list[] =
{
- {"rx100",RX100},
- {"rx200",RX200},
- {"rx600",RX600},
- {"rx610",RX610},
- {"rxv2",RXV2}
+ {"rx100", RX100, 0},
+ {"rx200", RX200, 0},
+ {"rx600", RX600, 0},
+ {"rx610", RX610, 0},
+ {"rxv2", RXV2, E_FLAG_RX_V2},
+ {"rxv3", RXV3, E_FLAG_RX_V3},
+ {"rxv3-dfpu", RXV3FPU, E_FLAG_RX_V3},
};
int
if (strcasecmp (arg, cpu_type_list[i].cpu_name) == 0)
{
rx_cpu = cpu_type_list[i].type;
- if (rx_cpu == RXV2)
- elf_flags |= E_FLAG_RX_V2;
+ elf_flags |= cpu_type_list[i].flag;
return 1;
}
}
fprintf (stream, _(" --mrelax\n"));
fprintf (stream, _(" --mpid\n"));
fprintf (stream, _(" --mint-register=<value>\n"));
- fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2>\n"));
+ fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2|rxv3|rxv3-dfpu>\n"));
fprintf (stream, _(" --mno-allow-string-insns"));
}
else
type = SHT_NOBITS;
- obj_elf_change_section (name, type, 0, attr, 0, NULL, FALSE, FALSE);
+ obj_elf_change_section (name, type, attr, 0, NULL, FALSE, FALSE);
}
else /* Try not to redefine a section, especially B_1. */
{
| ((flags & SEC_STRINGS) ? SHF_STRINGS : 0)
| ((flags & SEC_THREAD_LOCAL) ? SHF_TLS : 0);
- obj_elf_change_section (name, type, 0, attr, 0, NULL, FALSE, FALSE);
+ obj_elf_change_section (name, type, attr, 0, NULL, FALSE, FALSE);
}
- bfd_set_section_alignment (stdoutput, now_seg, align);
+ bfd_set_section_alignment (now_seg, align);
}
static void
fixS * fixP;
} fixups[2];
int n_fixups;
+ char post[1];
+ int n_post;
struct
{
char type;
int n_relax;
int link_relax;
fixS *link_relax_fixP;
- char times_grown;
- char times_shrank;
+ unsigned long times_grown;
+ unsigned long times_shrank;
} rx_bytesT;
static rx_bytesT rx_bytes;
rx_bytes.base[1] |= (val ) & 0x0f;
}
+void
+rx_bfield(expressionS s, expressionS d, expressionS w)
+{
+ int slsb = s.X_add_number;
+ int dlsb = d.X_add_number;
+ int width = w.X_add_number;
+ unsigned int imm =
+ (((dlsb + width) & 0x1f) << 10 | (dlsb << 5) |
+ ((dlsb - slsb) & 0x1f));
+ if ((slsb + width) > 32)
+ as_warn (_("Value %d and %d out of range"), slsb, width);
+ if ((dlsb + width) > 32)
+ as_warn (_("Value %d and %d out of range"), dlsb, width);
+ rx_bytes.ops[0] = imm & 0xff;
+ rx_bytes.ops[1] = (imm >> 8);
+ rx_bytes.n_ops = 2;
+}
+
#define OP(x) rx_bytes.ops[rx_bytes.n_ops++] = (x)
#define F_PRECISION 2
}
}
+void rx_post(char byte)
+{
+ rx_bytes.post[rx_bytes.n_post++] = byte;
+}
+
int
rx_wrap (void)
{
0 /* offset */,
0 /* opcode */);
frag_then->fr_opcode = bytes;
- frag_then->fr_fix += rx_bytes.n_base + rx_bytes.n_ops;
- frag_then->fr_subtype = rx_bytes.n_base + rx_bytes.n_ops;
+ frag_then->fr_fix += rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
+ frag_then->fr_subtype = rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
}
else
{
- bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops);
+ bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post);
frag_then = frag_now;
if (fetchalign_bytes)
- fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops;
+ fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
}
fetchalign_bytes = NULL;
APPEND (base, n_base);
APPEND (ops, n_ops);
+ APPEND (post, n_post);
if (rx_bytes.link_relax && rx_bytes.n_fixups)
{
if (frag_then->tc_frag_data)
frag_then->tc_frag_data->fixups[i].fixP = f;
}
-
dwarf2_emit_insn (idx);
}
valueT
md_section_align (segT segment, valueT size)
{
- int align = bfd_get_section_alignment (stdoutput, segment);
+ int align = bfd_section_alignment (segment);
return ((size + (1 << align) - 1) & -(1 << align));
}
fr_subtype to calculate the difference. */
int
-rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
+rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch, unsigned long max_iterations)
{
addressT addr0, sym_addr;
addressT mypc;
/* This prevents infinite loops in align-heavy sources. */
if (newsize < oldsize)
{
- if (fragP->tc_frag_data->times_shrank > 10
- && fragP->tc_frag_data->times_grown > 10)
- newsize = oldsize;
+ /* Make sure that our iteration limit is no bigger than the one being
+ used inside write.c:relax_segment(). Otherwise we can end up
+ iterating for too long, and triggering a fatal error there. See
+ PR 24464 for more details. */
+ unsigned long limit = max_iterations > 10 ? 10 : max_iterations;
+
+ if (fragP->tc_frag_data->times_shrank > limit
+ && fragP->tc_frag_data->times_grown > limit)
+ newsize = oldsize;
+
if (fragP->tc_frag_data->times_shrank < 20)
fragP->tc_frag_data->times_shrank ++;
}
fragP->fr_var = 0;
if (fragP->fr_next != NULL
- && ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
- != fragP->fr_fix))
+ && fragP->fr_next->fr_address - fragP->fr_address != fragP->fr_fix)
as_bad (_("bad frag at %p : fix %ld addr %ld %ld \n"), fragP,
(long) fragP->fr_fix,
(long) fragP->fr_address, (long) fragP->fr_next->fr_address);