diff --git a/gnu/dist/binutils/gas/config/tc-vax.c b/gnu/dist/binutils/gas/config/tc-vax.c index 80a166c1d690..38f17a7a0e46 100644 --- a/gnu/dist/binutils/gas/config/tc-vax.c +++ b/gnu/dist/binutils/gas/config/tc-vax.c @@ -3546,4 +3546,150 @@ tc_gen_reloc (section, fixp) } #endif /* BFD_ASSEMBLER */ +static char *vax_cons_special_reloc; + +void +vax_cons (exp, size) + expressionS *exp; + int size; +{ + char *save; + + SKIP_WHITESPACE (); + vax_cons_special_reloc = NULL; + save = input_line_pointer; + if (input_line_pointer[0] == '%') + { + if (strncmp (input_line_pointer + 1, "pcrel", 5) == 0) + { + input_line_pointer += 6; + vax_cons_special_reloc = "pcrel"; + } + if (vax_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; + default: + bad = 1; + break; + } + + if (bad) + { + as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"), + vax_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 ()"), + vax_cons_special_reloc, size * 8); + bad = 1; + } + } + + if (bad) + { + input_line_pointer = save; + vax_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 ()"), + vax_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 ()"), + vax_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()"), + vax_cons_special_reloc, size * 8); + } + } + } + } + } + if (vax_cons_special_reloc == NULL) + expression (exp); +} + +/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a + reloc for a cons. */ + +void +vax_cons_fix_new (frag, where, nbytes, exp) + fragS *frag; + int where; + unsigned int nbytes; + expressionS *exp; +{ + bfd_reloc_code_real_type r; + + r = (nbytes == 1 ? BFD_RELOC_8 : + (nbytes == 2 ? BFD_RELOC_16 : BFD_RELOC_32)); + + if (vax_cons_special_reloc) + { + if (*vax_cons_special_reloc == 'p') + { + 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; + default: abort (); + } + } + } + + fix_new_exp (frag, where, (int) nbytes, exp, 0, r); + vax_cons_special_reloc = NULL; +} + /* end of tc-vax.c */ diff --git a/gnu/dist/binutils/gas/config/tc-vax.h b/gnu/dist/binutils/gas/config/tc-vax.h index a1beb1c82e1a..53314db228f6 100644 --- a/gnu/dist/binutils/gas/config/tc-vax.h +++ b/gnu/dist/binutils/gas/config/tc-vax.h @@ -56,6 +56,14 @@ long md_chars_to_number PARAMS ((unsigned char *, int)); +#ifdef OBJ_ELF +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) vax_cons (EXP, NBYTES) +#define TC_CONS_FIX_NEW vax_cons_fix_new +void vax_cons PARAMS ((expressionS *, int)); +void vax_cons_fix_new + PARAMS ((struct frag *, int, unsigned int, struct expressionS *)); +#endif + extern const struct relax_type md_relax_table[]; #define TC_GENERIC_RELAX_TABLE md_relax_table