This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Revised m68k gas relaxing patch
- To: binutils at sourceware dot cygnus dot com
- Subject: Revised m68k gas relaxing patch
- From: msokolov at ivan dot Harhan dot ORG (Michael Sokolov)
- Date: Wed, 19 Apr 00 19:21:51 CDT
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"));