summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/gas/config/tc-sparc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/gas/config/tc-sparc.c')
-rw-r--r--contrib/binutils/gas/config/tc-sparc.c276
1 files changed, 213 insertions, 63 deletions
diff --git a/contrib/binutils/gas/config/tc-sparc.c b/contrib/binutils/gas/config/tc-sparc.c
index 558dc89..fe9f3f7 100644
--- a/contrib/binutils/gas/config/tc-sparc.c
+++ b/contrib/binutils/gas/config/tc-sparc.c
@@ -20,9 +20,9 @@
Boston, MA 02111-1307, USA. */
#include <stdio.h>
-#include <ctype.h>
#include "as.h"
+#include "safe-ctype.h"
#include "subsegs.h"
#include "opcode/sparc.h"
@@ -632,12 +632,12 @@ md_show_usage (stream)
continue;
if (arch != &sparc_arch_table[0])
fprintf (stream, " | ");
- if (column + strlen(arch->name) > 70)
+ if (column + strlen (arch->name) > 70)
{
column = 0;
fputc ('\n', stream);
}
- column += 5 + 2 + strlen(arch->name);
+ column += 5 + 2 + strlen (arch->name);
fprintf (stream, "-A%s", arch->name);
}
for (arch = &sparc_arch_table[0]; arch->name; arch++)
@@ -645,12 +645,12 @@ md_show_usage (stream)
if (!arch->user_option_p)
continue;
fprintf (stream, " | ");
- if (column + strlen(arch->name) > 65)
+ if (column + strlen (arch->name) > 65)
{
column = 0;
fputc ('\n', stream);
}
- column += 5 + 7 + strlen(arch->name);
+ column += 5 + 7 + strlen (arch->name);
fprintf (stream, "-xarch=%s", arch->name);
}
fprintf (stream, _("\n\
@@ -1385,11 +1385,11 @@ sparc_ip (str, pinsn)
int special_case = SPECIAL_CASE_NONE;
s = str;
- if (islower ((unsigned char) *s))
+ if (ISLOWER (*s))
{
do
++s;
- while (islower ((unsigned char) *s) || isdigit ((unsigned char) *s));
+ while (ISLOWER (*s) || ISDIGIT (*s));
}
switch (*s)
@@ -1617,11 +1617,11 @@ sparc_ip (str, pinsn)
{
s += 4;
- if (isdigit ((unsigned char) *s))
+ if (ISDIGIT (*s))
{
long num = 0;
- while (isdigit ((unsigned char) *s))
+ while (ISDIGIT (*s))
{
num = num * 10 + *s - '0';
++s;
@@ -1825,9 +1825,9 @@ sparc_ip (str, pinsn)
break;
case '#': /* Must be at least one digit. */
- if (isdigit ((unsigned char) *s++))
+ if (ISDIGIT (*s++))
{
- while (isdigit ((unsigned char) *s))
+ while (ISDIGIT (*s))
{
++s;
}
@@ -1846,10 +1846,10 @@ sparc_ip (str, pinsn)
case 'b': /* Next operand is a coprocessor register. */
case 'c':
case 'D':
- if (*s++ == '%' && *s++ == 'c' && isdigit ((unsigned char) *s))
+ if (*s++ == '%' && *s++ == 'c' && ISDIGIT (*s))
{
mask = *s++;
- if (isdigit ((unsigned char) *s))
+ if (ISDIGIT (*s))
{
mask = 10 * (mask - '0') + (*s++ - '0');
if (mask >= 32)
@@ -1942,7 +1942,7 @@ sparc_ip (str, pinsn)
goto error;
case 'r': /* any register */
- if (!isdigit ((unsigned char) (c = *s++)))
+ if (!ISDIGIT ((c = *s++)))
{
goto error;
}
@@ -1957,7 +1957,7 @@ sparc_ip (str, pinsn)
case '7':
case '8':
case '9':
- if (isdigit ((unsigned char) *s))
+ if (ISDIGIT (*s))
{
if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
{
@@ -2022,9 +2022,9 @@ sparc_ip (str, pinsn)
if (*s++ == '%'
&& ((format = *s) == 'f')
- && isdigit ((unsigned char) *++s))
+ && ISDIGIT (*++s))
{
- for (mask = 0; isdigit ((unsigned char) *s); ++s)
+ for (mask = 0; ISDIGIT (*s); ++s)
{
mask = 10 * mask + (*s - '0');
} /* read the number */
@@ -2240,7 +2240,7 @@ sparc_ip (str, pinsn)
for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
;
- if (s1 != s && isdigit ((unsigned char) s1[-1]))
+ if (s1 != s && ISDIGIT (s1[-1]))
{
if (s1[-2] == '%' && s1[-3] == '+')
s1 -= 3;
@@ -2663,7 +2663,7 @@ parse_keyword_arg (lookup_fn, input_pointerP, valueP)
p = *input_pointerP;
for (q = p + (*p == '#' || *p == '%');
- isalnum ((unsigned char) *q) || *q == '_';
+ ISALNUM (*q) || *q == '_';
++q)
continue;
c = *q;
@@ -2881,18 +2881,16 @@ md_number_to_chars (buf, val, n)
/* Apply a fixS to the frags, now that we know the value it ought to
hold. */
-int
-md_apply_fix3 (fixP, value, segment)
+void
+md_apply_fix3 (fixP, valP, segment)
fixS *fixP;
- valueT *value;
+ valueT *valP;
segT segment;
{
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
- offsetT val;
+ offsetT val = * (offsetT *) valP;
long insn;
- val = *value;
-
assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
fixP->fx_addnumber = val; /* Remember value for emit_reloc. */
@@ -2905,22 +2903,25 @@ md_apply_fix3 (fixP, value, segment)
don't want to include the value of an externally visible symbol. */
if (fixP->fx_addsy != NULL)
{
- if (symbol_used_in_reloc_p (fixP->fx_addsy)
- && (S_IS_EXTERNAL (fixP->fx_addsy)
- || S_IS_WEAK (fixP->fx_addsy)
+ symbolS * sym = fixP->fx_addsy;
+ segT seg = S_GET_SEGMENT (sym);
+
+ if (symbol_used_in_reloc_p (sym)
+ && (S_IS_EXTERNAL (sym)
+ || S_IS_WEAK (sym)
+ || (seg->flags & SEC_MERGE)
|| (sparc_pic_code && ! fixP->fx_pcrel)
- || (S_GET_SEGMENT (fixP->fx_addsy) != segment
- && ((bfd_get_section_flags (stdoutput,
- S_GET_SEGMENT (fixP->fx_addsy))
- & SEC_LINK_ONCE) != 0
- || strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
- ".gnu.linkonce",
- sizeof ".gnu.linkonce" - 1) == 0)))
- && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
- && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
- && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
- fixP->fx_addnumber -= S_GET_VALUE (fixP->fx_addsy);
- return 1;
+ || (seg != segment
+ && (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0)
+ || (strncmp (segment_name (seg),
+ ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0))))
+ && seg != absolute_section
+ && seg != undefined_section
+ && ! bfd_is_com_section (seg))
+ fixP->fx_addnumber -= S_GET_VALUE (sym);
+
+ return;
}
#endif
@@ -2991,7 +2992,7 @@ md_apply_fix3 (fixP, value, segment)
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
{
fixP->fx_done = 0;
- return 1;
+ return;
}
else
{
@@ -3163,14 +3164,10 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_SPARC_LM22:
case BFD_RELOC_HI22:
if (!fixP->fx_addsy)
- {
- insn |= (val >> 10) & 0x3fffff;
- }
+ insn |= (val >> 10) & 0x3fffff;
else
- {
- /* FIXME: Need comment explaining why we do this. */
- insn &= ~0xffff;
- }
+ /* FIXME: Need comment explaining why we do this. */
+ insn &= ~0xffff;
break;
case BFD_RELOC_SPARC22:
@@ -3186,14 +3183,10 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_LO10:
if (!fixP->fx_addsy)
- {
- insn |= val & 0x3ff;
- }
+ insn |= val & 0x3ff;
else
- {
- /* FIXME: Need comment explaining why we do this. */
- insn &= ~0xff;
- }
+ /* FIXME: Need comment explaining why we do this. */
+ insn &= ~0xff;
break;
case BFD_RELOC_SPARC_OLO10:
@@ -3264,8 +3257,6 @@ md_apply_fix3 (fixP, value, segment)
/* Are we finished with this relocation now? */
if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
fixP->fx_done = 1;
-
- return 1;
}
/* Translate internal representation of relocation info to BFD target
@@ -3322,6 +3313,12 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_SPARC_UA16:
case BFD_RELOC_SPARC_UA32:
case BFD_RELOC_SPARC_UA64:
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_64_PCREL:
+ case BFD_RELOC_SPARC_PLT32:
+ case BFD_RELOC_SPARC_PLT64:
case BFD_RELOC_VTABLE_ENTRY:
case BFD_RELOC_VTABLE_INHERIT:
code = fixp->fx_r_type;
@@ -3411,9 +3408,11 @@ tc_gen_reloc (section, fixp)
#else /* elf or coff */
- if (reloc->howto->pc_relative == 0
- || code == BFD_RELOC_SPARC_PC10
- || code == BFD_RELOC_SPARC_PC22)
+ if (code != BFD_RELOC_32_PCREL_S2
+ && code != BFD_RELOC_SPARC_WDISP22
+ && code != BFD_RELOC_SPARC_WDISP16
+ && code != BFD_RELOC_SPARC_WDISP19
+ && code != BFD_RELOC_SPARC_WPLT30)
reloc->addend = fixp->fx_addnumber;
else if (symbol_section_p (fixp->fx_addsy))
reloc->addend = (section->vma
@@ -3909,6 +3908,11 @@ s_proc (ignore)
static int sparc_no_align_cons = 0;
+/* This static variable is set by sparc_cons to emit requested types
+ of relocations in cons_fix_new_sparc. */
+
+static const char *sparc_cons_special_reloc;
+
/* This handles the unaligned space allocation pseudo-ops, such as
.uaword. .uaword is just like .word, but the value does not need
to be aligned. */
@@ -3920,6 +3924,7 @@ s_uacons (bytes)
/* Tell sparc_cons_align not to align this value. */
sparc_no_align_cons = 1;
cons (bytes);
+ sparc_no_align_cons = 0;
}
/* This handles the native word allocation pseudo-op .nword.
@@ -4180,6 +4185,134 @@ sparc_elf_final_processing ()
else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
}
+
+void
+sparc_cons (exp, size)
+ expressionS *exp;
+ int size;
+{
+ char *save;
+
+ SKIP_WHITESPACE ();
+ sparc_cons_special_reloc = NULL;
+ save = input_line_pointer;
+ if (input_line_pointer[0] == '%'
+ && input_line_pointer[1] == 'r'
+ && input_line_pointer[2] == '_')
+ {
+ if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
+ {
+ input_line_pointer += 7;
+ sparc_cons_special_reloc = "disp";
+ }
+ else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
+ {
+ if (size != 4 && size != 8)
+ as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
+ else
+ {
+ input_line_pointer += 6;
+ sparc_cons_special_reloc = "plt";
+ }
+ }
+ if (sparc_cons_special_reloc)
+ {
+ int bad = 0;
+
+ switch (size)
+ {
+ case 1:
+ if (*input_line_pointer != '8')
+ bad = 1;
+ input_line_pointer--;
+ break;
+ case 2:
+ if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+ bad = 1;
+ break;
+ case 4:
+ if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+ bad = 1;
+ break;
+ case 8:
+ if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
+ bad = 1;
+ break;
+ default:
+ bad = 1;
+ break;
+ }
+
+ if (bad)
+ {
+ as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+ sparc_cons_special_reloc, size * 8, size);
+ }
+ else
+ {
+ input_line_pointer += 2;
+ if (*input_line_pointer != '(')
+ {
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ sparc_cons_special_reloc, size * 8);
+ bad = 1;
+ }
+ }
+
+ if (bad)
+ {
+ input_line_pointer = save;
+ sparc_cons_special_reloc = NULL;
+ }
+ else
+ {
+ int c;
+ char *end = ++input_line_pointer;
+ int npar = 0;
+
+ while (! is_end_of_line[(c = *end)])
+ {
+ if (c == '(')
+ npar++;
+ else if (c == ')')
+ {
+ if (!npar)
+ break;
+ npar--;
+ }
+ end++;
+ }
+
+ if (c != ')')
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ sparc_cons_special_reloc, size * 8);
+ else
+ {
+ *end = '\0';
+ expression (exp);
+ *end = c;
+ if (input_line_pointer != end)
+ {
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ sparc_cons_special_reloc, size * 8);
+ }
+ else
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ c = *input_line_pointer;
+ if (! is_end_of_line[c] && c != ',')
+ as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+ sparc_cons_special_reloc, size * 8);
+ }
+ }
+ }
+ }
+ }
+ if (sparc_cons_special_reloc == NULL)
+ expression (exp);
+}
+
#endif
/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
@@ -4204,7 +4337,25 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
&& now_seg->flags & SEC_ALLOC)
r = BFD_RELOC_SPARC_REV32;
- if (sparc_no_align_cons)
+ if (sparc_cons_special_reloc)
+ {
+ if (*sparc_cons_special_reloc == 'd')
+ switch (nbytes)
+ {
+ case 1: r = BFD_RELOC_8_PCREL; break;
+ case 2: r = BFD_RELOC_16_PCREL; break;
+ case 4: r = BFD_RELOC_32_PCREL; break;
+ case 8: r = BFD_RELOC_64_PCREL; break;
+ default: abort ();
+ }
+ else
+ switch (nbytes)
+ {
+ case 4: r = BFD_RELOC_SPARC_PLT32; break;
+ case 8: r = BFD_RELOC_SPARC_PLT64; break;
+ }
+ }
+ else if (sparc_no_align_cons)
{
switch (nbytes)
{
@@ -4213,8 +4364,7 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
case 8: r = BFD_RELOC_SPARC_UA64; break;
default: abort ();
}
- sparc_no_align_cons = 0;
- }
+ }
fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
}
OpenPOWER on IntegriCloud