From: matt Date: Fri, 6 Apr 2007 16:36:48 +0000 (+0000) Subject: 2007-04-06 Matt Thomas X-Git-Tag: preoverlapped~1048 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=4ae862a8b706fa84587449b9f24212fd0bb232e7;p=pf3gnuchains%2Fpf3gnuchains4x.git 2007-04-06 Matt Thomas * config/tc-vax.c (vax_cons): Added to support %pcrel{8,16,32}(exp) to emit pcrel relocations by DWARF2 in non-code sections. Borrowed heavily from tc-sparc.c. (vax_cons_fix_new): Likewise. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 96abc6fadc..4c2e52c30a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2007-04-06 Matt Thomas + + * config/tc-vax.c (vax_cons): Added to support %pcrel{8,16,32}(exp) + to emit pcrel relocations by DWARF2 in non-code sections. Borrowed + heavily from tc-sparc.c. (vax_cons_fix_new): Likewise. + 2007-04-04 Kazu Hirata * config/tc-m68k.c (HAVE_LONG_BRANCH): Add fido_a. diff --git a/gas/config/tc-vax.c b/gas/config/tc-vax.c index 47b4fcaea2..93cacd6e69 100644 --- a/gas/config/tc-vax.c +++ b/gas/config/tc-vax.c @@ -3265,3 +3265,143 @@ md_begin (void) fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1]; } } + +static char *vax_cons_special_reloc; + +void +vax_cons (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 (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; +} diff --git a/gas/config/tc-vax.h b/gas/config/tc-vax.h index 715d54a812..4f16e5837d 100644 --- a/gas/config/tc-vax.h +++ b/gas/config/tc-vax.h @@ -47,6 +47,13 @@ #define md_operand(x) +#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 (expressionS *, int); +void vax_cons_fix_new (struct frag *, int, unsigned int, struct expressionS *); +#endif + extern const struct relax_type md_relax_table[]; #define TC_GENERIC_RELAX_TABLE md_relax_table