/* tc-sh.c -- Assemble code for the Renesas / SuperH SH
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1993-2016 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
accommodate the insns seen so far. */
static unsigned int valid_arch;
+#ifdef OBJ_ELF
/* Whether --fdpic was given. */
static int sh_fdpic;
+#endif
const char EXP_CHARS[] = "eE";
#if BFD_HOST_64BIT_LONG
/* The "reach" type is long, so we can only do this for a 64-bit-long
host. */
-#define SH64PCREL32_M (((long) -1 << 30) * 2 - 4)
+#define SH64PCREL32_M ((-((long) 1 << 30)) * 2 - 4)
#define SH64PCREL48_F ((((long) 1 << 47) - 1) - 4)
-#define SH64PCREL48_M (((long) -1 << 47) - 4)
+#define SH64PCREL48_M ((-((long) 1 << 47)) - 4)
#define SH64PCREL48_LENGTH (3 * 4)
#else
/* If the host does not have 64-bit longs, just make this state identical
in reach to the 32-bit state. Note that we have a slightly incorrect
reach, but the correct one above will overflow a 32-bit number. */
-#define SH64PCREL32_M (((long) -1 << 30) * 2)
+#define SH64PCREL32_M ((-((long) 1 << 30)) * 2)
#define SH64PCREL48_F SH64PCREL32_F
#define SH64PCREL48_M SH64PCREL32_M
#define SH64PCREL48_LENGTH (3 * 4)
#if BFD_HOST_64BIT_LONG
/* The "reach" type is long, so we can only do this for a 64-bit-long
host. */
-#define MOVI_32_M (((long) -1 << 30) * 2 - 4)
+#define MOVI_32_M ((-((long) 1 << 30)) * 2 - 4)
#define MOVI_48_F ((((long) 1 << 47) - 1) - 4)
-#define MOVI_48_M (((long) -1 << 47) - 4)
+#define MOVI_48_M ((-((long) 1 << 47)) - 4)
#else
/* If the host does not have 64-bit longs, just make this state identical
in reach to the 32-bit state. Note that we have a slightly incorrect
reach, but the correct one above will overflow a 32-bit number. */
-#define MOVI_32_M (((long) -1 << 30) * 2)
+#define MOVI_32_M ((-((long) 1 << 30)) * 2)
#define MOVI_48_F MOVI_32_F
#define MOVI_48_M MOVI_32_M
#endif /* BFD_HOST_64BIT_LONG */
/* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG. */
void
-sh_cons_fix_new (fragS *frag, int off, int size, expressionS *exp)
+sh_cons_fix_new (fragS *frag, int off, int size, expressionS *exp,
+ bfd_reloc_code_real_type r_type)
{
- bfd_reloc_code_real_type r_type = BFD_RELOC_UNUSED;
+ r_type = BFD_RELOC_UNUSED;
if (sh_check_fixup (exp, &r_type))
as_bad (_("Invalid PIC expression."));
r_type = BFD_RELOC_32;
break;
-#ifdef HAVE_SH64
case 8:
r_type = BFD_RELOC_64;
break;
-#endif
default:
goto error;
/* Clobbers input_line_pointer, checks end-of-line. */
/* NBYTES 1=.byte, 2=.word, 4=.long */
static void
-sh_elf_cons (register int nbytes)
+sh_elf_cons (int nbytes)
{
expressionS exp;
symbol_get_frag (r->X_add_symbol),
&frag_off))
{
- l->X_add_number -= r->X_add_number;
- l->X_add_number -= frag_off / OCTETS_PER_BYTE;
- l->X_add_number += (S_GET_VALUE (l->X_add_symbol)
- - S_GET_VALUE (r->X_add_symbol));
+ offsetT symval_diff = S_GET_VALUE (l->X_add_symbol)
+ - S_GET_VALUE (r->X_add_symbol);
+ subtract_from_result (l, r->X_add_number, r->X_extrabit);
+ subtract_from_result (l, frag_off / OCTETS_PER_BYTE, 0);
+ add_to_result (l, symval_diff, symval_diff < 0);
l->X_op = O_constant;
l->X_add_symbol = 0;
return 1;
md_begin (void)
{
const sh_opcode_info *opcode;
- char *prev_name = "";
+ const char *prev_name = "";
unsigned int target_arch;
target_arch
}
else
prefix = 0;
-
+
consumed = parse_reg_without_prefix (src, mode, reg);
if (consumed == 0)
get_specific (sh_opcode_info *opcode, sh_operand_info *operands)
{
sh_opcode_info *this_try = opcode;
- char *name = opcode->name;
+ const char *name = opcode->name;
int n = 0;
while (opcode->name)
static char *
insert_loop_bounds (char *output, sh_operand_info *operand)
{
- char *name;
symbolS *end_sym;
/* Since the low byte of the opcode will be overwritten by the reloc, we
if (sh_relax)
{
static int count = 0;
+ char name[11];
/* If the last loop insn is a two-byte-insn, it is in danger of being
swapped with the insn after it. To prevent this, create a new
right in the middle, but four byte insns are not swapped anyways. */
/* A REPEAT takes 6 bytes. The SH has a 32 bit address space.
Hence a 9 digit number should be enough to count all REPEATs. */
- name = alloca (11);
sprintf (name, "_R%x", count++ & 0x3fffffff);
end_sym = symbol_new (name, undefined_section, 0, &zero_address_frag);
/* Make this a local symbol. */
int low_byte = target_big_endian ? 1 : 0;
int max_index = 4;
bfd_reloc_code_real_type r_type;
+#ifdef OBJ_ELF
int unhandled_pic = 0;
+#endif
nbuf[0] = 0;
nbuf[1] = 0;
nbuf[6] = 0;
nbuf[7] = 0;
+#ifdef OBJ_ELF
for (indx = 0; indx < 3; indx++)
if (opcode->arg[indx] == A_IMM
&& operand[indx].type == A_IMM
|| sh_PIC_related_p (operand[indx].immediate.X_add_symbol)
|| sh_PIC_related_p (operand[indx].immediate.X_op_symbol)))
unhandled_pic = 1;
+#endif
if (SH_MERGE_ARCH_SET (opcode->arch, arch_op32))
{
break;
case IMM0_20:
r_type = BFD_RELOC_SH_DISP20;
+#ifdef OBJ_ELF
if (sh_check_fixup (&operand->immediate, &r_type))
as_bad (_("Invalid PIC expression."));
unhandled_pic = 0;
+#endif
insert4 (output, r_type, 0, operand);
break;
case IMM0_20BY8:
}
}
}
+#ifdef OBJ_ELF
if (unhandled_pic)
as_bad (_("misplaced PIC operand"));
+#endif
if (!target_big_endian)
{
output[1] = (nbuf[0] << 4) | (nbuf[1]);
unsigned char *op_start;
unsigned char *op_end;
char name[20];
- int nlen = 0;
+ unsigned int nlen = 0;
/* Drop leading whitespace. */
while (*str == ' ')
assemble_ppi, so the opcode might be terminated by an '@'. */
for (op_start = op_end = (unsigned char *) str;
*op_end
- && nlen < 20
+ && nlen < sizeof (name) - 1
&& !is_end_of_line[*op_end] && *op_end != ' ' && *op_end != '@';
op_end++)
{
size_t md_longopts_size = sizeof (md_longopts);
int
-md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
{
switch (c)
{
for (; bfd_arch; bfd_arch=bfd_arch->next)
{
int len = strlen(bfd_arch->printable_name);
-
+
if (bfd_arch->mach == bfd_mach_sh5)
continue;
-
+
if (strncasecmp (bfd_arch->printable_name, arg, len) != 0)
continue;
continue;
break;
}
-
+
if (!preset_target_arch)
as_bad (_("Invalid argument to --isa option: %s"), arg);
}
return size;
#else /* ! OBJ_ELF */
return ((size + (1 << bfd_get_section_alignment (stdoutput, seg)) - 1)
- & (-1 << bfd_get_section_alignment (stdoutput, seg)));
+ & -(1 << bfd_get_section_alignment (stdoutput, seg)));
#endif /* ! OBJ_ELF */
}
sh_cons_align (int nbytes)
{
int nalign;
- char *p;
if (sh_no_align_cons)
{
return;
}
- p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
- (symbolS *) NULL, (offsetT) nalign, (char *) NULL);
+ frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
+ (symbolS *) NULL, (offsetT) nalign, (char *) NULL);
record_alignment (now_seg, nalign);
}
the other symbol. We have to adjust the relocation type here. */
if (fixP->fx_pcrel)
{
+#ifndef HAVE_SH64
+ /* Safeguard; this must not occur for non-sh64 configurations. */
+ gas_assert (fixP->fx_r_type != BFD_RELOC_64);
+#endif
+
switch (fixP->fx_r_type)
{
default:
buf[highbyte] |= (val >> 8) & 0xf;
break;
+#ifndef HAVE_SH64
+ case BFD_RELOC_64:
+ apply_full_field_fix (fixP, buf, *valP, 8);
+ break;
+#endif
+
case BFD_RELOC_32:
case BFD_RELOC_32_PCREL:
apply_full_field_fix (fixP, buf, val, 4);
if (SWITCH_TABLE (fixp))
{
*rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
- rel->addend = 0;
+ rel->addend = rel->address - S_GET_VALUE(fixp->fx_subsy);
if (r_type == BFD_RELOC_16)
r_type = BFD_RELOC_SH_SWITCH16;
else if (r_type == BFD_RELOC_8)
#ifdef OBJ_ELF
inline static char *
-sh_end_of_match (char *cont, char *what)
+sh_end_of_match (char *cont, const char *what)
{
int len = strlen (what);
unsigned int i;
const char *p;
char *q;
- static struct { char *name; int dw2regnum; } regnames[] =
+ static struct { const char *name; int dw2regnum; } regnames[] =
{
{ "pr", 17 }, { "t", 18 }, { "gbr", 19 }, { "mach", 20 },
{ "macl", 21 }, { "fpul", 23 }