This is the mail archive of the binutils@sourceware.cygnus.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]

Revised m68k gas relaxing patch


OK guys,

Here is a revised version of my previous two patches to gas/config/tc-m68k.c
(-l fix and bogus CPU check removal). It has both of those and adds another
change that goes hand-in-hand with those: -pcrel option disabling relaxation of
PC-relative branches to absolute jumps. Right now it has the same effect as -l
(short references) on branches that would otherwise result in absolute jumps.
This is better than -l for this purpose becuase it forces a short reference
only where an absolute jump would result otherwise, instead of just banning all
long references. It also makes as squeak when an absolute jump does result
(when an intramodule reference exceeds 32 KB and there is no alternative to
absolute jumps), rather than letting the programmer scratch his/her head over a
crashing program.

I think these should remain separate options because they convey different
intentions: -l means keep external references short because the linker can't
relax (yet) and -pcrel means keep all references PC-relatives because absolute
ones are banned. It's just that right now they have pretty much the same effect
of disabling certain relaxation modes, but this will change soon. With the new
linker-based relaxer -l won't be necessary and will be ignored, while -pcrel
will offer new relaxation modes, not just disable current unacceptable ones.

This patch will apply cleanly against the current CVS. I'm submitting it as one
patch rather than breaking it up because if I do the latter, the pieces won't
apply cleanly (I correct the broken handling of -l and handle the new -pcrel in
the same lines).

My next patch will probably be a testsuite addition to test all this.

--
Michael Sokolov		Harhan Engineering Laboratory
Public Service Agent	International Free Computing Task Force
			International Engineering and Science Task Force
			615 N GOOD LATIMER EXPY STE #4
			DALLAS TX 75204-5852 USA

Phone: +1-214-824-7693 (Harhan Eng Lab office)
E-mail: msokolov@ivan.Harhan.ORG (ARPA TCP/SMTP) (UUCP coming soon)

2000-04-19  Michael Sokolov  <msokolov@ivan.Harhan.ORG>

	* config/tc-m68k.c (flag_keep_pcrel, OPTION_PCREL): add -pcrel option
	disabling relaxation of PC-relative branches to absolute jumps.
	(m68k-ip case ABSL): allow absolute reference => 16-bit PC-relative
	relaxation on all CPUs.
	(md_convert_frag_1): self-checks: make sure that the code for
	unconditional branches doesn't execute for conditional ones and that an
	absolute reference is not emitted with -pcrel.
	(md_estimate_size_before_relax): correctly handle -l and -pcrel, self-
	check to make sure that the code for unconditional branches doesn't
	execute for conditional ones, remove bogus CPU check for absolute
	reference => 16-bit PC-relative relaxation.

Index: tc-m68k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68k.c,v
retrieving revision 1.5
diff -c -3 -p -r1.5 tc-m68k.c
*** tc-m68k.c	1999/07/12 08:34:56	1.5
--- tc-m68k.c	2000/04/19 22:57:56
*************** int flag_want_pic;
*** 74,79 ****
--- 74,80 ----
  
  static int flag_short_refs;	/* -l option */
  static int flag_long_jumps;	/* -S option */
+ static int flag_keep_pcrel;	/* -pcrel option */
  
  #ifdef REGISTER_PREFIX_OPTIONAL
  int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
*************** m68k_ip (instring)
*** 2363,2370 ****
  		      addword (nextword);
  		      break;
  		    }
- 		  /* Don't generate pc relative code on 68010 and
- 		     68000.  */
  		  if (isvar (&opP->disp)
  		      && !subs (&opP->disp)
  		      && adds (&opP->disp)
--- 2364,2369 ----
*************** m68k_ip (instring)
*** 2375,2381 ****
  #endif
  		      && S_GET_SEGMENT (adds (&opP->disp)) == now_seg
  		      && relaxable_symbol (adds (&opP->disp))
- 		      && HAVE_LONG_BRANCH(current_architecture)
  		      && !flag_long_jumps
  		      && !strchr ("~%&$?", s[0]))
  		    {
--- 2374,2379 ----
*************** md_convert_frag_1 (fragP)
*** 4319,4324 ****
--- 4317,4324 ----
      case TAB (ABRANCH, LONG):
        if (!HAVE_LONG_BRANCH(current_architecture))
  	{
+ 	  if (flag_keep_pcrel)
+ 	    as_bad (_("long branch not supported"));
  	  if (fragP->fr_opcode[0] == 0x61)
  	    /* BSR */
  	    {
*************** md_convert_frag_1 (fragP)
*** 4348,4354 ****
  	    }
  	  else
  	    {
! 	      as_bad (_("Long branch offset not supported."));
  	    }
  	}
        else
--- 4348,4357 ----
  	    }
  	  else
  	    {
! 	      /* This should never happen, because if it's a conditional
! 	         branch and we are on a 68000, BCC68000 should have been
! 	         picked instead of ABRANCH. */
! 	      abort ();
  	    }
  	}
        else
*************** md_convert_frag_1 (fragP)
*** 4360,4365 ****
--- 4363,4370 ----
      case TAB (BCC68000, LONG):
        /* only Bcc 68000 instructions can come here */
        /* change bcc into b!cc/jmp absl long */
+       if (flag_keep_pcrel)
+ 	as_bad (_("long branch not supported"));
        fragP->fr_opcode[0] ^= 0x01;	/* invert bcc */
        fragP->fr_opcode[1] = 0x6;/* branch offset = 6 */
  
*************** md_convert_frag_1 (fragP)
*** 4377,4382 ****
--- 4382,4389 ----
      case TAB (DBCC, LONG):
        /* only DBcc 68000 instructions can come here */
        /* change dbcc into dbcc/jmp absl long */
+       if (flag_keep_pcrel)
+ 	as_bad (_("long branch not supported"));
        /* JF: these used to be fr_opcode[2-7], but that's wrong */
        *buffer_address++ = 0x00;	/* branch offset = 4 */
        *buffer_address++ = 0x04;
*************** md_estimate_size_before_relax (fragP, se
*** 4529,4534 ****
--- 4536,4550 ----
  	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
  	    break;
  	  }
+ 	else if ((fragP->fr_symbol != NULL)
+ 		 && (flag_short_refs || flag_keep_pcrel))
+ 	  {			/* Symbol is undefined and we want short ref */
+ 	    fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
+ 		     fragP->fr_offset, 1, NO_RELOC);
+ 	    fragP->fr_fix += 2;
+ 	    frag_wane (fragP);
+ 	    break;
+ 	  }
  	else if ((fragP->fr_symbol == 0) || !HAVE_LONG_BRANCH(current_architecture))
  	  {
  	    /* On 68000, or for absolute value, switch to abs long */
*************** md_estimate_size_before_relax (fragP, se
*** 4553,4559 ****
  	      }
  	    else
  	      {
! 		as_warn (_("Long branch offset to extern symbol not supported."));
  	      }
  	  }
  	else
--- 4569,4578 ----
  	      }
  	    else
  	      {
! 		/* This should never happen, because if it's a conditional
! 		   branch and we are on a 68000, BCC68000 should have been
! 		   picked instead of ABRANCH. */
! 		abort ();
  	      }
  	  }
  	else
*************** md_estimate_size_before_relax (fragP, se
*** 4593,4601 ****
        {
  	if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
  	     && relaxable_symbol (fragP->fr_symbol))
! 	    || flag_short_refs
! 	    || cpu_of_arch (current_architecture) < m68020
! 	    || cpu_of_arch (current_architecture) == mcf5200)
  	  {
  	    fragP->fr_subtype = TAB (PCREL, SHORT);
  	    fragP->fr_var += 2;
--- 4612,4618 ----
        {
  	if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
  	     && relaxable_symbol (fragP->fr_symbol))
! 	    || flag_short_refs)
  	  {
  	    fragP->fr_subtype = TAB (PCREL, SHORT);
  	    fragP->fr_var += 2;
*************** md_estimate_size_before_relax (fragP, se
*** 4618,4638 ****
  	    break;
  	  }
  	/* only Bcc 68000 instructions can come here */
! 	/* change bcc into b!cc/jmp absl long */
! 	fragP->fr_opcode[0] ^= 0x01;	/* invert bcc */
! 	if (flag_short_refs)
  	  {
! 	    fragP->fr_opcode[1] = 0x04;	/* branch offset = 6 */
! 	    /* JF: these were fr_opcode[2,3] */
! 	    buffer_address[0] = 0x4e;	/* put in jmp long (0x4ef9) */
! 	    buffer_address[1] = (char) 0xf8;
! 	    fragP->fr_fix += 2;	/* account for jmp instruction */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
! 		     fragP->fr_offset, 0, NO_RELOC);
  	    fragP->fr_fix += 2;
  	  }
  	else
  	  {
  	    fragP->fr_opcode[1] = 0x06;	/* branch offset = 6 */
  	    /* JF: these were fr_opcode[2,3] */
  	    buffer_address[0] = 0x4e;	/* put in jmp long (0x4ef9) */
--- 4635,4651 ----
  	    break;
  	  }
  	/* only Bcc 68000 instructions can come here */
! 	if ((fragP->fr_symbol != NULL) && (flag_short_refs || flag_keep_pcrel))
  	  {
! 	    /* the user wants short refs, so emit one */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
! 		     fragP->fr_offset, 1, NO_RELOC);
  	    fragP->fr_fix += 2;
  	  }
  	else
  	  {
+ 	    /* change bcc into b!cc/jmp absl long */
+ 	    fragP->fr_opcode[0] ^= 0x01;	/* invert bcc */
  	    fragP->fr_opcode[1] = 0x06;	/* branch offset = 6 */
  	    /* JF: these were fr_opcode[2,3] */
  	    buffer_address[0] = 0x4e;	/* put in jmp long (0x4ef9) */
*************** md_estimate_size_before_relax (fragP, se
*** 4657,4681 ****
  	    break;
  	  }
  	/* only DBcc 68000 instructions can come here */
- 	/* change dbcc into dbcc/jmp absl long */
- 	/* JF: these used to be fr_opcode[2-4], which is wrong. */
- 	buffer_address[0] = 0x00;	/* branch offset = 4 */
- 	buffer_address[1] = 0x04;
- 	buffer_address[2] = 0x60;	/* put in bra pc + ... */
  
! 	if (flag_short_refs)
  	  {
! 	    /* JF: these were fr_opcode[5-7] */
! 	    buffer_address[3] = 0x04;	/* plus 4 */
! 	    buffer_address[4] = 0x4e;	/* Put in Jump Word */
! 	    buffer_address[5] = (char) 0xf8;
! 	    fragP->fr_fix += 6;	/* account for bra/jmp instruction */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
! 		     fragP->fr_offset, 0, NO_RELOC);
  	    fragP->fr_fix += 2;
  	  }
  	else
  	  {
  	    /* JF: these were fr_opcode[5-7] */
  	    buffer_address[3] = 0x06;	/* Plus 6 */
  	    buffer_address[4] = 0x4e;	/* put in jmp long (0x4ef9) */
--- 4670,4690 ----
  	    break;
  	  }
  	/* only DBcc 68000 instructions can come here */
  
! 	if (fragP->fr_symbol != NULL && (flag_short_refs || flag_keep_pcrel))
  	  {
! 	    /* the user wants short refs, so emit one */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
! 		     fragP->fr_offset, 1, NO_RELOC);
  	    fragP->fr_fix += 2;
  	  }
  	else
  	  {
+ 	    /* change dbcc into dbcc/jmp absl long */
+ 	    /* JF: these used to be fr_opcode[2-4], which is wrong. */
+ 	    buffer_address[0] = 0x00;	/* branch offset = 4 */
+ 	    buffer_address[1] = 0x04;
+ 	    buffer_address[2] = 0x60;	/* put in bra pc + ... */
  	    /* JF: these were fr_opcode[5-7] */
  	    buffer_address[3] = 0x06;	/* Plus 6 */
  	    buffer_address[4] = 0x4e;	/* put in jmp long (0x4ef9) */
*************** s_mri_endw (ignore)
*** 6741,6746 ****
--- 6750,6756 ----
   *
   *	-pic	Indicates PIC.
   *	-k	Indicates PIC.  (Sun 3 only.)
+  *	-pcrel	Never turn PC-relative branches into absolute jumps.
   *
   *	--bitwise-or
   *		Permit `|' to be used in expressions.
*************** struct option md_longopts[] = {
*** 6769,6774 ****
--- 6779,6786 ----
    {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16},
  #define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6)
    {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
+ #define OPTION_PCREL (OPTION_MD_BASE + 7)
+   {"pcrel", no_argument, NULL, OPTION_PCREL},
    {NULL, no_argument, NULL, 0}
  };
  size_t md_longopts_size = sizeof(md_longopts);
*************** md_parse_option (c, arg)
*** 6790,6795 ****
--- 6802,6812 ----
        flag_long_jumps = 1;
        break;
  
+     case OPTION_PCREL:		/* -pcrel means never turn PC-relative branches
+ 				   into absolute jumps.  */
+       flag_keep_pcrel = 1;
+       break;
+ 
      case 'A':
        if (*arg == 'm')
   	arg++;
*************** md_show_usage (stream)
*** 6946,6951 ****
--- 6963,6969 ----
  			[default yes for 68020 and up]\n\
  -pic, -k		generate position independent code\n\
  -S			turn jbsr into jsr\n\
+ -pcrel			never turn PC-relative branches into absolute jumps\n\
  --register-prefix-optional\n\
  			recognize register names without prefix character\n\
  --bitwise-or		do not treat `|' as a comment character\n"));

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