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