Adding a MIPS -msym32 option (was Re: Address sizes on 64-bit MIPS targets)
Thiemo Seufer
ica2_ts@csv.ica.uni-stuttgart.de
Thu Mar 3 22:10:00 GMT 2005
Richard Sandiford wrote:
[snip]
> The patch adds two new .set directives:
>
> .set sym32
> .set nosym32
>
> for changing the assumed sizes of symbolic constants. It also adds
> two new command-line options, -msym32 and -mno-sym32, for changing
> the start-of-file setting. See the attached docs for more details.
Not that I were opposed to it, but when would those directives ever
be used? A kernel compiled with sym32 never links in nosym32 parts.
[snip]
> * config/tc-mips.c (mips_set_options): Add sym32 field.
> (mips_opts): Initialize it.
> (HAVE_32BIT_ADDRESSES): Set to true if pointers are 32 bits wide.
> (HAVE_64BIT_ADDRESSES): Redefine as !HAVE_32BIT_ADDRESSES.
> (HAVE_32BIT_SYMBOLS, HAVE_64BIT_SYMBOLS): New macros.
> (load_address): Use HAVE_64BIT_SYMBOLS instead of HAVE_64BIT_ADDRESSES
> when deciding whether to use a symbolic %highest/%higher expansion.
> (macro): Likewise. Remove o64/n32 linux hack. Always use
> ADDRESS_ADD*_INSN for address addition in the expansion of "dla"
> and "la". Handle constants separately from symbolic expressions in
> the "ld_st:" case, using 64-bit arithmetic if HAVE_64BIT_ADDRESSES
> and using load_register to load the high part of the address.
> (OPTION_MSYM32, OPTION_NO_MSYM32): New macros.
> (OPTION_ELF_BASE): Bump by 2.
> (md_longopts): Add entries for -msym32 and -mno-sym32.
> (md_parse_option): Handle them.
> (usage): Document them.
> (s_mipsset): Handle ".set sym32" and ".set nosym32".
> (s_cpload, s_cpsetup): Use HAVE_64BIT_SYMBOLS instead of
> HAVE_64BIT_ADDRESSES to detect 64-bit values of "_gp".
> * doc/c-mips.texi: Document ".set sym32", ".set nosym32",
> -msym32 and -mno-sym32.
>
> gas/testsuite/
> * gas/mips/ldstla-{n32.s, n32.d, n32-shared.d}: Delete.
> * gas/mips/ldstla-{n64.d, n64-shared.d}: Adjust expected output
> for loads and stores from constant addresses.
> * gas/mips/ldstla-{sym32.s, eabi64.d, n64-sym32.d}: New tests.
> * gas/mips/mips.exp: Run them.
Ok, with one minor addition:
[snip]
> @@ -5907,8 +5883,21 @@ macro (struct mips_cl_insn *ip)
>
> /* A constant expression in PIC code can be handled just as it
> is in non PIC code. */
> - if (mips_pic == NO_PIC
> - || offset_expr.X_op == O_constant)
> + if (offset_expr.X_op == O_constant)
> + {
> + if (!HAVE_64BIT_ADDRESSES
> + && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
> + as_bad (_("constant too large"));
> +
> + expr1.X_add_number = ((offset_expr.X_add_number + 0x8000)
> + & ~(bfd_vma) 0xffff);
> + load_register (tempreg, &expr1, HAVE_64BIT_ADDRESSES);
> + if (breg != 0)
> + macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
> + tempreg, tempreg, breg);
> + macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, tempreg);
> + }
> + else if (mips_pic == NO_PIC)
> {
> /* If this is a reference to a GP relative symbol, and there
> is no base register, we want
Splitting out the constant case...
> @@ -5964,39 +5953,8 @@ macro (struct mips_cl_insn *ip)
> <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
>
> For GP relative symbols in 64bit address space we can use
> - the same sequence as in 32bit address space.
> -
> - If we have 64-bit addresses, as an optimization, for
> - addresses which are 32-bit constants (e.g. kseg0/kseg1
> - addresses) we fall back to the 32-bit address generation
> - mechanism since it is more efficient. Note that due to
> - the signed offset used by memory operations, the 32-bit
> - range is shifted down by 32768 here. This code should
> - probably attempt to generate 64-bit constants more
> - efficiently in general.
> -
> - As an extension for architectures with 64-bit registers,
> - we don't truncate 64-bit addresses given as literal
> - constants down to 32 bits, to support existing practice
> - in the mips64 Linux (the kernel), that compiles source
> - files with -mabi=64, assembling them as o32 or n32 (with
> - -Wa,-32 or -Wa,-n32). This is not beautiful, but since
> - the whole kernel is loaded into a memory region that is
> - addressable with sign-extended 32-bit addresses, it is
> - wasteful to compute the upper 32 bits of every
> - non-literal address, that takes more space and time.
> - Some day this should probably be implemented as an
> - assembler option, such that the kernel doesn't have to
> - use such ugly hacks, even though it will still have to
> - end up converting the binary to ELF32 for a number of
> - platforms whose boot loaders don't support ELF64
> - binaries. */
> - if ((HAVE_64BIT_ADDRESSES
> - && ! (offset_expr.X_op == O_constant
> - && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
> - || (HAVE_64BIT_GPRS
> - && offset_expr.X_op == O_constant
> - && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
> + the same sequence as in 32bit address space. */
> + if (HAVE_64BIT_SYMBOLS)
> {
> if (offset_expr.X_op == O_symbol
... makes this O_symbol check obsolete as well.
Thiemo
More information about the Binutils
mailing list