From 5e0116d519c197dbd989e07c5e011e7a0dfd73c7 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 2 Feb 2003 19:37:20 +0000 Subject: [PATCH] gas/ * config/tc-mips.c (enum small_ex_type): Remove. (imm_unmatched_hi): Remove. (md_assemble): Remove use of imm_unmatched_hi. Remove the last argument from calls to append_insn. (append_insn): Remove unmatched_hi parameter; check reloc_type[0] instead. (macro_build): Update append_insn calls. (mips16_macro_build, macro_build_lui): Likewise. (mips_ip): Rework handling of small expressions. Move explicit relocation handling into my_getSmallExpression. Assume that the value of 'o' operands is zero if there is only one bracketed expression left. (percent_op): Make constant. Record the BFD relocation code associated with each operator. (my_getSmallParser, my_getPercentOp): Remove. (parse_relocation): New function. (my_getSamllExpression): Rework. Fill in relocations here rather than in mips_ip. gas/testsuite * gas/mips/elf-rel8.[sd], gas/mips/elf-rel9.[sd], gas/mips/elf-rel10.[sd], gas/mips/elf-rel11.[sd]: New tests. * gas/mips/mips.exp: Run elf-rel8 and elf-rel9 for all elf targets. Run elf-rel10 and elf-rel11 for NewABI targets. --- gas/ChangeLog | 21 ++ gas/config/tc-mips.c | 509 ++++++++--------------------- gas/testsuite/ChangeLog | 7 + gas/testsuite/gas/mips/elf-rel10.d | 29 ++ gas/testsuite/gas/mips/elf-rel10.s | 31 ++ gas/testsuite/gas/mips/elf-rel11.d | 43 +++ gas/testsuite/gas/mips/elf-rel11.s | 27 ++ gas/testsuite/gas/mips/elf-rel8.d | 57 ++++ gas/testsuite/gas/mips/elf-rel8.s | 53 +++ gas/testsuite/gas/mips/elf-rel9.d | 68 ++++ gas/testsuite/gas/mips/elf-rel9.s | 57 ++++ gas/testsuite/gas/mips/mips.exp | 10 +- 12 files changed, 542 insertions(+), 370 deletions(-) create mode 100644 gas/testsuite/gas/mips/elf-rel10.d create mode 100644 gas/testsuite/gas/mips/elf-rel10.s create mode 100644 gas/testsuite/gas/mips/elf-rel11.d create mode 100644 gas/testsuite/gas/mips/elf-rel11.s create mode 100644 gas/testsuite/gas/mips/elf-rel8.d create mode 100644 gas/testsuite/gas/mips/elf-rel8.s create mode 100644 gas/testsuite/gas/mips/elf-rel9.d create mode 100644 gas/testsuite/gas/mips/elf-rel9.s diff --git a/gas/ChangeLog b/gas/ChangeLog index e71d9653ac6..e4383bb66bd 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,24 @@ +2003-02-02 Richard Sandiford + + * config/tc-mips.c (enum small_ex_type): Remove. + (imm_unmatched_hi): Remove. + (md_assemble): Remove use of imm_unmatched_hi. Remove the last + argument from calls to append_insn. + (append_insn): Remove unmatched_hi parameter; check reloc_type[0] + instead. + (macro_build): Update append_insn calls. + (mips16_macro_build, macro_build_lui): Likewise. + (mips_ip): Rework handling of small expressions. Move explicit + relocation handling into my_getSmallExpression. Assume that the + value of 'o' operands is zero if there is only one bracketed + expression left. + (percent_op): Make constant. Record the BFD relocation code + associated with each operator. + (my_getSmallParser, my_getPercentOp): Remove. + (parse_relocation): New function. + (my_getSamllExpression): Rework. Fill in relocations here + rather than in mips_ip. + 2003-01-29 Nick Clifton * config/tc-i386.c (line_comment_chars): Add '#'. This makes the diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 446f95f4e6b..1d38d202d15 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -810,7 +810,7 @@ static void mips16_mark_labels PARAMS ((void)); static void append_insn PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p, - bfd_reloc_code_real_type *r, bfd_boolean)); + bfd_reloc_code_real_type *r)); static void mips_no_prev_insn PARAMS ((int)); static void mips_emit_delays @@ -856,12 +856,10 @@ static void mips16_ip static void mips16_immed PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean, bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *)); -static int my_getPercentOp - PARAMS ((char **, unsigned int *, int *)); -static int my_getSmallParser - PARAMS ((char **, unsigned int *, int *)); -static int my_getSmallExpression - PARAMS ((expressionS *, char *)); +static bfd_boolean parse_relocation + PARAMS ((char **, bfd_reloc_code_real_type *)); +static size_t my_getSmallExpression + PARAMS ((expressionS *, bfd_reloc_code_real_type *, char *)); static void my_getExpression PARAMS ((expressionS *, char *)); #ifdef OBJ_ELF @@ -946,32 +944,6 @@ static int mips_need_elf_addend_fixup PARAMS ((fixS *)); #endif -/* Return values of my_getSmallExpression(). */ - -enum small_ex_type -{ - S_EX_NONE = 0, - S_EX_REGISTER, - - /* Direct relocation creation by %percent_op(). */ - S_EX_HALF, - S_EX_HI, - S_EX_LO, - S_EX_GP_REL, - S_EX_GOT, - S_EX_CALL16, - S_EX_GOT_DISP, - S_EX_GOT_PAGE, - S_EX_GOT_OFST, - S_EX_GOT_HI, - S_EX_GOT_LO, - S_EX_NEG, - S_EX_HIGHER, - S_EX_HIGHEST, - S_EX_CALL_HI, - S_EX_CALL_LO -}; - /* Table and functions used to map between CPU/ISA names, and ISA levels, and CPU numbers. */ @@ -1136,10 +1108,6 @@ static bfd_reloc_code_real_type imm_reloc[3] static bfd_reloc_code_real_type offset_reloc[3] = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED}; -/* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc. */ - -static bfd_boolean imm_unmatched_hi; - /* These are set by mips16_ip if an explicit extension is used. */ static bfd_boolean mips16_small, mips16_ext; @@ -1430,7 +1398,6 @@ md_assemble (str) = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED}; imm_expr.X_op = O_absent; - imm_unmatched_hi = FALSE; offset_expr.X_op = O_absent; imm_reloc[0] = BFD_RELOC_UNUSED; imm_reloc[1] = BFD_RELOC_UNUSED; @@ -1464,11 +1431,11 @@ md_assemble (str) else { if (imm_expr.X_op != O_absent) - append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi); + append_insn (NULL, &insn, &imm_expr, imm_reloc); else if (offset_expr.X_op != O_absent) - append_insn (NULL, &insn, &offset_expr, offset_reloc, FALSE); + append_insn (NULL, &insn, &offset_expr, offset_reloc); else - append_insn (NULL, &insn, NULL, unused_reloc, FALSE); + append_insn (NULL, &insn, NULL, unused_reloc); } } @@ -1616,23 +1583,24 @@ mips16_mark_labels () used with RELOC_TYPE. */ static void -append_insn (place, ip, address_expr, reloc_type, unmatched_hi) +append_insn (place, ip, address_expr, reloc_type) char *place; struct mips_cl_insn *ip; expressionS *address_expr; bfd_reloc_code_real_type *reloc_type; - bfd_boolean unmatched_hi; { register unsigned long prev_pinfo, pinfo; char *f; fixS *fixp[3]; int nops = 0; + bfd_boolean unmatched_reloc_p; /* Mark instruction labels in mips16 mode. */ mips16_mark_labels (); prev_pinfo = prev_insn.insn_mo->pinfo; pinfo = ip->insn_mo->pinfo; + unmatched_reloc_p = FALSE; if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL)) { @@ -2176,17 +2144,17 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) || *reloc_type == BFD_RELOC_MIPS_RELGOT)) fixp[0]->fx_no_overflow = 1; - if (unmatched_hi) + if (reloc_type[0] == BFD_RELOC_HI16_S) { struct mips_hi_fixup *hi_fixup; - assert (*reloc_type == BFD_RELOC_HI16_S); hi_fixup = ((struct mips_hi_fixup *) xmalloc (sizeof (struct mips_hi_fixup))); hi_fixup->fixp = fixp[0]; hi_fixup->seg = now_seg; hi_fixup->next = mips_hi_fixup_list; mips_hi_fixup_list = hi_fixup; + unmatched_reloc_p = TRUE; } if (reloc_type[1] != BFD_RELOC_UNUSED) @@ -2743,7 +2711,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) reloc does not become a variant frag. Otherwise, the rearrangement of %hi relocs in frob_file may confuse tc_gen_reloc. */ - if (unmatched_hi) + if (unmatched_reloc_p) { frag_wane (frag_now); frag_new (0); @@ -3140,7 +3108,7 @@ macro_build (place, counter, ep, name, fmt, va_alist) va_end (args); assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL); - append_insn (place, &insn, ep, r, FALSE); + append_insn (place, &insn, ep, r); } static void @@ -3266,7 +3234,7 @@ mips16_macro_build (place, counter, ep, name, fmt, args) assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL); - append_insn (place, &insn, ep, r, FALSE); + append_insn (place, &insn, ep, r); } /* @@ -3356,10 +3324,10 @@ macro_build_lui (place, counter, ep, regnum) if (*r == BFD_RELOC_UNUSED) { insn.insn_opcode |= high_expr.X_add_number; - append_insn (place, &insn, NULL, r, FALSE); + append_insn (place, &insn, NULL, r); } else - append_insn (place, &insn, &high_expr, r, FALSE); + append_insn (place, &insn, &high_expr, r); } /* Generate a sequence of instructions to do a load or store from a constant @@ -9065,122 +9033,70 @@ mips_ip (str, ip) case 'i': /* 16 bit unsigned immediate */ case 'j': /* 16 bit signed immediate */ *imm_reloc = BFD_RELOC_LO16; - c = my_getSmallExpression (&imm_expr, s); - if (c != S_EX_NONE) - { - if (c != S_EX_LO) - { - if (c == S_EX_HI) - { - *imm_reloc = BFD_RELOC_HI16_S; - imm_unmatched_hi = TRUE; - } -#ifdef OBJ_ELF - else if (c == S_EX_HIGHEST) - *imm_reloc = BFD_RELOC_MIPS_HIGHEST; - else if (c == S_EX_HIGHER) - *imm_reloc = BFD_RELOC_MIPS_HIGHER; - else if (c == S_EX_GP_REL) - { - /* This occurs in NewABI only. */ - c = my_getSmallExpression (&imm_expr, s); - if (c != S_EX_NEG) - as_bad (_("bad composition of relocations")); - else - { - c = my_getSmallExpression (&imm_expr, s); - if (c != S_EX_LO) - as_bad (_("bad composition of relocations")); - else - { - imm_reloc[0] = BFD_RELOC_GPREL16; - imm_reloc[1] = BFD_RELOC_MIPS_SUB; - imm_reloc[2] = BFD_RELOC_LO16; - } - } - } -#endif - else - *imm_reloc = BFD_RELOC_HI16; - } - else if (imm_expr.X_op == O_constant) - imm_expr.X_add_number &= 0xffff; - } - if (*args == 'i') - { - if ((c == S_EX_NONE && imm_expr.X_op != O_constant) - || ((imm_expr.X_add_number < 0 - || imm_expr.X_add_number >= 0x10000) - && imm_expr.X_op == O_constant)) - { - if (insn + 1 < &mips_opcodes[NUMOPCODES] && - !strcmp (insn->name, insn[1].name)) - break; - if (imm_expr.X_op == O_constant - || imm_expr.X_op == O_big) - as_bad (_("16 bit expression not in range 0..65535")); - } - } - else + if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0) { int more; - offsetT max; - - /* The upper bound should be 0x8000, but - unfortunately the MIPS assembler accepts numbers - from 0x8000 to 0xffff and sign extends them, and - we want to be compatible. We only permit this - extended range for an instruction which does not - provide any further alternates, since those - alternates may handle other cases. People should - use the numbers they mean, rather than relying on - a mysterious sign extension. */ - more = (insn + 1 < &mips_opcodes[NUMOPCODES] && - strcmp (insn->name, insn[1].name) == 0); - if (more) - max = 0x8000; + offsetT minval, maxval; + + more = (insn + 1 < &mips_opcodes[NUMOPCODES] + && strcmp (insn->name, insn[1].name) == 0); + + /* If the expression was written as an unsigned number, + only treat it as signed if there are no more + alternatives. */ + if (more + && *args == 'j' + && sizeof (imm_expr.X_add_number) <= 4 + && imm_expr.X_op == O_constant + && imm_expr.X_add_number < 0 + && imm_expr.X_unsigned + && HAVE_64BIT_GPRS) + break; + + /* For compatibility with older assemblers, we accept + 0x8000-0xffff as signed 16-bit numbers when only + signed numbers are allowed. */ + if (*args == 'i') + minval = 0, maxval = 0xffff; + else if (more) + minval = -0x8000, maxval = 0x7fff; else - max = 0x10000; - if ((c == S_EX_NONE && imm_expr.X_op != O_constant) - || ((imm_expr.X_add_number < -0x8000 - || imm_expr.X_add_number >= max) - && imm_expr.X_op == O_constant) - || (more - && imm_expr.X_add_number < 0 - && HAVE_64BIT_GPRS - && imm_expr.X_unsigned - && sizeof (imm_expr.X_add_number) <= 4)) + minval = -0x8000, maxval = 0xffff; + + if (imm_expr.X_op != O_constant + || imm_expr.X_add_number < minval + || imm_expr.X_add_number > maxval) { if (more) break; if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big) - as_bad (_("16 bit expression not in range -32768..32767")); + as_bad (_("expression out of range")); } } s = expr_end; continue; case 'o': /* 16 bit offset */ - c = my_getSmallExpression (&offset_expr, s); + /* Check whether there is only a single bracketed expression + left. If so, it must be the base register and the + constant must be zero. */ + if (*s == '(' && strchr (s + 1, '(') == 0) + { + offset_expr.X_op = O_constant; + offset_expr.X_add_number = 0; + continue; + } /* If this value won't fit into a 16 bit offset, then go find a macro that will generate the 32 bit offset code pattern. */ - if (c == S_EX_NONE + if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0 && (offset_expr.X_op != O_constant || offset_expr.X_add_number >= 0x8000 || offset_expr.X_add_number < -0x8000)) break; - if (c == S_EX_HI) - { - if (offset_expr.X_op != O_constant) - break; - offset_expr.X_add_number = - (offset_expr.X_add_number >> 16) & 0xffff; - } - *offset_reloc = BFD_RELOC_LO16; s = expr_end; continue; @@ -9191,49 +9107,10 @@ mips_ip (str, ip) continue; case 'u': /* upper 16 bits */ - c = my_getSmallExpression (&imm_expr, s); - *imm_reloc = BFD_RELOC_LO16; - if (c != S_EX_NONE) - { - if (c != S_EX_LO) - { - if (c == S_EX_HI) - { - *imm_reloc = BFD_RELOC_HI16_S; - imm_unmatched_hi = TRUE; - } -#ifdef OBJ_ELF - else if (c == S_EX_HIGHEST) - *imm_reloc = BFD_RELOC_MIPS_HIGHEST; - else if (c == S_EX_GP_REL) - { - /* This occurs in NewABI only. */ - c = my_getSmallExpression (&imm_expr, s); - if (c != S_EX_NEG) - as_bad (_("bad composition of relocations")); - else - { - c = my_getSmallExpression (&imm_expr, s); - if (c != S_EX_HI) - as_bad (_("bad composition of relocations")); - else - { - imm_reloc[0] = BFD_RELOC_GPREL16; - imm_reloc[1] = BFD_RELOC_MIPS_SUB; - imm_reloc[2] = BFD_RELOC_HI16_S; - } - } - } -#endif - else - *imm_reloc = BFD_RELOC_HI16; - } - else if (imm_expr.X_op == O_constant) - imm_expr.X_add_number &= 0xffff; - } - else if (imm_expr.X_op == O_constant - && (imm_expr.X_add_number < 0 - || imm_expr.X_add_number >= 0x10000)) + if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0 + && imm_expr.X_op == O_constant + && (imm_expr.X_add_number < 0 + || imm_expr.X_add_number >= 0x10000)) as_bad (_("lui expression not in range 0..65535")); s = expr_end; continue; @@ -10070,222 +9947,118 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend, } } -static struct percent_op_match +static const struct percent_op_match { - const char *str; - const enum small_ex_type type; + const char *str; + bfd_reloc_code_real_type reloc; } percent_op[] = { - {"%lo", S_EX_LO}, + {"%lo", BFD_RELOC_LO16}, #ifdef OBJ_ELF - {"%call_hi", S_EX_CALL_HI}, - {"%call_lo", S_EX_CALL_LO}, - {"%call16", S_EX_CALL16}, - {"%got_disp", S_EX_GOT_DISP}, - {"%got_page", S_EX_GOT_PAGE}, - {"%got_ofst", S_EX_GOT_OFST}, - {"%got_hi", S_EX_GOT_HI}, - {"%got_lo", S_EX_GOT_LO}, - {"%got", S_EX_GOT}, - {"%gp_rel", S_EX_GP_REL}, - {"%half", S_EX_HALF}, - {"%highest", S_EX_HIGHEST}, - {"%higher", S_EX_HIGHER}, - {"%neg", S_EX_NEG}, + {"%call_hi", BFD_RELOC_MIPS_CALL_HI16}, + {"%call_lo", BFD_RELOC_MIPS_CALL_LO16}, + {"%call16", BFD_RELOC_MIPS_CALL16}, + {"%got_disp", BFD_RELOC_MIPS_GOT_DISP}, + {"%got_page", BFD_RELOC_MIPS_GOT_PAGE}, + {"%got_ofst", BFD_RELOC_MIPS_GOT_OFST}, + {"%got_hi", BFD_RELOC_MIPS_GOT_HI16}, + {"%got_lo", BFD_RELOC_MIPS_GOT_LO16}, + {"%got", BFD_RELOC_MIPS_GOT16}, + {"%gp_rel", BFD_RELOC_GPREL16}, + {"%half", BFD_RELOC_16}, + {"%highest", BFD_RELOC_MIPS_HIGHEST}, + {"%higher", BFD_RELOC_MIPS_HIGHER}, + {"%neg", BFD_RELOC_MIPS_SUB}, #endif - {"%hi", S_EX_HI} + {"%hi", BFD_RELOC_HI16_S} }; -/* Parse small expression input. STR gets adjusted to eat up whitespace. - It detects valid "%percent_op(...)" and "($reg)" strings. Percent_op's - can be nested, this is handled by blanking the innermost, parsing the - rest by subsequent calls. */ -static int -my_getSmallParser (str, len, nestlevel) +/* Return true if *STR points to a relocation operator. When returning true, + move *STR over the operator and store its relocation code in *RELOC. + Leave both *STR and *RELOC alone when returning false. */ + +static bfd_boolean +parse_relocation (str, reloc) char **str; - unsigned int *len; - int *nestlevel; + bfd_reloc_code_real_type *reloc; { - *len = 0; - *str += strspn (*str, " \t"); - /* Check for expression in parentheses. */ - if (**str == '(') - { - char *b = *str + 1 + strspn (*str + 1, " \t"); - char *e; - - /* Check for base register. */ - if (b[0] == '$') - { - if (strchr (b, ')') - && (e = b + strcspn (b, ") \t")) - && e - b > 1 && e - b < 4) - { - if ((e - b == 3 - && ((b[1] == 'f' && b[2] == 'p') - || (b[1] == 's' && b[2] == 'p') - || (b[1] == 'g' && b[2] == 'p') - || (b[1] == 'a' && b[2] == 't') - || (ISDIGIT (b[1]) - && ISDIGIT (b[2])))) - || (ISDIGIT (b[1]))) - { - *len = strcspn (*str, ")") + 1; - return S_EX_REGISTER; - } - } - } - /* Check for percent_op (in parentheses). */ - else if (b[0] == '%') - { - *str = b; - return my_getPercentOp (str, len, nestlevel); - } + size_t i; - /* Some other expression in the parentheses, which can contain - parentheses itself. Attempt to find the matching one. */ + for (i = 0; i < ARRAY_SIZE (percent_op); i++) + if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0) { - int pcnt = 1; - char *s; + *str += strlen (percent_op[i].str); + *reloc = percent_op[i].reloc; - *len = 1; - for (s = *str + 1; *s && pcnt; s++, (*len)++) + /* Check whether the output BFD supports this relocation. + If not, issue an error and fall back on something safe. */ + if (!bfd_reloc_type_lookup (stdoutput, percent_op[i].reloc)) { - if (*s == '(') - ++pcnt; - else if (*s == ')') - --pcnt; + as_bad ("relocation %s isn't supported by the current ABI", + percent_op[i].str); + *reloc = BFD_RELOC_LO16; } + return TRUE; } - } - /* Check for percent_op (outside of parentheses). */ - else if (*str[0] == '%') - return my_getPercentOp (str, len, nestlevel); - - /* Any other expression. */ - return S_EX_NONE; + return FALSE; } -static int -my_getPercentOp (str, len, nestlevel) - char **str; - unsigned int *len; - int *nestlevel; -{ - char *tmp = *str + 1; - unsigned int i = 0; - while (ISALPHA (*tmp) || *tmp == '_') - { - *tmp = TOLOWER (*tmp); - tmp++; - } - while (i < (sizeof (percent_op) / sizeof (struct percent_op_match))) - { - if (strncmp (*str, percent_op[i].str, strlen (percent_op[i].str))) - i++; - else - { - int type = percent_op[i].type; +/* Parse string STR as a 16-bit relocatable operand. Store the + expression in *EP and the relocations in the array starting + at RELOC. Return the number of relocation operators used. - /* Only %hi and %lo are allowed for OldABI. */ - if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO) - return S_EX_NONE; + On exit, EXPR_END points to the first character after the expression. + If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16. */ - *len = strlen (percent_op[i].str); - ++(*nestlevel); - return type; - } - } - return S_EX_NONE; -} - -static int -my_getSmallExpression (ep, str) +static size_t +my_getSmallExpression (ep, reloc, str) expressionS *ep; + bfd_reloc_code_real_type *reloc; char *str; { - static char *oldstr = NULL; - int c = S_EX_NONE; - int oldc; - int nestlevel = -1; - unsigned int len; + bfd_reloc_code_real_type reversed_reloc[3]; + size_t reloc_index, i; + int bracket_depth; - /* Don't update oldstr if the last call had nested percent_op's. We need - it to parse the outer ones later. */ - if (! oldstr) - oldstr = str; + reloc_index = 0; + bracket_depth = 0; - do + /* Search for the start of the main expression, recoding relocations + in REVERSED_RELOC. */ + for (;;) { - oldc = c; - c = my_getSmallParser (&str, &len, &nestlevel); - if (c != S_EX_NONE && c != S_EX_REGISTER) - str += len; + if (*str == '(') + bracket_depth++, str++; + else if (*str == ' ' || *str == '\t') + str++; + else if (*str == '%' + && reloc_index < (HAVE_NEWABI ? 3 : 1) + && parse_relocation (&str, &reversed_reloc[reloc_index])) + reloc_index++; + else + break; } - while (c != S_EX_NONE && c != S_EX_REGISTER); - if (nestlevel >= 0) - { - /* A percent_op was encountered. Don't try to get an expression if - it is already blanked out. */ - if (*(str + strspn (str + 1, " )")) != ')') - { - char save; - - /* Let my_getExpression() stop at the closing parenthesis. */ - save = *(str + len); - *(str + len) = '\0'; - my_getExpression (ep, str); - *(str + len) = save; - } - if (nestlevel > 0) - { - /* Blank out including the % sign and the proper matching - parenthesis. */ - int pcnt = 1; - char *s = strrchr (oldstr, '%'); - char *end; + my_getExpression (ep, str); + str = expr_end; - for (end = strchr (s, '(') + 1; *end && pcnt; end++) - { - if (*end == '(') - ++pcnt; - else if (*end == ')') - --pcnt; - } + /* Match every open bracket. */ + while (bracket_depth > 0 && (*str == ')' || *str == ' ' || *str == '\t')) + if (*str++ == ')') + bracket_depth--; - memset (s, ' ', end - s); - str = oldstr; - } - else - expr_end = str + len; + if (bracket_depth > 0) + as_bad ("unclosed '('"); - c = oldc; - } - else if (c == S_EX_NONE) - { - my_getExpression (ep, str); - } - else if (c == S_EX_REGISTER) - { - ep->X_op = O_constant; - expr_end = str; - ep->X_add_symbol = NULL; - ep->X_op_symbol = NULL; - ep->X_add_number = 0; - } - else - { - as_fatal (_("internal error")); - } + expr_end = str; - if (nestlevel <= 0) - /* All percent_op's have been handled. */ - oldstr = NULL; + reloc[0] = BFD_RELOC_LO16; + for (i = 0; i < reloc_index; i++) + reloc[i] = reversed_reloc[reloc_index - 1 - i]; - return c; + return reloc_index; } static void diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index d4dacdf2aae..7729161f89b 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2003-02-02 Richard Sandiford + + * gas/mips/elf-rel8.[sd], gas/mips/elf-rel9.[sd], + gas/mips/elf-rel10.[sd], gas/mips/elf-rel11.[sd]: New tests. + * gas/mips/mips.exp: Run elf-rel8 and elf-rel9 for all elf + targets. Run elf-rel10 and elf-rel11 for NewABI targets. + 2003-01-27 Alexandre Oliva * gas/mips/n32-consec.d: New. diff --git a/gas/testsuite/gas/mips/elf-rel10.d b/gas/testsuite/gas/mips/elf-rel10.d new file mode 100644 index 00000000000..eb12f13689e --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel10.d @@ -0,0 +1,29 @@ +#as: -march=mips3 -mabi=n32 -KPIC +#readelf: --relocs +#name: MIPS ELF reloc 10 + +Relocation section '\.rela\.text' at offset .* contains 22 entries: + *Offset * Info * Type * Sym\.Value * Sym\. Name \+ Addend +0+0000 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0 +0+0000 * 0+0018 * R_MIPS_SUB * 0+0000 +0+0000 * 0+0005 * R_MIPS_HI16 * 0+0000 +0+0004 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0 +0+0004 * 0+0018 * R_MIPS_SUB * 0+0000 +0+0004 * 0+0006 * R_MIPS_LO16 * 0+0000 +0+000c * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c +0+000c * 0+0018 * R_MIPS_SUB * 0+0000 +0+000c * 0+0005 * R_MIPS_HI16 * 0+0000 +0+0010 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c +0+0010 * 0+0018 * R_MIPS_SUB * 0+0000 +0+0010 * 0+0006 * R_MIPS_LO16 * 0+0000 +0+0018 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 0 +0+001c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 0 +0+0020 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 1234 +0+0024 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 1234 +0+0028 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ c +0+002c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ c +0+0030 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ 33221d +0+0034 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ 33221d +0+0038 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * frob \+ 0 +0+003c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * frob \+ 0 +#pass diff --git a/gas/testsuite/gas/mips/elf-rel10.s b/gas/testsuite/gas/mips/elf-rel10.s new file mode 100644 index 00000000000..cda73de6c43 --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel10.s @@ -0,0 +1,31 @@ + .globl foo + .ent foo +foo: + lui $gp,%hi(%neg(%gp_rel(foo))) + addiu $gp,$gp,%lo(%neg(%gp_rel(foo))) + daddu $gp,$gp,$25 + .end foo + + .ent bar +bar: + lui $gp,%hi(%neg(%gp_rel(bar))) + addiu $gp,$gp,%lo(%neg(%gp_rel(bar))) + daddu $gp,$gp,$25 + .end bar + + .ent frob + lw $4,%got_page(foo)($gp) + addiu $4,$4,%got_ofst(foo) + + lw $4,%got_page(foo + 0x1234)($gp) + addiu $4,$4,%got_ofst(foo + 0x1234) + + lw $4,%got_page(bar)($gp) + addiu $4,$4,%got_ofst(bar) + + lw $4,%got_page(bar + 0x332211)($gp) + addiu $4,$4,%got_ofst(bar + 0x332211) + + lw $4,%got_page(frob)($gp) + addiu $4,$4,%got_ofst(frob) + .end frob diff --git a/gas/testsuite/gas/mips/elf-rel11.d b/gas/testsuite/gas/mips/elf-rel11.d new file mode 100644 index 00000000000..408795dad09 --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel11.d @@ -0,0 +1,43 @@ +#as: -march=mips3 -mabi=64 +#readelf: --relocs +#name: MIPS ELF reloc 11 + +Relocation section '\.rela\.text' at offset .* contains 12 entries: + *Offset * Info * Type * Sym\. Value * Sym\. Name \+ Addend +0+0000 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 0 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0008 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 0 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0004 * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 0 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+000c * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 0 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0018 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 12345678 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0020 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 12345678 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+001c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 12345678 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0024 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 12345678 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0030 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * \.data \+ 10 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0034 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * \.data \+ 10 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+003c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * \.data \+ 10 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +0+0044 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * \.data \+ 10 + * Type2: R_MIPS_NONE * + * Type3: R_MIPS_NONE * +#pass diff --git a/gas/testsuite/gas/mips/elf-rel11.s b/gas/testsuite/gas/mips/elf-rel11.s new file mode 100644 index 00000000000..e8f5378c4cb --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel11.s @@ -0,0 +1,27 @@ + .ent foo +foo: + lui $4,%highest(bar) + lui $5,%hi(bar) + daddiu $4,$4,%higher(bar) + daddiu $5,$5,%lo(bar) + dsll32 $4,$4,0 + daddu $4,$4,$5 + + lui $4,%highest(bar + 0x12345678) + lui $5,%hi(bar + 0x12345678) + daddiu $4,$4,%higher(bar + 0x12345678) + daddiu $5,$5,%lo(bar + 0x12345678) + dsll32 $4,$4,0 + daddu $4,$4,$5 + + lui $4,%highest(l1) + daddiu $4,$4,%higher(l1) + dsll $4,$4,16 + daddiu $4,$4,%hi(l1) + dsll $4,$4,16 + lw $4,%lo(l1)($4) + .end foo + + .data + .word 1,2,3,4 +l1: .word 4,5 diff --git a/gas/testsuite/gas/mips/elf-rel8.d b/gas/testsuite/gas/mips/elf-rel8.d new file mode 100644 index 00000000000..270533b2883 --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel8.d @@ -0,0 +1,57 @@ +#as: -march=mips2 -mabi=32 +#objdump: -M gpr-names=numeric -dr +#name: MIPS ELF reloc 8 + +.*: file format .* + +Disassembly of section \.text: + +0+00 : + 0: 3c040000 lui \$4,0x0 + 0: R_MIPS_HI16 gvar + 4: 24840000 addiu \$4,\$4,0 + 4: R_MIPS_LO16 gvar + 8: 8ca40000 lw \$4,0\(\$5\) + 8: R_MIPS_LO16 gvar + c: 8fc40002 lw \$4,2\(\$30\) + 10: 3c040000 lui \$4,0x0 + 10: R_MIPS_CALL_HI16 gfunc + 14: 009c2021 addu \$4,\$4,\$28 + 18: 8c990000 lw \$25,0\(\$4\) + 18: R_MIPS_CALL_LO16 gfunc + 1c: 3c040000 lui \$4,0x0 + 1c: R_MIPS_GOT_HI16 gvar + 20: 009c2021 addu \$4,\$4,\$28 + 24: 8c850000 lw \$5,0\(\$4\) + 24: R_MIPS_GOT_LO16 gvar + 28: 8f840000 lw \$4,0\(\$28\) + 28: R_MIPS_GOT16 \.data + 2c: a0850000 sb \$5,0\(\$4\) + 2c: R_MIPS_LO16 \.data + 30: 3c040000 lui \$4,0x0 + 30: R_MIPS_CALL_HI16 gfunc + 34: 24840000 addiu \$4,\$4,0 + 34: R_MIPS_CALL_LO16 gfunc + 38: 3c040000 lui \$4,0x0 + 38: R_MIPS_GOT_HI16 gvar + 3c: 24840000 addiu \$4,\$4,0 + 3c: R_MIPS_GOT_LO16 gvar + 40: 8f840000 lw \$4,0\(\$28\) + 40: R_MIPS_GOT16 \.data + 44: 24840000 addiu \$4,\$4,0 + 44: R_MIPS_LO16 \.data + 48: 8f990000 lw \$25,0\(\$28\) + 48: R_MIPS_CALL16 gfunc + 4c: 27840000 addiu \$4,\$28,0 + 4c: R_MIPS_CALL16 gfunc + 50: 8f840000 lw \$4,0\(\$28\) + 50: R_MIPS_GOT_DISP gvar + 54: 27840000 addiu \$4,\$28,0 + 54: R_MIPS_GOT_DISP gvar + 58: 8f840000 lw \$4,0\(\$28\) + 58: R_MIPS_GPREL16 gvar + 5c: af840000 sw \$4,0\(\$28\) + 5c: R_MIPS_GPREL16 gvar + 60: 27840000 addiu \$4,\$28,0 + 60: R_MIPS_GPREL16 gvar + \.\.\. diff --git a/gas/testsuite/gas/mips/elf-rel8.s b/gas/testsuite/gas/mips/elf-rel8.s new file mode 100644 index 00000000000..b3f5dab58d6 --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel8.s @@ -0,0 +1,53 @@ + .equ $fprel, 2 + + .ent foo +foo: + # Test various forms of relocation syntax. + + lui $4,(%hi gvar) + addiu $4,$4,(%lo (gvar)) + lw $4,%lo gvar($5) + + # Check that registers aren't confused with $ identifiers. + + lw $4,($fprel)($fp) + + # Check various forms of paired relocations. + + lui $4,%call_hi(gfunc) + addu $4,$4,$gp + lw $25,%call_lo(gfunc)($4) + + lui $4,%got_hi(gvar) + addu $4,$4,$gp + lw $5,%got_lo(gvar)($4) + + lw $4,%got(lvar)($28) + sb $5,%lo(lvar)($4) + + lui $4,%call_hi(gfunc) + addiu $4,$4,%call_lo(gfunc) + + lui $4,%got_hi(gvar) + addiu $4,$4,%got_lo(gvar) + + lw $4,%got(lvar)($28) + addiu $4,$4,%lo(lvar) + + # Check individual relocations. + + lw $25,%call16(gfunc)($28) + addiu $4,$28,%call16(gfunc) + + lw $4,%got_disp(gvar)($28) + addiu $4,$28,%got_disp(gvar) + + lw $4,%gp_rel(gvar)($28) + sw $4,%gp_rel(gvar)($28) + addiu $4,$28,%gp_rel(gvar) + + .space 64 + .end foo + + .data +lvar: .word 1,2 diff --git a/gas/testsuite/gas/mips/elf-rel9.d b/gas/testsuite/gas/mips/elf-rel9.d new file mode 100644 index 00000000000..c78a4bf86ba --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel9.d @@ -0,0 +1,68 @@ +#as: -march=mips2 -mabi=32 +#objdump: -M gpr-names=numeric -dr +#name: MIPS ELF reloc 9 + +.*: file format .* + +Disassembly of section \.text: + +0+00 : + 0: 8f840000 lw \$4,0\(\$28\) + 0: R_MIPS_GOT16 \.data + 4: 24840010 addiu \$4,\$4,16 + 4: R_MIPS_LO16 \.data + 8: 8f840000 lw \$4,0\(\$28\) + 8: R_MIPS_GOT16 \.data + c: 24840020 addiu \$4,\$4,32 + c: R_MIPS_LO16 \.data + 10: 8f840000 lw \$4,0\(\$28\) + 10: R_MIPS_GOT16 \.data + 14: 24847ffc addiu \$4,\$4,32764 + 14: R_MIPS_LO16 \.data + 18: 8f840001 lw \$4,1\(\$28\) + 18: R_MIPS_GOT16 \.data + 1c: 24848000 addiu \$4,\$4,-32768 + 1c: R_MIPS_LO16 \.data + 20: 8f840001 lw \$4,1\(\$28\) + 20: R_MIPS_GOT16 \.data + 24: 2484fffc addiu \$4,\$4,-4 + 24: R_MIPS_LO16 \.data + 28: 8f840001 lw \$4,1\(\$28\) + 28: R_MIPS_GOT16 \.data + 2c: 24840000 addiu \$4,\$4,0 + 2c: R_MIPS_LO16 \.data + 30: 8f840002 lw \$4,2\(\$28\) + 30: R_MIPS_GOT16 \.data + 34: 24848010 addiu \$4,\$4,-32752 + 34: R_MIPS_LO16 \.data + 38: 8f840002 lw \$4,2\(\$28\) + 38: R_MIPS_GOT16 \.data + 3c: 2484f000 addiu \$4,\$4,-4096 + 3c: R_MIPS_LO16 \.data + 40: 8f840002 lw \$4,2\(\$28\) + 40: R_MIPS_GOT16 \.data + 44: 2484ffff addiu \$4,\$4,-1 + 44: R_MIPS_LO16 \.data + 48: 8f840002 lw \$4,2\(\$28\) + 48: R_MIPS_GOT16 \.data + 4c: 2484f100 addiu \$4,\$4,-3840 + 4c: R_MIPS_LO16 \.data + 50: 8f840003 lw \$4,3\(\$28\) + 50: R_MIPS_GOT16 \.data + 54: 24841345 addiu \$4,\$4,4933 + 54: R_MIPS_LO16 \.data + 58: 8f84c000 lw \$4,-16384\(\$28\) + 58: R_MIPS_GPREL16 \.sdata\+0x4000 + 5c: 8f84c004 lw \$4,-16380\(\$28\) + 5c: R_MIPS_GPREL16 \.sdata\+0x4000 + 60: 8f84c004 lw \$4,-16380\(\$28\) + 60: R_MIPS_GPREL16 \.sdata\+0x4000 + 64: 8f84c008 lw \$4,-16376\(\$28\) + 64: R_MIPS_GPREL16 \.sdata\+0x4000 + 68: 8f84c00c lw \$4,-16372\(\$28\) + 68: R_MIPS_GPREL16 \.sdata\+0x4000 + 6c: 8f84c014 lw \$4,-16364\(\$28\) + 6c: R_MIPS_GPREL16 \.sdata\+0x4000 + 70: 8f84c018 lw \$4,-16360\(\$28\) + 70: R_MIPS_GPREL16 \.sdata\+0x4000 + \.\.\. diff --git a/gas/testsuite/gas/mips/elf-rel9.s b/gas/testsuite/gas/mips/elf-rel9.s new file mode 100644 index 00000000000..4768c245336 --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel9.s @@ -0,0 +1,57 @@ + .ent foo +foo: + lw $4,%got(l1)($28) + addiu $4,$4,%lo(l1) + + lw $4,%got(l1 + 16)($28) + addiu $4,$4,%lo(l1 + 16) + + lw $4,%got(l1 + 0x7fec)($28) + addiu $4,$4,%lo(l1 + 0x7fec) + + lw $4,%got(l1 + 0x7ff0)($28) + addiu $4,$4,%lo(l1 + 0x7ff0) + + lw $4,%got(l1 + 0xffec)($28) + addiu $4,$4,%lo(l1 + 0xffec) + + lw $4,%got(l1 + 0xfff0)($28) + addiu $4,$4,%lo(l1 + 0xfff0) + + lw $4,%got(l1 + 0x18000)($28) + addiu $4,$4,%lo(l1 + 0x18000) + + lw $4,%got(l2)($28) + addiu $4,$4,%lo(l2) + + lw $4,%got(l2 + 0xfff)($28) + addiu $4,$4,%lo(l2 + 0xfff) + + lw $4,%got(l2 + 0x1000)($28) + addiu $4,$4,%lo(l2 + 0x100) + + lw $4,%got(l2 + 0x12345)($28) + addiu $4,$4,%lo(l2 + 0x12345) + + lw $4,%gp_rel(l3)($28) + lw $4,%gp_rel(l3 + 4)($28) + lw $4,%gp_rel(l4)($28) + lw $4,%gp_rel(l4 + 4)($28) + lw $4,%gp_rel(l5)($28) + lw $4,%gp_rel(l5 + 8)($28) + lw $4,%gp_rel(l5 + 12)($28) + + .space 64 + .end foo + + .data + .word 1,2,3,4 +l1: .word 4,5 + .space 0x1f000 - 24 +l2: .word 7,8 + + .sdata +l3: .word 1 +l4: .word 2 + .word 3 +l5: .word 4 diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 046a33f5282..43b21939932 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -376,7 +376,7 @@ if { [istarget mips*-*-*] } then { set ilocks [istarget mipstx39*-*-*] set gpr_ilocks [expr [istarget mipstx39*-*-*]] set addr32 [expr [istarget mipstx39*-*-*]] - set hasn32 [expr [istarget *-*-irix6*] || [istarget mips64*-*-linux*]] + set has_newabi [expr [istarget *-*-irix6*] || [istarget mips64*-*-linux*]] if { [istarget "mips*-*-*linux*"] } then { set tmips "t" @@ -602,6 +602,12 @@ if { [istarget mips*-*-*] } then { run_dump_test "elf-rel5" run_dump_test "elf-rel6" run_dump_test "elf-rel7" + run_dump_test "elf-rel8" + run_dump_test "elf-rel9" + if $has_newabi { + run_dump_test "elf-rel10" + run_dump_test "elf-rel11" + } run_dump_test "${tmips}${el}empic" run_dump_test "empic2" run_dump_test "empic3_e" @@ -614,7 +620,7 @@ if { [istarget mips*-*-*] } then { run_dump_test "elf-consthilo" } - if $hasn32 { + if $has_newabi { run_dump_test "n32-consec" } -- 2.30.2