diff options
Diffstat (limited to 'contrib/binutils/gas/config/tc-sparc.c')
-rw-r--r-- | contrib/binutils/gas/config/tc-sparc.c | 276 |
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); } |