aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2002-08-29 06:49:35 +0000
committerNick Clifton <nickc@redhat.com>2002-08-29 06:49:35 +0000
commit86aba9dbfa7eb9bf07dd611c85e3cff31ebaa740 (patch)
tree28cea41b52ede49cce06280bbf5c3702ba3a0df4 /gas
parent6ba3d7ed59de300442a9273d85c7a178e2296c3d (diff)
downloadgdb-86aba9dbfa7eb9bf07dd611c85e3cff31ebaa740.zip
gdb-86aba9dbfa7eb9bf07dd611c85e3cff31ebaa740.tar.gz
gdb-86aba9dbfa7eb9bf07dd611c85e3cff31ebaa740.tar.bz2
Add linker relaxation to v850 toolchain
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog21
-rw-r--r--gas/config/tc-v850.c118
-rw-r--r--gas/config/tc-v850.h5
-rw-r--r--gas/doc/c-v850.texi23
4 files changed, 142 insertions, 25 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index e8bf9fe..a083a87 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,24 @@
+2000-08-28 Catherine Moore <clm@redhat.com>
+
+ * tc-v850.c (v850_relax): Declare.
+ (v850_longcode): New routine.
+ (v850_handle_align): New routine.
+ (md_pseudo_table): Add longcall and longjump.
+ (md_parse_option): Check for relax option.
+ (tc_gen_reloc): Handle BFD_RELOC_V850_LONGCALL,
+ BFD_RELOC_V850_LONGJUMP, and BFD_RELOC_V850_ALIGN.
+ (md_apply_fix3): Likewise.
+ (v850_force_relocation): Likewise.
+ (v850_comm): Change the current section.
+ (md_assemble): Ensure that the correct value is put in the
+ fixup.
+ (v850_sdata, v850_tdata, v850_zdata, v850_sbss, v850_tbss,
+ v850_zbss, v850_rosdata, v850_rozdata): Fix section book keeping.
+ Remove redundant v850ea support.
+ * tc-v850.h (HANDLE_ALIGN): Define.
+ (v850_handle_align): Declare.
+ * doc/c-v850.c: Document -mrelax, .longcall and .longjump.
+
2002-08-28 Svein E. Seldal <Svein.Seldal@solidas.com>
* configure.in: Add tic4x-coff* and c4x-coff*-coff-coff targets.
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
index 2d159cd..aa789b3 100644
--- a/gas/config/tc-v850.c
+++ b/gas/config/tc-v850.c
@@ -78,6 +78,8 @@ const relax_typeS md_relax_table[] = {
{0x1fffff, -0x200000, 4, 0},
};
+static int v850_relax = 0;
+
/* Fixups. */
#define MAX_INSN_FIXUPS (5)
struct v850_fixup {
@@ -394,7 +396,13 @@ v850_comm (area)
}
else
{
+ segT old_sec;
+ int old_subsec;
+
allocate_common:
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+
S_SET_VALUE (symbolP, (valueT) size);
S_SET_ALIGN (symbolP, temp);
S_SET_EXTERNAL (symbolP);
@@ -411,6 +419,9 @@ v850_comm (area)
default:
abort ();
}
+
+ obj_elf_section_change_hook ();
+ subseg_set (old_sec, old_subsec);
}
}
else
@@ -468,10 +479,45 @@ set_machine (number)
{
case 0: processor_mask = PROCESSOR_V850; break;
case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break;
- case bfd_mach_v850ea: processor_mask = PROCESSOR_V850EA; break;
}
}
+static void v850_longcode PARAMS ((int));
+
+static void
+v850_longcode (type)
+ int type;
+{
+ expressionS ex;
+
+ if (! v850_relax)
+ {
+ if (type == 1)
+ as_warn (".longcall pseudo-op seen when not relaxing");
+ else
+ as_warn (".longjump pseudo-op seen when not relaxing");
+ }
+
+ expression (&ex);
+
+ if (ex.X_op != O_symbol || ex.X_add_number != 0)
+ {
+ as_bad ("bad .longcall format");
+ ignore_rest_of_line ();
+
+ return;
+ }
+
+ if (type == 1)
+ fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
+ BFD_RELOC_V850_LONGCALL);
+ else
+ fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
+ BFD_RELOC_V850_LONGJUMP);
+
+ demand_empty_rest_of_line ();
+}
+
/* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] = {
{ "sdata", v850_seg, SDATA_SECTION },
@@ -492,9 +538,10 @@ const pseudo_typeS md_pseudo_table[] = {
{ "call_table_data", v850_seg, CALL_TABLE_DATA_SECTION },
{ "call_table_text", v850_seg, CALL_TABLE_TEXT_SECTION },
{ "v850e", set_machine, bfd_mach_v850e },
- { "v850ea", set_machine, bfd_mach_v850ea },
{ "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
+ { "longcall", v850_longcode, 1 },
+ { "longjump", v850_longcode, 2 },
{ NULL, NULL, 0 }
};
@@ -1103,8 +1150,9 @@ md_show_usage (stream)
fprintf (stream, _(" -mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n"));
fprintf (stream, _(" -mv850 The code is targeted at the v850\n"));
fprintf (stream, _(" -mv850e The code is targeted at the v850e\n"));
- fprintf (stream, _(" -mv850ea The code is targeted at the v850ea\n"));
fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n"));
+ fprintf (stream, _(" -mrelax Enable relaxation\n"));
+
}
int
@@ -1138,19 +1186,16 @@ md_parse_option (c, arg)
machine = bfd_mach_v850e;
processor_mask = PROCESSOR_V850E;
}
- else if (strcmp (arg, "v850ea") == 0)
- {
- machine = bfd_mach_v850ea;
- processor_mask = PROCESSOR_V850EA;
- }
else if (strcmp (arg, "v850any") == 0)
{
/* Tell the world that this is for any v850 chip. */
machine = 0;
/* But support instructions for the extended versions. */
- processor_mask = PROCESSOR_V850EA;
+ processor_mask = PROCESSOR_V850E;
}
+ else if (strcmp (arg, "relax") == 0)
+ v850_relax = 1;
else
{
/* xgettext:c-format */
@@ -1275,17 +1320,9 @@ void
md_begin ()
{
char *prev_name = "";
- register const struct v850_opcode *op;
-
- if (strncmp (TARGET_CPU, "v850ea", 6) == 0)
- {
- if (machine == -1)
- machine = bfd_mach_v850ea;
+ const struct v850_opcode *op;
- if (processor_mask == -1)
- processor_mask = PROCESSOR_V850EA;
- }
- else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
+ if (strncmp (TARGET_CPU, "v850e", 5) == 0)
{
if (machine == -1)
machine = bfd_mach_v850e;
@@ -1750,8 +1787,7 @@ md_assemble (str)
extra_data_after_insn = true;
extra_data_len = 4;
- extra_data = ex.X_add_number;
- ex.X_add_number = 0;
+ extra_data = 0;
break;
default:
@@ -2215,12 +2251,32 @@ tc_gen_reloc (seg, fixp)
if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
reloc->addend = fixp->fx_offset;
+ else if ( fixp->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixp->fx_r_type == BFD_RELOC_V850_LONGJUMP
+ || fixp->fx_r_type == BFD_RELOC_V850_ALIGN)
+ reloc->addend = fixp->fx_offset;
else
reloc->addend = fixp->fx_addnumber;
return reloc;
}
+void
+v850_handle_align (frag)
+ fragS * frag;
+{
+ if (v850_relax
+ && frag->fr_type == rs_align
+ && frag->fr_address + frag->fr_fix > 0
+ && frag->fr_offset > 1
+ && now_seg != bss_section
+ && now_seg != v850_seg_table[SBSS_SECTION].s
+ && now_seg != v850_seg_table[TBSS_SECTION].s
+ && now_seg != v850_seg_table[ZBSS_SECTION].s)
+ fix_new (frag, frag->fr_fix, 2, & abs_symbol, frag->fr_offset, 0,
+ BFD_RELOC_V850_ALIGN);
+}
+
/* Return current size of variable part of frag. */
int
@@ -2261,6 +2317,8 @@ md_apply_fix3 (fixP, valueP, seg)
char *where;
if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
{
fixP->fx_done = 0;
@@ -2268,10 +2326,11 @@ md_apply_fix3 (fixP, valueP, seg)
}
if (fixP->fx_addsy == (symbolS *) NULL)
+ fixP->fx_addnumber = value,
fixP->fx_done = 1;
else if (fixP->fx_pcrel)
- ;
+ fixP->fx_addnumber = fixP->fx_offset;
else
{
@@ -2287,6 +2346,7 @@ md_apply_fix3 (fixP, valueP, seg)
_("expression too complex"));
}
}
+ fixP->fx_addnumber = value;
}
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
@@ -2345,8 +2405,6 @@ md_apply_fix3 (fixP, valueP, seg)
else if (fixP->fx_size == 4)
bfd_putl32 (value, (unsigned char *) where);
}
-
- fixP->fx_addnumber = value;
}
/* Parse a cons expression. We have to handle hi(), lo(), etc
@@ -2430,5 +2488,17 @@ v850_force_relocation (fixP)
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 1;
+ if ( fixP->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP)
+ return 1;
+
+ if (v850_relax
+ && (fixP->fx_pcrel
+ || fixP->fx_r_type == BFD_RELOC_V850_ALIGN
+ || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_9_PCREL
+ || fixP->fx_r_type >= BFD_RELOC_UNUSED))
+ return 1;
+
return 0;
}
diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h
index 8257428..f3827e7 100644
--- a/gas/config/tc-v850.h
+++ b/gas/config/tc-v850.h
@@ -70,6 +70,11 @@ extern void cons_fix_new_v850 PARAMS ((fragS *, int, int, expressionS *));
#define TC_GENERIC_RELAX_TABLE md_relax_table
extern const struct relax_type md_relax_table[];
+/* When relaxing, we need to generate
+ relocations for alignment directives. */
+#define HANDLE_ALIGN(frag) v850_handle_align (frag)
+extern void v850_handle_align PARAMS ((fragS *));
+
/* This section must be in the small data area (pointed to by GP). */
#define SHF_V850_GPREL 0x10000000
/* This section must be in the tiny data area (pointed to by EP). */
diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi
index 4b36461..f67ad5c 100644
--- a/gas/doc/c-v850.texi
+++ b/gas/doc/c-v850.texi
@@ -62,6 +62,14 @@ routines used by the code produced by GCC for all versions of the v850
architecture, together with support routines only used by the V850E
architecture.
+@cindex @code{-mrelax} command line option, V850
+@item -mrelax
+Enables relaxation. This allows the .longcall and .longjump pseudo
+ops to be used in the assembler source code. These ops label sections
+of code which are either a long function call or a long branch. The
+assembler will then flag these sections of code and the linker will
+attempt to relax them.
+
@end table
@@ -354,10 +362,23 @@ example:
will put the call the function whoes address is held in the call table
at the location labeled 'table_func1'.
+@cindex @code{longcall} pseudo-op, V850
+@item .longcall @code{name}
+Indicates that the following sequence of instructions is a long call
+to function @code{name}. The linker will attempt to shorten this call
+sequence if @code{name} is within a 22bit offset of the call. Only
+valid if the @code{-mrelax} command line switch has been enabled.
+
+@cindex @code{longjump} pseudo-op, V850
+@item .longjump @code{name}
+Indicates that the following sequence of instructions is a long jump
+to label @code{name}. The linker will attempt to shorten this code
+sequence if @code{name} is within a 22bit offset of the jump. Only
+valid if the @code{-mrelax} command line switch has been enabled.
+
@end table
For information on the V850 instruction set, see @cite{V850
Family 32-/16-Bit single-Chip Microcontroller Architecture Manual} from NEC.
Ltd.
-