/* tc-rx.c -- Assembler for the Renesas RX
- Copyright (C) 2008-2015 Free Software Foundation, Inc.
+ Copyright (C) 2008-2016 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
OPTION_USES_GCC_ABI,
OPTION_USES_RX_ABI,
OPTION_CPU,
+ OPTION_DISALLOW_STRING_INSNS,
};
#define RX_SHORTOPTS ""
{"mint-register", required_argument, NULL, OPTION_INT_REGS},
{"mgcc-abi", no_argument, NULL, OPTION_USES_GCC_ABI},
{"mrx-abi", no_argument, NULL, OPTION_USES_RX_ABI},
- {"mcpu",required_argument,NULL,OPTION_CPU},
+ {"mcpu", required_argument, NULL, OPTION_CPU},
+ {"mno-allow-string-insns", no_argument, NULL, OPTION_DISALLOW_STRING_INSNS},
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
+struct cpu_type
+{
+ char *cpu_name;
+ int type;
+};
+
+struct cpu_type cpu_type_list[] =
+{
+ {"rx100",RX100},
+ {"rx200",RX200},
+ {"rx600",RX600},
+ {"rx610",RX610},
+ {"rxv2",RXV2}
+};
+
int
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
{
return 1;
case OPTION_CPU:
- if (strcasecmp (arg, "rx100") == 0)
- rx_cpu = RX100;
- else if (strcasecmp (arg, "rx200") == 0)
- rx_cpu = RX200;
- else if (strcasecmp (arg, "rx600") == 0)
- rx_cpu = RX600;
- else if (strcasecmp (arg, "rx610") == 0)
- rx_cpu = RX610;
- else
- {
- as_warn (_("unrecognised RX CPU type %s"), arg);
- break;
- }
+ {
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE (cpu_type_list); i++)
+ {
+ 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;
+ return 1;
+ }
+ }
+ as_warn (_("unrecognised RX CPU type %s"), arg);
+ break;
+ }
+
+ case OPTION_DISALLOW_STRING_INSNS:
+ elf_flags |= E_FLAG_RX_SINSNS_SET | E_FLAG_RX_SINSNS_NO;
return 1;
}
+
return 0;
}
fprintf (stream, _(" --mrelax\n"));
fprintf (stream, _(" --mpid\n"));
fprintf (stream, _(" --mint-register=<value>\n"));
- fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610>\n"));
+ fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2>\n"));
+ fprintf (stream, _(" --mno-allow-string-insns"));
}
static void
FILE * try;
char * path;
char * filename;
- char * current_filename;
+ const char * current_filename;
char * last_char;
- char * p;
- char * d;
+ const char * p;
+ const char * d;
char * f;
char end_char;
size_t len;
return;
}
- as_where (& current_filename, NULL);
+ current_filename = as_where (NULL);
f = (char *) xmalloc (strlen (current_filename) + strlen (filename) + 1);
/* Check the filename. If [@]..FILE[@] is found then replace
of any directory prefixes or extensions. */
if ((p = rx_strcasestr (filename, "..file")) != NULL)
{
- char * c;
+ const char * c;
len = 6; /* strlen ("..file"); */
asection * sec;
int type;
int attr = SHF_ALLOC | SHF_EXECINSTR;
- int align = 2;
+ int align = 1;
char end_char;
do
p++;
switch (*p)
{
- case '2': align = 2; break;
- case '4': align = 4; break;
- case '8': align = 8; break;
+ case '2': align = 1; break;
+ case '4': align = 2; break;
+ case '8': align = 3; break;
default:
as_bad (_("unrecognised alignment value in .SECTION directive: %s"), p);
ignore_rest_of_line ();
void
rx_op (expressionS exp, int nbytes, int type)
{
- int v = 0;
+ offsetT v = 0;
if ((exp.X_op == O_constant || exp.X_op == O_big)
&& type != RXREL_PCREL)
{
- if (exp.X_op == O_big && exp.X_add_number <= 0)
+ if (exp.X_op == O_big)
{
- LITTLENUM_TYPE w[2];
- char * ip = rx_bytes.ops + rx_bytes.n_ops;
+ if (exp.X_add_number == -1)
+ {
+ LITTLENUM_TYPE w[2];
+ char * ip = rx_bytes.ops + rx_bytes.n_ops;
- gen_to_words (w, F_PRECISION, 8);
+ gen_to_words (w, F_PRECISION, 8);
#if RX_OPCODE_BIG_ENDIAN
- ip[0] = w[0] >> 8;
- ip[1] = w[0];
- ip[2] = w[1] >> 8;
- ip[3] = w[1];
+ ip[0] = w[0] >> 8;
+ ip[1] = w[0];
+ ip[2] = w[1] >> 8;
+ ip[3] = w[1];
#else
- ip[3] = w[0] >> 8;
- ip[2] = w[0];
- ip[1] = w[1] >> 8;
- ip[0] = w[1];
+ ip[3] = w[0] >> 8;
+ ip[2] = w[0];
+ ip[1] = w[1] >> 8;
+ ip[0] = w[1];
#endif
- rx_bytes.n_ops += 4;
+ rx_bytes.n_ops += 4;
+ return;
+ }
+
+ v = ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
+ | (generic_bignum[0] & LITTLENUM_MASK);
+
}
else
+ v = exp.X_add_number;
+
+ while (nbytes)
{
- v = exp.X_add_number;
- while (nbytes)
- {
#if RX_OPCODE_BIG_ENDIAN
- OP ((v >> (8 * (nbytes - 1))) & 0xff);
+ OP ((v >> (8 * (nbytes - 1))) & 0xff);
#else
- OP (v & 0xff);
- v >>= 8;
+ OP (v & 0xff);
+ v >>= 8;
#endif
- nbytes --;
- }
+ nbytes --;
}
}
else
md_section_align (segT segment, valueT size)
{
int align = bfd_get_section_alignment (stdoutput, segment);
- return ((size + (1 << align) - 1) & (-1 << align));
+ return ((size + (1 << align) - 1) & -(1 << align));
}
/* NOP - 1 cycle */
static unsigned char nop_5[] = { 0x77, 0x10, 0x01, 0x00, 0x00 };
/* MUL #1,R0 - 1 cycle */
static unsigned char nop_6[] = { 0x74, 0x10, 0x01, 0x00, 0x00, 0x00 };
- /* BRA.S .+7 - 1 cycle */
-static unsigned char nop_7[] = { 0x0F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ /* MAX 0x80000000,R0 - 1 cycle */
+static unsigned char nop_7[] = { 0xFD, 0x70, 0x40, 0x00, 0x00, 0x00, 0x80 };
static unsigned char *nops[] = { NULL, nop_1, nop_2, nop_3, nop_4, nop_5, nop_6, nop_7 };
#define BIGGEST_NOP 7
if (fragP->fr_subtype >= next_size)
fragP->fr_subtype = 0;
tprintf ("\033[34m -> mypc %lu next_size %u new %d old %d delta %d (fetchalign)\033[0m\n",
- mypc & 7,
+ (unsigned long) (mypc & 7),
next_size, fragP->fr_subtype, oldsize, fragP->fr_subtype-oldsize);
newsize = fragP->fr_subtype;
}
else if (sec)
is_opcode = sec->flags & SEC_CODE;
-
+
/* Certain BFD relocations cannot be translated directly into
a single (non-Red Hat) RX relocation, but instead need
multiple RX relocations - handle them here. */
return reloc;
}
+void
+rx_note_string_insn_use (void)
+{
+ if ((elf_flags & E_FLAG_RX_SINSNS_MASK) == (E_FLAG_RX_SINSNS_SET | E_FLAG_RX_SINSNS_NO))
+ as_bad (_("Use of an RX string instruction detected in a file being assembled without string instruction support"));
+ elf_flags |= E_FLAG_RX_SINSNS_SET | E_FLAG_RX_SINSNS_YES;
+}
+
/* Set the ELF specific flags. */
void