This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Patch to extend explicit reloc support in MIPS gas
- From: Eric Christopher <echristo at redhat dot com>
- To: Richard Sandiford <rsandifo at redhat dot com>
- Cc: binutils at sources dot redhat dot com
- Date: 27 Jan 2003 12:25:11 -0800
- Subject: Re: Patch to extend explicit reloc support in MIPS gas
- References: <m3n0loay5w.fsf@localhost.localdomain>
> On the other hand, an error or warning might trap mistakes earlier.
> I can add some new checking code if that's what folks prefer.
>
Error checking code is always good, but not necessary for the patch.
>
> OK to install?
>
OK. Wonderful work. Thanks.
-eric
> 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.
>
> Index: config/tc-mips.c
> ===================================================================
> RCS file: /cvs/src/src/gas/config/tc-mips.c,v
> retrieving revision 1.188
> diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.188 tc-mips.c
> *** config/tc-mips.c 23 Jan 2003 12:51:05 -0000 1.188
> --- config/tc-mips.c 26 Jan 2003 12:09:08 -0000
> *************** static void mips16_mark_labels
> *** 810,816 ****
> PARAMS ((void));
> static void append_insn
> PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
> ! bfd_reloc_code_real_type *r, bfd_boolean));
> static void mips_no_prev_insn
> PARAMS ((int));
> static void mips_emit_delays
> --- 810,816 ----
> PARAMS ((void));
> static void append_insn
> PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
> ! bfd_reloc_code_real_type *r));
> static void mips_no_prev_insn
> PARAMS ((int));
> static void mips_emit_delays
> *************** static void mips16_ip
> *** 856,867 ****
> 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 void my_getExpression
> PARAMS ((expressionS *, char *));
> #ifdef OBJ_ELF
> --- 856,865 ----
> static void mips16_immed
> PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean,
> bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *));
> ! 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
> *************** static int mips_need_elf_addend_fixup
> *** 946,977 ****
> 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. */
>
> --- 944,949 ----
> *************** static bfd_reloc_code_real_type imm_relo
> *** 1136,1145 ****
> 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;
> --- 1108,1113 ----
> *************** md_assemble (str)
> *** 1430,1436 ****
> = {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;
> --- 1398,1403 ----
> *************** md_assemble (str)
> *** 1464,1474 ****
> else
> {
> if (imm_expr.X_op != O_absent)
> ! append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi);
> else if (offset_expr.X_op != O_absent)
> ! append_insn (NULL, &insn, &offset_expr, offset_reloc, FALSE);
> else
> ! append_insn (NULL, &insn, NULL, unused_reloc, FALSE);
> }
> }
>
> --- 1431,1441 ----
> else
> {
> if (imm_expr.X_op != O_absent)
> ! append_insn (NULL, &insn, &imm_expr, imm_reloc);
> else if (offset_expr.X_op != O_absent)
> ! append_insn (NULL, &insn, &offset_expr, offset_reloc);
> else
> ! append_insn (NULL, &insn, NULL, unused_reloc);
> }
> }
>
> *************** mips16_mark_labels ()
> *** 1616,1638 ****
> used with RELOC_TYPE. */
>
> static void
> ! append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
> 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;
>
> /* Mark instruction labels in mips16 mode. */
> mips16_mark_labels ();
>
> prev_pinfo = prev_insn.insn_mo->pinfo;
> pinfo = ip->insn_mo->pinfo;
>
> if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
> {
> --- 1583,1606 ----
> used with RELOC_TYPE. */
>
> static void
> ! 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;
> {
> 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))
> {
> *************** #define emit_nop() \
> *** 2176,2192 ****
> || *reloc_type == BFD_RELOC_MIPS_RELGOT))
> fixp[0]->fx_no_overflow = 1;
>
> ! if (unmatched_hi)
> {
> 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;
> }
>
> if (reloc_type[1] != BFD_RELOC_UNUSED)
> --- 2144,2160 ----
> || *reloc_type == BFD_RELOC_MIPS_RELGOT))
> fixp[0]->fx_no_overflow = 1;
>
> ! if (reloc_type[0] == BFD_RELOC_HI16_S)
> {
> struct mips_hi_fixup *hi_fixup;
>
> 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)
> *************** #define emit_nop() \
> *** 2743,2749 ****
> reloc does not become a variant frag. Otherwise, the
> rearrangement of %hi relocs in frob_file may confuse
> tc_gen_reloc. */
> ! if (unmatched_hi)
> {
> frag_wane (frag_now);
> frag_new (0);
> --- 2711,2717 ----
> reloc does not become a variant frag. Otherwise, the
> rearrangement of %hi relocs in frob_file may confuse
> tc_gen_reloc. */
> ! if (unmatched_reloc_p)
> {
> frag_wane (frag_now);
> frag_new (0);
> *************** macro_build (place, counter, ep, name, f
> *** 3140,3146 ****
> va_end (args);
> assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
>
> ! append_insn (place, &insn, ep, r, FALSE);
> }
>
> static void
> --- 3108,3114 ----
> va_end (args);
> assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
>
> ! append_insn (place, &insn, ep, r);
> }
>
> static void
> *************** mips16_macro_build (place, counter, ep,
> *** 3266,3272 ****
>
> assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
>
> ! append_insn (place, &insn, ep, r, FALSE);
> }
>
> /*
> --- 3234,3240 ----
>
> assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
>
> ! append_insn (place, &insn, ep, r);
> }
>
> /*
> *************** macro_build_lui (place, counter, ep, reg
> *** 3356,3365 ****
> if (*r == BFD_RELOC_UNUSED)
> {
> insn.insn_opcode |= high_expr.X_add_number;
> ! append_insn (place, &insn, NULL, r, FALSE);
> }
> else
> ! append_insn (place, &insn, &high_expr, r, FALSE);
> }
>
> /* Generate a sequence of instructions to do a load or store from a constant
> --- 3324,3333 ----
> if (*r == BFD_RELOC_UNUSED)
> {
> insn.insn_opcode |= high_expr.X_add_number;
> ! append_insn (place, &insn, NULL, r);
> }
> else
> ! append_insn (place, &insn, &high_expr, r);
> }
>
> /* Generate a sequence of instructions to do a load or store from a constant
> *************** mips_ip (str, ip)
> *** 9065,9186 ****
> 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
> {
> 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;
> 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))
> {
> 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"));
> }
> }
> s = expr_end;
> continue;
>
> case 'o': /* 16 bit offset */
> ! c = my_getSmallExpression (&offset_expr, s);
>
> /* 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
> && (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;
>
> --- 9033,9102 ----
> case 'i': /* 16 bit unsigned immediate */
> case 'j': /* 16 bit signed immediate */
> *imm_reloc = BFD_RELOC_LO16;
> ! if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0)
> {
> int more;
> ! 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
> ! 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 (_("expression out of range"));
> }
> }
> s = expr_end;
> continue;
>
> case 'o': /* 16 bit offset */
> ! /* 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 (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;
>
> s = expr_end;
> continue;
>
> *************** mips_ip (str, ip)
> *** 9191,9239 ****
> 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))
> as_bad (_("lui expression not in range 0..65535"));
> s = expr_end;
> continue;
> --- 9107,9116 ----
> continue;
>
> case 'u': /* upper 16 bits */
> ! 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;
> *************** mips16_immed (file, line, type, val, war
> *** 10070,10291 ****
> }
> }
>
> ! static struct percent_op_match
> {
> ! const char *str;
> ! const enum small_ex_type type;
> } percent_op[] =
> {
> ! {"%lo", S_EX_LO},
> #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},
> #endif
> ! {"%hi", S_EX_HI}
> };
>
> - /* 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)
> char **str;
> ! unsigned int *len;
> ! int *nestlevel;
> {
> ! *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);
> ! }
>
> ! /* Some other expression in the parentheses, which can contain
> ! parentheses itself. Attempt to find the matching one. */
> {
> ! int pcnt = 1;
> ! char *s;
>
> ! *len = 1;
> ! for (s = *str + 1; *s && pcnt; s++, (*len)++)
> {
> ! if (*s == '(')
> ! ++pcnt;
> ! else if (*s == ')')
> ! --pcnt;
> }
> }
> ! }
> ! /* Check for percent_op (outside of parentheses). */
> ! else if (*str[0] == '%')
> ! return my_getPercentOp (str, len, nestlevel);
> !
> ! /* Any other expression. */
> ! return S_EX_NONE;
> }
>
> - 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;
> !
> ! /* Only %hi and %lo are allowed for OldABI. */
> ! if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO)
> ! return S_EX_NONE;
>
> ! *len = strlen (percent_op[i].str);
> ! ++(*nestlevel);
> ! return type;
> ! }
> ! }
> ! return S_EX_NONE;
> ! }
>
> ! static int
> ! my_getSmallExpression (ep, str)
> expressionS *ep;
> char *str;
> {
> ! static char *oldstr = NULL;
> ! int c = S_EX_NONE;
> ! int oldc;
> ! int nestlevel = -1;
> ! unsigned int len;
>
> ! /* 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;
>
> ! do
> {
> ! oldc = c;
> ! c = my_getSmallParser (&str, &len, &nestlevel);
> ! if (c != S_EX_NONE && c != S_EX_REGISTER)
> ! str += len;
> }
> - 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;
>
> ! for (end = strchr (s, '(') + 1; *end && pcnt; end++)
> ! {
> ! if (*end == '(')
> ! ++pcnt;
> ! else if (*end == ')')
> ! --pcnt;
> ! }
>
> ! memset (s, ' ', end - s);
> ! str = oldstr;
> ! }
> ! else
> ! expr_end = str + len;
>
> ! 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"));
> ! }
>
> ! if (nestlevel <= 0)
> ! /* All percent_op's have been handled. */
> ! oldstr = NULL;
>
> ! return c;
> }
>
> static void
> --- 9947,10064 ----
> }
> }
>
> ! static const struct percent_op_match
> {
> ! const char *str;
> ! bfd_reloc_code_real_type reloc;
> } percent_op[] =
> {
> ! {"%lo", BFD_RELOC_LO16},
> #ifdef OBJ_ELF
> ! {"%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", BFD_RELOC_HI16_S}
> };
>
>
> ! /* 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;
> ! bfd_reloc_code_real_type *reloc;
> {
> ! size_t i;
>
> ! for (i = 0; i < ARRAY_SIZE (percent_op); i++)
> ! if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0)
> {
> ! *str += strlen (percent_op[i].str);
> ! *reloc = percent_op[i].reloc;
>
> ! /* 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))
> {
> ! as_bad ("relocation %s isn't supported by the current ABI",
> ! percent_op[i].str);
> ! *reloc = BFD_RELOC_LO16;
> }
> + return TRUE;
> }
> ! return FALSE;
> }
>
>
> ! /* 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.
>
> ! 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. */
>
> ! static size_t
> ! my_getSmallExpression (ep, reloc, str)
> expressionS *ep;
> + bfd_reloc_code_real_type *reloc;
> char *str;
> {
> ! bfd_reloc_code_real_type reversed_reloc[3];
> ! size_t reloc_index, i;
> ! int bracket_depth;
>
> ! reloc_index = 0;
> ! bracket_depth = 0;
>
> ! /* Search for the start of the main expression, recoding relocations
> ! in REVERSED_RELOC. */
> ! for (;;)
> {
> ! 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;
> }
>
> ! my_getExpression (ep, str);
> ! str = expr_end;
>
> ! /* Match every open bracket. */
> ! while (bracket_depth > 0 && (*str == ')' || *str == ' ' || *str == '\t'))
> ! if (*str++ == ')')
> ! bracket_depth--;
>
> ! if (bracket_depth > 0)
> ! as_bad ("unclosed '('");
>
> ! expr_end = str;
>
> ! reloc[0] = BFD_RELOC_LO16;
> ! for (i = 0; i < reloc_index; i++)
> ! reloc[i] = reversed_reloc[reloc_index - 1 - i];
>
> ! return reloc_index;
> }
>
> static void
> Index: testsuite/gas/mips/mips.exp
> ===================================================================
> RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
> retrieving revision 1.57
> diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.57 mips.exp
> *** testsuite/gas/mips/mips.exp 31 Dec 2002 08:11:17 -0000 1.57
> --- testsuite/gas/mips/mips.exp 26 Jan 2003 12:09:08 -0000
> *************** if { [istarget mips*-*-*] } then {
> *** 376,381 ****
> --- 376,383 ----
> set ilocks [istarget mipstx39*-*-*]
> set gpr_ilocks [expr [istarget mipstx39*-*-*]]
> set addr32 [expr [istarget mipstx39*-*-*]]
> + set have_newabi [expr [istarget mips-*-irix6*] \
> + || [istarget mips64*-*-linux*]]
>
> if { [istarget "mips*-*-*linux*"] } then {
> set tmips "t"
> *************** if { [istarget mips*-*-*] } then {
> *** 601,606 ****
> --- 603,614 ----
> 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 {$have_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"
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel8.d Sat Jan 25 15:32:10 2003
> ***************
> *** 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 <foo>:
> + 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
> + \.\.\.
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel8.s Sat Jan 25 17:01:55 2003
> ***************
> *** 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
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel9.d Sat Jan 25 15:31:55 2003
> ***************
> *** 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 <foo>:
> + 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
> + \.\.\.
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel9.s Sat Jan 25 14:42:36 2003
> ***************
> *** 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
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel10.d Sat Jan 25 20:29:39 2003
> ***************
> *** 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
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel10.s Sat Jan 25 17:13:28 2003
> ***************
> *** 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
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel11.d Sat Jan 25 21:54:02 2003
> ***************
> *** 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
> *** /dev/null Thu Apr 11 15:25:15 2002
> --- testsuite/gas/mips/elf-rel11.s Sat Jan 25 21:07:29 2003
> ***************
> *** 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
--
Strapping on the jetpack...