This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add support for MIPS16 PIC


This patch extends the o32 PIC support to MIPS16.  It's work I did under
contract to Specifix, so I'd like to thank them for funding it.

The patch supports both soft-float and hard-float, but it doesn't yet
support -mxgot or TLS.  The work is in four main parts:

(1) Extending binutils' R_MIPS_GOT16 and R_MIPS_CALL16 support to cover
    R_MIPS16_GOT16 and R_MIPS16_CALL16.  The relocation numbers were
    reserved by:

    2005-02-15  Nigel Stephens  <nigel@mips.com>
		Maciej W. Rozycki  <macro@mips.com>

	    * mips.h (R_MIPS16_GOT16): New reloc code.
	    (R_MIPS16_CALL16): Likewise.
	    (R_MIPS16_HI16): Likewise.
	    (R_MIPS16_LO16): Likewise.
	    (R_MIPS16_min): New fake reloc code.
	    (R_MIPS16_max): Likewise.

    but are not currently used.

    I've done this by introducing various helper functions:

    got16_reloc_p
    call16_reloc_p
    hi16_reloc_p
    lo16_reloc_p

    each of which handles R_MIPS_FOO and R_MIPS16_FOO.  There are now
    quite a few MIPS16 relocations, so I also replaced two lists of
    equality checks with calls to a mips16_reloc_p function.

    R_MIPS16_GOT16s against local symbols must have a partnering
    R_MIPS16_LO16 relocation, just as R_MIP_GOT16s against local
    symbols have partnering R_MIPS_LO16 relocations.  This has
    an impact on both bfd and gas.

(2) Adding a MIPS16 GP-setup sequence.

    Well, that's not work at all, because we already have one:

	        0: li      $v0,%hi(_gp_disp)
	        4: addiupc $v1,%lo(_gp_disp)
	        8: sll     $v0,16
	       12: addu    $v0,$v1

    The code to handle this still works.

(3) Deciding how to handle dynamic symbols.

    MIPS16 function symbols currently have an even address and size,
    using an st_other field of STO_MIPS16 to distinguish them from
    ordinary functions.  The problem with doing the same for dynamic
    symbols is that all dynamic symbol lookups in glibc need the
    ISA-encoded address.  It would be tedious and slow to have:

      if (sym->st_other == STO_MIPS16)
	value++;

    every time we read st_value.  It would also require folk to
    upgrade their libc.

    In contrast, things Just Work if we use odd-valued (i.e. ISA-encoded)
    addresses, subtracting 1 from the st_size to compensate.  That's the
    approach I went for.

    Having two ways of representing the same thing is far from ideal,
    but I think it's the sensible choice given the status quo.  In bfd,
    we can use _bfd_mips_elf_symbol_processing to convert an external
    ISA-encoded representation into an internal STO_MIPS16-based
    representation, so that both external representations are treated
    in the same way internally.

    In contrast, gdb already uses the ISA-encoded form as its canonical
    representation, although this is taken from bfd's internal STO_MIPS16-
    based representation.

(4) Extend the hard-float support to PIC functions.

    This is where things get complicated.  To recap, the hard-float
    support has two sides:

    - Non-MIPS16 calls to MIPS16 functions.

      Each MIPS16 "hard-float" function has a .mips16.fn.blah section
      that copies arguments from FPRs to GPRs, calls the MIPS16
      function, then copies the return value from GPRs to FPRs
      (if appropriate).  The first relocation against the
      .mips16.fn.blah section identifies the target function.

      The linker remembers whether a given function has a hard-float
      stub.  If it does, all non-R_MIPS16_26 relocations are redirected
      to the stub, except for those in the stub itself.

    - MIPS16 calls to non-MIPS16 functions.

      MIPS16 calls to hard-float non-MIPS16 functions should go via a
      stub.  This stub copies the GPRs to FPRs, calls the non-MIPS16
      function, then copies the FPR result to a GPR (if appropriate).

      If the call is a direct JAL, the compiler can construct a function
      that is specialised for the call target.  This function goes in a
      .mips16.call.blah section.

      As above, the linker uses the first relocation to determine
      the target function and remembers which functions have stubs.
      If a MIPS16 JAL calls such a function directly, the linker
      converts the JAL to a JALX and redirects it to the stub.

      If the call is indirect, the compiler uses a special
      libgcc stub.  The linker does nothing special.

    Let's follow bfd parlance and call these stubs the "FN" and "CALL"
    stubs respectively.  There are several points to consider:

    - If a hard-float MIPS16 function is exported as a dynamic symbol,
      that dynamic symbol should follow the normal calling conventions.
      In other words, if a dynamic function has an FN stub, the symbol
      should refer to that stub instead of the target function.

      It is helpful to create a "shadow" symbol to represent the
      original MIPS16 function, so that gdb and the disassembler
      can still identify it as MIPS16 code.

    - For CALL stubs, do we treat %call16 calls as direct or indirect?
      If we treat them as direct, the compiler would need to create a
      .mips16.call.blah stub for each target function, and that stub
      would be significantly bigger than its non-PIC counterpart.
      On the positive side, treating %call16s as direct allows the
      linker to avoid the stub altogether if the target turns out
      to be MIPS16.

      In practice, we are rarely going to want to use %call16s for
      functions that are known at link time to be MIPS16.  Most %call16s
      refer to what will become dynamic symbols, and which we must
      therefore assume follow the non-MIPS16 convention.  This is
      especially true once we have non-PIC executable support;
      most executable calls will be JALs.

      Under those circumstances, it seems more appropriate to treat
      the calls as indirect.

    - Should FN stubs treat MIPS16 %call16 relocations in the same
      way as JALs?  The nice thing about the answer to the previous
      point is that it doesn't matter whether the target of an
      R_MIPS16_CALL16 follows the hard-float or soft-float conventions;
      the call will be via a libgcc stub, so both sets of argument
      registers will be correct.  In other words:

      - An R_MIPS16_CALL16 relocation should not force the use of a stub.
      	It can happily point directly at the MIPS16 function.

      - If the GOT slot ends up pointing at the stub anyway,
        the R_MIPS16_CALL16 relocation can still use it.
      
    - In a PIC world, the natural implementation of an FN stub would
      be to initialise $gp and use a local or global GOT call sequence.
      However, doing this throws up a couple of problems:

      - The first relocation in a PIC stub would be against
      	__gnu_local_gp or _gp_disp, depending on whether this is
	-mno-shared or -mshared code.  We need to be more selective
	when identifying the target function.

        Although we could add some code to make an "intelligent" choice,
	I think the simplest and most robust approach is to trust the
	first R_MIPS_NONE relocation.  We can fall back on the current
	behaviour when there is no R_MIPS_NONE relocation.

      - If the stub uses R_MIPS_CALL16 to call a global target function,
        that particular relocation would still go directly to the MIPS16
	function, whereas R_MIPS_CALL16 relocations from other sections
	would go to the stub.  Having two GOT slots for (conceptually)
        the same symbol throws up some implementation difficulties.
	We would also want to avoid allocating the GOT slot unless we
        know that the stub is needed.

        Stubs are defined in the same object as the target function,
        so it seems simpler to call a local alias instead.

Tested on mips64-linux-gnu and mips64el-linux-gnu.  OK to install?

Richard


bfd/
	* reloc.c (BFD_RELOC_MIPS16_GOT16, BFD_RELOC_MIPS16_CALL16): Declare.
	* libbfd.h, bfd-in2.h: Regenerate.
	* elf32-mips.c (elf_mips16_howto_table_rel): Fill in reserved
	R_MIPS16_GOT16 and R_MIPS16_CALL16 entries.
	(mips16_reloc_map): Add mappings.
	* elf64-mips.c (mips16_elf64_howto_table_rel): Fill in reserved
	R_MIPS16_GOT16 and R_MIPS16_CALL16 entries.
	(mips16_elf64_howto_table_rela): Likewise.
	(mips16_reloc_map): Add mappings.
	* elfn32-mips.c (elf_mips16_howto_table_rel): Fill in reserved
	R_MIPS16_GOT16 and R_MIPS16_CALL16 entries.
	(elf_mips16_howto_table_rela): Likewise.
	(mips16_reloc_map): Add mappings.
	* elfxx-mips.c (mips_elf_create_shadow_symbol): New function.
	(section_allows_mips16_refs_p): Likewise.
	(mips16_stub_symndx): Likewise.
	(mips_elf_check_mips16_stubs): Treat the data argument as a
	bfd_link_info.  Mark every dynamic symbol as needing MIPS16 stubs
	and create a "shadow" symbol for the original MIPS16 definition.
	(mips16_reloc_p, got16_reloc_p, call16_reloc_p, hi16_reloc_p)
	(lo16_reloc_p, mips16_call_reloc_p): New functions.
	(_bfd_mips16_elf_reloc_unshuffle): Use mips16_reloc_p to generalize
	relocation checks.
	(_bfd_mips16_elf_reloc_shuffle): Likewise.
	(_bfd_mips_elf_lo16_reloc): Handle R_MIPS16_GOT16.
	(mips_elf_got16_entry): Add comment.
	(mips_elf_calculate_relocation): Use hi16_reloc_p,
	lo16_reloc_p, mips16_call_reloc_p, call16_reloc_p and got16_reloc_p
	to generalize relocation checks.  Use section_allows_mips16_refs_p
	instead of mips16_stub_section_p.   Handle R_MIPS16_CALL16 and
	R_MIPS16_GOT16, allowing the former to refer directly to a
	MIPS16 function if its stub is not needed.
	(mips16_stub_section_p): Delete.
	(_bfd_mips_elf_symbol_processing): Convert odd-valued function
	symbols into even MIPS16 symbols.
	(mips_elf_add_lo16_rel_addend): Use mips16_reloc_p to generalize
	relocation checks.
	(_bfd_mips_elf_check_relocs): Use mips16_stub_symndx to
	identify the target function.  Avoid out-of-bounds accesses
	when the stub has no relocations; report an error instead.
	Use section_allows_mips16_refs_p instead of mips16_stub_section_p.
	Use mips16_call_reloc_p and got16_reloc_p to generalize relocation
	checks.  Handle R_MIPS16_CALL16 and R_MIPS16_GOT16.  Don't create
	dynamic relocations for absolute references to __gnu_local_gp.
	(_bfd_mips_elf_always_size_sections): Pass a bfd_link_info as
	the argument to mips_elf_check_mips16_stubs.  Generalize comment.
	(_bfd_mips_elf_relocate_section): Use hi16_reloc_p and got16_reloc_p
	to generalize relocation checks.
	(_bfd_mips_elf_finish_dynamic_symbol): If a dynamic MIPS16 function
	symbol has a non-MIPS16 stub, redirect the symbol to the stub.
	Fix an overly long line.  Don't give dynamic symbols type STO_MIPS16.
	(_bfd_mips_vxworks_finish_dynamic_symbol): Use ELF_ST_IS_MIPS16.
	(_bfd_mips_elf_gc_sweep_hook): Handle R_MIPS16_CALL16 and
	R_MIPS16_GOT16.

gas/
	* config/tc-mips.c (mips16_reloc_p, got16_reloc_p, hi16_reloc_p)
	(lo16_reloc_p): New functions.
	(reloc_needs_lo_p): Use hi16_reloc_p and got16_reloc_p to
	generalize relocation checks.
	(matching_lo_reloc): New function.
	(fixup_has_matching_lo_p): Use it.
	(mips16_mark_labels): Don't clobber a symbol's visibility.
	(append_insn): Use hi16_reloc_p and lo16_reloc_p.
	(mips16_ip): Handle BFD_RELOC_MIPS16_GOT16 and BFD_RELOC_MIPS16_CALL16.
	(md_apply_fix): Likewise.
	(mips16_percent_op): Add %got and %call16.
	(mips_frob_file): Use got16_reloc_p to generalize relocation checks.
	Use matching_lo_reloc.
	(mips_force_relocation): Use hi16_reloc_p and lo16_reloc_p to
	generalize relocation checks.
	(mips_fix_adjustable): Use lo16_reloc_p to generalize relocation
	checks.

gas/testsuite/
	* gas/mips/elf-rel8-mips16.d, gas/mips/elf-rel8-mips16.s,
	* gas/mips/elf-rel9-mips16.d, gas/mips/elf-rel9-mips16.s,
	* gas/mips/elf-rel13-mips16.d, gas/mips/elf-rel13-mips16.s: New tests.
	* gas/mips/mips.exp: Run them.

ld/testsuite/
	* ld-mips-elf/mips16-local-stubs-1.d: Remove stub_for_h3,
	which was only referenced by the .pdr section, and was not
	actually needed by code.
	* ld-mips-elf/mips16-intermix.d: Remove unused static function stubs.
	* ld-mips-elf/mips16-pic-1a.s,
	ld-mips-elf/mips16-pic-1b.s,
	ld-mips-elf/mips16-pic-1-dummy.s,
	ld-mips-elf/mips16-pic-1.dd,
	ld-mips-elf/mips16-pic-1.gd,
	ld-mips-elf/mips16-pic-1.inc,
	ld-mips-elf/mips16-pic-1.ld,
	ld-mips-elf/mips16-pic-2a.s,
	ld-mips-elf/mips16-pic-2b.s,
	ld-mips-elf/mips16-pic-2.ad,
	ld-mips-elf/mips16-pic-2.dd,
	ld-mips-elf/mips16-pic-2.gd,
	ld-mips-elf/mips16-pic-2.nd,
	ld-mips-elf/mips16-pic-2.rd: New tests.
	* ld-mips-elf/mips-elf.exp: Run them.

Index: bfd/reloc.c
===================================================================
--- bfd/reloc.c	2008-06-28 17:09:18.000000000 +0100
+++ bfd/reloc.c	2008-06-28 17:14:17.000000000 +0100
@@ -2154,6 +2154,13 @@ SPARC.  (SPARC tools generally refer to 
   Low 16 bits of pc-relative value
 
 ENUM
+  BFD_RELOC_MIPS16_GOT16
+ENUMX
+  BFD_RELOC_MIPS16_CALL16
+ENUMDOC
+  Equivalent of BFD_RELOC_MIPS_*, but with the MIPS16 layout of
+     16-bit immediate fields
+ENUM
   BFD_RELOC_MIPS16_HI16
 ENUMDOC
   MIPS16 high 16 bits of 32-bit value.
Index: bfd/libbfd.h
===================================================================
--- bfd/libbfd.h	2008-06-28 17:09:18.000000000 +0100
+++ bfd/libbfd.h	2008-06-28 17:14:17.000000000 +0100
@@ -964,6 +964,8 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_HI16_PCREL",
   "BFD_RELOC_HI16_S_PCREL",
   "BFD_RELOC_LO16_PCREL",
+  "BFD_RELOC_MIPS16_GOT16",
+  "BFD_RELOC_MIPS16_CALL16",
   "BFD_RELOC_MIPS16_HI16",
   "BFD_RELOC_MIPS16_HI16_S",
   "BFD_RELOC_MIPS16_LO16",
Index: bfd/bfd-in2.h
===================================================================
--- bfd/bfd-in2.h	2008-06-28 17:09:18.000000000 +0100
+++ bfd/bfd-in2.h	2008-06-28 17:14:18.000000000 +0100
@@ -2609,6 +2609,11 @@ away some literal section references.  T
 /* Low 16 bits of pc-relative value  */
   BFD_RELOC_LO16_PCREL,
 
+/* Equivalent of BFD_RELOC_MIPS_*, but with the MIPS16 layout of
+16-bit immediate fields  */
+  BFD_RELOC_MIPS16_GOT16,
+  BFD_RELOC_MIPS16_CALL16,
+
 /* MIPS16 high 16 bits of 32-bit value.  */
   BFD_RELOC_MIPS16_HI16,
 
Index: bfd/elf32-mips.c
===================================================================
--- bfd/elf32-mips.c	2008-06-28 17:09:18.000000000 +0100
+++ bfd/elf32-mips.c	2008-06-28 17:14:17.000000000 +0100
@@ -771,11 +771,35 @@ static reloc_howto_type elf_mips16_howto
 	 0x0000ffff,	        /* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 reference to global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_GOT16),
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_got16_reloc, /* special_function */
+	 "R_MIPS16_GOT16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 16 bit call through global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_CALL16),
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS16_CALL16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
   /* MIPS16 high 16 bits of symbol value.  */
   HOWTO (R_MIPS16_HI16,		/* type */
@@ -1224,6 +1248,8 @@ static const struct elf_reloc_map mips16
 {
   { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_GOT16, R_MIPS16_GOT16 - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_CALL16, R_MIPS16_CALL16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
 };
Index: bfd/elf64-mips.c
===================================================================
--- bfd/elf64-mips.c	2008-06-28 17:09:18.000000000 +0100
+++ bfd/elf64-mips.c	2008-06-28 17:14:17.000000000 +0100
@@ -1503,11 +1503,35 @@ static reloc_howto_type mips16_elf64_how
 	 0x0000ffff,	        /* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 reference to global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_GOT16),
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_got16_reloc, /* special_function */
+	 "R_MIPS16_GOT16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 16 bit call through global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_CALL16),
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS16_CALL16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
   /* MIPS16 high 16 bits of symbol value.  */
   HOWTO (R_MIPS16_HI16,		/* type */
@@ -1575,11 +1599,35 @@ static reloc_howto_type mips16_elf64_how
 	 0x0000ffff,	        /* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 reference to global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_GOT16),
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_got16_reloc, /* special_function */
+	 "R_MIPS16_GOT16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 16 bit call through global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_CALL16),
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS16_CALL16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
   /* MIPS16 high 16 bits of symbol value.  */
   HOWTO (R_MIPS16_HI16,		/* type */
@@ -2197,6 +2245,8 @@ static const struct elf_reloc_map mips16
 {
   { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_GOT16, R_MIPS16_GOT16 - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_CALL16, R_MIPS16_CALL16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
 };
Index: bfd/elfn32-mips.c
===================================================================
--- bfd/elfn32-mips.c	2008-06-28 17:09:18.000000000 +0100
+++ bfd/elfn32-mips.c	2008-06-28 17:14:17.000000000 +0100
@@ -1496,11 +1496,35 @@ static reloc_howto_type elf_mips16_howto
 	 0x0000ffff,	        /* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 reference to global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_GOT16),
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_got16_reloc, /* special_function */
+	 "R_MIPS16_GOT16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 16 bit call through global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_CALL16),
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS16_CALL16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
   /* MIPS16 high 16 bits of symbol value.  */
   HOWTO (R_MIPS16_HI16,		/* type */
@@ -1568,11 +1592,35 @@ static reloc_howto_type elf_mips16_howto
 	 0x0000ffff,	        /* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 reference to global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_GOT16),
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_got16_reloc, /* special_function */
+	 "R_MIPS16_GOT16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
-  /* A placeholder for MIPS16 16 bit call through global offset table.  */
-  EMPTY_HOWTO (R_MIPS16_CALL16),
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS16_CALL16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,	        /* dst_mask */
+	 FALSE),		/* pcrel_offset */
 
   /* MIPS16 high 16 bits of symbol value.  */
   HOWTO (R_MIPS16_HI16,		/* type */
@@ -2041,6 +2089,8 @@ static const struct elf_reloc_map mips16
 {
   { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_GOT16, R_MIPS16_GOT16 - R_MIPS16_min },
+  { BFD_RELOC_MIPS16_CALL16, R_MIPS16_CALL16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
   { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
 };
Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c	2008-06-28 17:14:15.000000000 +0100
+++ bfd/elfxx-mips.c	2008-06-28 17:14:17.000000000 +0100
@@ -525,8 +525,6 @@ #define rpdNil ((pRPDR) 0)
   (struct mips_elf_link_hash_entry *, void *);
 static bfd_vma mips_elf_high
   (bfd_vma);
-static bfd_boolean mips16_stub_section_p
-  (bfd *, asection *);
 static bfd_boolean mips_elf_create_dynamic_relocation
   (bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
    struct mips_elf_link_hash_entry *, asection *, bfd_vma,
@@ -1148,17 +1146,104 @@ mips_elf_create_procedure_table (void *h
     free (sv);
   return FALSE;
 }
+
+/* We're about to redefine H.  Create a symbol to represent H's
+   current value and size, to help make the disassembly easier
+   to read.  */
+
+static bfd_boolean
+mips_elf_create_shadow_symbol (struct bfd_link_info *info,
+			       struct mips_elf_link_hash_entry *h,
+			       const char *prefix)
+{
+  struct bfd_link_hash_entry *bh;
+  struct elf_link_hash_entry *elfh;
+  const char *name;
+  asection *s;
+  bfd_vma value;
+
+  /* Read the symbol's value.  */
+  BFD_ASSERT (h->root.root.type == bfd_link_hash_defined
+	      || h->root.root.type == bfd_link_hash_defweak);
+  s = h->root.root.u.def.section;
+  value = h->root.root.u.def.value;
+
+  /* Create a new symbol.  */
+  name = ACONCAT ((prefix, h->root.root.root.string, NULL));
+  bh = NULL;
+  if (!_bfd_generic_link_add_one_symbol (info, s->owner, name,
+					 BSF_LOCAL, s, value, NULL,
+					 TRUE, FALSE, &bh))
+    return FALSE;
+
+  /* Make it local and copy the other attributes from H.  */
+  elfh = (struct elf_link_hash_entry *) bh;
+  elfh->type = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (h->root.type));
+  elfh->other = h->root.other;
+  elfh->size = h->root.size;
+  elfh->forced_local = 1;
+  return TRUE;
+}
+
+/* Return TRUE if relocations in SECTION can refer directly to a MIPS16
+   function rather than to a hard-float stub.  */
+
+static bfd_boolean
+section_allows_mips16_refs_p (asection *section)
+{
+  const char *name;
+
+  name = bfd_get_section_name (section->owner, section);
+  return (FN_STUB_P (name)
+	  || CALL_STUB_P (name)
+	  || CALL_FP_STUB_P (name)
+	  || strcmp (name, ".pdr") == 0);
+}
+
+/* [RELOCS, RELEND) are the relocations against SEC, which is a MIPS16
+   stub section of some kind.  Return the R_SYMNDX of the target
+   function, or 0 if we can't decide which function that is.  */
+
+static unsigned long
+mips16_stub_symndx (asection *sec, const Elf_Internal_Rela *relocs,
+		    const Elf_Internal_Rela *relend)
+{
+  const Elf_Internal_Rela *rel;
+
+  /* Trust the first R_MIPS_NONE relocation, if any.  */
+  for (rel = relocs; rel < relend; rel++)
+    if (ELF_R_TYPE (sec->owner, rel->r_info) == R_MIPS_NONE)
+      return ELF_R_SYM (sec->owner, rel->r_info);
+
+  /* Otherwise trust the first relocation, whatever its kind.  This is
+     the traditional behavior.  */
+  if (relocs < relend)
+    return ELF_R_SYM (sec->owner, relocs->r_info);
+
+  return 0;
+}
 
 /* Check the mips16 stubs for a particular symbol, and see if we can
    discard them.  */
 
 static bfd_boolean
-mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
-			     void *data ATTRIBUTE_UNUSED)
+mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h, void *data)
 {
+  struct bfd_link_info *info;
+
+  info = (struct bfd_link_info *) data;
   if (h->root.root.type == bfd_link_hash_warning)
     h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
 
+  /* Dynamic symbols must use the standard call interface, in case other
+     objects try to call them.  */
+  if (h->fn_stub != NULL
+      && h->root.dynindx != -1)
+    {
+      mips_elf_create_shadow_symbol (info, h, ".mips16.");
+      h->need_fn_stub = TRUE;
+    }
+
   if (h->fn_stub != NULL
       && ! h->need_fn_stub)
     {
@@ -1257,8 +1342,18 @@ mips_elf_check_mips16_stubs (struct mips
    let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
    ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)
 
-   R_MIPS16_GPREL is used for GP-relative addressing in mips16
-   mode.  A typical instruction will have a format like this:
+   The table below lists the other MIPS16 instruction relocations.
+   Each one is calculated in the same way as the non-MIPS16 relocation
+   given on the right, but using the extended MIPS16 layout of 16-bit
+   immediate fields:
+
+	R_MIPS16_GPREL		R_MIPS_GPREL16
+	R_MIPS16_GOT16		R_MIPS_GOT16
+	R_MIPS16_CALL16		R_MIPS_CALL16
+	R_MIPS16_HI16		R_MIPS_HI16
+	R_MIPS16_LO16		R_MIPS_LO16
+
+   A typical instruction will have a format like this:
 
    +--------------+--------------------------------+
    |    EXTEND    |     Imm 10:5    |   Imm 15:11  |
@@ -1269,28 +1364,65 @@ mips_elf_check_mips16_stubs (struct mips
    EXTEND is the five bit value 11110.  Major is the instruction
    opcode.
 
-   This is handled exactly like R_MIPS_GPREL16, except that the
-   addend is retrieved and stored as shown in this diagram; that
-   is, the Imm fields above replace the V-rel16 field.
-
-   All we need to do here is shuffle the bits appropriately.  As
-   above, the two 16-bit halves must be swapped on a
-   little-endian system.
-
-   R_MIPS16_HI16 and R_MIPS16_LO16 are used in mips16 mode to
-   access data when neither GP-relative nor PC-relative addressing
-   can be used.  They are handled like R_MIPS_HI16 and R_MIPS_LO16,
-   except that the addend is retrieved and stored as shown above
-   for R_MIPS16_GPREL.
-  */
+   All we need to do here is shuffle the bits appropriately.
+   As above, the two 16-bit halves must be swapped on a
+   little-endian system.  */
+
+static inline bfd_boolean
+mips16_reloc_p (int r_type)
+{
+  switch (r_type)
+    {
+    case R_MIPS16_26:
+    case R_MIPS16_GPREL:
+    case R_MIPS16_GOT16:
+    case R_MIPS16_CALL16:
+    case R_MIPS16_HI16:
+    case R_MIPS16_LO16:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+static inline bfd_boolean
+got16_reloc_p (int r_type)
+{
+  return r_type == R_MIPS_GOT16 || r_type == R_MIPS16_GOT16;
+}
+
+static inline bfd_boolean
+call16_reloc_p (int r_type)
+{
+  return r_type == R_MIPS_CALL16 || r_type == R_MIPS16_CALL16;
+}
+
+static inline bfd_boolean
+hi16_reloc_p (int r_type)
+{
+  return r_type == R_MIPS_HI16 || r_type == R_MIPS16_HI16;
+}
+
+static inline bfd_boolean
+lo16_reloc_p (int r_type)
+{
+  return r_type == R_MIPS_LO16 || r_type == R_MIPS16_LO16;
+}
+
+static inline bfd_boolean
+mips16_call_reloc_p (int r_type)
+{
+  return r_type == R_MIPS16_26 || r_type == R_MIPS16_CALL16;
+}
+
 void
 _bfd_mips16_elf_reloc_unshuffle (bfd *abfd, int r_type,
 				 bfd_boolean jal_shuffle, bfd_byte *data)
 {
   bfd_vma extend, insn, val;
 
-  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
-      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+  if (!mips16_reloc_p (r_type))
     return;
 
   /* Pick up the mips16 extend instruction and the real instruction.  */
@@ -1316,8 +1448,7 @@ _bfd_mips16_elf_reloc_shuffle (bfd *abfd
 {
   bfd_vma extend, insn, val;
 
-  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
-      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+  if (!mips16_reloc_p (r_type))
     return;
 
   val = bfd_get_32 (abfd, data);
@@ -1446,7 +1577,7 @@ _bfd_mips_elf_hi16_reloc (bfd *abfd ATTR
   return bfd_reloc_ok;
 }
 
-/* A howto special_function for REL R_MIPS_GOT16 relocations.  This is just
+/* A howto special_function for REL R_MIPS*_GOT16 relocations.  This is just
    like any other 16-bit relocation when applied to global symbols, but is
    treated in the same as R_MIPS_HI16 when applied to local symbols.  */
 
@@ -1495,13 +1626,15 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, are
 
       hi = mips_hi16_list;
 
-      /* R_MIPS_GOT16 relocations are something of a special case.  We
-	 want to install the addend in the same way as for a R_MIPS_HI16
+      /* R_MIPS*_GOT16 relocations are something of a special case.  We
+	 want to install the addend in the same way as for a R_MIPS*_HI16
 	 relocation (with a rightshift of 16).  However, since GOT16
 	 relocations can also be used with global symbols, their howto
 	 has a rightshift of 0.  */
       if (hi->rel.howto->type == R_MIPS_GOT16)
 	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);
+      else if (hi->rel.howto->type == R_MIPS16_GOT16)
+	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS16_HI16, FALSE);
 
       /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
 	 carry or borrow will induce a change of +1 or -1 in the high part.  */
@@ -2620,7 +2753,7 @@ mips_elf_got_page (bfd *abfd, bfd *ibfd,
   return index;
 }
 
-/* Find a local GOT entry for an R_MIPS_GOT16 relocation against VALUE.
+/* Find a local GOT entry for an R_MIPS*_GOT16 relocation against VALUE.
    EXTERNAL is true if the relocation was against a global symbol
    that has been forced local.  */
 
@@ -2641,6 +2774,9 @@ mips_elf_got16_entry (bfd *abfd, bfd *ib
 
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
+  /* It doesn't matter whether the original relocation was R_MIPS_GOT16,
+     R_MIPS16_GOT16, R_MIPS_CALL16, etc.  The format of the entry is the
+     same in all cases.  */
   entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
 					   value, 0, NULL, R_MIPS_GOT16);
   if (entry)
@@ -4216,8 +4352,7 @@ mips_elf_calculate_relocation (bfd *abfd
 	{
 	  /* Relocations against _gp_disp are permitted only with
 	     R_MIPS_HI16 and R_MIPS_LO16 relocations.  */
-	  if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16
-	      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+	  if (!hi16_reloc_p (r_type) && !lo16_reloc_p (r_type))
 	    return bfd_reloc_notsupported;
 
 	  gp_disp_p = TRUE;
@@ -4291,15 +4426,24 @@ mips_elf_calculate_relocation (bfd *abfd
       target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
     }
 
-  /* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
-     need to redirect the call to the stub, unless we're already *in*
-     a stub.  */
-  if (r_type != R_MIPS16_26 && !info->relocatable
-      && ((h != NULL && h->fn_stub != NULL)
+  /* If this is a reference to a 16-bit function with a stub, we need
+     to redirect the relocation to the stub unless:
+
+     (a) the relocation is for a MIPS16 JAL;
+
+     (b) the relocation is for a MIPS16 PIC call, and there are no
+	 non-MIPS16 uses of the GOT slot; or
+
+     (c) the section allows direct references to MIPS16 functions.  */
+  if (r_type != R_MIPS16_26
+      && !info->relocatable
+      && ((h != NULL
+	   && h->fn_stub != NULL
+	   && (r_type != R_MIPS16_CALL16 || h->need_fn_stub))
 	  || (local_p
 	      && elf_tdata (input_bfd)->local_stubs != NULL
 	      && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
-      && !mips16_stub_section_p (input_bfd, input_section))
+      && !section_allows_mips16_refs_p (input_section))
     {
       /* This is a 32- or 64-bit call to a 16-bit function.  We should
 	 have already noticed that we were going to need the
@@ -4317,7 +4461,9 @@ mips_elf_calculate_relocation (bfd *abfd
       target_is_16_bit_code_p = FALSE;
     }
   /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
-     need to redirect the call to the stub.  */
+     need to redirect the call to the stub.  Note that we specifically
+     exclude R_MIPS16_CALL16 from this behavior; indirect calls should
+     use an indirect stub instead.  */
   else if (r_type == R_MIPS16_26 && !info->relocatable
 	   && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL))
 	       || (local_p
@@ -4389,6 +4535,8 @@ mips_elf_calculate_relocation (bfd *abfd
 	break;
       /* Fall through.  */
 
+    case R_MIPS16_CALL16:
+    case R_MIPS16_GOT16:
     case R_MIPS_CALL16:
     case R_MIPS_GOT16:
     case R_MIPS_GOT_DISP:
@@ -4414,7 +4562,7 @@ mips_elf_calculate_relocation (bfd *abfd
 	  if (htab->is_vxworks
 	      && (r_type == R_MIPS_CALL_HI16
 		  || r_type == R_MIPS_CALL_LO16
-		  || r_type == R_MIPS_CALL16))
+		  || call16_reloc_p (r_type)))
 	    {
 	      BFD_ASSERT (addend == 0);
 	      BFD_ASSERT (h->root.needs_plt);
@@ -4444,7 +4592,7 @@ mips_elf_calculate_relocation (bfd *abfd
 	    }
 	}
       else if (!htab->is_vxworks
-	       && (r_type == R_MIPS_CALL16 || (r_type == R_MIPS_GOT16)))
+	       && (call16_reloc_p (r_type) || got16_reloc_p (r_type)))
 	/* The calculation below does not involve "g".  */
 	break;
       else
@@ -4671,10 +4819,12 @@ mips_elf_calculate_relocation (bfd *abfd
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
+    case R_MIPS16_GOT16:
+    case R_MIPS16_CALL16:
     case R_MIPS_GOT16:
     case R_MIPS_CALL16:
       /* VxWorks does not have separate local and global semantics for
-	 R_MIPS_GOT16; every relocation evaluates to "G".  */
+	 R_MIPS*_GOT16; every relocation evaluates to "G".  */
       if (!htab->is_vxworks && local_p)
 	{
 	  bfd_boolean forced;
@@ -4918,16 +5068,6 @@ mips_elf_perform_relocation (struct bfd_
 
   return TRUE;
 }
-
-/* Returns TRUE if SECTION is a MIPS16 stub section.  */
-
-static bfd_boolean
-mips16_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
-{
-  const char *name = bfd_get_section_name (abfd, section);
-
-  return FN_STUB_P (name) || CALL_STUB_P (name) || CALL_FP_STUB_P (name);
-}
 
 /* Add room for N relocations to the .rel(a).dyn section in ABFD.  */
 
@@ -5309,14 +5449,14 @@ elf_mips_abi_name (bfd *abfd)
 static asymbol mips_elf_acom_symbol;
 static asymbol *mips_elf_acom_symbol_ptr;
 
-/* Handle the special MIPS section numbers that a symbol may use.
-   This is used for both the 32-bit and the 64-bit ABI.  */
+/* This is used for both the 32-bit and the 64-bit ABI.  */
 
 void
 _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
 {
   elf_symbol_type *elfsym;
 
+  /* Handle the special MIPS section numbers that a symbol may use.  */
   elfsym = (elf_symbol_type *) asym;
   switch (elfsym->internal_elf_sym.st_shndx)
     {
@@ -5404,6 +5544,20 @@ _bfd_mips_elf_symbol_processing (bfd *ab
       }
       break;
     }
+
+  /* If this is an odd-valued function symbol, assume it's a MIPS16 one.  */
+  if (ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_FUNC
+      && (asym->value & 1) != 0)
+    {
+      asym->value--;
+      elfsym->internal_elf_sym.st_other
+	= ELF_ST_SET_MIPS16 (elfsym->internal_elf_sym.st_other);
+
+      /* If the function size was odd, assume that the real end of the
+	 function was the original value + the original size.  */
+      if (elfsym->internal_elf_sym.st_size & 1)
+	elfsym->internal_elf_sym.st_size++;
+    }
 }
 
 /* Implement elf_backend_eh_frame_address_size.  This differs from
@@ -6396,7 +6550,7 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
   bfd_vma l;
 
   r_type = ELF_R_TYPE (abfd, rel->r_info);
-  if (r_type == R_MIPS16_HI16)
+  if (mips16_reloc_p (r_type))
     lo16_type = R_MIPS16_LO16;
   else
     lo16_type = R_MIPS_LO16;
@@ -6476,6 +6630,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
   bfd_byte *contents;
   bfd_vma addend;
   reloc_howto_type *howto;
+  bfd_boolean mips16_fn_stub_p;
 
   if (info->relocatable)
     return TRUE;
@@ -6486,17 +6641,30 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
   sym_hashes = elf_sym_hashes (abfd);
   extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
 
+  bed = get_elf_backend_data (abfd);
+  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+
   /* Check for the mips16 stub sections.  */
 
   name = bfd_get_section_name (abfd, sec);
-  if (FN_STUB_P (name))
+  mips16_fn_stub_p = FN_STUB_P (name);
+  if (mips16_fn_stub_p)
     {
       unsigned long r_symndx;
 
       /* Look at the relocation information to figure out which symbol
          this is for.  */
 
-      r_symndx = ELF_R_SYM (abfd, relocs->r_info);
+      r_symndx = mips16_stub_symndx (sec, relocs, rel_end);
+      if (r_symndx == 0)
+	{
+	  (*_bfd_error_handler)
+	    (_("%B: Warning: cannot determine the target function for"
+	       " stub section `%s'"),
+	     abfd, name);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
 
       if (r_symndx < extsymoff
 	  || sym_hashes[r_symndx - extsymoff] == NULL)
@@ -6514,7 +6682,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	      /* We can ignore stub sections when looking for relocs.  */
 	      if ((o->flags & SEC_RELOC) == 0
 		  || o->reloc_count == 0
-		  || mips16_stub_section_p (abfd, o))
+		  || section_allows_mips16_refs_p (o))
 		continue;
 
 	      sec_relocs
@@ -6526,7 +6694,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	      rend = sec_relocs + o->reloc_count;
 	      for (r = sec_relocs; r < rend; r++)
 		if (ELF_R_SYM (abfd, r->r_info) == r_symndx
-		    && ELF_R_TYPE (abfd, r->r_info) != R_MIPS16_26)
+		    && !mips16_call_reloc_p (ELF_R_TYPE (abfd, r->r_info)))
 		  break;
 
 	      if (elf_section_data (o)->relocs != sec_relocs)
@@ -6612,7 +6780,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
       /* Look at the relocation information to figure out which symbol
          this is for.  */
 
-      r_symndx = ELF_R_SYM (abfd, relocs->r_info);
+      r_symndx = mips16_stub_symndx (sec, relocs, rel_end);
+      if (r_symndx == 0)
+	{
+	  (*_bfd_error_handler)
+	    (_("%B: Warning: cannot determine the target function for"
+	       " stub section `%s'"),
+	     abfd, name);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
 
       if (r_symndx < extsymoff
 	  || sym_hashes[r_symndx - extsymoff] == NULL)
@@ -6630,7 +6807,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	      /* We can ignore stub sections when looking for relocs.  */
 	      if ((o->flags & SEC_RELOC) == 0
 		  || o->reloc_count == 0
-		  || mips16_stub_section_p (abfd, o))
+		  || section_allows_mips16_refs_p (o))
 		continue;
 
 	      sec_relocs
@@ -6777,6 +6954,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	{
 	  switch (r_type)
 	    {
+	    case R_MIPS16_GOT16:
+	    case R_MIPS16_CALL16:
 	    case R_MIPS_GOT16:
 	    case R_MIPS_CALL16:
 	    case R_MIPS_CALL_HI16:
@@ -6846,13 +7025,13 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
       else if (r_type == R_MIPS_CALL_LO16
 	       || r_type == R_MIPS_GOT_LO16
 	       || r_type == R_MIPS_GOT_DISP
-	       || (r_type == R_MIPS_GOT16 && htab->is_vxworks))
+	       || (got16_reloc_p (r_type) && htab->is_vxworks))
 	{
 	  /* We may need a local GOT entry for this relocation.  We
 	     don't count R_MIPS_GOT_PAGE because we can estimate the
 	     maximum number of pages needed by looking at the size of
-	     the segment.  Similar comments apply to R_MIPS_GOT16 and
-	     R_MIPS_CALL16, except on VxWorks, where GOT relocations
+	     the segment.  Similar comments apply to R_MIPS*_GOT16 and
+	     R_MIPS*_CALL16, except on VxWorks, where GOT relocations
 	     always evaluate to "G".  We don't count R_MIPS_GOT_HI16, or
 	     R_MIPS_CALL_HI16 because these are always followed by an
 	     R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.  */
@@ -6864,6 +7043,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
       switch (r_type)
 	{
 	case R_MIPS_CALL16:
+	case R_MIPS16_CALL16:
 	  if (h == NULL)
 	    {
 	      (*_bfd_error_handler)
@@ -6914,6 +7094,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	    }
 	  /* Fall through.  */
 
+	case R_MIPS16_GOT16:
 	case R_MIPS_GOT16:
 	case R_MIPS_GOT_HI16:
 	case R_MIPS_GOT_LO16:
@@ -6998,6 +7179,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	     are handled using copy relocs or PLT stubs, so there's
 	     no need to add a .rela.dyn entry for this relocation.  */
 	  if ((info->shared || (h != NULL && !htab->is_vxworks))
+	      && !(h && strcmp (h->root.root.string, "__gnu_local_gp") == 0)
 	      && (sec->flags & SEC_ALLOC) != 0)
 	    {
 	      if (sreloc == NULL)
@@ -7102,6 +7284,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	  default:
 	    ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
 	    break;
+	  case R_MIPS16_CALL16:
 	  case R_MIPS_CALL16:
 	  case R_MIPS_CALL_HI16:
 	  case R_MIPS_CALL_LO16:
@@ -7109,12 +7292,13 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	    break;
 	  }
 
-      /* If this reloc is not a 16 bit call, and it has a global
-         symbol, then we will need the fn_stub if there is one.
-         References from a stub section do not count.  */
+      /* See if this reloc would need to refer to a MIPS16 hard-float stub,
+	 if there is one.  We only need to handle global symbols here;
+	 we decide whether to keep or delete stubs for local symbols
+	 when processing the stub's relocations.  */
       if (h != NULL
-	  && r_type != R_MIPS16_26
-	  && !mips16_stub_section_p (abfd, sec))
+	  && !mips16_call_reloc_p (r_type)
+	  && !section_allows_mips16_refs_p (sec))
 	{
 	  struct mips_elf_link_hash_entry *mh;
 
@@ -7579,7 +7763,7 @@ _bfd_mips_elf_always_size_sections (bfd 
   if (! (info->relocatable
 	 || ! mips_elf_hash_table (info)->mips16_stubs_seen))
     mips_elf_link_hash_traverse (mips_elf_hash_table (info),
-				 mips_elf_check_mips16_stubs, NULL);
+				 mips_elf_check_mips16_stubs, info);
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
@@ -7641,7 +7825,7 @@ _bfd_mips_elf_always_size_sections (bfd 
   loadable_size += htab->function_stub_size * (i + 1);
 
   if (htab->is_vxworks)
-    /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
+    /* There's no need to allocate page entries for VxWorks; R_MIPS*_GOT16
        relocations against local symbols evaluate to "G", and the EABI does
        not include R_MIPS_GOT_PAGE.  */
     page_gotno = 0;
@@ -8186,9 +8370,8 @@ _bfd_mips_elf_relocate_section (bfd *out
 	      rela_relocation_p = FALSE;
 	      addend = mips_elf_read_rel_addend (input_bfd, rel,
 						 howto, contents);
-	      if (r_type == R_MIPS_HI16
-		  || r_type == R_MIPS16_HI16
-		  || (r_type == R_MIPS_GOT16
+	      if (hi16_reloc_p (r_type)
+		  || (got16_reloc_p (r_type)
 		      && mips_elf_local_relocation_p (input_bfd, rel,
 						      local_sections, FALSE)))
 		{
@@ -8227,8 +8410,7 @@ _bfd_mips_elf_relocate_section (bfd *out
 	  if (!rela_relocation_p && rel->r_addend)
 	    {
 	      addend += rel->r_addend;
-	      if (r_type == R_MIPS_HI16
-		  || r_type == R_MIPS_GOT16)
+	      if (hi16_reloc_p (r_type) || got16_reloc_p (r_type))
 		addend = mips_elf_high (addend);
 	      else if (r_type == R_MIPS_HIGHER)
 		addend = mips_elf_higher (addend);
@@ -8493,9 +8675,11 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
   const char *name;
   int idx;
   struct mips_elf_link_hash_table *htab;
+  struct mips_elf_link_hash_entry *hmips;
 
   htab = mips_elf_hash_table (info);
   dynobj = elf_hash_table (info)->dynobj;
+  hmips = (struct mips_elf_link_hash_entry *) h;
 
   if (h->plt.offset != MINUS_ONE)
     {
@@ -8558,6 +8742,18 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
 		       + h->plt.offset);
     }
 
+  /* If we have a MIPS16 function with a stub, the dynamic symbol must
+     refer to the stub, since only the stub uses the standard calling
+     conventions.  */
+  if (h->dynindx != -1 && hmips->fn_stub != NULL)
+    {
+      BFD_ASSERT (hmips->need_fn_stub);
+      sym->st_value = (hmips->fn_stub->output_section->vma
+		       + hmips->fn_stub->output_offset);
+      sym->st_size = hmips->fn_stub->size;
+      sym->st_other = ELF_ST_VISIBILITY (sym->st_other);
+    }
+
   BFD_ASSERT (h->dynindx != -1
 	      || h->forced_local);
 
@@ -8576,7 +8772,8 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
       bfd_vma value;
 
       value = sym->st_value;
-      offset = mips_elf_global_got_index (dynobj, output_bfd, h, R_MIPS_GOT16, info);
+      offset = mips_elf_global_got_index (dynobj, output_bfd, h,
+					  R_MIPS_GOT16, info);
       MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
     }
 
@@ -8590,7 +8787,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
 
       e.abfd = output_bfd;
       e.symndx = -1;
-      e.d.h = (struct mips_elf_link_hash_entry *)h;
+      e.d.h = hmips;
       e.tls_type = 0;
 
       for (g = g->next; g->next != gg; g = g->next)
@@ -8706,9 +8903,15 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
 	}
     }
 
-  /* If this is a mips16 symbol, force the value to be even.  */
+  /* Keep dynamic MIPS16 symbols odd and reduce their size accordingly.
+     This allows the dynamic linker to treat MIPS16 symbols like any
+     other.  */
   if (ELF_ST_IS_MIPS16 (sym->st_other))
-    sym->st_value &= ~1;
+    {
+      BFD_ASSERT (sym->st_value & 1);
+      sym->st_other -= STO_MIPS16;
+      sym->st_size -= 1;
+    }
 
   return TRUE;
 }
@@ -9936,6 +10139,8 @@ _bfd_mips_elf_gc_sweep_hook (bfd *abfd A
   for (rel = relocs; rel < relend; rel++)
     switch (ELF_R_TYPE (abfd, rel->r_info))
       {
+      case R_MIPS16_GOT16:
+      case R_MIPS16_CALL16:
       case R_MIPS_GOT16:
       case R_MIPS_CALL16:
       case R_MIPS_CALL_HI16:
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c	2008-06-28 17:14:12.000000000 +0100
+++ gas/config/tc-mips.c	2008-06-28 17:14:17.000000000 +0100
@@ -2105,6 +2105,46 @@ md_assemble (char *str)
     }
 }
 
+/* Convenience functions for abstracting away the differences between
+   MIPS16 and non-MIPS16 relocations.  */
+
+static inline bfd_boolean
+mips16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  switch (reloc)
+    {
+    case BFD_RELOC_MIPS16_JMP:
+    case BFD_RELOC_MIPS16_GPREL:
+    case BFD_RELOC_MIPS16_GOT16:
+    case BFD_RELOC_MIPS16_CALL16:
+    case BFD_RELOC_MIPS16_HI16_S:
+    case BFD_RELOC_MIPS16_HI16:
+    case BFD_RELOC_MIPS16_LO16:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+static inline bfd_boolean
+got16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  return reloc == BFD_RELOC_MIPS_GOT16 || reloc == BFD_RELOC_MIPS16_GOT16;
+}
+
+static inline bfd_boolean
+hi16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  return reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_MIPS16_HI16_S;
+}
+
+static inline bfd_boolean
+lo16_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  return reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16;
+}
+
 /* Return true if the given relocation might need a matching %lo().
    This is only "might" because SVR4 R_MIPS_GOT16 relocations only
    need a matching %lo() when applied to local symbols.  */
@@ -2113,11 +2153,19 @@ md_assemble (char *str)
 reloc_needs_lo_p (bfd_reloc_code_real_type reloc)
 {
   return (HAVE_IN_PLACE_ADDENDS
-	  && (reloc == BFD_RELOC_HI16_S
-	      || reloc == BFD_RELOC_MIPS16_HI16_S
+	  && (hi16_reloc_p (reloc)
 	      /* VxWorks R_MIPS_GOT16 relocs never need a matching %lo();
 		 all GOT16 relocations evaluate to "G".  */
-	      || (reloc == BFD_RELOC_MIPS_GOT16 && mips_pic != VXWORKS_PIC)));
+	      || (got16_reloc_p (reloc) && mips_pic != VXWORKS_PIC)));
+}
+
+/* Return the type of %lo() reloc needed by RELOC, given that
+   reloc_needs_lo_p.  */
+
+static inline bfd_reloc_code_real_type
+matching_lo_reloc (bfd_reloc_code_real_type reloc)
+{
+  return mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16 : BFD_RELOC_LO16;
 }
 
 /* Return true if the given fixup is followed by a matching R_MIPS_LO16
@@ -2127,8 +2175,7 @@ reloc_needs_lo_p (bfd_reloc_code_real_ty
 fixup_has_matching_lo_p (fixS *fixp)
 {
   return (fixp->fx_next != NULL
-	  && (fixp->fx_next->fx_r_type == BFD_RELOC_LO16
-	     || fixp->fx_next->fx_r_type == BFD_RELOC_MIPS16_LO16)
+	  && fixp->fx_next->fx_r_type == matching_lo_reloc (fixp->fx_r_type)
 	  && fixp->fx_addsy == fixp->fx_next->fx_addsy
 	  && fixp->fx_offset == fixp->fx_next->fx_offset);
 }
@@ -2910,8 +2957,6 @@ append_insn (struct mips_cl_insn *ip, ex
 	      && (reloc_type[0] == BFD_RELOC_16
 		  || reloc_type[0] == BFD_RELOC_32
 		  || reloc_type[0] == BFD_RELOC_MIPS_JMP
-		  || reloc_type[0] == BFD_RELOC_HI16_S
-		  || reloc_type[0] == BFD_RELOC_LO16
 		  || reloc_type[0] == BFD_RELOC_GPREL16
 		  || reloc_type[0] == BFD_RELOC_MIPS_LITERAL
 		  || reloc_type[0] == BFD_RELOC_GPREL32
@@ -2924,8 +2969,8 @@ append_insn (struct mips_cl_insn *ip, ex
 		  || reloc_type[0] == BFD_RELOC_MIPS_REL16
 		  || reloc_type[0] == BFD_RELOC_MIPS_RELGOT
 		  || reloc_type[0] == BFD_RELOC_MIPS16_GPREL
-		  || reloc_type[0] == BFD_RELOC_MIPS16_HI16_S
-		  || reloc_type[0] == BFD_RELOC_MIPS16_LO16))
+		  || hi16_reloc_p (reloc_type[0])
+		  || lo16_reloc_p (reloc_type[0])))
 	    ip->fixp[0]->fx_no_overflow = 1;
 
 	  if (mips_relax.sequence)
@@ -9899,6 +9944,8 @@ mips16_ip (char *str, struct mips_cl_ins
 		  /* Stuff the immediate value in now, if we can.  */
 		  if (imm_expr.X_op == O_constant
 		      && *imm_reloc > BFD_RELOC_UNUSED
+		      && *imm_reloc != BFD_RELOC_MIPS16_GOT16
+		      && *imm_reloc != BFD_RELOC_MIPS16_CALL16
 		      && insn->pinfo != INSN_MACRO)
 		    {
 		      valueT tmp;
@@ -10668,6 +10715,8 @@ static const struct percent_op_match mip
 {
   {"%lo", BFD_RELOC_MIPS16_LO16},
   {"%gprel", BFD_RELOC_MIPS16_GPREL},
+  {"%got", BFD_RELOC_MIPS16_GOT16},
+  {"%call16", BFD_RELOC_MIPS16_CALL16},
   {"%hi", BFD_RELOC_MIPS16_HI16_S}
 };
 
@@ -11761,7 +11810,7 @@ mips_frob_file (void)
 
       /* If a GOT16 relocation turns out to be against a global symbol,
 	 there isn't supposed to be a matching LO.  */
-      if (l->fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
+      if (got16_reloc_p (l->fixp->fx_r_type)
 	  && !pic_need_relax (l->fixp->fx_addsy, l->seg))
 	continue;
 
@@ -11779,12 +11828,7 @@ mips_frob_file (void)
       hi_pos = NULL;
       lo_pos = NULL;
       matched_lo_p = FALSE;
-      
-      if (l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16
-	   || l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16_S)
-        looking_for_rtype = BFD_RELOC_MIPS16_LO16;
-      else
-        looking_for_rtype = BFD_RELOC_LO16;
+      looking_for_rtype = matching_lo_reloc (l->fixp->fx_r_type);
 
       for (pos = &seginfo->fix_root; *pos != NULL; pos = &(*pos)->fx_next)
 	{
@@ -11837,8 +11881,8 @@ mips_force_relocation (fixS *fixp)
   if (HAVE_NEWABI
       && S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
       && (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
-	  || fixp->fx_r_type == BFD_RELOC_HI16_S
-	  || fixp->fx_r_type == BFD_RELOC_LO16))
+	  || hi16_reloc_p (fixp->fx_r_type)
+	  || lo16_reloc_p (fixp->fx_r_type)))
     return 1;
 
   return 0;
@@ -11926,6 +11970,8 @@ md_apply_fix (fixS *fixP, valueT *valP, 
     case BFD_RELOC_MIPS_CALL_HI16:
     case BFD_RELOC_MIPS_CALL_LO16:
     case BFD_RELOC_MIPS16_GPREL:
+    case BFD_RELOC_MIPS16_GOT16:
+    case BFD_RELOC_MIPS16_CALL16:
     case BFD_RELOC_MIPS16_HI16:
     case BFD_RELOC_MIPS16_HI16_S:
     case BFD_RELOC_MIPS16_JMP:
@@ -13733,8 +13779,7 @@ mips_fix_adjustable (fixS *fixp)
      placed anywhere.  Rather than break backwards compatibility by changing
      this, it seems better not to force the issue, and instead keep the
      original symbol.  This will work with either linker behavior.  */
-  if ((fixp->fx_r_type == BFD_RELOC_LO16
-       || fixp->fx_r_type == BFD_RELOC_MIPS16_LO16
+  if ((lo16_reloc_p (fixp->fx_r_type)
        || reloc_needs_lo_p (fixp->fx_r_type))
       && HAVE_IN_PLACE_ADDENDS
       && (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) != 0)
Index: gas/testsuite/gas/mips/elf-rel8-mips16.d
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel8-mips16.d	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,38 @@
+#as: -march=mips2 -mabi=32
+#objdump: -M gpr-names=numeric -dr
+#name: MIPS ELF reloc 8 (MIPS16 version)
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+00 <foo>:
+   0:	675c      	move	\$2,\$28
+   2:	f000 6c00 	li	\$4,0
+			2: R_MIPS16_HI16	gvar
+   6:	f400 3480 	sll	\$4,16
+   a:	f000 4c00 	addiu	\$4,0
+			a: R_MIPS16_LO16	gvar
+   e:	f000 9d80 	lw	\$4,0\(\$5\)
+			e: R_MIPS16_LO16	gvar
+  12:	f000 9982 	lw	\$4,2\(\$17\)
+  16:	f000 9a80 	lw	\$4,0\(\$2\)
+			16: R_MIPS16_GOT16	\.data
+  1a:	f000 c4a0 	sb	\$5,0\(\$4\)
+			1a: R_MIPS16_LO16	\.data
+  1e:	f000 9a80 	lw	\$4,0\(\$2\)
+			1e: R_MIPS16_GOT16	\.data
+  22:	f000 4c00 	addiu	\$4,0
+			22: R_MIPS16_LO16	\.data
+  26:	f000 9a60 	lw	\$3,0\(\$2\)
+			26: R_MIPS16_CALL16	gfunc
+  2a:	f000 4c00 	addiu	\$4,0
+			2a: R_MIPS16_CALL16	gfunc
+  2e:	f000 9a80 	lw	\$4,0\(\$2\)
+			2e: R_MIPS16_GPREL	gvar
+  32:	f000 da80 	sw	\$4,0\(\$2\)
+			32: R_MIPS16_GPREL	gvar
+  36:	f000 4c00 	addiu	\$4,0
+			36: R_MIPS16_GPREL	gvar
+  3a:	6500      	nop
+#pass
Index: gas/testsuite/gas/mips/elf-rel8-mips16.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel8-mips16.s	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,39 @@
+	.equ	$fprel, 2
+	.set	mips16
+
+	.ent	foo
+foo:
+	move	$2,$gp
+
+	# Test various forms of relocation syntax.
+
+	li	$4,(%hi gvar)
+	sll	$4,16
+	addiu	$4,(%lo (gvar))
+	lw	$4,%lo gvar($5)
+
+	# Check that registers aren't confused with $ identifiers.
+
+	lw	$4,($fprel)($17)
+
+	# Check various forms of paired relocations.
+
+	lw	$4,%got(lvar)($2)
+	sb	$5,%lo(lvar)($4)
+
+	lw	$4,%got(lvar)($2)
+	addiu	$4,%lo(lvar)
+
+	# Check individual relocations.
+
+	lw	$3,%call16(gfunc)($2)
+	addiu	$4,%call16(gfunc)
+
+	lw	$4,%gprel(gvar)($2)
+	sw	$4,%gprel(gvar)($2)
+	addiu	$4,%gprel(gvar)
+	.align	6
+	.end	foo
+
+	.data
+lvar:	.word	1,2
Index: gas/testsuite/gas/mips/elf-rel9-mips16.d
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel9-mips16.d	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,70 @@
+#as: -march=mips2 -mabi=32
+#objdump: -M gpr-names=numeric -dr
+#name: MIPS ELF reloc 9 (MIPS16 version)
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+00 <foo>:
+   0:	675c      	move	\$2,\$28
+   2:	f000 9a80 	lw	\$4,0\(\$2\)
+			2: R_MIPS16_GOT16	\.data
+   6:	f000 4c10 	addiu	\$4,16
+			6: R_MIPS16_LO16	\.data
+   a:	f000 9a80 	lw	\$4,0\(\$2\)
+			a: R_MIPS16_GOT16	\.data
+   e:	f020 4c00 	addiu	\$4,32
+			e: R_MIPS16_LO16	\.data
+  12:	f000 9a80 	lw	\$4,0\(\$2\)
+			12: R_MIPS16_GOT16	\.data
+  16:	f7ef 4c1c 	addiu	\$4,32764
+			16: R_MIPS16_LO16	\.data
+  1a:	f000 9a81 	lw	\$4,1\(\$2\)
+			1a: R_MIPS16_GOT16	\.data
+  1e:	f010 4c00 	addiu	\$4,-32768
+			1e: R_MIPS16_LO16	\.data
+  22:	f000 9a81 	lw	\$4,1\(\$2\)
+			22: R_MIPS16_GOT16	\.data
+  26:	f7ff 4c1c 	addiu	\$4,-4
+			26: R_MIPS16_LO16	\.data
+  2a:	f000 9a81 	lw	\$4,1\(\$2\)
+			2a: R_MIPS16_GOT16	\.data
+  2e:	f000 4c00 	addiu	\$4,0
+			2e: R_MIPS16_LO16	\.data
+  32:	f000 9a82 	lw	\$4,2\(\$2\)
+			32: R_MIPS16_GOT16	\.data
+  36:	f010 4c10 	addiu	\$4,-32752
+			36: R_MIPS16_LO16	\.data
+  3a:	f000 9a82 	lw	\$4,2\(\$2\)
+			3a: R_MIPS16_GOT16	\.data
+  3e:	f01e 4c00 	addiu	\$4,-4096
+			3e: R_MIPS16_LO16	\.data
+  42:	f000 9a82 	lw	\$4,2\(\$2\)
+			42: R_MIPS16_GOT16	\.data
+  46:	f7ff 4c1f 	addiu	\$4,-1
+			46: R_MIPS16_LO16	\.data
+  4a:	f000 9a82 	lw	\$4,2\(\$2\)
+			4a: R_MIPS16_GOT16	\.data
+  4e:	f000 4c00 	addiu	\$4,0
+			4e: R_MIPS16_LO16	\.data
+  52:	f000 9a83 	lw	\$4,3\(\$2\)
+			52: R_MIPS16_GOT16	\.data
+  56:	f342 4c05 	addiu	\$4,4933
+			56: R_MIPS16_LO16	\.data
+  5a:	f018 9a80 	lw	\$4,-16384\(\$2\)
+			5a: R_MIPS16_GPREL	\.sdata
+  5e:	f018 9a84 	lw	\$4,-16380\(\$2\)
+			5e: R_MIPS16_GPREL	\.sdata
+  62:	f018 9a84 	lw	\$4,-16380\(\$2\)
+			62: R_MIPS16_GPREL	\.sdata
+  66:	f018 9a88 	lw	\$4,-16376\(\$2\)
+			66: R_MIPS16_GPREL	\.sdata
+  6a:	f018 9a8c 	lw	\$4,-16372\(\$2\)
+			6a: R_MIPS16_GPREL	\.sdata
+  6e:	f018 9a94 	lw	\$4,-16364\(\$2\)
+			6e: R_MIPS16_GPREL	\.sdata
+  72:	f018 9a98 	lw	\$4,-16360\(\$2\)
+			72: R_MIPS16_GPREL	\.sdata
+  76:	6500      	nop
+#pass
Index: gas/testsuite/gas/mips/elf-rel9-mips16.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel9-mips16.s	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,59 @@
+	.set	mips16
+	.ent	foo
+foo:
+	move	$2,$28
+	lw	$4,%got(l1)($2)
+	addiu	$4,%lo(l1)
+
+	lw	$4,%got(l1 + 16)($2)
+	addiu	$4,%lo(l1 + 16)
+
+	lw	$4,%got(l1 + 0x7fec)($2)
+	addiu	$4,%lo(l1 + 0x7fec)
+
+	lw	$4,%got(l1 + 0x7ff0)($2)
+	addiu	$4,%lo(l1 + 0x7ff0)
+
+	lw	$4,%got(l1 + 0xffec)($2)
+	addiu	$4,%lo(l1 + 0xffec)
+
+	lw	$4,%got(l1 + 0xfff0)($2)
+	addiu	$4,%lo(l1 + 0xfff0)
+
+	lw	$4,%got(l1 + 0x18000)($2)
+	addiu	$4,%lo(l1 + 0x18000)
+
+	lw	$4,%got(l2)($2)
+	addiu	$4,%lo(l2)
+
+	lw	$4,%got(l2 + 0xfff)($2)
+	addiu	$4,%lo(l2 + 0xfff)
+
+	lw	$4,%got(l2 + 0x1000)($2)
+	addiu	$4,%lo(l2 + 0x1000)
+
+	lw	$4,%got(l2 + 0x12345)($2)
+	addiu	$4,%lo(l2 + 0x12345)
+
+	lw	$4,%gprel(l3)($2)
+	lw	$4,%gprel(l3 + 4)($2)
+	lw	$4,%gprel(l4)($2)
+	lw	$4,%gprel(l4 + 4)($2)
+	lw	$4,%gprel(l5)($2)
+	lw	$4,%gprel(l5 + 8)($2)
+	lw	$4,%gprel(l5 + 12)($2)
+
+	.align	6
+	.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
Index: gas/testsuite/gas/mips/elf-rel13-mips16.d
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel13-mips16.d	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,17 @@
+#as: -march=mips2 -mabi=32 -KPIC
+#readelf: --relocs
+#name: MIPS ELF reloc 13 (MIPS16 version)
+
+Relocation section '\.rel\.text' at offset .* contains 9 entries:
+ *Offset * Info * Type * Sym\.Value * Sym\. Name
+0+0002 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.data
+0+0016 * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.data
+0+0012 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.data
+0+001a * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.data
+# The next two lines could be in either order.
+0+000e * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.rodata
+0+000a * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.rodata
+0+001e * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.rodata
+0+0006 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.bss
+0+0022 * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.bss
+#pass
Index: gas/testsuite/gas/mips/elf-rel13-mips16.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ gas/testsuite/gas/mips/elf-rel13-mips16.s	2008-06-28 17:14:17.000000000 +0100
@@ -0,0 +1,24 @@
+	.set	mips16
+	.ent	foo
+foo:
+	move	$2,$28
+	lw	$4,%got(l1)($2)
+	lw	$4,%got(l2)($2)
+	lw	$4,%got(l3)($2)
+	lw	$4,%got(l3)($2)
+	lw	$4,%got(l1+0x400)($2)
+	addiu	$4,%lo(l1)
+	addiu	$4,%lo(l1+0x400)
+	addiu	$4,%lo(l3)
+	addiu	$4,%lo(l2)
+	.align	5
+	.end	foo
+
+	.data
+l1:	.word	1
+
+	.lcomm	l2, 4
+
+	.rdata
+	.word	1
+l3:	.word	2
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
--- gas/testsuite/gas/mips/mips.exp	2008-06-28 17:14:12.000000000 +0100
+++ gas/testsuite/gas/mips/mips.exp	2008-06-28 17:14:17.000000000 +0100
@@ -647,13 +647,16 @@ if { [istarget mips*-*-vxworks*] } {
 	}
 	run_dump_test "elf-rel7"
 	run_dump_test "elf-rel8"
+	run_dump_test "elf-rel8-mips16"
 	run_dump_test "elf-rel9"
+	run_dump_test "elf-rel9-mips16"
 	if $has_newabi {
 	    run_dump_test "elf-rel10"
 	    run_dump_test "elf-rel11"
 	}
 	run_dump_test "elf-rel12"
 	run_dump_test "elf-rel13"
+	run_dump_test "elf-rel13-mips16"
 	run_dump_test "elf-rel14"
 
 	if $has_newabi {
Index: ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d	2008-06-28 17:09:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d	2008-06-28 17:14:17.000000000 +0100
@@ -57,13 +57,13 @@ Disassembly of section \.text:
 20000068:	00000000 	nop
 
 2000006c <caller2>:
-2000006c:	1c00 0030 	jalx	200000c0 <stub_for_f1>
+2000006c:	1c00 002c 	jalx	200000b0 <stub_for_f1>
 20000070:	6500      	nop
-20000072:	1c00 0038 	jalx	200000e0 <stub_for_f2>
+20000072:	1c00 0034 	jalx	200000d0 <stub_for_f2>
 20000076:	6500      	nop
-20000078:	1c00 0034 	jalx	200000d0 <stub_for_g1>
+20000078:	1c00 0030 	jalx	200000c0 <stub_for_g1>
 2000007c:	6500      	nop
-2000007e:	1c00 003c 	jalx	200000f0 <stub_for_g2>
+2000007e:	1c00 0038 	jalx	200000e0 <stub_for_g2>
 20000082:	6500      	nop
 20000084:	1800 0004 	jal	20000010 <h1>
 20000088:	6500      	nop
@@ -82,33 +82,26 @@ Disassembly of section \.text:
 200000a8:	00200008 	jr	at
 200000ac:	00000000 	nop
 
-# This isn't actually called, but is referenced from the .pdr section.
-200000b0 <stub_for_h3>:
+200000b0 <stub_for_f1>:
 200000b0:	3c012000 	lui	at,0x2000
-200000b4:	24210039 	addiu	at,at,57
+200000b4:	24210000 	addiu	at,at,0
 200000b8:	00200008 	jr	at
 200000bc:	00000000 	nop
 
-200000c0 <stub_for_f1>:
+200000c0 <stub_for_g1>:
 200000c0:	3c012000 	lui	at,0x2000
-200000c4:	24210000 	addiu	at,at,0
+200000c4:	24210008 	addiu	at,at,8
 200000c8:	00200008 	jr	at
 200000cc:	00000000 	nop
 
-200000d0 <stub_for_g1>:
+200000d0 <stub_for_f2>:
 200000d0:	3c012000 	lui	at,0x2000
-200000d4:	24210008 	addiu	at,at,8
+200000d4:	24210014 	addiu	at,at,20
 200000d8:	00200008 	jr	at
 200000dc:	00000000 	nop
 
-200000e0 <stub_for_f2>:
+200000e0 <stub_for_g2>:
 200000e0:	3c012000 	lui	at,0x2000
-200000e4:	24210014 	addiu	at,at,20
+200000e4:	2421001c 	addiu	at,at,28
 200000e8:	00200008 	jr	at
 200000ec:	00000000 	nop
-
-200000f0 <stub_for_g2>:
-200000f0:	3c012000 	lui	at,0x2000
-200000f4:	2421001c 	addiu	at,at,28
-200000f8:	00200008 	jr	at
-200000fc:	00000000 	nop
Index: ld/testsuite/ld-mips-elf/mips16-intermix.d
===================================================================
--- ld/testsuite/ld-mips-elf/mips16-intermix.d	2008-06-28 17:09:18.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips16-intermix.d	2008-06-28 17:14:17.000000000 +0100
@@ -14,7 +14,6 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_d
 .* l     F .text	0+[0-9a-f]+ m32_static_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_d
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static_d
 .* l     F .text	0+[0-9a-f]+ m32_static1_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static1_d
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static1_d
@@ -23,7 +22,6 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static32_d
 .* l     F .text	0+[0-9a-f]+ m32_static16_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static16_d
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static16_d
 .* l     F .text	0+[0-9a-f]+ m32_static_ld
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_ld
 .* l     F .text	0+[0-9a-f]+ m32_static1_ld
@@ -35,7 +33,6 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_dl
 .* l     F .text	0+[0-9a-f]+ m32_static_dl
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_dl
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static_dl
 .* l     F .text	0+[0-9a-f]+ m32_static1_dl
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static1_dl
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static1_dl
@@ -44,11 +41,9 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static32_dl
 .* l     F .text	0+[0-9a-f]+ m32_static16_dl
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static16_dl
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static16_dl
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_dlld
 .* l     F .text	0+[0-9a-f]+ m32_static_dlld
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_dlld
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static_dlld
 .* l     F .text	0+[0-9a-f]+ m32_static1_dlld
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static1_dlld
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static1_dlld
@@ -57,7 +52,6 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static32_dlld
 .* l     F .text	0+[0-9a-f]+ m32_static16_dlld
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static16_dlld
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static16_dlld
 .* l     F .text	0+[0-9a-f]+ m32_static_d_l
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_d_l
 .* l     F .text	0+[0-9a-f]+ m32_static1_d_l
@@ -66,10 +60,11 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static32_d_l
 .* l     F .text	0+[0-9a-f]+ m32_static16_d_l
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static16_d_l
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_d_d
+# ??? We aren't yet able to get rid of the symbol table entry for
+# __fn_stub_m16_d_d, or its .pdr entry.
+.* l     F .text	0+[0-9a-f]+ *
 .* l     F .text	0+[0-9a-f]+ m32_static_d_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static_d_d
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static_d_d
 .* l     F .text	0+[0-9a-f]+ m32_static1_d_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static1_d_d
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static1_d_d
@@ -78,7 +73,6 @@ SYMBOL TABLE:
 .* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static32_d_d
 .* l     F .text	0+[0-9a-f]+ m32_static16_d_d
 .* l     F .text	0+[0-9a-f]+ 0xf0 m16_static16_d_d
-.* l     F .text	0+[0-9a-f]+ __fn_stub_m16_static16_d_d
 #...
 .* l     F .text	0+[0-9a-f]+ __call_stub_m32_static1_d
 .* l     F .text	0+[0-9a-f]+ __call_stub_m16_static1_d
Index: ld/testsuite/ld-mips-elf/mips16-pic-1a.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1a.s	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,144 @@
+	.abicalls
+	.set	noreorder
+	.include "mips16-pic-1.inc"
+
+	# Test local stubs that are only used by MIPS16 PIC calls in this file.
+	decl	unused1,lstub
+	callpic	unused1,mips16
+
+	# Test local stubs that are only used by MIPS16 jals in this file.
+	decl	unused2,lstub
+	jals	unused2,mips16
+
+	# Test local stubs that aren't called at all.
+	decl	unused3,lstub
+
+	# Test hidden stubs that are called by MIPS16 PIC calls in this file.
+	decl	unused4,hstub
+	callpic	unused4,mips16
+
+	# Test hidden stubs that are called by MIPS16 jals in this file.
+	decl	unused5,hstub
+	jals	unused5,mips16
+
+	# Test hidden stubs that are called by MIPS16 PIC calls in another file.
+	decl	unused6,hstub
+
+	# Test hidden stubs that are called by MIPS16 jals in another file.
+	decl	unused7,hstub
+
+	# Test hidden stubs that aren't called at all.
+	decl	unused8,hstub
+
+	# Test global stubs that are called by MIPS16 jals in this file.
+	decl	unused9,gstub
+	jals	unused9,mips16
+
+	# Test global stubs that are called by MIPS16 jals in another file.
+	decl	unused10,gstub
+
+	# Test global stubs that aren't called at all.
+	decl	unused11,gstub
+
+	# Test local stubs that are used by non-MIPS16 PIC calls in this file.
+	decl	used1,lstub
+	callpic	used1,nomips16
+
+	# Test local stubs that are used by non-MIPS16 jals in this file.
+	decl	used2,lstub
+	jals	used2,nomips16
+
+	# Test local stubs that are used by both MIPS16 and non-MIPS16 PIC
+	# calls in this file.
+	decl	used3,lstub
+	callpic	used3,nomips16
+	callpic	used3,mips16
+
+	# Test local stubs that are used by both MIPS16 and non-MIPS16 jals
+	# in this file.
+	decl	used4,lstub
+	jals	used4,nomips16
+	jals	used4,mips16
+
+	# Test local stubs that are used by a combination of MIPS16 PIC calls
+	# and non-MIPS16 jals in this file.
+	decl	used5,lstub
+	jals	used5,nomips16
+	callpic	used5,mips16
+
+	# Test hidden stubs that are used by non-MIPS16 PIC calls in this file.
+	decl	used6,hstub
+	callpic	used6,nomips16
+
+	# Test hidden stubs that are used by non-MIPS16 jals in this file.
+	decl	used7,hstub
+	jals	used7,nomips16
+
+	# Test hidden stubs that are used by non-MIPS16 PIC calls in another
+	# file.
+	decl	used8,hstub
+
+	# Test hidden stubs that are used by non-MIPS16 jals in another
+	# file.
+	decl	used9,hstub
+
+	# Test hidden stubs that are used by both MIPS16 and non-MIPS16 PIC
+	# calls in this file.
+	decl	used10,hstub
+	callpic	used10,nomips16
+	callpic	used10,mips16
+
+	# Test hidden stubs that are used by both MIPS16 and non-MIPS16 jals
+	# in this file.
+	decl	used11,hstub
+	jals	used11,nomips16
+	jals	used11,mips16
+
+	# Test hidden stubs that are used by a combination of MIPS16 PIC calls
+	# and non-MIPS16 jals in this file.
+	decl	used12,hstub
+	jals	used12,nomips16
+	callpic	used12,mips16
+
+	# Test global stubs that are used by non-MIPS16 PIC calls in this file.
+	decl	used13,gstub
+	callpic	used13,nomips16
+
+	# Test global stubs that are used by non-MIPS16 jals in this file.
+	decl	used14,gstub
+	jals	used14,nomips16
+
+	# Test global stubs that are used by non-MIPS16 PIC calls in another
+	# file.
+	decl	used15,gstub
+
+	# Test global stubs that are used by non-MIPS16 jals in another file.
+	decl	used16,gstub
+
+	# Test global stubs that are used by both MIPS16 and non-MIPS16 PIC
+	# calls in this file.
+	decl	used17,gstub
+	callpic	used17,nomips16
+	callpic	used17,mips16
+
+	# Test global stubs that are used by both MIPS16 and non-MIPS16 jals
+	# in this file.
+	decl	used18,gstub
+	jals	used18,nomips16
+	jals	used18,mips16
+
+	# Test global stubs that are used by a combination of MIPS16 PIC calls
+	# and non-MIPS16 jals in this file.
+	decl	used19,gstub
+	jals	used19,nomips16
+	callpic	used19,mips16
+
+	# Test global stubs that are used by MIPS16 PIC calls in this file.
+	# We currently force all targets of call16 relocations to be dynamic,
+	# and the stub must be the definition of the dynamic symbol.
+	decl	used20,gstub
+	callpic	used20,mips16
+
+	# Test global stubs that are used by MIPS16 PIC calls in another file.
+	# Needed for the same reason as used21.
+	decl	used21,gstub
Index: ld/testsuite/ld-mips-elf/mips16-pic-1b.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1b.s	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,19 @@
+	.abicalls
+	.set	noreorder
+	.include "mips16-pic-1.inc"
+
+	callpic	unused6,mips16
+	jals	unused7,mips16
+	jals	unused10,mips16
+	callpic	used8,nomips16
+	jals	used9,nomips16
+	callpic	used15,nomips16
+	jals	used16,nomips16
+	callpic	used21,mips16
+
+	.globl	__start
+	.ent	__start
+	.set	nomips16
+__start:
+	nop
+	.end	__start
Index: ld/testsuite/ld-mips-elf/mips16-pic-1-dummy.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1-dummy.s	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,15 @@
+	.abicalls
+	nop
+
+	.macro	dummyfn,name
+	.global	\name
+	.ent	\name
+\name:
+	jr	$31
+	.end	\name
+	.endm
+
+	dummyfn	extern1
+	dummyfn	extern2
+	dummyfn	extern3
+	dummyfn	extern4
Index: ld/testsuite/ld-mips-elf/mips16-pic-1.dd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1.dd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,1227 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+00040400 <a_unused1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040404 <b_unused1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040408 <callpic_unused1_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 0x40400: a_unused1
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1025
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+# 0x40404: b_unused2
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1029
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040444 <a_unused2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040448 <b_unused2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004044c <jals_unused2_mips16>:
+.*:	[^\t]*	jal	.* <a_unused2>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_unused2>
+.*:	[^\t]*	nop
+
+00040458 <a_unused3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004045c <b_unused3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040460 <a_unused4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040464 <b_unused4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040468 <callpic_unused4_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32740\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32736\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+0004049c <a_unused5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404a0 <b_unused5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404a4 <jals_unused5_mips16>:
+.*:	[^\t]*	jal	.* <a_unused5>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_unused5>
+.*:	[^\t]*	nop
+
+000404b0 <a_unused6>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404b4 <b_unused6>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404b8 <a_unused7>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404bc <b_unused7>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404c0 <a_unused8>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404c4 <b_unused8>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404c8 <a_unused9>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404cc <b_unused9>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404d0 <jals_unused9_mips16>:
+.*:	[^\t]*	jal	.* <a_unused9>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_unused9>
+.*:	[^\t]*	nop
+
+000404dc <a_unused10>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404e0 <b_unused10>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404e4 <a_unused11>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404e8 <b_unused11>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404ec <a_used1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404f0 <b_used1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000404f4 <callpic_used1_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 0x40b10: __fn_a_used1
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,v0,2832
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+# 0x40b24: __fn_b_used1
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,v0,2852
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+0004054c <a_used2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040550 <b_used2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040554 <jals_used2_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used2>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used2>
+.*:	[^\t]*	nop
+
+00040564 <a_used3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040568 <b_used3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004056c <callpic_used3_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 0x40b80: __fn_a_used3
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,v0,2944
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+# 0x40b94: __fn_b_used3
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,v0,2964
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+000405c4 <callpic_used3_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 0x40564: a_used3
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1381
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+# 0x40568: b_used3
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1385
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040600 <a_used4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040604 <b_used4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040608 <jals_used4_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used4>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used4>
+.*:	[^\t]*	nop
+
+00040618 <jals_used4_mips16>:
+.*:	[^\t]*	jal	.* <a_used4>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_used4>
+.*:	[^\t]*	nop
+
+00040624 <a_used5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040628 <b_used5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004062c <jals_used5_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used5>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used5>
+.*:	[^\t]*	nop
+
+0004063c <callpic_used5_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 0x40624: a_used5
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1573
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+# 0x40628: b_used5
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1577
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040678 <a_used6>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004067c <b_used6>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040680 <callpic_used6_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32732\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32728\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+000406d0 <a_used7>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406d4 <b_used7>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406d8 <jals_used7_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used7>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used7>
+.*:	[^\t]*	nop
+
+000406e8 <a_used8>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406ec <b_used8>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406f0 <a_used9>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406f4 <b_used9>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406f8 <a_used10>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000406fc <b_used10>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040700 <callpic_used10_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32724\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32720\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+00040750 <callpic_used10_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32724\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32720\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040784 <a_used11>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040788 <b_used11>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004078c <jals_used11_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used11>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used11>
+.*:	[^\t]*	nop
+
+0004079c <jals_used11_mips16>:
+.*:	[^\t]*	jal	.* <a_used11>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_used11>
+.*:	[^\t]*	nop
+
+000407a8 <a_used12>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000407ac <b_used12>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000407b0 <jals_used12_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used12>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used12>
+.*:	[^\t]*	nop
+
+000407c0 <callpic_used12_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32716\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32712\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+000407f4 <.mips16.a_used13>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000407f8 <.mips16.b_used13>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000407fc <callpic_used13_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32660\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32632\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+0004084c <a_used14>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040850 <b_used14>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040854 <jals_used14_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used14>
+.*:	[^\t]*	nop
+ .*:	[^\t]*	jal	.* <__fn_b_used14>
+.*:	[^\t]*	nop
+
+00040864 <.mips16.a_used15>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040868 <.mips16.b_used15>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004086c <a_used16>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040870 <b_used16>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040874 <.mips16.a_used17>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040878 <.mips16.b_used17>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004087c <callpic_used17_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32676\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32656\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+000408cc <callpic_used17_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32676\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32656\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040900 <a_used18>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040904 <b_used18>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040908 <jals_used18_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used18>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used18>
+.*:	[^\t]*	nop
+
+00040918 <jals_used18_mips16>:
+.*:	[^\t]*	jal	.* <a_used18>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_used18>
+.*:	[^\t]*	nop
+
+00040924 <.mips16.a_used19>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040928 <.mips16.b_used19>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004092c <jals_used19_nomips16>:
+.*:	[^\t]*	jal	.* <a_used19>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_used19>
+.*:	[^\t]*	nop
+
+0004093c <callpic_used19_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32644\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32672\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040970 <.mips16.a_used20>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040974 <.mips16.b_used20>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040978 <callpic_used20_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32668\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32652\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+000409ac <.mips16.a_used21>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+000409b0 <.mips16.b_used21>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+#...
+
+000409c0 <callpic_unused6_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32708\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32704\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+000409f4 <jals_unused7_mips16>:
+.*:	[^\t]*	jal	.* <a_unused7>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_unused7>
+.*:	[^\t]*	nop
+
+00040a00 <jals_unused10_mips16>:
+.*:	[^\t]*	jal	.* <a_unused10>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <b_unused10>
+.*:	[^\t]*	nop
+
+00040a0c <callpic_used8_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32700\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32696\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+00040a5c <jals_used9_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used9>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used9>
+.*:	[^\t]*	nop
+
+00040a6c <callpic_used15_nomips16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+.*:	[^\t]*	move	v0,gp
+.*:	[^\t]*	addiu	sp,sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32664\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32640\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,sp,32
+
+00040abc <jals_used16_nomips16>:
+.*:	[^\t]*	jal	.* <__fn_a_used16>
+.*:	[^\t]*	nop
+.*:	[^\t]*	jal	.* <__fn_b_used16>
+.*:	[^\t]*	nop
+
+00040acc <callpic_used21_mips16>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32648\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32636\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+
+00040b00 <__start>:
+	\.\.\.
+
+00040b10 <__fn_a_used1>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040b24 <__fn_b_used1>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x404f0: b_used1
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1265
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040b48 <__fn_a_used2>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040b5c <__fn_b_used2>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40550: b_used2
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1361
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040b80 <__fn_a_used3>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040b94 <__fn_b_used3>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40568: b_used3
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1385
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040bb8 <__fn_a_used4>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040bcc <__fn_b_used4>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40604: b_used4
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1541
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040bf0 <__fn_a_used5>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c04 <__fn_b_used5>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40628: b_used5
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1577
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c28 <__fn_a_used6>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c3c <__fn_b_used6>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x4067c: b_used6
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1661
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c60 <__fn_a_used7>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c74 <__fn_b_used7>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x406d4: b_used7
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1749
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040c98 <__fn_a_used8>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040cac <__fn_b_used8>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x406ec: b_used8
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1773
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040cd0 <__fn_a_used9>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040ce4 <__fn_b_used9>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x406f4: b_used9
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1781
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d08 <__fn_a_used10>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d1c <__fn_b_used10>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x406fc: b_used10
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1789
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d40 <__fn_a_used11>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d54 <__fn_b_used11>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40788: b_used11
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1929
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d78 <__fn_a_used12>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040d8c <__fn_b_used12>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x407ac: b_used12
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1965
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040db0 <a_used13>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040dc4 <b_used13>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x407f8: .mips16.b_used13
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2041
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040de8 <__fn_a_used14>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040dfc <__fn_b_used14>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40850: b_used14
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2129
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040e20 <a_used15>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040e34 <b_used15>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40628: .mips16.b_used15
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2153
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040e58 <__fn_a_used16>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040e6c <__fn_b_used16>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40870: b_used16
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2161
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040e90 <a_used17>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040ea4 <b_used17>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40878: .mips16.b_used17
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2169
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040ec8 <__fn_a_used18>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040edc <__fn_b_used18>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40904: b_used18
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2309
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f00 <a_used19>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f14 <b_used19>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40928: .mips16.b_used19
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2345
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f38 <a_used20>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f4c <b_used20>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x40974: .mips16.b_used20
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2421
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f70 <a_used21>:
+.*:	[^\t]*	lui	v0,.*
+.*:	[^\t]*	addiu	v0,v0,.*
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040f84 <b_used21>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 0x409b0: .mips16.b_used21
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,2481
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
Index: ld/testsuite/ld-mips-elf/mips16-pic-1.gd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1.gd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,57 @@
+
+Primary GOT:
+ Canonical gp value: 00057ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  00050000 -32752\(gp\) 00000000 Lazy resolver
+  00050004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+
+ Local entries:
+   Address     Access  Initial
+# GOT page entry
+  00050008 -32744\(gp\) 00040000
+# a_unused4
+  0005000c -32740\(gp\) 00040461
+# b_unused4
+  00050010 -32736\(gp\) 00040465
+# __fn_a_used6
+  00050014 -32732\(gp\) 00040c28
+# __fn_b_used6
+  00050018 -32728\(gp\) 00040c3c
+# __fn_a_used10
+  0005001c -32724\(gp\) 00040d08
+# __fn_b_used10
+  00050020 -32720\(gp\) 00040d1c
+# __fn_a_used12
+  00050024 -32716\(gp\) 00040d78
+# __fn_b_used12
+  00050028 -32712\(gp\) 00040d8c
+# a_unused6
+  0005002c -32708\(gp\) 000404b1
+# b_unused6
+  00050030 -32704\(gp\) 000404b5
+# __fn_a_used8
+  00050034 -32700\(gp\) 00040c98
+# __fn_b_used8
+  00050038 -32696\(gp\) 00040cac
+  0005003c -32692\(gp\) 00000000
+  00050040 -32688\(gp\) 00000000
+  00050044 -32684\(gp\) 00000000
+  00050048 -32680\(gp\) 00000000
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  0005004c -32676\(gp\) 00040e90 00040e90 FUNC      7 a_used17
+  00050050 -32672\(gp\) 00040f14 00040f14 FUNC      7 b_used19
+  00050054 -32668\(gp\) 00040f38 00040f38 FUNC      7 a_used20
+  00050058 -32664\(gp\) 00040e20 00040e20 FUNC      7 a_used15
+  0005005c -32660\(gp\) 00040db0 00040db0 FUNC      7 a_used13
+  00050060 -32656\(gp\) 00040ea4 00040ea4 FUNC      7 b_used17
+  00050064 -32652\(gp\) 00040f4c 00040f4c FUNC      7 b_used20
+  00050068 -32648\(gp\) 00040f70 00040f70 FUNC      7 a_used21
+  0005006c -32644\(gp\) 00040f00 00040f00 FUNC      7 a_used19
+  00050070 -32640\(gp\) 00040e34 00040e34 FUNC      7 b_used15
+  00050074 -32636\(gp\) 00040f84 00040f84 FUNC      7 b_used21
+  00050078 -32632\(gp\) 00040dc4 00040dc4 FUNC      7 b_used13
+
Index: ld/testsuite/ld-mips-elf/mips16-pic-1.inc
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1.inc	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,147 @@
+	# Declare a function called NAME and an __fn_NAME stub for it.
+	# Make the stub use la_TYPE to load the the target address into $2.
+	.macro	stub,name,type
+	.set	nomips16
+	.section .mips16.fn.\name, "ax", @progbits
+	.ent	__fn_\name
+__fn_\name:
+	la_\type \name
+	mfc1	$4,$f12
+	jr	$2
+	nop
+	.end	__fn_\name
+
+	.set	mips16
+	.text
+	.ent	\name
+\name:
+__fn_local_\name:
+	jr	$31
+	nop
+	.end	\name
+	.endm
+
+	# Like stub, but ensure NAME is a local symbol.
+	.macro	lstub,name,type
+	stub	\name, \type
+	.equ	local_\name,1
+	.endm
+
+	# Like stub, but ensure NAME is a hidden symbol.
+	.macro	hstub,name,type
+	.globl	\name
+	.hidden	\name
+	stub	\name, \type
+	.endm
+
+	# Like lstub, but make the MIPS16 function global rather than local.
+	.macro	gstub,name,type
+	.globl	\name
+	stub	\name, \type
+	.endm
+
+	# Use an absolute sequence to load NAME into a register.
+	.macro	la_noshared,name
+	lui	$2,%hi(\name)
+	addiu	$2,$2,%lo(\name)
+	.endm
+
+	# Use the normal PIC sequence to load __fn_local_NAME into $2
+	# and emit a dummy relocation against NAME.  This macro is always
+	# used at the start of a function.
+	.macro	la_shared,name
+	.reloc	0,R_MIPS_NONE,\name
+	.cpload	$25
+	la	$2,__fn_local_\name
+	.endm
+
+	# Use TYPE (either LSTUB, HSTUB or GSTUB) to define functions
+	# called a_NAME and b_NAME.  The former uses absolute accesses
+	# and the latter uses PIC accesses.
+	.macro	decl,name,type
+	\type	a_\name, noshared
+	\type	b_\name, shared
+	.endm
+
+	# Emit the MIPS16 PIC sequence for setting $28 from $25.
+	# Make the value of $25 available in $2 as well.
+	.macro	cpload_mips16
+	li	$2,%hi(_gp_disp)
+	addiu	$3,$pc,%lo(_gp_disp)
+	sll	$2,16
+	addu	$2,$2,$3
+	move	$28,$2
+	.endm
+
+	# Likewise, but for non-MIPS16 code.
+	.macro	cpload_nomips16
+	.cpload	$25
+	move	$2,$28
+	.endm
+
+	# Start a PIC function in ISA mode MODE, which is either "mips16"
+	# or "nomips16".
+	.macro	pic_prologue,mode
+	cpload_\mode
+	addiu	$sp,$sp,-32
+	sw	$2,16($sp)
+	sw	$31,20($sp)
+	.endm
+
+	# Use a PIC function to call NAME.
+	.macro	pic_call,name,mode
+	.ifdef	local_\name
+	.ifc	\mode,mips16
+	lw	$2,%got(__fn_local_\name)($2)
+	addiu	$2,%lo(__fn_local_\name)
+	.else
+	lw	$2,%got(\name)($2)
+	addiu	$2,%lo(\name)
+	.endif
+	.else
+	lw	$2,%call16(\name)($2)
+	.endif
+	jalr	$2
+	move	$25,$2
+	lw	$2,16($sp)
+	move	$28,$2
+	.endm
+
+	# Finish a PIC function started by pic_prologue.
+	.macro	pic_epilogue
+	lw	$2,20($sp)
+	jr	$2
+	addiu	$sp,$sp,32
+	.endm
+
+	# Use PIC %call16 sequences to call a_NAME and b_NAME.
+	# MODE selects the ISA mode of the code: either "mips16"
+	# or "nomips16".
+	.macro	callpic,name,mode
+	.text
+	.set	\mode
+	.ent	callpic_\name\()_\mode
+callpic_\name\()_\mode:
+	pic_prologue \mode
+	pic_call     a_\name,\mode
+	pic_call     b_\name,\mode
+	pic_epilogue
+	.end	callpic_\name\()_\mode
+	.endm
+
+	# Use absolute jals to call a_NAME and b_NAME.  MODE selects the
+	# ISA mode of the code: either "mips16" or "nomips16".
+	.macro	jals,name,mode
+	.text
+	.set	\mode
+	.ent	jals_\name\()_\mode
+jals_\name\()_\mode:
+	.option	pic0
+	jal	a_\name
+	nop
+
+	jal	b_\name
+	nop
+	.option	pic2
+	.end	jals_\name\()_\mode
+	.endm
Index: ld/testsuite/ld-mips-elf/mips16-pic-1.ld
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-1.ld	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,22 @@
+SECTIONS
+{
+  . = 0x40000;
+  .interp : { *(.interp) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .dynamic : { *(.dynamic) }
+  .reginfo : { *(.reginfo) }
+  .hash : { *(.hash) }
+  . = ALIGN (0x400);
+  .text : { *(.text) *(.mips16.*) }
+  .MIPS.stubs : { *(.MIPS.stubs) }
+  . = ALIGN (0x400);
+  .rel.plt : { *(.rel.plt) }
+  .rel.dyn : { *(.rel.dyn) }
+  . = 0x50000;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+  . = 0x50400;
+  .data : { *(.data) }
+  .rld_map : { *(.rld_map) }
+}
Index: ld/testsuite/ld-mips-elf/mips16-pic-2a.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2a.s	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,63 @@
+	.abicalls
+	.set	noreorder
+	.include "mips16-pic-1.inc"
+
+	# Test local stubs that are only used by MIPS16 PIC calls in this file.
+	lstub	unused1,shared
+
+	# Test local stubs that aren't called at all.
+	lstub	unused2,shared
+
+	# Test hidden stubs that are called by MIPS16 PIC calls in this file.
+	hstub	unused3,shared
+
+	# Test hidden stubs that are called by MIPS16 PIC calls in another file.
+	hstub	unused4,shared
+
+	# Test hidden stubs that aren't called at all.
+	hstub	unused5,shared
+
+
+	# Test local stubs that are referenced by absolute relocations
+	# in this file.
+	lstub	used1,shared
+
+	# Test hidden stubs that are referenced by absolute relocations
+	# in this file.
+	hstub	used2,shared
+
+	# Test hidden stubs that are referenced by absolute relocations
+	# in another file.
+	hstub	used3,shared
+
+	# Test global stubs that are referenced by absolute relocations
+	# in this file.
+	gstub	used4,shared
+
+	# Test global stubs that are referenced by absolute relocations
+	# in another file.
+	gstub	used5,shared
+
+	# Test global stubs that are called by MIPS16 PIC calls in this file.
+	gstub	used6,shared
+
+	# Test global stubs that are called by MIPS16 PIC calls in another file.
+	gstub	used7,shared
+
+	# Test global stubs that aren't referenced at all.
+	gstub	used8,shared
+
+	.set	mips16
+	.ent	foo
+foo:
+	pic_prologue mips16
+	pic_call     unused1,mips16
+	pic_call     unused3,mips16
+	pic_call     used6,mips16
+	pic_epilogue
+	.end	foo
+
+	.data
+	.word	used1
+	.word	used2
+	.word	used4
Index: ld/testsuite/ld-mips-elf/mips16-pic-2b.s
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2b.s	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,16 @@
+	.abicalls
+	.set	noreorder
+	.include "mips16-pic-1.inc"
+
+	.set	mips16
+	.ent	bar
+bar:
+	pic_prologue mips16
+	pic_call     unused4,mips16
+	pic_call     used7,mips16
+	pic_epilogue
+	.end	bar
+
+	.data
+	.word	used3
+	.word	used5
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.ad
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.ad	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,6 @@
+# [MIPS_GOTSYM, MIPS_SYMTABNO) covers used4...used7.
+#...
+ .* \(MIPS_SYMTABNO\) * 10
+#...
+ .* \(MIPS_GOTSYM\) * 0x6
+#pass
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.dd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.dd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,208 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+00040400 <unused1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040404 <unused2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040408 <unused3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004040c <unused4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040410 <unused5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040414 <used1>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040418 <used2>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004041c <used3>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040420 <\.mips16\.used4>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040424 <\.mips16\.used5>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040428 <\.mips16\.used6>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+0004042c <\.mips16\.used7>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040430 <\.mips16\.used8>:
+.*:	[^\t]*	jr	ra
+.*:	[^\t]*	nop
+
+00040434 <foo>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+# 40400: unused1
+.*:	[^\t]*	lw	v0,-32744\(v0\)
+.*:	[^\t]*	addiu	v0,1025
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32740\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32708\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+#...
+
+00040480 <bar>:
+.*:	[^\t]*	li	v0,1
+.*:	[^\t]*	la	v1,47ff0 <.*>
+.*:	[^\t]*	sll	v0,16
+.*:	[^\t]*	addu	v0,v1
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	addiu	sp,-32
+.*:	[^\t]*	sw	v0,16\(sp\)
+.*:	[^\t]*	sw	ra,20\(sp\)
+.*:	[^\t]*	lw	v0,-32736\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,-32696\(v0\)
+.*:	[^\t]*	jalr	v0
+.*:	[^\t]*	move	t9,v0
+.*:	[^\t]*	lw	v0,16\(sp\)
+.*:	[^\t]*	move	gp,v0
+.*:	[^\t]*	lw	v0,20\(sp\)
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	addiu	sp,32
+#...
+
+000404c0 <__fn_used1>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40414: used1
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1045
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+000404e4 <__fn_used2>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40418: used2
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1049
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040508 <__fn_used3>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 4041c: used3
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1053
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+0004052c <used4>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40420: used4
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1057
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040550 <used5>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40424: used5
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1061
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040574 <used6>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40428: used6
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1065
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+00040598 <used7>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 4042c: used7
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1069
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
+
+000405bc <used8>:
+.*:	[^\t]*	lui	gp,.*
+.*:	[^\t]*	addiu	gp,gp,.*
+.*:	[^\t]*	addu	gp,gp,t9
+# 40430: used8
+.*:	[^\t]*	lw	v0,-32744\(gp\)
+.*:	[^\t]*	nop
+.*:	[^\t]*	addiu	v0,v0,1073
+.*:	[^\t]*	mfc1	a0,\$f12
+.*:	[^\t]*	jr	v0
+.*:	[^\t]*	nop
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.gd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.gd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,28 @@
+
+Primary GOT:
+ Canonical gp value: 00057ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  00050000 -32752\(gp\) 00000000 Lazy resolver
+  00050004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+
+ Local entries:
+   Address     Access  Initial
+  00050008 -32744\(gp\) 00040000
+  0005000c -32740\(gp\) 00040409
+  00050010 -32736\(gp\) 0004040d
+  00050014 -32732\(gp\) 00000000
+  00050018 -32728\(gp\) 00000000
+  0005001c -32724\(gp\) 00000000
+  00050020 -32720\(gp\) 00000000
+  00050024 -32716\(gp\) 00000000
+  00050028 -32712\(gp\) 00000000
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  0005002c -32708\(gp\) 00040574 00040574 FUNC      6 used6
+  00050030 -32704\(gp\) 0004052c 0004052c FUNC      6 used4
+  00050034 -32700\(gp\) 00040550 00040550 FUNC      6 used5
+  00050038 -32696\(gp\) 00040598 00040598 FUNC      6 used7
+
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.nd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.nd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,10 @@
+# used8 should come before MIPS_GOTSYM.
+#...
+     4: 000405bc    36 FUNC    GLOBAL DEFAULT .* used8
+     5: .* _GLOBAL_OFFSET_TABLE_
+     6: 00040574    36 FUNC    GLOBAL DEFAULT .* used6
+     7: 0004052c    36 FUNC    GLOBAL DEFAULT .* used4
+     8: 00040550    36 FUNC    GLOBAL DEFAULT .* used5
+     9: 00040598    36 FUNC    GLOBAL DEFAULT .* used7
+
+#pass
Index: ld/testsuite/ld-mips-elf/mips16-pic-2.rd
===================================================================
--- /dev/null	2008-06-21 07:33:38.548096750 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-2.rd	2008-06-28 17:14:18.000000000 +0100
@@ -0,0 +1,9 @@
+
+Relocation section '\.rel\.dyn' .*:
+.*
+0+00000 * [0-9]+ * R_MIPS_NONE *
+0+50400 * [0-9]+ * R_MIPS_REL32 *
+0+50404 * [0-9]+ * R_MIPS_REL32 *
+0+50410 * [0-9]+ * R_MIPS_REL32 *
+0+50408 * [0-9]+ * R_MIPS_REL32 * 0004052c * used4
+0+50414 * [0-9]+ * R_MIPS_REL32 * 00040550 * used5
Index: ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- ld/testsuite/ld-mips-elf/mips-elf.exp	2008-06-28 17:14:15.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips-elf.exp	2008-06-28 17:14:18.000000000 +0100
@@ -56,6 +56,30 @@ set has_newabi [expr [istarget *-*-irix6
 set linux_gnu [expr [istarget mips*-*-linux*]]
 set embedded_elf [expr [istarget mips*-*-elf]]
 
+if { $linux_gnu } {
+    run_ld_link_tests [list \
+	[list "Dummy shared library for MIPS16 PIC test 1" \
+	      "-shared -melf32btsmip" \
+	      "-EB -32" { mips16-pic-1-dummy.s } \
+	      {} \
+	      "mips16-pic-1-dummy.so"] \
+	[list "MIPS16 PIC test 1" \
+	      "-melf32btsmip -T mips16-pic-1.ld tmpdir/mips16-pic-1-dummy.so" \
+	      "-EB -32 -I $srcdir/$subdir" { mips16-pic-1a.s mips16-pic-1b.s } \
+	      { { objdump { -dr -j.text } mips16-pic-1.dd }
+		{ readelf -A mips16-pic-1.gd } } \
+	      "mips16-pic-1"] \
+	[list "MIPS16 PIC test 2" \
+	      "-melf32btsmip -T mips16-pic-1.ld -shared" \
+	      "-EB -32 -I $srcdir/$subdir" { mips16-pic-2a.s mips16-pic-2b.s } \
+	      { { objdump { -dr -j.text } mips16-pic-2.dd } \
+		{ readelf -A mips16-pic-2.gd } \
+	        { readelf --symbols mips16-pic-2.nd } \
+		{ readelf --relocs mips16-pic-2.rd } \
+		{ readelf -d mips16-pic-2.ad } } \
+	     "mips16-pic-2"]]
+}
+
 if { [istarget mips64*-linux-gnu] } {
     set o32_as_flags "-32 -EB"
     set o32_ld_flags "-melf32btsmip"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]