This is the mail archive of the binutils@sources.redhat.com 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]

Committed, MMIX: On-demand global register allocation


Allocate global registers on-demand, by handling unmatched
BFD_RELOC_MMIX_BASE_PLUS_OFFSET in the linker.  This is supposed
to be used to load constants/addresses; the linker will allocate
and fill in registers (their values in the register contents
section, the register numbers and offsets according to the
register number) as needed.  This idiom is used in most MMIX
examples.  Right, that approach is useful only for targets with
*lots* of registers.  And a few tweaks and bug-fixes for things
I spotted.

gas:
	Support on-demand global register allocation by passing on
	base-plus-offset relocs to the linker.
	* config/tc-mmix.c: Tweak and fix typos in comments.
 	(allocate_undefined_gregs_in_linker): New variable.
	(OPTION_LINKER_ALLOCATED_GREGS): New option macro.
	(md_longopts): Add --linker-allocated-gregs.
	(md_parse_option) <case 'x'>: Imply --linker-allocated-gregs.
	<case OPTION_LINKER_ALLOCATED_GREGS>: New.
	(md_show_usage): Update text for -x.  Add text for
	--linker-allocated-gregs.
	(tc_gen_reloc): Derive default value for addend from val and
	baddsy.  Use addsec and bfd_is_abs_section in more places.  Don't
	emit error for BFD_RELOC_MMIX_BASE_PLUS_OFFSET without suitable
	GREG if allocate_undefined_gregs_in_linker.
	* doc/as.texinfo (Overview) <Target MMIX options>: Add
	--linker-allocated-gregs.
	* doc/c-mmix.texi (MMIX-Opts): Add blurb about
	--linker-allocated-gregs.  Mention that it's implied by -x.
	(MMIX-Pseudos) <GREG>: Mention when and how a GREG can be omitted.
	(MMIX-mmixal): Clarify dated comparison and location of MMIXware.

	* config/tc-mmix.h (md_parse_name): Use ISUPPER, not isupper.

ld:
	Support on-demand global register allocation from
	R_MMIX_BASE_PLUS_OFFSET relocs.
	* emultempl/mmix-elfnmmo.em (mmix_after_allocation): Rename from
	mmix_set_reg_section_vma.  Call
	_bfd_mmix_finalize_linker_allocated_gregs.
	(mmix_before_allocation): New function.
	(LDEMUL_AFTER_ALLOCATION): Set to mmix_after_allocation.
	(LDEMUL_BEFORE_ALLOCATION): Define to mmix_before_allocation.
	* scripttempl/mmo.sc (.text): Mark .init, .fini as KEEP.
	(.MMIX.reg_contents): Add .MMIX.reg_contents.linker_allocated
	before .MMIX.reg_contents.
	* emultempl/mmo.em (gldmmo_before_allocation): Define to default.
	(mmo_after_open): New function.
	(LDEMUL_AFTER_OPEN): Define to mmo_after_open.
	* emulparams/elf64mmix.sh (OTHER_SECTIONS): Tweak formatting.  Add
	.MMIX.reg_contents.linker_allocated before .MMIX.reg_contents.

bfd:
	Perform on-demand global register allocation from
	R_MMIX_BASE_PLUS_OFFSET relocs.
	* elf64-mmix.c (struct bpo_reloc_section_info, struct
	bpo_reloc_request, struct bpo_greg_section_info): New.
	(mmix_elf_check_common_relocs, mmix_elf_gc_sweep_hook,
	bpo_reloc_request_sort_fn, mmix_elf_relax_section,
	_bfd_mmix_check_all_relocs,
	_bfd_mmix_prepare_linker_allocated_gregs,
	_bfd_mmix_finalize_linker_allocated_gregs): New functions.
	(elf_mmix_howto_table): Correct src_mask for most relocs.
	(mmix_elf_perform_relocation) <case R_MMIX_BASE_PLUS_OFFSET>: New
	case.
	(mmix_final_link_relocate) <case R_MMIX_BASE_PLUS_OFFSET>: New
	case.  Fix typo in comment.  New label do_mmix_reloc.
	(mmix_elf_check_relocs): Abuse bfd_link_info member base_file to
	store first object file with a base-plus-offset reloc.  Call
	mmix_elf_check_common_relocs for the part common with mmo.
	(mmix_elf_final_link): Write out linker-allocated register
	contents section.
	(elf_backend_gc_sweep_hook): Define.
	(bfd_elf64_bfd_relax_section): Define.

	* mmo.c: Don't include <ctype.h>
	(mmo_init): Correct init-once logic.

include/elf:
	* mmix.h: Tweak comments.
	(MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME): New.
	[BFD_ARCH_SIZE] (_bfd_mmix_prepare_linker_allocated_gregs,
	_bfd_mmix_finalize_linker_allocated_gregs,
	_bfd_mmix_check_all_relocs): Provide prototypes.

gas/testsuite:
	* gas/mmix/basep-1b.d, gas/mmix/basep-2b.d, gas/mmix/basep-7.d,
	gas/mmix/err-bpo2.s, gas/mmix/basep-3b.d, gas/mmix/err-bpo3.s,
	gas/mmix/basep-4.d, gas/mmix/err-bpo4.s, gas/mmix/err-bpo5.s,
	gas/mmix/basep-5.d, gas/mmix/basep-6.d: New tests.

ld/testsuite:
	* ld-mmix/bpo-1.d, ld-mmix/bpo-1.s, ld-mmix/bpo-1m.d,
	ld-mmix/bpo-15.d, ld-mmix/bpo-4.s, ld-mmix/bpo-6.d,
	ld-mmix/bpo-6.s, ld-mmix/bpo-2.d, ld-mmix/bpo-6m.d,
	ld-mmix/bpo-12m.d, ld-mmix/bpo-2m.d, ld-mmix/bpo-2.s,
	ld-mmix/bpo-5.s, ld-mmix/bpo-3.d, ld-mmix/start3.s,
	ld-mmix/bpo-3m.d, ld-mmix/bpo-9m.d, ld-mmix/bpo-4.d,
	ld-mmix/bpo-3.s, ld-mmix/bpo-4m.d, ld-mmix/bpo-7.d,
	ld-mmix/bpo-5.d, ld-mmix/bpo-16.d, ld-mmix/bpo-5m.d,
	ld-mmix/bpo-7m.d, ld-mmix/bpo-9.d, ld-mmix/bpo-8.d,
	ld-mmix/start4.s, ld-mmix/bpo-8m.d, ld-mmix/bpo-13m.d,
	ld-mmix/bpo-15m.d, ld-mmix/bpo-10.d, ld-mmix/bpo-11.d,
	ld-mmix/bpo-14m.d, ld-mmix/bpo-13.d, ld-mmix/bpo-7.s,
	ld-mmix/bpo-12.d, ld-mmix/bpo-16m.d, ld-mmix/bpo-14.d,
	ld-mmix/bpo-8.s, ld-mmix/bpo-17.d, ld-mmix/bpo-17m.d: New tests.

Index: config/tc-mmix.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mmix.c,v
retrieving revision 1.3
diff -p -c -r1.3 tc-mmix.c
*** tc-mmix.c	2002/01/05 13:13:18	1.3
--- tc-mmix.c	2002/02/01 07:19:52
***************
*** 1,5 ****
  /* tc-mmix.c -- Assembler for Don Knuth's MMIX.
!    Copyright (C) 2001 Free Software Foundation.

     This file is part of GAS, the GNU Assembler.

--- 1,5 ----
  /* tc-mmix.c -- Assembler for Don Knuth's MMIX.
!    Copyright (C) 2001, 2002 Free Software Foundation.

     This file is part of GAS, the GNU Assembler.

*************** static int warn_on_expansion = 1;
*** 154,164 ****
  /* Should we merge non-zero GREG register definitions?  */
  static int merge_gregs = 1;

  /* Should we emit built-in symbols?  */
  static int predefined_syms = 1;

! /* Should we anything but the listed special register name (e.g. equated
!    symbols)?  */
  static int equated_spec_regs = 1;

  /* Do we require standard GNU syntax?  */
--- 154,168 ----
  /* Should we merge non-zero GREG register definitions?  */
  static int merge_gregs = 1;

+ /* Should we pass on undefined BFD_RELOC_MMIX_BASE_PLUS_OFFSET relocs
+    (missing suitable GREG definitions) to the linker?  */
+ static int allocate_undefined_gregs_in_linker = 0;
+
  /* Should we emit built-in symbols?  */
  static int predefined_syms = 1;

! /* Should we allow anything but the listed special register name
!    (e.g. equated symbols)?  */
  static int equated_spec_regs = 1;

  /* Do we require standard GNU syntax?  */
*************** struct option md_longopts[] =
*** 185,190 ****
--- 189,195 ----
  #define OPTION_GNU_SYNTAX  (OPTION_NOSYMS + 1)
  #define OPTION_GLOBALIZE_SYMBOLS  (OPTION_GNU_SYNTAX + 1)
  #define OPTION_FIXED_SPEC_REGS  (OPTION_GLOBALIZE_SYMBOLS + 1)
+ #define OPTION_LINKER_ALLOCATED_GREGS  (OPTION_FIXED_SPEC_REGS + 1)
     {"linkrelax", no_argument, NULL, OPTION_RELAX},
     {"no-expand", no_argument, NULL, OPTION_NOEXPAND},
     {"no-merge-gregs", no_argument, NULL, OPTION_NOMERGEGREG},
*************** struct option md_longopts[] =
*** 193,198 ****
--- 198,205 ----
     {"globalize-symbols", no_argument, NULL, OPTION_GLOBALIZE_SYMBOLS},
     {"fixed-special-register-names", no_argument, NULL,
      OPTION_FIXED_SPEC_REGS},
+    {"linker-allocated-gregs", no_argument, NULL,
+     OPTION_LINKER_ALLOCATED_GREGS},
     {NULL, no_argument, NULL, 0}
   };

*************** md_parse_option (c, arg)
*** 621,626 ****
--- 628,634 ----
      {
      case 'x':
        warn_on_expansion = 0;
+       allocate_undefined_gregs_in_linker = 1;
        break;

      case OPTION_RELAX:
*************** md_parse_option (c, arg)
*** 653,658 ****
--- 661,670 ----
        equated_spec_regs = 0;
        break;

+     case OPTION_LINKER_ALLOCATED_GREGS:
+       allocate_undefined_gregs_in_linker = 1;
+       break;
+
      default:
        return 0;
      }
*************** md_show_usage (stream)
*** 685,693 ****
    fprintf (stream, _("\
    -no-merge-gregs         Do not merge GREG definitions with nearby values.\n"));
    fprintf (stream, _("\
    -x                      Do not warn when an operand to GETA, a branch,\n\
                            PUSHJ or JUMP is not known to be within range.\n\
!                           The linker will catch any errors.\n"));
  }

  /* Step to end of line, but don't step over the end of the line.  */
--- 697,709 ----
    fprintf (stream, _("\
    -no-merge-gregs         Do not merge GREG definitions with nearby values.\n"));
    fprintf (stream, _("\
+   -linker-allocated-gregs If there's no suitable GREG definition for the\
+                           operands of an instruction, let the linker resolve.\n"));
+   fprintf (stream, _("\
    -x                      Do not warn when an operand to GETA, a branch,\n\
                            PUSHJ or JUMP is not known to be within range.\n\
!                           The linker will catch any errors.  Implies\n\
!                           -linker-allocated-gregs."));
  }

  /* Step to end of line, but don't step over the end of the line.  */
*************** md_assemble (str)
*** 1031,1040 ****
        current_fb_label = -1;
      }

!   /* We also assume that the length of the instruction is determinable
!      from the first format character.  Currently *all* the information is
!      in the first character.  We need a self-contained frag since we want
!      the relocation to point to the instruction, not the variant part.  */

    opcodep = frag_more (4);
    mmix_opcode_frag = opc_fragP = frag_now;
--- 1047,1056 ----
        current_fb_label = -1;
      }

!   /* We also assume that the length of the instruction is at least 4, the
!      size of an unexpanded instruction.  We need a self-contained frag
!      since we want the relocation to point to the instruction, not the
!      variant part.  */

    opcodep = frag_more (4);
    mmix_opcode_frag = opc_fragP = frag_now;
*************** tc_gen_reloc (section, fixP)
*** 2577,2584 ****
    char *buf  = fixP->fx_where + fixP->fx_frag->fr_literal;
    symbolS *addsy = fixP->fx_addsy;
    asection *addsec = addsy == NULL ? NULL : S_GET_SEGMENT (addsy);
-   bfd_vma addend = fixP->fx_offset;
    asymbol *baddsy = addsy != NULL ? symbol_get_bfdsym (addsy) : NULL;

    /* A single " LOCAL expression" in the wrong section will not work when
       linking to MMO; relocations for zero-content sections are then
--- 2593,2600 ----
    char *buf  = fixP->fx_where + fixP->fx_frag->fr_literal;
    symbolS *addsy = fixP->fx_addsy;
    asection *addsec = addsy == NULL ? NULL : S_GET_SEGMENT (addsy);
    asymbol *baddsy = addsy != NULL ? symbol_get_bfdsym (addsy) : NULL;
+   bfd_vma addend = val - (baddsy == NULL ? 0 : bfd_asymbol_value (baddsy));

    /* A single " LOCAL expression" in the wrong section will not work when
       linking to MMO; relocations for zero-content sections are then
*************** tc_gen_reloc (section, fixP)
*** 2608,2615 ****
      case BFD_RELOC_8:
        code = fixP->fx_r_type;

!       if (addsy == NULL
! 	  || bfd_is_abs_section (S_GET_SEGMENT (addsy)))
  	{
  	  /* Resolve this reloc now, as md_apply_fix3 would have done (not
  	     called if -linkrelax).  There is no point in keeping a reloc
--- 2624,2630 ----
      case BFD_RELOC_8:
        code = fixP->fx_r_type;

!       if (addsy == NULL || bfd_is_abs_section (addsec))
  	{
  	  /* Resolve this reloc now, as md_apply_fix3 would have done (not
  	     called if -linkrelax).  There is no point in keeping a reloc
*************** tc_gen_reloc (section, fixP)
*** 2658,2664 ****
  	 register contents section (that is, to a register), then we can't
  	 resolve the relocation here.  */
        if (addsy != NULL
! 	  && (bfd_is_und_section (S_GET_SEGMENT (addsy))
  	      || strcmp (bfd_get_section_name (addsec->owner, addsec),
  			 MMIX_REG_CONTENTS_SECTION_NAME) == 0))
  	{
--- 2673,2679 ----
  	 register contents section (that is, to a register), then we can't
  	 resolve the relocation here.  */
        if (addsy != NULL
! 	  && (bfd_is_und_section (addsec)
  	      || strcmp (bfd_get_section_name (addsec->owner, addsec),
  			 MMIX_REG_CONTENTS_SECTION_NAME) == 0))
  	{
*************** tc_gen_reloc (section, fixP)
*** 2672,2685 ****
  	  && (S_GET_SEGMENT (addsy) != real_reg_section
  	      || val > 255
  	      || val < 0)
! 	  && ! bfd_is_abs_section (S_GET_SEGMENT (addsy)))
  	goto badop;

        /* Set the "immediate" bit of the insn if this relocation is to Z
  	 field when the value is a numeric value, i.e. not a register.  */
        if ((fixP->fx_where & 3) == 3
! 	  && (addsy == NULL
! 	      || S_GET_SEGMENT (addsy) == absolute_section))
  	buf[-3] |= IMM_OFFSET_BIT;

        buf[0] = val;
--- 2687,2699 ----
  	  && (S_GET_SEGMENT (addsy) != real_reg_section
  	      || val > 255
  	      || val < 0)
! 	  && ! bfd_is_abs_section (addsec))
  	goto badop;

        /* Set the "immediate" bit of the insn if this relocation is to Z
  	 field when the value is a numeric value, i.e. not a register.  */
        if ((fixP->fx_where & 3) == 3
! 	  && (addsy == NULL || bfd_is_abs_section (addsec)))
  	buf[-3] |= IMM_OFFSET_BIT;

        buf[0] = val;
*************** tc_gen_reloc (section, fixP)
*** 2687,2694 ****

      case BFD_RELOC_MMIX_BASE_PLUS_OFFSET:
        if (addsy != NULL
! 	  &&  strcmp (bfd_get_section_name (addsec->owner, addsec),
! 		      MMIX_REG_CONTENTS_SECTION_NAME) == 0)
  	{
  	  /* This changed into a register; the relocation is for the
  	     register-contents section.  The constant part remains zero.  */
--- 2701,2708 ----

      case BFD_RELOC_MMIX_BASE_PLUS_OFFSET:
        if (addsy != NULL
! 	  && strcmp (bfd_get_section_name (addsec->owner, addsec),
! 		     MMIX_REG_CONTENTS_SECTION_NAME) == 0)
  	{
  	  /* This changed into a register; the relocation is for the
  	     register-contents section.  The constant part remains zero.  */
*************** tc_gen_reloc (section, fixP)
*** 2701,2716 ****

  	 If we encounter any other defined symbol, then we must find a
  	 suitable register and emit a reloc.  */
!       if (addsy == NULL
! 	  || S_GET_SEGMENT (addsy) != real_reg_section)
  	{
  	  struct mmix_symbol_gregs *gregs;
  	  struct mmix_symbol_greg_fixes *fix;

  	  if (S_IS_DEFINED (addsy))
  	    {
! 	      if (! symbol_section_p (addsy)
! 		  && ! bfd_is_abs_section (S_GET_SEGMENT (addsy)))
  		as_fatal (_("internal: BFD_RELOC_MMIX_BASE_PLUS_OFFSET not resolved to section"));

  	      /* If this is an absolute symbol sufficiently near
--- 2715,2728 ----

  	 If we encounter any other defined symbol, then we must find a
  	 suitable register and emit a reloc.  */
!       if (addsy == NULL || addsec != real_reg_section)
  	{
  	  struct mmix_symbol_gregs *gregs;
  	  struct mmix_symbol_greg_fixes *fix;

  	  if (S_IS_DEFINED (addsy))
  	    {
! 	      if (! symbol_section_p (addsy) && ! bfd_is_abs_section (addsec))
  		as_fatal (_("internal: BFD_RELOC_MMIX_BASE_PLUS_OFFSET not resolved to section"));

  	      /* If this is an absolute symbol sufficiently near
*************** tc_gen_reloc (section, fixP)
*** 2720,2726 ****
  		 comparisons.  */
  	      if (lowest_data_loc != (bfd_vma) -1
  		  && (bfd_vma) val + 256 > lowest_data_loc
! 		  && bfd_is_abs_section (S_GET_SEGMENT (addsy)))
  		{
  		  val -= (offsetT) lowest_data_loc;
  		  addsy = section_symbol (data_section);
--- 2732,2738 ----
  		 comparisons.  */
  	      if (lowest_data_loc != (bfd_vma) -1
  		  && (bfd_vma) val + 256 > lowest_data_loc
! 		  && bfd_is_abs_section (addsec))
  		{
  		  val -= (offsetT) lowest_data_loc;
  		  addsy = section_symbol (data_section);
*************** tc_gen_reloc (section, fixP)
*** 2728,2734 ****
  	      /* Likewise text section.  */
  	      else if (lowest_text_loc != (bfd_vma) -1
  		       && (bfd_vma) val + 256 > lowest_text_loc
! 		       && bfd_is_abs_section (S_GET_SEGMENT (addsy)))
  		{
  		  val -= (offsetT) lowest_text_loc;
  		  addsy = section_symbol (text_section);
--- 2740,2746 ----
  	      /* Likewise text section.  */
  	      else if (lowest_text_loc != (bfd_vma) -1
  		       && (bfd_vma) val + 256 > lowest_text_loc
! 		       && bfd_is_abs_section (addsec))
  		{
  		  val -= (offsetT) lowest_text_loc;
  		  addsy = section_symbol (text_section);
*************** tc_gen_reloc (section, fixP)
*** 2738,2745 ****
  	  gregs = *symbol_get_tc (addsy);

  	  /* If that symbol does not have any associated GREG definitions,
! 	     we can't do anything.  FIXME: implement allocate-on-demand in
! 	     the linker.  */
  	  if (gregs == NULL
  	      || (fix = bsearch (&val, gregs->greg_fixes, gregs->n_gregs,
  				 sizeof (gregs->greg_fixes[0]),
--- 2750,2756 ----
  	  gregs = *symbol_get_tc (addsy);

  	  /* If that symbol does not have any associated GREG definitions,
! 	     we can't do anything.  */
  	  if (gregs == NULL
  	      || (fix = bsearch (&val, gregs->greg_fixes, gregs->n_gregs,
  				 sizeof (gregs->greg_fixes[0]),
*************** tc_gen_reloc (section, fixP)
*** 2750,2757 ****
  		 before the address we want.  */
  	      || fix->offs + 255 < val)
  	    {
! 	      as_bad_where (fixP->fx_file, fixP->fx_line,
! 			    _("no suitable GREG definition for operands"));
  	      return NULL;
  	    }
  	  else
--- 2761,2777 ----
  		 before the address we want.  */
  	      || fix->offs + 255 < val)
  	    {
! 	      /* We can either let the linker allocate GREGs
! 		 automatically, or emit an error.  */
! 	      if (allocate_undefined_gregs_in_linker)
! 		{
! 		  /* The values in baddsy and addend are right.  */
! 		  code = fixP->fx_r_type;
! 		  break;
! 		}
! 	      else
! 		as_bad_where (fixP->fx_file, fixP->fx_line,
! 			      _("no suitable GREG definition for operands"));
  	      return NULL;
  	    }
  	  else
*************** tc_gen_reloc (section, fixP)
*** 2781,2787 ****

      case BFD_RELOC_MMIX_REG:
        if (addsy != NULL
! 	  && (bfd_is_und_section (S_GET_SEGMENT (addsy))
  	      || strcmp (bfd_get_section_name (addsec->owner, addsec),
  			 MMIX_REG_CONTENTS_SECTION_NAME) == 0))
  	{
--- 2801,2807 ----

      case BFD_RELOC_MMIX_REG:
        if (addsy != NULL
! 	  && (bfd_is_und_section (addsec)
  	      || strcmp (bfd_get_section_name (addsec->owner, addsec),
  			 MMIX_REG_CONTENTS_SECTION_NAME) == 0))
  	{
*************** tc_gen_reloc (section, fixP)
*** 2790,2799 ****
  	}

        if (addsy != NULL
! 	  && (S_GET_SEGMENT (addsy) != real_reg_section
  	      || val > 255
  	      || val < 0)
! 	  && ! bfd_is_und_section (S_GET_SEGMENT (addsy)))
  	/* Drop through to error message.  */
  	;
        else
--- 2810,2819 ----
  	}

        if (addsy != NULL
! 	  && (addsec != real_reg_section
  	      || val > 255
  	      || val < 0)
! 	  && ! bfd_is_und_section (addsec))
  	/* Drop through to error message.  */
  	;
        else
Index: config/tc-mmix.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mmix.h,v
retrieving revision 1.2
diff -p -c -r1.2 tc-mmix.h
*** tc-mmix.h	2001/11/15 21:28:57	1.2
--- tc-mmix.h	2002/02/01 07:19:52
***************
*** 1,5 ****
  /* tc-mmix.h -- Header file for tc-mmix.c.
!    Copyright (C) 2001 Free Software Foundation, Inc.
     Written by Hans-Peter Nilsson (hp@bitrange.com).

     This file is part of GAS, the GNU Assembler.
--- 1,5 ----
  /* tc-mmix.h -- Header file for tc-mmix.c.
!    Copyright (C) 2001, 2002 Free Software Foundation, Inc.
     Written by Hans-Peter Nilsson (hp@bitrange.com).

     This file is part of GAS, the GNU Assembler.
*************** extern int mmix_gnu_syntax;
*** 75,81 ****
    && (name[0] == '@'						\
        ? (! is_part_of_name (name[1])				\
  	 && mmix_current_location (current_location, exp))	\
!       : ((name[0] == ':' || isupper (name[0]))			\
  	 && mmix_parse_predefined_name (name, exp))))

  extern char *mmix_prefix_name PARAMS ((char *));
--- 75,81 ----
    && (name[0] == '@'						\
        ? (! is_part_of_name (name[1])				\
  	 && mmix_current_location (current_location, exp))	\
!       : ((name[0] == ':' || ISUPPER (name[0]))			\
  	 && mmix_parse_predefined_name (name, exp))))

  extern char *mmix_prefix_name PARAMS ((char *));
Index: doc/c-mmix.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-mmix.texi,v
retrieving revision 1.2
diff -p -c -r1.2 c-mmix.texi
*** c-mmix.texi	2001/11/19 01:19:07	1.2
--- c-mmix.texi	2002/02/01 07:47:06
***************
*** 1,4 ****
! @c Copyright 2001 Free Software Foundation, Inc.
  @c This is part of the GAS manual.
  @c For copying conditions, see the file as.texinfo.
  @c MMIX description by Hans-Peter Nilsson, hp@bitrange.com
--- 1,4 ----
! @c Copyright 2001, 2002 Free Software Foundation, Inc.
  @c This is part of the GAS manual.
  @c For copying conditions, see the file as.texinfo.
  @c MMIX description by Hans-Peter Nilsson, hp@bitrange.com
*************** is specified, and assembly fails otherwi
*** 79,86 ****
  be expanded.  It needs to be kept in mind that @code{mmixal} is both an
  assembler and linker, while @code{@value{AS}} will expand instructions
  that at link stage can be contracted.  (Though linker relaxation isn't yet
! implemented in @code{@value{LD}}.)

  @node MMIX-Expand
  @section Instruction expansion

--- 79,94 ----
  be expanded.  It needs to be kept in mind that @code{mmixal} is both an
  assembler and linker, while @code{@value{AS}} will expand instructions
  that at link stage can be contracted.  (Though linker relaxation isn't yet
! implemented in @code{@value{LD}}.)  The option @samp{-x} also imples
! @samp{--linker-allocated-gregs}.

+ @cindex @samp{--linker-allocated-gregs} command line option, MMIX
+ Usually a two-operand-expression (@pxref{GREG-base}) without a matching
+ @samp{GREG} directive is treated as an error by @code{@value{AS}}.  When
+ the option @samp{--linker-allocated-gregs} is in effect, they are instead
+ passed through to the linker, which will allocate as many global registers
+ as is needed.
+
  @node MMIX-Expand
  @section Instruction expansion

*************** Global registers allocated with this dir
*** 381,387 ****
  higher-to-lower within a file.  Other than that, the exact order of
  register allocation and elimination is undefined.  For example, the order
  is undefined when more than one file with such directives are linked
! together.

  @item BYTE
  @cindex assembler directive BYTE, MMIX
--- 389,398 ----
  higher-to-lower within a file.  Other than that, the exact order of
  register allocation and elimination is undefined.  For example, the order
  is undefined when more than one file with such directives are linked
! together.  With the options @samp{-x} and @samp{--linker-allocated-gregs},
! @samp{GREG} directives for two-operand cases like the one mentioned above
! can be omitted.  Sufficient global registers will then be allocated by the
! linker.

  @item BYTE
  @cindex assembler directive BYTE, MMIX
*************** upper-case characters.
*** 544,553 ****

  There's no unicode support.

! The following is a list of programs in
! @url{http://www-cs-faculty.stanford.edu/~knuth/mmix-news.html} dated
! 2001-08-25 (md5sum c393470cfc86fac040487d22d2bf0172) that assemble with
! @code{mmixal} but do not assemble with @code{@value{AS}}:

  @table @code
  @item silly.mms
--- 555,565 ----

  There's no unicode support.

! The following is a list of programs in @samp{mmix.tar.gz}, available at
! @url{http://www-cs-faculty.stanford.edu/~knuth/mmix-news.html}, last
! checked with the version dated 2001-08-25 (md5sum
! c393470cfc86fac040487d22d2bf0172) that assemble with @code{mmixal} but do
! not assemble with @code{@value{AS}}:

  @table @code
  @item silly.mms
Index: doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.52
diff -p -c -r1.52 as.texinfo
*** as.texinfo	2002/01/21 00:20:58	1.52
--- as.texinfo	2002/02/01 07:48:34
***************
*** 1,6 ****
  \input texinfo @c                               -*-Texinfo-*-
  @c  Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
! @c  2001
  @c  Free Software Foundation, Inc.
  @c UPDATE!!  On future updates--
  @c   (1)   check for new machine-dep cmdline options in
--- 1,6 ----
  \input texinfo @c                               -*-Texinfo-*-
  @c  Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
! @c  2001, 2002
  @c  Free Software Foundation, Inc.
  @c UPDATE!!  On future updates--
  @c   (1)   check for new machine-dep cmdline options in
*************** END-INFO-DIR-ENTRY
*** 127,133 ****
  This file documents the GNU Assembler "@value{AS}".

  @c man begin COPYRIGHT
! Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc.

  Permission is granted to copy, distribute and/or modify this document
  under the terms of the GNU Free Documentation License, Version 1.1
--- 127,133 ----
  This file documents the GNU Assembler "@value{AS}".

  @c man begin COPYRIGHT
! Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002 Free Software Foundation, Inc.

  Permission is granted to copy, distribute and/or modify this document
  under the terms of the GNU Free Documentation License, Version 1.1
*************** done.
*** 180,186 ****
  @end tex

  @vskip 0pt plus 1filll
! Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc.

        Permission is granted to copy, distribute and/or modify this document
        under the terms of the GNU Free Documentation License, Version 1.1
--- 180,186 ----
  @end tex

  @vskip 0pt plus 1filll
! Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002 Free Software Foundation, Inc.

        Permission is granted to copy, distribute and/or modify this document
        under the terms of the GNU Free Documentation License, Version 1.1
*************** gcc(1), ld(1), and the Info entries for
*** 354,359 ****
--- 354,360 ----
     [@b{--fixed-special-register-names}] [@b{--globalize-symbols}]
     [@b{--gnu-syntax}] [@b{--relax}] [@b{--no-predefined-symbols}]
     [@b{--no-expand}] [@b{--no-merge-gregs}] [@b{-x}]
+    [@b{--linker-allocated-gregs}]
  @end ifset
  @ifset PDP11

Index: emultempl/mmix-elfnmmo.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/mmix-elfnmmo.em,v
retrieving revision 1.1
diff -p -c -r1.1 mmix-elfnmmo.em
*** mmix-elfnmmo.em	2001/10/30 15:20:11	1.1
--- mmix-elfnmmo.em	2002/02/01 07:44:55
***************
*** 1,5 ****
  # This shell script emits a C file. -*- C -*-
! #   Copyright 2001 Free Software Foundation, Inc.
  #
  # This file is part of GLD, the Gnu Linker.
  #
--- 1,5 ----
  # This shell script emits a C file. -*- C -*-
! #   Copyright 2001, 2002 Free Software Foundation, Inc.
  #
  # This file is part of GLD, the Gnu Linker.
  #
***************
*** 24,36 ****
  cat >>e${EMULATION_NAME}.c <<EOF
  #include "elf/mmix.h"

! static void mmix_set_reg_section_vma PARAMS ((void));

  /* We need to set the VMA of the .MMIX.reg_contents section when it has
!    been allocated.  */

  static void
! mmix_set_reg_section_vma ()
  {
    asection *sec
      = bfd_get_section_by_name (output_bfd, MMIX_REG_CONTENTS_SECTION_NAME);
--- 24,61 ----
  cat >>e${EMULATION_NAME}.c <<EOF
  #include "elf/mmix.h"

! static void mmix_before_allocation PARAMS ((void));
! static void mmix_after_allocation PARAMS ((void));

+ /* Set up handling of linker-allocated global registers.  */
+
+ static void
+ mmix_before_allocation ()
+ {
+   /* Call the default first.  */
+   gld${EMULATION_NAME}_before_allocation ();
+
+   /* There's a needrelax.em which uses this ..._before_allocation-hook and
+      just has the statement below as payload.  It's more of a hassle to
+      use that than to just include these two lines and take the
+      maintenance burden to keep them in sync.  (Of course we lose the
+      maintenance burden of checking that it still does what we need.)  */
+
+   /* Force -relax on if not doing a relocatable link.  */
+   if (! link_info.relocateable)
+     command_line.relax = true;
+
+   if (!_bfd_mmix_prepare_linker_allocated_gregs (output_bfd, &link_info))
+     einfo ("%X%P: Internal problems setting up section %s",
+ 	   MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ }
+
  /* We need to set the VMA of the .MMIX.reg_contents section when it has
!    been allocated, and produce the final settings for the linker-generated
!    GREGs.  */

  static void
! mmix_after_allocation ()
  {
    asection *sec
      = bfd_get_section_by_name (output_bfd, MMIX_REG_CONTENTS_SECTION_NAME);
*************** mmix_set_reg_section_vma ()
*** 61,74 ****
      }

    /* Simplify symbol output for the register section (without contents;
!      created for register symbols) by setting the output offset to 0.  */
    sec = bfd_get_section_by_name (output_bfd, MMIX_REG_SECTION_NAME);
!   if (sec == NULL)
!     return;
!
!   bfd_set_section_vma (abfd, sec, 0);

  }
  EOF

! LDEMUL_AFTER_ALLOCATION=mmix_set_reg_section_vma
--- 86,105 ----
      }

    /* Simplify symbol output for the register section (without contents;
!      created for register symbols) by setting the output offset to 0.
!      This section is only present when there are register symbols.  */
    sec = bfd_get_section_by_name (output_bfd, MMIX_REG_SECTION_NAME);
!   if (sec != NULL)
!     bfd_set_section_vma (abfd, sec, 0);

+   if (!_bfd_mmix_finalize_linker_allocated_gregs (output_bfd, &link_info))
+     {
+       einfo ("%X%P: Can't finalize linker-allocated global registers\n");
+       /* In case stuff is added after this conditional.  */
+       return;
+     }
  }
  EOF

! LDEMUL_AFTER_ALLOCATION=mmix_after_allocation
! LDEMUL_BEFORE_ALLOCATION=mmix_before_allocation
Index: emultempl/mmo.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/mmo.em,v
retrieving revision 1.3
diff -p -c -r1.3 mmo.em
*** mmo.em	2002/01/05 13:14:00	1.3
--- mmo.em	2002/02/01 07:50:10
***************
*** 1,5 ****
  # This shell script emits a C file. -*- C -*-
! #   Copyright 2001 Free Software Foundation, Inc.
  #
  # This file is part of GLD, the Gnu Linker.
  #
--- 1,5 ----
  # This shell script emits a C file. -*- C -*-
! #   Copyright 2001, 2002 Free Software Foundation, Inc.
  #
  # This file is part of GLD, the Gnu Linker.
  #
***************
*** 21,26 ****
--- 21,33 ----
  # This file is sourced from elf32.em and mmo.em, used to define
  # linker MMIX-specifics common to ELF and MMO.

+ cat >>e${EMULATION_NAME}.c <<EOF
+ /* Need to have this define before mmix-elfnmmo, which includes
+    needrelax.em which uses this name for the before_allocation function,
+    normally defined in elf32.em.  */
+ #define gldmmo_before_allocation before_allocation_default
+ EOF
+
  . ${srcdir}/emultempl/mmix-elfnmmo.em

  cat >>e${EMULATION_NAME}.c <<EOF
*************** static asection *output_prev_sec_find
*** 31,36 ****
--- 38,44 ----
    PARAMS ((lang_output_section_statement_type *));
  static void mmo_finish PARAMS ((void));
  static void mmo_wipe_sec_reloc_flag PARAMS ((bfd *, asection *, PTR));
+ static void mmo_after_open PARAMS ((void));

  /* Find the last output section before given output statement.
     Used by place_orphan.  */
*************** mmo_finish ()
*** 220,227 ****
--- 228,253 ----
  {
    bfd_map_over_sections (output_bfd, mmo_wipe_sec_reloc_flag, NULL);
  }
+
+ /* To get on-demand global register allocation right, we need to parse the
+    relocs, like what happens when linking to ELF.  It needs to be done
+    before all input sections are supposed to be present.  When linking to
+    ELF, it's done when reading symbols.  When linking to mmo, we do it
+    when all input files are seen, which is equivalent.  */

+ static void
+ mmo_after_open ()
+ {
+   LANG_FOR_EACH_INPUT_STATEMENT (is)
+     {
+       if (bfd_get_flavour (is->the_bfd) == bfd_target_elf_flavour
+ 	  && !_bfd_mmix_check_all_relocs (is->the_bfd, &link_info))
+ 	einfo ("%X%P: Internal problems scanning %B after opening it",
+ 	       is->the_bfd);
+     }
+ }
  EOF

  LDEMUL_PLACE_ORPHAN=mmo_place_orphan
  LDEMUL_FINISH=mmo_finish
+ LDEMUL_AFTER_OPEN=mmo_after_open
Index: scripttempl/mmo.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/mmo.sc,v
retrieving revision 1.2
diff -p -c -r1.2 mmo.sc
*** mmo.sc	2001/12/16 12:23:01	1.2
--- mmo.sc	2002/02/01 07:44:56
*************** SECTIONS
*** 16,27 ****
      /* FIXME: Move .init, .fini, .ctors and .dtors to their own sections.  */
      ${RELOCATING+ PROVIDE (_init_start = .);}
      ${RELOCATING+ PROVIDE (_init = .);}
!     ${RELOCATING+ *(.init)}
      ${RELOCATING+ PROVIDE (_init_end = .);}

      ${RELOCATING+ PROVIDE (_fini_start = .);}
      ${RELOCATING+ PROVIDE (_fini = .);}
!     ${RELOCATING+ *(.fini)}
      ${RELOCATING+ PROVIDE (_fini_end = .);}

      /* FIXME: Align ctors, dtors, ehframe.  */
--- 16,27 ----
      /* FIXME: Move .init, .fini, .ctors and .dtors to their own sections.  */
      ${RELOCATING+ PROVIDE (_init_start = .);}
      ${RELOCATING+ PROVIDE (_init = .);}
!     ${RELOCATING+ KEEP (*(.init))}
      ${RELOCATING+ PROVIDE (_init_end = .);}

      ${RELOCATING+ PROVIDE (_fini_start = .);}
      ${RELOCATING+ PROVIDE (_fini = .);}
!     ${RELOCATING+ KEEP (*(.fini))}
      ${RELOCATING+ PROVIDE (_fini_end = .);}

      /* FIXME: Align ctors, dtors, ehframe.  */
*************** SECTIONS
*** 115,120 ****
--- 115,121 ----
    {
      /* Note that this section always has a fixed VMA - that of its
         first register * 8.  */
+     *(.MMIX.reg_contents.linker_allocated);
      *(.MMIX.reg_contents);
    }

Index: emulparams/elf64mmix.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf64mmix.sh,v
retrieving revision 1.2
diff -p -c -r1.2 elf64mmix.sh
*** elf64mmix.sh	2001/11/22 09:08:04	1.2
--- elf64mmix.sh	2002/02/01 07:44:56
*************** OTHER_TEXT_SECTIONS='
*** 44,57 ****
   PROVIDE (Main = DEFINED (Main) ? Main : (DEFINED (_start) ? _start : _start.));
  '

! OTHER_SECTIONS="
   .MMIX.reg_contents :
   {
     /* Note that this section always has a fixed VMA - that of its
        first register * 8.  */
     *(.MMIX.reg_contents);
   }
! "

  # FIXME: Also bit by the PROVIDE bug?  If not, this could be
  # EXECUTABLE_SYMBOLS.
--- 44,58 ----
   PROVIDE (Main = DEFINED (Main) ? Main : (DEFINED (_start) ? _start : _start.));
  '

! OTHER_SECTIONS='
   .MMIX.reg_contents :
   {
     /* Note that this section always has a fixed VMA - that of its
        first register * 8.  */
+    *(.MMIX.reg_contents.linker_allocated);
     *(.MMIX.reg_contents);
   }
! '

  # FIXME: Also bit by the PROVIDE bug?  If not, this could be
  # EXECUTABLE_SYMBOLS.
Index: elf64-mmix.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-mmix.c,v
retrieving revision 1.7
diff -p -c -r1.7 elf64-mmix.c
*** elf64-mmix.c	2002/01/30 16:07:28	1.7
--- elf64-mmix.c	2002/02/01 07:24:00
*************** Foundation, Inc., 59 Temple Place - Suit
*** 21,28 ****
  /* No specific ABI or "processor-specific supplement" defined.  */

  /* TODO:
!    - Linker relaxation.
!    - On-demand register allocation (from R_MMIX_BASE_PLUS_OFFSET).  */

  #include "bfd.h"
  #include "sysdep.h"
--- 21,27 ----
  /* No specific ABI or "processor-specific supplement" defined.  */

  /* TODO:
!    - Linker relaxation.  */

  #include "bfd.h"
  #include "sysdep.h"
*************** Foundation, Inc., 59 Temple Place - Suit
*** 42,47 ****
--- 41,125 ----
   _bfd_abort (__FILE__, __LINE__,		\
  	     "bad case for " #x)

+ /* For each section containing a base-plus-offset (BPO) reloc, we attach
+    this struct as elf_section_data (section)->tdata, which is otherwise
+    NULL.  */
+ struct bpo_reloc_section_info
+   {
+     /* The base is 1; this is the first number in this section.  */
+     size_t first_base_plus_offset_reloc;
+
+     /* Number of BPO-relocs in this section.  */
+     size_t n_bpo_relocs_this_section;
+
+     /* Running index, used at relocation time.  */
+     size_t bpo_index;
+
+     /* We don't have access to the bfd_link_info struct in
+        mmix_final_link_relocate.  What we really want to get at is the
+        global single struct greg_relocation, so we stash it here.  */
+     asection *bpo_greg_section;
+   };
+
+ /* Helper struct (in global context) for the one below.
+    There's one of these created for every BPO reloc.  */
+ struct bpo_reloc_request
+   {
+     bfd_vma value;
+
+     /* Valid after relaxation.  The base is 0; the first register number
+        must be added.  The offset is in range 0..255.  */
+     size_t regindex;
+     size_t offset;
+
+     /* The order number for this BPO reloc, corresponding to the order in
+        which BPO relocs were found.  Used to create an index after reloc
+        requests are sorted.  */
+     size_t bpo_reloc_no;
+
+     /* Set when the value is computed.  Better than coding "guard values"
+        into the other members.  Is false only for BPO relocs in a GC:ed
+        section.  */
+     boolean valid;
+   };
+
+ /* We attach this as elf_section_data (sec)->tdata in the linker-allocated
+    greg contents section (MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME),
+    which is linked into the register contents section
+    (MMIX_REG_CONTENTS_SECTION_NAME).  This section is created by the
+    linker; using the same hook as for usual with BPO relocs does not
+    collide.  */
+ struct bpo_greg_section_info
+   {
+     /* After GC, this reflects the number of remaining, non-excluded
+        BPO-relocs.  */
+     size_t n_bpo_relocs;
+
+     /* This is the number of allocated bpo_reloc_requests; the size of
+        sorted_indexes.  Valid after the check.*relocs functions are called
+        for all incoming sections.  It includes the number of BPO relocs in
+        sections that were GC:ed.  */
+     size_t n_max_bpo_relocs;
+
+     /* A counter used to find out when to fold the BPO gregs, since we
+        don't have a single "after-relaxation" hook.  */
+     size_t n_remaining_bpo_relocs_this_relaxation_round;
+
+     /* The number of linker-allocated GREGs resulting from BPO relocs.
+        This is an approximation after _bfd_mmix_allocated_gregs_init and
+        supposedly accurate after mmix_elf_relax_section is called for all
+        incoming non-collected sections.  */
+     size_t n_allocated_bpo_gregs;
+
+     /* Index into reloc_request[], sorted on increasing "value", secondary
+        by increasing index for strict sorting order.  */
+     size_t *bpo_reloc_indexes;
+
+     /* An array of all relocations, with the "value" member filled in by
+        the relaxation function.  */
+     struct bpo_reloc_request *reloc_request;
+   };
+
  static boolean mmix_elf_link_output_symbol_hook
    PARAMS ((bfd *, struct bfd_link_info *, const char *,
  	   Elf_Internal_Sym *, asection *));
*************** static boolean mmix_elf_check_relocs
*** 61,66 ****
--- 139,148 ----
    PARAMS ((bfd *, struct bfd_link_info *, asection *,
  	   const Elf_Internal_Rela *));

+ static boolean mmix_elf_check_common_relocs
+   PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ 	   const Elf_Internal_Rela *));
+
  static boolean mmix_elf_relocate_section
    PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
  	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
*************** static asection * mmix_elf_gc_mark_hook
*** 69,74 ****
--- 151,160 ----
    PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
  	   struct elf_link_hash_entry *, Elf_Internal_Sym *));

+ static boolean mmix_elf_gc_sweep_hook
+   PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ 	   const Elf_Internal_Rela *));
+
  static bfd_reloc_status_type mmix_final_link_relocate
    PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
  	   bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
*************** static boolean mmix_elf_add_symbol_hook
*** 86,91 ****
--- 172,183 ----
  static boolean mmix_elf_is_local_label_name
    PARAMS ((bfd *, const char *));

+ static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR));
+
+ static boolean mmix_elf_relax_section
+   PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
+ 	   boolean *again));
+
  extern boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *));

  extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *));
*************** static reloc_howto_type elf_mmix_howto_t
*** 120,126 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_8",		/* name */
  	 false,			/* partial_inplace */
! 	 0xff,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

--- 212,218 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_8",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 135,141 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_16",		/* name */
  	 false,			/* partial_inplace */
! 	 0xffff,		/* src_mask */
  	 0xffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

--- 227,233 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_16",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 150,156 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_24",		/* name */
  	 false,			/* partial_inplace */
! 	 0xffffff,		/* src_mask */
  	 0xffffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

--- 242,248 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_24",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0xffffff,		/* src_mask */
  	 0xffffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 165,171 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_32",		/* name */
  	 false,			/* partial_inplace */
! 	 0xffffffff,		/* src_mask */
  	 0xffffffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

--- 257,263 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_32",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xffffffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 180,186 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_64",		/* name */
  	 false,			/* partial_inplace */
! 	 MINUS_ONE,		/* src_mask */
  	 MINUS_ONE,		/* dst_mask */
  	 false),		/* pcrel_offset */

--- 272,278 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_64",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 MINUS_ONE,		/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 195,201 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_8",		/* name */
  	 false,			/* partial_inplace */
! 	 0xff,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 true),			/* pcrel_offset */

--- 287,293 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_8",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 210,216 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_16",	/* name */
  	 false,			/* partial_inplace */
! 	 0xffff,		/* src_mask */
  	 0xffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 302,308 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_16",	/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 225,231 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_24",	/* name */
  	 false,			/* partial_inplace */
! 	 0xffffff,		/* src_mask */
  	 0xffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 317,323 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_24",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0xffffff,		/* src_mask */
  	 0xffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 240,246 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_32",	/* name */
  	 false,			/* partial_inplace */
! 	 0xffffffff,		/* src_mask */
  	 0xffffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 332,338 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_32",	/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xffffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 255,261 ****
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_64",	/* name */
  	 false,			/* partial_inplace */
! 	 MINUS_ONE,		/* src_mask */
  	 MINUS_ONE,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 347,353 ----
  	 bfd_elf_generic_reloc,	/* special_function */
  	 "R_MMIX_PC_64",	/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 MINUS_ONE,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 303,309 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA",		/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 395,401 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 317,323 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_1",		/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 409,415 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_1",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 331,337 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_2",		/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 423,429 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_2",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 345,351 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_3",		/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 437,443 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_GETA_3",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 363,369 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),		       	/* pcrel_offset */

--- 455,461 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),		       	/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 377,383 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_J",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 469,475 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_J",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 391,397 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_1",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 483,489 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_1",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 405,411 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_2",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 497,503 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_2",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 419,425 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_3",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 511,517 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_CBRANCH_3",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 438,444 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 530,536 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 452,458 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_1",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 544,550 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_1",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 466,472 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_2",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 558,564 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_2",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 480,486 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_3",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 572,578 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_PUSHJ_3",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 498,504 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP",		/* name */
  	 false,			/* partial_inplace */
! 	 0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 590,596 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP",		/* name */
  	 false,			/* partial_inplace */
! 	 ~0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 512,518 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_1",	/* name */
  	 false,			/* partial_inplace */
! 	 0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 604,610 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_1",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 526,532 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_2",	/* name */
  	 false,			/* partial_inplace */
! 	 0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 618,624 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_2",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 540,546 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_3",	/* name */
  	 false,			/* partial_inplace */
! 	 0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 632,638 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_JMP_3",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 557,563 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_ADDR19",	/* name */
  	 false,			/* partial_inplace */
! 	 0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 649,655 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_ADDR19",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x0100ffff,		/* src_mask */
  	 0x0100ffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 572,578 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_ADDR27",	/* name */
  	 false,			/* partial_inplace */
! 	 0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

--- 664,670 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_ADDR27",	/* name */
  	 false,			/* partial_inplace */
! 	 ~0x1ffffff,		/* src_mask */
  	 0x1ffffff,		/* dst_mask */
  	 true),			/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 588,594 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_REG_OR_BYTE",	/* name */
  	 false,			/* partial_inplace */
! 	 0xff,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

--- 680,686 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_REG_OR_BYTE",	/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 603,609 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_REG",		/* name */
  	 false,			/* partial_inplace */
! 	 0xff,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

--- 695,701 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_REG",		/* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xff,			/* dst_mask */
  	 false),		/* pcrel_offset */

*************** static reloc_howto_type elf_mmix_howto_t
*** 620,626 ****
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_BASE_PLUS_OFFSET", /* name */
  	 false,			/* partial_inplace */
! 	 0xffff,		/* src_mask */
  	 0xffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

--- 712,718 ----
  	 mmix_elf_reloc,	/* special_function */
  	 "R_MMIX_BASE_PLUS_OFFSET", /* name */
  	 false,			/* partial_inplace */
! 	 0,			/* src_mask */
  	 0xffff,		/* dst_mask */
  	 false),		/* pcrel_offset */

*************** mmix_elf_perform_relocation (isec, howto
*** 874,880 ****
  	  value >>= 2;

  	  bfd_put_32 (abfd,
! 		      (in1 & ~howto->src_mask)
  		      | highbit
  		      | (value & howto->dst_mask),
  		      (bfd_byte *) datap);
--- 966,972 ----
  	  value >>= 2;

  	  bfd_put_32 (abfd,
! 		      (in1 & howto->src_mask)
  		      | highbit
  		      | (value & howto->dst_mask),
  		      (bfd_byte *) datap);
*************** mmix_elf_perform_relocation (isec, howto
*** 884,889 ****
--- 976,1023 ----
        else
  	return bfd_reloc_overflow;

+     case R_MMIX_BASE_PLUS_OFFSET:
+       {
+ 	struct bpo_reloc_section_info *bpodata
+ 	  = (struct bpo_reloc_section_info *)
+ 	  elf_section_data (isec)->tdata;
+ 	asection *bpo_greg_section
+ 	  = bpodata->bpo_greg_section;
+ 	struct bpo_greg_section_info *gregdata
+ 	  = (struct bpo_greg_section_info *)
+ 	  elf_section_data (bpo_greg_section)->tdata;
+ 	size_t bpo_index
+ 	  = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
+
+ 	/* A consistency check: The value we now have in "relocation" must
+ 	   be the same as the value we stored for that relocation.  It
+ 	   doesn't cost much, so can be left in at all times.  */
+ 	if (value != gregdata->reloc_request[bpo_index].value)
+ 	  {
+ 	    (*_bfd_error_handler)
+ 	      (_("%s: Internal inconsistency error for value for\n\
+  linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n"),
+ 	       bfd_get_filename (isec->owner),
+ 	       (unsigned long) (value >> 32), (unsigned long) value,
+ 	       (unsigned long) (gregdata->reloc_request[bpo_index].value
+ 				>> 32),
+ 	       (unsigned long) gregdata->reloc_request[bpo_index].value);
+ 	    bfd_set_error (bfd_error_bad_value);
+ 	    return bfd_reloc_overflow;
+ 	  }
+
+ 	/* Then store the register number and offset for that register
+ 	   into datap and datap + 1 respectively.  */
+ 	bfd_put_8 (abfd,
+ 		   gregdata->reloc_request[bpo_index].regindex
+ 		   + bpo_greg_section->output_section->vma / 8,
+ 		   datap);
+ 	bfd_put_8 (abfd,
+ 		   gregdata->reloc_request[bpo_index].offset,
+ 		   ((unsigned char *) datap) + 1);
+ 	return bfd_reloc_ok;
+       }
+
      case R_MMIX_REG_OR_BYTE:
      case R_MMIX_REG:
        if (value > 255)
*************** mmix_final_link_relocate (howto, input_s
*** 1231,1236 ****
--- 1365,1396 ----
  				       addr, srel);
        break;

+     case R_MMIX_BASE_PLUS_OFFSET:
+       if (symsec == NULL)
+ 	return bfd_reloc_undefined;
+
+       /* Check that we're not relocating against a register symbol.  */
+       if (strcmp (bfd_get_section_name (symsec->owner, symsec),
+ 		  MMIX_REG_CONTENTS_SECTION_NAME) == 0
+ 	  || strcmp (bfd_get_section_name (symsec->owner, symsec),
+ 		     MMIX_REG_SECTION_NAME) == 0)
+ 	{
+ 	  /* Note: This is separated out into two messages in order
+ 	     to ease the translation into other languages.  */
+ 	  if (symname == NULL || *symname == 0)
+ 	    (*_bfd_error_handler)
+ 	      (_("%s: base-plus-offset relocation against register symbol: (unknown) in %s"),
+ 	       bfd_get_filename (input_section->owner),
+ 	       bfd_get_section_name (symsec->owner, symsec));
+ 	  else
+ 	    (*_bfd_error_handler)
+ 	      (_("%s: base-plus-offset relocation against register symbol: %s in %s"),
+ 	       bfd_get_filename (input_section->owner), symname,
+ 	       bfd_get_section_name (symsec->owner, symsec));
+ 	  return bfd_reloc_overflow;
+ 	}
+       goto do_mmix_reloc;
+
      case R_MMIX_REG_OR_BYTE:
      case R_MMIX_REG:
        /* For now, we handle these alike.  They must refer to an register
*************** mmix_final_link_relocate (howto, input_s
*** 1264,1270 ****
  	}
        else
  	{
! 	  /* Note: This is seperated out into two messages in order
  	     to ease the translation into other languages.  */
  	  if (symname == NULL || *symname == 0)
  	    (*_bfd_error_handler)
--- 1424,1430 ----
  	}
        else
  	{
! 	  /* Note: This is separated out into two messages in order
  	     to ease the translation into other languages.  */
  	  if (symname == NULL || *symname == 0)
  	    (*_bfd_error_handler)
*************** mmix_final_link_relocate (howto, input_s
*** 1281,1286 ****
--- 1441,1447 ----
  	     better value, will not get us an error.  */
  	  return bfd_reloc_overflow;
  	}
+     do_mmix_reloc:
        contents += r_offset;
        r = mmix_elf_perform_relocation (input_section, howto, contents,
  				       addr, srel);
*************** mmix_elf_gc_mark_hook (abfd, info, rel,
*** 1396,1401 ****
--- 1557,1593 ----

    return NULL;
  }
+
+ /* Update relocation info for a GC-excluded section.  We could supposedly
+    perform the allocation after GC, but there's no suitable hook between
+    GC (or section merge) and the point when all input sections must be
+    present.  Better to waste some memory and (perhaps) a little time.  */
+
+ static boolean
+ mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      struct bfd_link_info *info ATTRIBUTE_UNUSED;
+      asection *sec ATTRIBUTE_UNUSED;
+      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+ {
+   struct bpo_reloc_section_info *bpodata
+     = (struct bpo_reloc_section_info *)
+     elf_section_data (sec)->tdata;
+   asection *allocated_gregs_section;
+
+   /* If no bpodata here, we have nothing to do.  */
+   if (bpodata == NULL)
+     return true;
+
+   allocated_gregs_section = bpodata->bpo_greg_section;
+
+   ((struct bpo_greg_section_info *)
+    elf_section_data (allocated_gregs_section)->tdata)
+     ->n_bpo_relocs
+     -= bpodata->n_bpo_relocs_this_section;
+
+   return true;
+ }

  /* Sort register relocs to come before expanding relocs.  */

*************** mmix_elf_sort_relocs (p1, p2)
*** 1432,1437 ****
--- 1624,1737 ----
    return 0;
  }

+ /* Subset of mmix_elf_check_relocs, common to ELF and mmo linking.  */
+
+ static boolean
+ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
+      bfd *abfd;
+      struct bfd_link_info *info;
+      asection *sec;
+      const Elf_Internal_Rela *relocs;
+ {
+   bfd *bpo_greg_owner = NULL;
+   asection *allocated_gregs_section = NULL;
+   struct bpo_greg_section_info *gregdata = NULL;
+   struct bpo_reloc_section_info *bpodata = NULL;
+   const Elf_Internal_Rela *rel;
+   const Elf_Internal_Rela *rel_end;
+
+   if (info->relocateable)
+     return true;
+
+   /* We currently have to abuse this COFF-specific member, since there's
+      no target-machine-dedicated member.  There's no alternative outside
+      the bfd_link_info struct; we can't specialize a hash-table since
+      they're different between ELF and mmo.  */
+   bpo_greg_owner = (bfd *) info->base_file;
+
+   rel_end = relocs + sec->reloc_count;
+   for (rel = relocs; rel < rel_end; rel++)
+     {
+       switch (ELF64_R_TYPE (rel->r_info))
+         {
+ 	  /* This relocation causes a GREG allocation.  We need to count
+ 	     them, and we need to create a section for them, so we need an
+ 	     object to fake as the owner of that section.  We can't use
+ 	     the ELF dynobj for this, since the ELF bits assume lots of
+ 	     DSO-related stuff if that member is non-NULL.  */
+ 	case R_MMIX_BASE_PLUS_OFFSET:
+ 	  if (bpo_greg_owner == NULL)
+ 	    {
+ 	      bpo_greg_owner = abfd;
+ 	      info->base_file = (PTR) bpo_greg_owner;
+ 	    }
+
+ 	  allocated_gregs_section
+ 	    = bfd_get_section_by_name (bpo_greg_owner,
+ 				       MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ 	  if (allocated_gregs_section == NULL)
+ 	    {
+ 	      allocated_gregs_section
+ 		= bfd_make_section (bpo_greg_owner,
+ 				    MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ 	      /* Setting both SEC_ALLOC and SEC_LOAD means the section is
+ 		 treated like any other section, and we'd get errors for
+ 		 address overlap with the text section.  Let's set none of
+ 		 those flags, as that is what currently happens for usual
+ 		 GREG allocations, and that works.  */
+ 	      if (allocated_gregs_section == NULL
+ 		  || !bfd_set_section_flags (bpo_greg_owner,
+ 					     allocated_gregs_section,
+ 					     (SEC_HAS_CONTENTS
+ 					      | SEC_IN_MEMORY
+ 					      | SEC_LINKER_CREATED))
+ 		  || !bfd_set_section_alignment (bpo_greg_owner,
+ 						 allocated_gregs_section,
+ 						 3))
+ 		return false;
+
+ 	      gregdata = (struct bpo_greg_section_info *)
+ 		bfd_zalloc (bpo_greg_owner, sizeof (struct bpo_greg_section_info));
+ 	      if (gregdata == NULL)
+ 		return false;
+ 	      elf_section_data (allocated_gregs_section)->tdata = gregdata;
+ 	    }
+ 	  else if (gregdata == NULL)
+ 	    gregdata = elf_section_data (allocated_gregs_section)->tdata;
+
+ 	  /* Get ourselves some auxiliary info for the BPO-relocs.  */
+ 	  if (bpodata == NULL)
+ 	    {
+ 	      /* No use doing a separate iteration pass to find the upper
+ 		 limit - just use the number of relocs.  */
+ 	      bpodata = (struct bpo_reloc_section_info *)
+ 		bfd_alloc (bpo_greg_owner,
+ 			   sizeof (struct bpo_reloc_section_info)
+ 			   * (sec->reloc_count + 1));
+ 	      if (bpodata == NULL)
+ 		return false;
+ 	      elf_section_data (sec)->tdata = bpodata;
+ 	      bpodata->first_base_plus_offset_reloc
+ 		= bpodata->bpo_index
+ 		= gregdata->n_max_bpo_relocs;
+ 	      bpodata->bpo_greg_section
+ 		= allocated_gregs_section;
+ 	    }
+
+ 	  bpodata->n_bpo_relocs_this_section++;
+ 	  gregdata->n_max_bpo_relocs++;
+
+ 	  /* We don't get another chance to set this before GC; we've not
+ 	     set up set up any hook that runs before GC.  */
+ 	  gregdata->n_bpo_relocs
+ 	    = gregdata->n_max_bpo_relocs;
+ 	  break;
+ 	}
+     }
+
+   return true;
+ }
+
  /* Look through the relocs for a section during the first phase.  */

  static boolean
*************** mmix_elf_check_relocs (abfd, info, sec,
*** 1460,1465 ****
--- 1760,1769 ----
    qsort ((PTR) relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
  	 mmix_elf_sort_relocs);

+   /* Do the common part.  */
+   if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs))
+     return false;
+
    rel_end = relocs + sec->reloc_count;
    for (rel = relocs; rel < rel_end; rel++)
      {
*************** mmix_elf_check_relocs (abfd, info, sec,
*** 1473,1479 ****
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];

        switch (ELF64_R_TYPE (rel->r_info))
!         {
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
          case R_MMIX_GNU_VTINHERIT:
--- 1777,1783 ----
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];

        switch (ELF64_R_TYPE (rel->r_info))
! 	{
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
          case R_MMIX_GNU_VTINHERIT:
*************** mmix_elf_check_relocs (abfd, info, sec,
*** 1487,1497 ****
            if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
              return false;
            break;
!         }
      }

    return true;
  }

  /* Change symbols relative to the reg contents section to instead be to
     the register section, and scale them down to correspond to the register
--- 1791,1842 ----
            if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
              return false;
            break;
! 	}
      }

    return true;
  }
+
+ /* Wrapper for mmix_elf_check_common_relocs, called when linking to mmo.
+    Copied from elf_link_add_object_symbols.  */
+
+ boolean
+ _bfd_mmix_check_all_relocs (abfd, info)
+      bfd *abfd;
+      struct bfd_link_info *info;
+ {
+   asection *o;
+
+   for (o = abfd->sections; o != NULL; o = o->next)
+     {
+       Elf_Internal_Rela *internal_relocs;
+       boolean ok;
+
+       if ((o->flags & SEC_RELOC) == 0
+ 	  || o->reloc_count == 0
+ 	  || ((info->strip == strip_all || info->strip == strip_debugger)
+ 	      && (o->flags & SEC_DEBUGGING) != 0)
+ 	  || bfd_is_abs_section (o->output_section))
+ 	continue;
+
+       internal_relocs
+ 	= _bfd_elf64_link_read_relocs (abfd, o, (PTR) NULL,
+ 				       (Elf_Internal_Rela *) NULL,
+ 				       info->keep_memory);
+       if (internal_relocs == NULL)
+ 	return false;
+
+       ok = mmix_elf_check_common_relocs (abfd, info, o, internal_relocs);
+
+       if (! info->keep_memory)
+ 	free (internal_relocs);
+
+       if (! ok)
+ 	return false;
+     }
+
+   return true;
+ }

  /* Change symbols relative to the reg contents section to instead be to
     the register section, and scale them down to correspond to the register
*************** mmix_elf_final_link (abfd, info)
*** 1685,1691 ****
--- 2030,2486 ----
    if (! bfd_elf64_bfd_final_link (abfd, info))
      return false;

+   /* Since this section is marked SEC_LINKER_CREATED, it isn't output by
+      the regular linker machinery.  We do it here, like other targets with
+      special sections.  */
+   if (info->base_file != NULL)
+     {
+       asection *greg_section
+ 	= bfd_get_section_by_name ((bfd *) info->base_file,
+ 				   MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+       if (!bfd_set_section_contents (abfd,
+ 				     greg_section->output_section,
+ 				     greg_section->contents,
+ 				     (file_ptr) greg_section->output_offset,
+ 				     greg_section->_cooked_size))
+ 	return false;
+     }
+   return true;
+ }
+
+ /* Initialize stuff for the linker-generated GREGs to match
+    R_MMIX_BASE_PLUS_OFFSET relocs seen by the linker.  */
+
+ boolean
+ _bfd_mmix_prepare_linker_allocated_gregs (abfd, info)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      struct bfd_link_info *info;
+ {
+   asection *bpo_gregs_section;
+   bfd *bpo_greg_owner;
+   struct bpo_greg_section_info *gregdata;
+   size_t n_gregs;
+   bfd_vma gregs_size;
+   size_t i;
+   size_t *bpo_reloc_indexes;
+
+   /* The bpo_greg_owner bfd is supposed to have been set by
+      mmix_elf_check_relocs when the first R_MMIX_BASE_PLUS_OFFSET is seen.
+      If there is no such object, there was no R_MMIX_BASE_PLUS_OFFSET.  */
+   bpo_greg_owner = (bfd *) info->base_file;
+   if (bpo_greg_owner == NULL)
+     return true;
+
+   bpo_gregs_section
+     = bfd_get_section_by_name (bpo_greg_owner,
+ 			       MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+
+   /* This can't happen without DSO handling.  When DSOs are handled
+      without any R_MMIX_BASE_PLUS_OFFSET seen, there will be no such
+      section.  */
+   if (bpo_gregs_section == NULL)
+     return true;
+
+   /* We use the target-data handle in the ELF section data.  */
+   gregdata = (struct bpo_greg_section_info *)
+     elf_section_data (bpo_gregs_section)->tdata;
+   if (gregdata == NULL)
+     return false;
+
+   n_gregs = gregdata->n_bpo_relocs;
+   gregdata->n_allocated_bpo_gregs = n_gregs;
+
+   /* When this reaches zero during relaxation, all entries have been
+      filled in and the size of the linker gregs can be calculated.  */
+   gregdata->n_remaining_bpo_relocs_this_relaxation_round = n_gregs;
+
+   /* Set the zeroth-order estimate for the GREGs size.  */
+   gregs_size = n_gregs * 8;
+
+   if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size))
+     return false;
+
+   /* Allocate and set up the GREG arrays.  They're filled in at relaxation
+      time.  Note that we must use the max number ever noted for the array,
+      since the index numbers were created before GC.  */
+   gregdata->reloc_request
+     = bfd_zalloc (bpo_greg_owner,
+ 		  sizeof (struct bpo_reloc_request)
+ 		  * gregdata->n_max_bpo_relocs);
+
+   gregdata->bpo_reloc_indexes
+     = bpo_reloc_indexes
+     = bfd_alloc (bpo_greg_owner,
+ 		 gregdata->n_max_bpo_relocs
+ 		 * sizeof (size_t));
+   if (bpo_reloc_indexes == NULL)
+     return false;
+
+   /* The default order is an identity mapping.  */
+   for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
+     {
+       bpo_reloc_indexes[i] = i;
+       gregdata->reloc_request[i].bpo_reloc_no = i;
+     }
+
+   return true;
+ }
+
+ /* Fill in contents in the linker allocated gregs.  Everything is
+    calculated at this point; we just move the contents into place here.  */
+
+ boolean
+ _bfd_mmix_finalize_linker_allocated_gregs (abfd, link_info)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      struct bfd_link_info *link_info;
+ {
+   asection *bpo_gregs_section;
+   bfd *bpo_greg_owner;
+   struct bpo_greg_section_info *gregdata;
+   size_t n_gregs;
+   size_t i, j;
+   size_t lastreg;
+   bfd_byte *contents;
+
+   /* The bpo_greg_owner bfd is supposed to have been set by mmix_elf_check_relocs
+      when the first R_MMIX_BASE_PLUS_OFFSET is seen.  If there is no such
+      object, there was no R_MMIX_BASE_PLUS_OFFSET.  */
+   bpo_greg_owner = (bfd *) link_info->base_file;
+   if (bpo_greg_owner == NULL)
+     return true;
+
+   bpo_gregs_section
+     = bfd_get_section_by_name (bpo_greg_owner,
+ 			       MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+
+   /* This can't happen without DSO handling.  When DSOs are handled
+      without any R_MMIX_BASE_PLUS_OFFSET seen, there will be no such
+      section.  */
+   if (bpo_gregs_section == NULL)
+     return true;
+
+   /* We use the target-data handle in the ELF section data.  */
+
+   gregdata = (struct bpo_greg_section_info *)
+     elf_section_data (bpo_gregs_section)->tdata;
+   if (gregdata == NULL)
+     return false;
+
+   n_gregs = gregdata->n_allocated_bpo_gregs;
+
+   bpo_gregs_section->contents
+     = contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->_cooked_size);
+   if (contents == NULL)
+     return false;
+
+   for (lastreg = 255, i = 0, j = 0; j < n_gregs; i++)
+     if (gregdata->reloc_request[i].regindex != lastreg)
+       {
+ 	bfd_put_64 (bpo_greg_owner, gregdata->reloc_request[i].value,
+ 		    contents + j * 8);
+ 	lastreg = gregdata->reloc_request[i].regindex;
+ 	j++;
+       }
+
+   return true;
+ }
+
+ /* Sort valid relocs to come before non-valid relocs, then on increasing
+    value.  */
+
+ static int
+ bpo_reloc_request_sort_fn (p1, p2)
+      const PTR p1;
+      const PTR p2;
+ {
+   const struct bpo_reloc_request *r1 = (const struct bpo_reloc_request *) p1;
+   const struct bpo_reloc_request *r2 = (const struct bpo_reloc_request *) p2;
+
+   /* Primary function is validity; non-valid relocs sorted after valid
+      ones.  */
+   if (r1->valid != r2->valid)
+     return r2->valid - r1->valid;
+
+   /* Then sort on value.  */
+   if (r1->value != r2->value)
+     return r1->value - r2->value;
+
+   /* As a last re-sort, use the address so we get a stable sort.  */
+   return r1 > r2 ? 1 : (r1 < r2 ? -1 : 0);
+ }
+
+ /* This links all R_MMIX_BASE_PLUS_OFFSET relocs into a special array, and
+    when the last such reloc is done, an index-array is sorted according to
+    the values and iterated over to produce register numbers (indexed by 0
+    from the first allocated register number) and offsets for use in real
+    relocation.
+
+    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
+
+ static boolean
+ mmix_elf_relax_section (abfd, sec, link_info, again)
+      bfd *abfd;
+      asection *sec;
+      struct bfd_link_info *link_info;
+      boolean *again;
+ {
+
+   Elf_Internal_Shdr *symtab_hdr;
+   Elf_Internal_Shdr *shndx_hdr;
+   Elf_Internal_Rela *internal_relocs;
+   Elf_Internal_Rela *free_relocs = NULL;
+   Elf_Internal_Rela *irel, *irelend;
+   asection *bpo_gregs_section = NULL;
+   struct bpo_greg_section_info *gregdata;
+   struct bpo_reloc_section_info *bpodata
+     = (struct bpo_reloc_section_info *)
+     elf_section_data (sec)->tdata;
+   size_t bpono;
+   bfd *bpo_greg_owner;
+   Elf64_External_Sym *extsyms = NULL;
+   Elf64_External_Sym *free_extsyms = NULL;
+   Elf_External_Sym_Shndx *shndx_buf = NULL;
+
+   /* Assume nothing changes.  */
+   *again = false;
+
+   /* If this is the first time we have been called for this section,
+      initialize the cooked size.  */
+   if (sec->_cooked_size == 0)
+     sec->_cooked_size = sec->_raw_size;
+
+   /* We don't have to do anything for a relocateable link, if
+      this section does not have relocs, or if this is not a
+      code section.  */
+   if (link_info->relocateable
+       || (sec->flags & SEC_RELOC) == 0
+       || sec->reloc_count == 0
+       || (sec->flags & SEC_CODE) == 0
+       || (sec->flags & SEC_LINKER_CREATED) != 0
+       /* If no R_MMIX_BASE_PLUS_OFFSET relocs, then nothing to do.  */
+       || bpodata == NULL)
+     return true;
+
+   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+   shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+
+   bpo_greg_owner = (bfd *) link_info->base_file;
+   bpo_gregs_section = bpodata->bpo_greg_section;
+   gregdata = (struct bpo_greg_section_info *)
+     elf_section_data (bpo_gregs_section)->tdata;
+
+   bpono = bpodata->first_base_plus_offset_reloc;
+
+   /* Get a copy of the native relocations.  */
+   internal_relocs
+     = _bfd_elf64_link_read_relocs (abfd, sec, (PTR) NULL,
+ 				   (Elf_Internal_Rela *) NULL,
+ 				   link_info->keep_memory);
+   if (internal_relocs == NULL)
+     goto error_return;
+   if (! link_info->keep_memory)
+     free_relocs = internal_relocs;
+
+   /* Walk through them looking for relaxing opportunities.  */
+   irelend = internal_relocs + sec->reloc_count;
+   for (irel = internal_relocs; irel < irelend; irel++)
+     {
+       bfd_vma symval;
+
+       if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET)
+ 	continue;
+
+       /* Read this BFD's symbols if we haven't done so already.  */
+       if (extsyms == NULL)
+ 	{
+ 	  /* Get cached copy if it exists.  */
+ 	  if (symtab_hdr->contents != NULL)
+ 	    extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
+ 	  else
+ 	    {
+ 	      /* Go get them off disk.  */
+ 	      bfd_size_type amt;
+
+ 	      amt = symtab_hdr->sh_info;
+ 	      amt *= sizeof (Elf64_External_Sym);
+ 	      extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
+ 	      if (extsyms == NULL)
+ 		goto error_return;
+ 	      free_extsyms = extsyms;
+ 	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ 		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
+ 		goto error_return;
+ 	      symtab_hdr->contents = (bfd_byte *) extsyms;
+ 	    }
+
+ 	  /* If >64k sections, this presumable happens.  No test-case.  */
+ 	  if (shndx_hdr->sh_size != 0)
+ 	    {
+ 	      bfd_size_type amt;
+
+ 	      amt = symtab_hdr->sh_info;
+ 	      amt *= sizeof (Elf_External_Sym_Shndx);
+ 	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ 	      if (shndx_buf == NULL)
+ 		goto error_return;
+ 	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+ 		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+ 		goto error_return;
+ 	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
+ 	    }
+ 	}
+
+       /* Get the value of the symbol referred to by the reloc.  */
+       if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+ 	{
+ 	  /* A local symbol.  */
+ 	  Elf64_External_Sym *esym;
+ 	  Elf_External_Sym_Shndx *shndx;
+ 	  Elf_Internal_Sym isym;
+ 	  asection *sym_sec;
+
+ 	  esym = extsyms + ELF64_R_SYM (irel->r_info);
+ 	  shndx = shndx_buf + (shndx_buf
+ 			       ? ELF64_R_SYM (irel->r_info) : 0);
+ 	  bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
+
+ 	  if (isym.st_shndx == SHN_UNDEF)
+ 	    sym_sec = bfd_und_section_ptr;
+ 	  else if (isym.st_shndx == SHN_ABS)
+ 	    sym_sec = bfd_abs_section_ptr;
+ 	  else if (isym.st_shndx == SHN_COMMON)
+ 	    sym_sec = bfd_com_section_ptr;
+ 	  else
+ 	    sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ 	  symval = (isym.st_value
+ 		    + sym_sec->output_section->vma
+ 		    + sym_sec->output_offset);
+ 	}
+       else
+ 	{
+ 	  unsigned long indx;
+ 	  struct elf_link_hash_entry *h;
+
+ 	  /* An external symbol.  */
+ 	  indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+ 	  h = elf_sym_hashes (abfd)[indx];
+ 	  BFD_ASSERT (h != NULL);
+ 	  if (h->root.type != bfd_link_hash_defined
+ 	      && h->root.type != bfd_link_hash_defweak)
+ 	    {
+ 	      /* This appears to be a reference to an undefined
+                  symbol.  Just ignore it--it will be caught by the
+                  regular reloc processing.  */
+ 	      continue;
+ 	    }
+
+ 	  symval = (h->root.u.def.value
+ 		    + h->root.u.def.section->output_section->vma
+ 		    + h->root.u.def.section->output_offset);
+ 	}
+
+       gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono]].value
+ 	= symval + irel->r_addend;
+       gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono++]].valid = true;
+       gregdata->n_remaining_bpo_relocs_this_relaxation_round--;
+     }
+
+   /* Check if that was the last BPO-reloc.  If so, sort the values and
+      calculate how many registers we need to cover them.  Set the size of
+      the linker gregs, and if the number of registers changed, indicate
+      that we need to relax some more because we have more work to do.  */
+   if (gregdata->n_remaining_bpo_relocs_this_relaxation_round == 0)
+     {
+       size_t i;
+       bfd_vma prev_base;
+       size_t regindex;
+
+       /* First, reset the remaining relocs for the next round.  */
+       gregdata->n_remaining_bpo_relocs_this_relaxation_round
+ 	= gregdata->n_bpo_relocs;
+
+       qsort ((PTR) gregdata->reloc_request,
+ 	     gregdata->n_max_bpo_relocs,
+ 	     sizeof (struct bpo_reloc_request),
+ 	     bpo_reloc_request_sort_fn);
+
+       /* Recalculate indexes.  When we find a change (however unlikely
+ 	 after the initial iteration), we know we need to relax again,
+ 	 since items in the GREG-array are sorted by increasing value and
+ 	 stored in the relaxation phase.  */
+       for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
+ 	if (gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
+ 	    != i)
+ 	  {
+ 	    gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
+ 	      = i;
+ 	    *again = true;
+ 	  }
+
+       /* Allocate register numbers (indexing from 0).  Stop at the first
+ 	 non-valid reloc.  */
+       for (i = 0, regindex = 0, prev_base = gregdata->reloc_request[0].value;
+ 	   i < gregdata->n_bpo_relocs;
+ 	   i++)
+ 	{
+ 	  if (gregdata->reloc_request[i].value > prev_base + 255)
+ 	    {
+ 	      regindex++;
+ 	      prev_base = gregdata->reloc_request[i].value;
+ 	    }
+ 	  gregdata->reloc_request[i].regindex = regindex;
+ 	  gregdata->reloc_request[i].offset
+ 	    = gregdata->reloc_request[i].value - prev_base;
+ 	}
+
+       /* If it's not the same as the last time, we need to relax again,
+ 	 because the size of the section has changed.  I'm not sure we
+ 	 actually need to do any adjustments since the shrinking happens
+ 	 at the start of this section, but better safe than sorry.  */
+       if (gregdata->n_allocated_bpo_gregs != regindex + 1)
+ 	{
+ 	  gregdata->n_allocated_bpo_gregs = regindex + 1;
+ 	  *again = true;
+ 	}
+
+       bpo_gregs_section->_cooked_size = (regindex + 1) * 8;
+     }
+
+   if (free_relocs != NULL)
+     free (free_relocs);
+
+   if (shndx_buf != NULL)
+     {
+       shndx_hdr->contents = NULL;
+       free (shndx_buf);
+     }
+
+   if (free_extsyms != NULL)
+     {
+       if (! link_info->keep_memory)
+ 	{
+ 	  symtab_hdr->contents = NULL;
+ 	  free (free_extsyms);
+ 	}
+     }
+
    return true;
+
+  error_return:
+   if (free_relocs != NULL)
+     free (free_relocs);
+   if (shndx_buf != NULL)
+     {
+       shndx_hdr->contents = NULL;
+       free (shndx_buf);
+     }
+   if (free_extsyms != NULL)
+     {
+       symtab_hdr->contents = NULL;
+       free (free_extsyms);
+     }
+
+   return false;
  }

  #define ELF_ARCH		bfd_arch_mmix
*************** mmix_elf_final_link (abfd, info)
*** 1712,1717 ****
--- 2507,2514 ----
  #define elf_info_to_howto		mmix_info_to_howto_rela
  #define elf_backend_relocate_section	mmix_elf_relocate_section
  #define elf_backend_gc_mark_hook	mmix_elf_gc_mark_hook
+ #define elf_backend_gc_sweep_hook	mmix_elf_gc_sweep_hook
+
  #define elf_backend_link_output_symbol_hook \
  	mmix_elf_link_output_symbol_hook
  #define elf_backend_add_symbol_hook	mmix_elf_add_symbol_hook
*************** mmix_elf_final_link (abfd, info)
*** 1731,1735 ****
--- 2528,2533 ----
  	mmix_elf_section_from_bfd_section

  #define bfd_elf64_bfd_final_link	mmix_elf_final_link
+ #define bfd_elf64_bfd_relax_section	mmix_elf_relax_section

  #include "elf64-target.h"
Index: mmo.c
===================================================================
RCS file: /cvs/src/src/bfd/mmo.c,v
retrieving revision 1.3
diff -p -c -r1.3 mmo.c
*** mmo.c	2002/01/06 07:30:35	1.3
--- mmo.c	2002/02/01 07:24:01
*************** EXAMPLE
*** 201,207 ****
  #include "libiberty.h"
  #include "elf/mmix.h"
  #include "opcode/mmix.h"
- #include <ctype.h>

  #define LOP 0x98
  #define LOP_QUOTE 0
--- 201,206 ----
*************** mmo_init ()
*** 481,490 ****
    static const char letters[]
      = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_";

!   if (inited == false)
!     {
!       inited = true;
!     }

    /* Fill in the set of valid symbol characters.  */
    strcpy (valid_mmo_symbol_character_set, letters);
--- 480,488 ----
    static const char letters[]
      = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_";

!   if (inited == true)
!     return;
!   inited = true;

    /* Fill in the set of valid symbol characters.  */
    strcpy (valid_mmo_symbol_character_set, letters);
Index: mmix.h
===================================================================
RCS file: /cvs/src/src/include/elf/mmix.h,v
retrieving revision 1.1
diff -p -c -r1.1 mmix.h
*** mmix.h	2001/10/30 15:20:09	1.1
--- mmix.h	2002/02/01 07:09:44
***************
*** 1,5 ****
  /* MMIX support for BFD.
!    Copyright (C) 2001 Free Software Foundation, Inc.

  This file is part of BFD, the Binary File Descriptor library.

--- 1,5 ----
  /* MMIX support for BFD.
!    Copyright (C) 2001, 2002 Free Software Foundation, Inc.

  This file is part of BFD, the Binary File Descriptor library.

*************** START_RELOC_NUMBERS (elf_mmix_reloc_type
*** 82,88 ****
    /* A general register. */
    RELOC_NUMBER (R_MMIX_REG, 33)

!   /* A global register and an offset, equivalent of the expression.  */
    RELOC_NUMBER (R_MMIX_BASE_PLUS_OFFSET, 34)

    /* A LOCAL assertion.  */
--- 82,91 ----
    /* A general register. */
    RELOC_NUMBER (R_MMIX_REG, 33)

!   /* A global register and an offset, the global register (allocated at
!      link time) contents plus the offset made equivalent to the relocation
!      expression at link time.  The relocation must point at the Y field of
!      an instruction.  */
    RELOC_NUMBER (R_MMIX_BASE_PLUS_OFFSET, 34)

    /* A LOCAL assertion.  */
*************** END_RELOC_NUMBERS (R_MMIX_max)
*** 107,112 ****
--- 110,120 ----
     unspecified) ABI.  */
  #define MMIX_REG_CONTENTS_SECTION_NAME ".MMIX.reg_contents"

+ /* At link time, a section by this name is created, expected to be
+    included in MMIX_REG_CONTENTS_SECTION_NAME in the output.  */
+ #define MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME \
+  ".MMIX.reg_contents.linker_allocated"
+
  /* This is a faked section holding symbols with SHN_REGISTER.  Don't
     confuse it with MMIX_REG_CONTENTS_SECTION_NAME; this one has no
     contents, just values.  It is an error for a value in this section to
*************** END_RELOC_NUMBERS (R_MMIX_max)
*** 147,151 ****
--- 155,168 ----
  #define MMO_SEC_NEVER_LOAD 0x400
  #define MMO_SEC_IS_COMMON 0x8000
  #define MMO_SEC_DEBUGGING 0x10000
+
+ #ifdef BFD_ARCH_SIZE
+ extern boolean _bfd_mmix_prepare_linker_allocated_gregs
+  PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean _bfd_mmix_finalize_linker_allocated_gregs
+  PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean _bfd_mmix_check_all_relocs
+  PARAMS ((bfd *, struct bfd_link_info *));
+ #endif

  #endif /* ELF_MMIX_H */
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-1b.d	Fri Feb  1 04:20:40 2002
***************
*** 0 ****
--- 1,14 ----
+ #source: basep-1.s
+ #as: -linker-allocated-gregs
+ #objdump: -dr
+
+ # Check that this test isn't mistreated with -linker-allocated-gregs.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0+ <a>:
+    0:	0000002a 	trap 0,0,42
+    4:	8d2b0034 	ldo \$43,\$0,52
+ 			6: R_MMIX_REG	\.MMIX\.reg_contents
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-2b.d	Fri Feb  1 04:20:57 2002
***************
*** 0 ****
--- 1,26 ----
+ #source: basep-2.s
+ #as: --no-predefined-syms -linker-allocated-gregs
+ #objdump: -dr
+
+ # Check that this test isn't mistreated with -linker-allocated-gregs.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0000000000000000 <a>:
+    0:	0000002a 	trap 0,0,42
+    4:	8d2b0034 	ldo \$43,\$0,52
+ 			6: R_MMIX_REG	\.MMIX\.reg_contents\+0x8
+ 	\.\.\.
+
+ 0000000000000108 <d>:
+  108:	0000001c 	trap 0,0,28
+  10c:	8d8f000c 	ldo \$143,\$0,12
+ 			10e: R_MMIX_REG	\.MMIX\.reg_contents
+  110:	8df3000c 	ldo \$243,\$0,12
+ 			112: R_MMIX_REG	\.MMIX\.reg_contents\+0x8
+  114:	23670028 	addu \$103,\$0,40
+ 			116: R_MMIX_REG	\.MMIX\.reg_contents
+  118:	230d0018 	addu \$13,\$0,24
+ 			11a: R_MMIX_REG	\.MMIX\.reg_contents\+0x8
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-7.d	Fri Feb  1 04:21:44 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: err-bpo5.s
+ #as: -linker-allocated-gregs
+ #objdump: -drt
+
+ # The -linker-allocated-gregs option validates omissions of GREG.
+ # Note the inconsequence in relocs regarding forward and backward
+ # references (not specific to this functionality); they may change.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 0+ l    d  \.data	0+
+ 0+ l    d  \.bss	0+
+ 0+2a l       \*ABS\*	0+ a
+ 0+70 l       \*ABS\*	0+ b
+ 0+48 l       \*ABS\*	0+ c
+ 0+3 l       \*ABS\*	0+ d
+
+ Disassembly of section \.text:
+
+ 0+ <\.text>:
+    0:	8d2b0000 	ldo \$43,\$0,0
+ 			2: R_MMIX_BASE_PLUS_OFFSET	\*ABS\*\+0x5e
+    4:	232f0000 	addu \$47,\$0,0
+ 			6: R_MMIX_BASE_PLUS_OFFSET	\*ABS\*\+0x9a
+    8:	23300000 	addu \$48,\$0,0
+ 			a: R_MMIX_BASE_PLUS_OFFSET	\*ABS\*\+0x86
+    c:	8d2b0000 	ldo \$43,\$0,0
+ 			e: R_MMIX_BASE_PLUS_OFFSET	c\+0x2
+   10:	232f0000 	addu \$47,\$0,0
+ 			12: R_MMIX_BASE_PLUS_OFFSET	d\+0xd4
+   14:	23300000 	addu \$48,\$0,0
+ 			16: R_MMIX_BASE_PLUS_OFFSET	c\+0x15
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/err-bpo2.s	Sat Jan  5 20:18:41 2002
***************
*** 0 ****
--- 1,6 ----
+ % { dg-do assemble { target mmix-*-* } }
+
+ # Check that base-plus-offset relocs without suitable GREGs are not passed
+ # through (without -linker-allocated-gregs).
+ a TETRA 42
+   LDO $43,a+52		% { dg-error "no suitable GREG definition" "" }
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-3b.d	Fri Feb  1 04:22:18 2002
***************
*** 0 ****
--- 1,17 ----
+ #source: basep-3.s
+ #as: -linker-allocated-gregs
+ #objdump: -dr
+
+ # Check that this test isn't mistreated with -linker-allocated-gregs.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0+ <Main>:
+    0:	bf2a0000 	pushgo \$42,\$0,0
+ 			2: R_MMIX_REG	\.MMIX\.reg_contents
+    4:	fd000000 	swym 0,0,0
+
+ 0+8 <extfn>:
+    8:	f8000000 	pop 0,0
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/err-bpo3.s	Fri Feb  1 04:23:09 2002
***************
*** 0 ****
--- 1,13 ----
+ % { dg-do assemble { target mmix-*-* } }
+
+ # Base-plus-offset without -linker-allocated-gregs.
+
+ a TETRA 42
+   LDO $43,a+52		% { dg-error "no suitable GREG definition" "" }
+
+   LOC @+256
+ d TETRA 28
+   LDO $143,d+12		% { dg-error "no suitable GREG definition" "" }
+   LDO $243,a+12		% { dg-error "no suitable GREG definition" "" }
+   LDA $103,d+40		% { dg-error "no suitable GREG definition" "" }
+   LDA $13,a+24		% { dg-error "no suitable GREG definition" "" }
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-4.d	Fri Feb  1 04:23:19 2002
***************
*** 0 ****
--- 1,14 ----
+ #source: err-bpo2.s
+ #as: -linker-allocated-gregs
+ #objdump: -dr
+
+ # The -linker-allocated-gregs option validates omissions of GREG.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0+ <a>:
+    0:	0000002a 	trap 0,0,42
+    4:	8d2b0000 	ldo \$43,\$0,0
+ 			6: R_MMIX_BASE_PLUS_OFFSET	\.text\+0x34
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/err-bpo4.s	Fri Feb  1 04:23:50 2002
***************
*** 0 ****
--- 1,7 ----
+ % { dg-do assemble { target mmix-*-* } }
+
+ # Base-plus-offset without -linker-allocated-gregs.
+
+ Main PUSHGO $42,fn		% { dg-error "no suitable GREG definition" "" }
+  SWYM 0
+ extfn POP 0,0
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/err-bpo5.s	Fri Feb  1 04:24:04 2002
***************
*** 0 ****
--- 1,14 ----
+ % { dg-do assemble { target mmix-*-* } }
+
+ # Base-plus-offset without -linker-allocated-gregs.  Note the constant.
+
+ a IS 42
+ b IS 112
+   LDO $43,a+52		% { dg-error "no suitable GREG definition" "" }
+   LDA $47,a+112		% { dg-error "no suitable GREG definition" "" }
+   LDA $48,b+22		% { dg-error "no suitable GREG definition" "" }
+   LDO $43,c+2		% { dg-error "no suitable GREG definition" "" }
+   LDA $47,d+212		% { dg-error "no suitable GREG definition" "" }
+   LDA $48,c+21		% { dg-error "no suitable GREG definition" "" }
+ c IS 72
+ d IS 3
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-5.d	Fri Feb  1 04:24:24 2002
***************
*** 0 ****
--- 1,26 ----
+ #source: err-bpo3.s
+ #as: -linker-allocated-gregs
+ #objdump: -dr
+
+ # The -linker-allocated-gregs option validates omissions of GREG.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0+ <a>:
+    0:	0000002a 	trap 0,0,42
+    4:	8d2b0000 	ldo \$43,\$0,0
+ 			6: R_MMIX_BASE_PLUS_OFFSET	\.text\+0x34
+ 	\.\.\.
+
+ 0+108 <d>:
+  108:	0000001c 	trap 0,0,28
+  10c:	8d8f0000 	ldo \$143,\$0,0
+ 			10e: R_MMIX_BASE_PLUS_OFFSET	\.text\+0x114
+  110:	8df30000 	ldo \$243,\$0,0
+ 			112: R_MMIX_BASE_PLUS_OFFSET	\.text\+0xc
+  114:	23670000 	addu \$103,\$0,0
+ 			116: R_MMIX_BASE_PLUS_OFFSET	\.text\+0x130
+  118:	230d0000 	addu \$13,\$0,0
+ 			11a: R_MMIX_BASE_PLUS_OFFSET	\.text\+0x18
*** /dev/null	Tue Jan  1 05:00:00 1980
--- gas/mmix/basep-6.d	Fri Feb  1 04:24:34 2002
***************
*** 0 ****
--- 1,17 ----
+ #source: err-bpo4.s
+ #as: -linker-allocated-gregs
+ #objdump: -dr
+
+ # The -linker-allocated-gregs option validates omissions of GREG.
+
+ .*:     file format elf64-mmix
+
+ Disassembly of section \.text:
+
+ 0+ <Main>:
+    0:	bf2a0000 	pushgo \$42,\$0,0
+ 			2: R_MMIX_BASE_PLUS_OFFSET	fn
+    4:	fd000000 	swym 0,0,0
+
+ 0+8 <extfn>:
+    8:	f8000000 	pop 0,0
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-1.d	Mon Jan 14 04:37:17 2002
***************
*** 0 ****
--- 1,33 ----
+ #source: start.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Just a simple linker-allocated GREG with no explicit GREGs.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0000000000000000 l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+4 l       \.text	0+ x
+ 0+ g       \.text	0+ _start
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+
+ Contents of section \.text:
+  0000 e3fd0001 232afe00                    .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 0000002e                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-1.s	Thu Jan 10 03:23:36 2002
***************
*** 0 ****
--- 1,2 ----
+ # A most simple instruction needing a linker-supplied GREG.
+ x LDA $42,x+42
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-1m.d	Mon Jan 14 04:37:28 2002
***************
*** 0 ****
--- 1,18 ----
+ #source: start.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Just a simple linker-allocated GREG with no explicit GREGs.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+
+ Contents of section \.text:
+  0000 e3fd0001 232afe00                    .*
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 0000002e                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-15.d	Mon Jan 28 04:43:44 2002
***************
*** 0 ****
--- 1,7 ----
+ #source: start.s
+ #source: bpo-7.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #error: ^[^c][^h][^i][^l][^d].* undefined reference to `areg'$
+
+ # A BPO against an undefined symbol.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-4.s	Mon Jan 14 05:12:17 2002
***************
*** 0 ****
--- 1,5 ----
+  .set i,0
+  .rept 223
+  LDA $11,_start+i*256
+  .set i,i+1
+  .endr
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-6.d	Fri Feb  1 04:28:18 2002
***************
*** 0 ****
--- 1,41 ----
+ #source: start.s
+ #source: bpo-4.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # 223 (max) linker-allocated GREGs.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+100 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+df l       \*ABS\*	0+ i
+ 0+ g       \.text	0+ _start
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 230b2000 230b2100 230b2200  .*
+  0010 230b2300 230b2400 230b2500 230b2600  .*
+ #...
+  0360 230bf700 230bf800 230bf900 230bfa00  .*
+  0370 230bfb00 230bfc00 230bfd00 230bfe00  .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  0100 00000000 00000000 00000000 00000100  .*
+  0110 00000000 00000200 00000000 00000300  .*
+ #...
+  07d0 00000000 0000da00 00000000 0000db00  .*
+  07e0 00000000 0000dc00 00000000 0000dd00  .*
+  07f0 00000000 0000de00                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-6.s	Sun Jan 27 20:36:51 2002
***************
*** 0 ****
--- 1,4 ----
+ # A section with a symbol and a BPO allocation.
+  .section .text.x2,"ax",@progbits
+  .global x2
+ x2 LDA $45,x2+42000
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-2.d	Fri Feb  1 04:29:06 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: start.s
+ #source: greg-1.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Just a simple linker-allocated GREG plus one explicit GREG.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7e8 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+4 l       \.text	0+ x
+ 0+ g       \.text	0+ _start
+ 0+fe g       \*REG\*	0+ areg
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 232afd00                    .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 0000002e 00007048 860f3a38  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-6m.d	Fri Feb  1 04:29:27 2002
***************
*** 0 ****
--- 1,27 ----
+ #source: start.s
+ #source: bpo-4.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # 223 (max) linker-allocated GREGs.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+
+ Contents of section \.text:
+  0000 e3fd0001 230b2000 230b2100 230b2200  .*
+  0010 230b2300 230b2400 230b2500 230b2600  .*
+ #...
+  0360 230bf700 230bf800 230bf900 230bfa00  .*
+  0370 230bfb00 230bfc00 230bfd00 230bfe00  .*
+ Contents of section \.MMIX\.reg_contents:
+  0100 00000000 00000000 00000000 00000100  .*
+  0110 00000000 00000200 00000000 00000300  .*
+ #...
+  07d0 00000000 0000da00 00000000 0000db00  .*
+  07e0 00000000 0000dc00 00000000 0000dd00  .*
+  07f0 00000000 0000de00                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-12m.d	Mon Jan 28 02:00:33 2002
***************
*** 0 ****
--- 1,9 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: greg-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #error: base-plus-offset relocation against register symbol
+
+ # Check that we get an error message if we see a BPO against a register
+ # symbol.  Variant 1: a GREG allocated register.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-2m.d	Fri Feb  1 04:30:53 2002
***************
*** 0 ****
--- 1,21 ----
+ #source: start.s
+ #source: greg-1.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Just a simple linker-allocated GREG plus one explicit GREG.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+fe g       \*REG\* areg
+
+ Contents of section \.text:
+  0000 e3fd0001 232afd00                    .*
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 0000002e 00007048 860f3a38  .*
+
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-2.s	Sun Jan 13 12:33:56 2002
***************
*** 0 ****
--- 1,2 ----
+ 	.global y
+ y	LDA	$33,y+8
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-5.s	Sun Jan 27 19:34:25 2002
***************
*** 0 ****
--- 1,4 ----
+ # A section with a symbol and a BPO allocation.
+  .section .text.x,"ax",@progbits
+  .global x
+ x LDA $45,x+4200
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-3.d	Mon Jan 14 04:40:19 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: start.s
+ #source: bpo-1.s
+ #source: bpo-2.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Just two BPO relocs merged as one linker-allocated GREG.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+4 l       \.text	0+ x
+ 0+ g       \.text	0+ _start
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 0+8 g       \.text	0+ y
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 232afe1e 2321fe00           .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000010                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/start3.s	Sun Jan 27 21:07:23 2002
***************
*** 0 ****
--- 1,7 ----
+ # When GC, all sections in each file must be referenced from within a kept
+ # section.
+  .section .init,"ax",@progbits
+ _start:
+  .quad x+41
+  .quad x2+42
+
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-3m.d	Fri Feb  1 04:32:33 2002
***************
*** 0 ****
--- 1,20 ----
+ #source: start.s
+ #source: bpo-1.s
+ #source: bpo-2.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Just two BPO relocs merged as one linker-allocated GREG.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+8 g       \.text y
+
+ Contents of section \.text:
+  0000 e3fd0001 232afe1e 2321fe00           .*
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000010                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-9m.d	Fri Feb  1 04:33:49 2002
***************
*** 0 ****
--- 1,22 ----
+ #source: start3.s
+ #source: bpo-6.s
+ #source: bpo-5.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo --gc-sections
+ #objdump: -st
+
+ # Check that GC does not mess up things when no BPO:s are collected.
+ # Note that mmo doesn't support GC at the moment; it's a nop.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+4 g       \.text x
+ 0+ g       \.text x2
+
+ Contents of section \.text:
+  0000 232dfe00 232dfd00 00000000 0000002d  .*
+  0010 00000000 0000002a                    .*
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 0000106c 00000000 0000a410  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-4.d	Mon Jan 14 04:42:59 2002
***************
*** 0 ****
--- 1,36 ----
+ #source: start.s
+ #source: greg-1.s
+ #source: bpo-3.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Three GREGs: one explicit, two linker-allocated.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7e0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+8 l       \.text	0+ x
+ 0+ g       \.text	0+ _start
+ 0+fe g       \*REG\*	0+ areg
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 8f79fd00 232afc00           .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07e0 00000000 00000032 00000000 00000133  .*
+  07f0 00007048 860f3a38                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-3.s	Mon Jan 14 01:32:06 2002
***************
*** 0 ****
--- 1 ----
+  LDOU $121,_start+42+4+4+257
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-4m.d	Fri Feb  1 04:39:03 2002
***************
*** 0 ****
--- 1,22 ----
+ #source: start.s
+ #source: greg-1.s
+ #source: bpo-3.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Three GREGs: one explicit, two linker-allocated.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+fe g       \*REG\* areg
+
+ Contents of section \.text:
+  0000 e3fd0001 8f79fd00 232afc00           .*
+ Contents of section \.MMIX\.reg_contents:
+  07e0 00000000 00000032 00000000 00000133  .*
+  07f0 00007048 860f3a38                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-7.d	Sun Jan 27 19:42:07 2002
***************
*** 0 ****
--- 1,6 ----
+ #source: start.s
+ #source: bpo-4.s
+ #source: greg-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #error: Too many global registers: 224
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-5.d	Fri Feb  1 04:39:37 2002
***************
*** 0 ****
--- 1,35 ----
+ #source: start.s
+ #source: bpo-1.s
+ #source: bpo-3.s
+ #source: bpo-2.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Three linker-allocated GREGs: one eliminated.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7e8 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+4 l       \.text	0+ x
+ 0+ g       \.text	0+ _start
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 0+c g       \.text	0+ y
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 232afd1a 8f79fe00 2321fd00  .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 00000014 00000000 00000133  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-16.d	Fri Feb  1 05:27:11 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: bpo-7.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # Two BPO:s against the same value get merged.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ g       \.text	0+ _start
+ 0+c g       \.text	0+ areg
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 234dfe00 234dfe00 fd040810  .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000007                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-5m.d	Fri Feb  1 04:40:37 2002
***************
*** 0 ****
--- 1,21 ----
+ #source: start.s
+ #source: bpo-1.s
+ #source: bpo-3.s
+ #source: bpo-2.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Three linker-allocated GREGs: one eliminated.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+c g       \.text y
+
+ Contents of section \.text:
+  0000 e3fd0001 232afd1a 8f79fe00 2321fd00  .*
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 00000014 00000000 00000133  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-7m.d	Sun Jan 27 19:39:50 2002
***************
*** 0 ****
--- 1,6 ----
+ #source: start.s
+ #source: bpo-4.s
+ #source: greg-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #error: Too many global registers: 224
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-9.d	Fri Feb  1 04:41:19 2002
***************
*** 0 ****
--- 1,36 ----
+ #source: start3.s
+ #source: bpo-6.s
+ #source: bpo-5.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix --gc-sections
+ #objdump: -st
+
+ # Check that GC does not mess up things when no BPO:s are collected.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.init	0+
+ 0+10 l    d  \.text	0+
+ 20+ l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7e8 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l       \.init	0+ _start
+ 0+14 g       \.text	0+ x
+ 0+10 g       \.text	0+ x2
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+10 g     O \.text	0+ _start\.
+
+ Contents of section \.init:
+  0000 00000000 0000003d 00000000 0000003a  .*
+ Contents of section \.text:
+  0010 232dfe00 232dfd00                    .*
+ Contents of section \.sbss:
+ Contents of section \.bss:
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 0000107c 00000000 0000a420  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-8.d	Fri Feb  1 05:19:59 2002
***************
*** 0 ****
--- 1,7 ----
+ #source: start.s
+ #source: bpo-4.s
+ #source: pad2p18m32.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #error: Too many global registers: 224
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/start4.s	Fri Feb  1 05:17:21 2002
***************
*** 0 ****
--- 1,6 ----
+ # When GC, all sections in each file must be referenced from within a kept
+ # section (which .init is, which .text isn't).  Here, we don't refer to
+ # anything so whatever is linked will be discarded.
+  .section .init,"ax",@progbits
+ _start:
+  SETL $119,1190
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-8m.d	Fri Feb  1 05:20:09 2002
***************
*** 0 ****
--- 1,7 ----
+ #source: start.s
+ #source: bpo-4.s
+ #source: pad2p18m32.s
+ #source: bpo-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #error: Too many global registers: 224
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-13m.d	Mon Jan 28 02:00:47 2002
***************
*** 0 ****
--- 1,9 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: areg-256.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #error: base-plus-offset relocation against register symbol
+
+ # Check that we get an error message if we see a BPO against a register
+ # symbol.  Variant 2: a register symbol.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-15m.d	Mon Jan 28 04:44:26 2002
***************
*** 0 ****
--- 1,7 ----
+ #source: start.s
+ #source: bpo-7.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #error: ^[^c][^h][^i][^l][^d].* undefined reference to `areg'$
+
+ # A BPO against an undefined symbol.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-10.d	Sun Jan 27 21:21:44 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: start4.s
+ #source: bpo-6.s
+ #source: bpo-5.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix --gc-sections
+ #objdump: -st
+
+ # Check that GC removes all (two) BPO:s when all are collected.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.init	0+
+ 0+4 l    d  \.text	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f8 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l       \.init	0+ _start
+ 0+ g       \*ABS\*	0+
+ 0+ g       \*ABS\*	0+
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+4 g     O \.text	0+ _start\.
+
+ Contents of section \.init:
+  0000 e37704a6                             .*
+ Contents of section \.text:
+ Contents of section \.sbss:
+ Contents of section \.bss:
+ Contents of section \.MMIX\.reg_contents:
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-11.d	Fri Feb  1 05:25:29 2002
***************
*** 0 ****
--- 1,39 ----
+ #source: start3.s
+ #source: bpo-6.s
+ #source: bpo-2.s
+ #source: bpo-5.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix --gc-sections
+ #objdump: -st
+
+ # Check that GC removes one of the three BPO:s, for the collected section.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.init	0+
+ 0+10 l    d  \.text	0+
+ 20+ l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7e8 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l       \.init	0+ _start
+ 0+14 g       \.text	0+ x
+ 0+10 g       \.text	0+ x2
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 0+ g       \*ABS\*	0+
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+10 g     O \.text	0+ _start\.
+
+
+ Contents of section \.init:
+  0000 00000000 0000003d 00000000 0000003a  .*
+ Contents of section \.text:
+  0010 232dfe00 232dfd00                    .*
+ Contents of section \.sbss:
+ Contents of section \.bss:
+ Contents of section \.MMIX\.reg_contents:
+  07e8 00000000 0000107c 00000000 0000a420  .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-14m.d	Mon Jan 28 02:03:07 2002
***************
*** 0 ****
--- 1,20 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # A BPO against an external symbol.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+8 g       \.text areg
+
+ Contents of section \.text:
+  0000 e3fd0001 234dfe00 fd040810           .*
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000003                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-13.d	Mon Jan 28 01:18:47 2002
***************
*** 0 ****
--- 1,9 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: areg-256.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #error: base-plus-offset relocation against register symbol
+
+ # Check that we get an error message if we see a BPO against a register
+ # symbol.  Variant 2: a register symbol.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-7.s	Mon Jan 28 01:13:17 2002
***************
*** 0 ****
--- 1,2 ----
+ # If the symbol is a register then this is an error.
+  LDA $77,areg-5
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-12.d	Mon Jan 28 01:16:58 2002
***************
*** 0 ****
--- 1,9 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: greg-1.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #error: base-plus-offset relocation against register symbol
+
+ # Check that we get an error message if we see a BPO against a register
+ # symbol.  Variant 1: a GREG allocated register.
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-16m.d	Fri Feb  1 05:26:59 2002
***************
*** 0 ****
--- 1,21 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: bpo-7.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # Two BPO:s against the same value get merged.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+c g       \.text areg
+
+ Contents of section \.text:
+  0000 e3fd0001 234dfe00 234dfe00 fd040810  .*
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000007                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-14.d	Mon Jan 28 01:23:40 2002
***************
*** 0 ****
--- 1,33 ----
+ #source: start.s
+ #source: bpo-7.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # A BPO against an external symbol.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ g       \.text	0+ _start
+ 0+8 g       \.text	0+ areg
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 234dfe00 fd040810           .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000003                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-8.s	Mon Jan 28 05:05:43 2002
***************
*** 0 ****
--- 1,3 ----
+ # A BPO and an ordinary reloc in the same section.
+  LDA $54,areg-8
+  .quad areg-4
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-17.d	Fri Feb  1 05:27:42 2002
***************
*** 0 ****
--- 1,34 ----
+ #source: start.s
+ #source: bpo-8.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m elf64mmix
+ #objdump: -st
+
+ # A BPO and another reloc in the same section.
+
+ .*:     file format elf64-mmix
+
+ SYMBOL TABLE:
+ 0+ l    d  \.text	0+
+ 2000000000000000 l    d  \.data	0+
+ 2000000000000000 l    d  \.sbss	0+
+ 2000000000000000 l    d  \.bss	0+
+ 0+7f0 l    d  \.MMIX\.reg_contents	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ l    d  \*ABS\*	0+
+ 0+ g       \.text	0+ _start
+ 0+10 g       \.text	0+ areg
+ 2000000000000000 g     O \*ABS\*	0+ __bss_start
+ 2000000000000000 g     O \*ABS\*	0+ _edata
+ 2000000000000000 g     O \*ABS\*	0+ _end
+ 0+ g     O \.text	0+ _start\.
+
+ Contents of section \.text:
+  0000 e3fd0001 2336fe00 00000000 0000000c  .*
+  0010 fd040810                             .*
+ Contents of section \.data:
+ Contents of section \.sbss:
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000008                    .*
*** /dev/null	Tue Jan  1 05:00:00 1980
--- ld-mmix/bpo-17m.d	Fri Feb  1 05:27:51 2002
***************
*** 0 ****
--- 1,22 ----
+ #source: start.s
+ #source: bpo-8.s
+ #source: areg-t.s
+ #as: -linker-allocated-gregs
+ #ld: -m mmo
+ #objdump: -st
+
+ # A BPO and another reloc in the same section.
+
+ .*:     file format mmo
+
+ SYMBOL TABLE:
+ 0+ g       \.text Main
+ 0+ g       \.text _start
+ 0+10 g       \.text areg
+
+
+ Contents of section \.text:
+  0000 e3fd0001 2336fe00 00000000 0000000c  .*
+  0010 fd040810                             .*
+ Contents of section \.MMIX\.reg_contents:
+  07f0 00000000 00000008                    .*

brgds, H-P


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