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]

PATCH to gas: --pcrel option for m68k


Hi there,

Back in April, after a thorough discussion with then-maintainer Ian, I posted a
patch adding a --pcrel option to m68k gas (for use in parallel with -mpcrel in
current gcc) that keeps all branches always PC-relative, never turning them
into absolute jumps. That patch fell through the cracks. I didn't bug anyone
because I didn't have a copyright assignment, but now I do. Below is this patch
brought up-to-date with the current CVS. Can Nick or another maintainer please
review it? TIA.

--
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-07-23  Michael Sokolov  <msokolov@ivan.Harhan.ORG>

	* config/tc-m68k.c (flag_keep_pcrel, OPTION_PCREL): Add --pcrel option.
	(md_convert_frag_1, md_estimate_size_before_relax): When making DBcc
	long emit a long branch if available instead of an absolute jump, never
	emit absolute jumps for anything with --pcrel.

Index: tc-m68k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68k.c,v
retrieving revision 1.8
diff -c -r1.8 tc-m68k.c
*** tc-m68k.c	2000/07/07 16:58:24	1.8
--- tc-m68k.c	2000/07/23 17:30:07
***************
*** 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;
***************
*** 4319,4324 ****
--- 4320,4327 ----
      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 */
  	    {
***************
*** 4363,4368 ****
--- 4366,4373 ----
      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 */
  
***************
*** 4379,4396 ****
        break;
      case TAB (DBCC, LONG):
        /* only DBcc 68000 instructions can come here */
!       /* change dbcc into dbcc/jmp absl long */
        /* JF: these used to be fr_opcode[2-7], but that's wrong */
        *buffer_address++ = 0x00;	/* branch offset = 4 */
        *buffer_address++ = 0x04;
        *buffer_address++ = 0x60;	/* put in bra pc+6 */
        *buffer_address++ = 0x06;
!       *buffer_address++ = 0x4e;	/* put in jmp long (0x4ef9) */
!       *buffer_address++ = (char) 0xf9;
  
        fragP->fr_fix += 6;	/* account for bra/jmp instructions */
        fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
! 	       fragP->fr_offset, 0, NO_RELOC);
        fragP->fr_fix += 4;
        ext = 0;
        break;
--- 4384,4412 ----
        break;
      case TAB (DBCC, LONG):
        /* only DBcc 68000 instructions can come here */
!       /* change dbcc into dbcc/bral */
!       if (!HAVE_LONG_BRANCH(current_architecture) && 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;
        *buffer_address++ = 0x60;	/* put in bra pc+6 */
        *buffer_address++ = 0x06;
!       if (HAVE_LONG_BRANCH(current_architecture))
! 	{
! 	  *buffer_address++ = 0x60;	/* put in bral (0x60ff) */
! 	  *buffer_address++ = (char) 0xff;
! 	}
!       else
! 	{
! 	  *buffer_address++ = 0x4e;	/* put in jmp long (0x4ef9) */
! 	  *buffer_address++ = (char) 0xf9;
! 	}
  
        fragP->fr_fix += 6;	/* account for bra/jmp instructions */
        fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
! 	       fragP->fr_offset, HAVE_LONG_BRANCH(current_architecture),
! 	       NO_RELOC);
        fragP->fr_fix += 4;
        ext = 0;
        break;
***************
*** 4532,4538 ****
  	    fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
  	    break;
  	  }
! 	else if ((fragP->fr_symbol != NULL) && flag_short_refs)
  	  {			/* 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);
--- 4548,4555 ----
  	    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);
***************
*** 4630,4636 ****
  	    break;
  	  }
  	/* only Bcc 68000 instructions can come here */
! 	if ((fragP->fr_symbol != NULL) && flag_short_refs)
  	  {
  	    /* the user wants short refs, so emit one */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
--- 4647,4653 ----
  	    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,
***************
*** 4666,4672 ****
  	  }
  	/* only DBcc 68000 instructions can come here */
  
! 	if (fragP->fr_symbol != NULL && flag_short_refs)
  	  {
  	    /* the user wants short refs, so emit one */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
--- 4683,4690 ----
  	  }
  	/* only DBcc 68000 instructions can come here */
  
! 	if (fragP->fr_symbol != NULL && (flag_short_refs
! 	    || !HAVE_LONG_BRANCH(current_architecture) && flag_keep_pcrel))
  	  {
  	    /* the user wants short refs, so emit one */
  	    fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
***************
*** 4675,4692 ****
  	  }
  	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) */
! 	    buffer_address[5] = (char) 0xf9;
  	    fragP->fr_fix += 6;	/* account for bra/jmp instruction */
  	    fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
! 		     fragP->fr_offset, 0, NO_RELOC);
  	    fragP->fr_fix += 4;
  	  }
  
--- 4693,4719 ----
  	  }
  	else
  	  {
! 	    /* change dbcc into dbcc/bral */
  	    /* 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 */
! 	    if (HAVE_LONG_BRANCH(current_architecture))
! 	      {
! 		buffer_address[4] = 0x60;	/* put in bral (0x60ff) */
! 		buffer_address[5] = (char) 0xff;
! 	      }
! 	    else
! 	      {
! 		buffer_address[4] = 0x4e;	/* put in jmp long (0x4ef9) */
! 		buffer_address[5] = (char) 0xf9;
! 	      }
  	    fragP->fr_fix += 6;	/* account for bra/jmp instruction */
  	    fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
! 		     fragP->fr_offset, HAVE_LONG_BRANCH(current_architecture),
! 		     NO_RELOC);
  	    fragP->fr_fix += 4;
  	  }
  
***************
*** 6745,6750 ****
--- 6772,6778 ----
   *
   *	-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.
***************
*** 6773,6778 ****
--- 6801,6808 ----
    {"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);
***************
*** 6794,6799 ****
--- 6824,6834 ----
        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++;
***************
*** 6950,6955 ****
--- 6985,6991 ----
  			[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]