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]

[patch] New target - Fujitsu FRV


Hi,

Attached is a patch which adds bfd/gas/ld/binutils support for Fujitsu's FRV architecture targeting frv-elf, including models for the FR400 and FR500. This patch is part of a larger submission of bfd, gas, ld, binutils, sim, gdb and newlib for the FRV by Red Hat.

Seeking approval to commit.

Dave

opcodes/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	* po/POTFILES.in: Add frv-*.[ch].
	* disassemble.c (ARCH_frv): New macro.
	(disassembler): Handle bfd_arch_frv.
	* configure.in: Support frv_bfd_arch.
	* Makefile.am (HFILES): Add frv-*.h.
	(CFILES): Add frv-*.c
	(ALL_MACHINES): Add frv-*.lo.
	(CLEANFILES): Add stamp-frv.
	(FRV_DEPS): New variable.
	(stamp-frv): New target.
	(frv-asm.lo): New target.
	(frv-desc.lo): New target.
	(frv-dis.lo): New target.
	(frv-ibld.lo): New target.
	(frv-opc.lo): New target.
	(frv-*.[ch]): New files.

ld/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Catherine Moore, Michael Meissner, Jim Blandy:
	* emulparams/elf32frv.sh: New file.
	* configure.tgt: Support frv-*-*.
	* Makefile.am (ALL_EMULATIONS): Add eelf32frv.o.
	(eelf32frv.c): New target.

include/elf/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Catherine Moore, Michael Meissner, Dave Brolley:
	* common.h (EM_CYGNUS_FRV): New macro.
	* frv.h: New file.

include/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Catherine Moore:
	* dis-asm.h (print_insn_frv): New prototype.

gas/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Catherine Moore, Michael Meissner, Richard Sandiford, Dave Brolley:
	* po/POTFILES.in: Add tc-frv.c, tc-frv.h.
	* configure.in: Support frv-*-*.
	* Makefile.am (CPU_TYPES): Add frv.
	(TARGET_CPU_CFILES): Add tc-frv.c.
	(TARGET_CPU_HFILES): Add tc-frv.h.
	(DEPTC_frv_coff): New variable.
	(DEPTC_frv_elf): New variable.
	(DEPOBJ_frv_coff): New variable.
	(DEPOBJ_frv_elf): New variable.
	(DEP_frv_coff): New variable.
	(DEP_frv_elf): New variable.
	* tc-frv.c: New file.
	* tc-frv.h: New file.

binutils/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Caherine Moore:
	* readelf.c (elf/frv.h): #include it.
	(guess_is_rela): Support EM_CYGNUS_FRV.
	(dump_relocations): Ditto.
	(get_machine_name): Ditto.
	* Makefile.am (readelf.o): add dependency on $(INCDIR)/elf/frv.h.

bfd/ChangeLog:
2002-06-11  Dave Brolley  <brolley@redhat.com>

	From Catherine Moore, Michael Meissner, Dave Brolley:
	* po/SRC-POTFILES.in: Add cpu-frv.c and elf32-frv.c
	* targets.c: Support bfd_elf32_frv_vec.
	* reloc.c: Add FRV relocs.
	* configure.in: Add support for bfd-elf32-frv-vec.
	* config.bfd (targ_cpu): Add support for frv-*-elf.
	* archures.c: Add frv arch and machines.
	* Makefile.am (ALL_MACHINES): Add cpu-frv.lo.
	(ALL_MACHINES_CFILES): Add cpu-frv.c.
	(BFD32_BACKENDS): Add elf32-frv.lo.
	(BFD32_BACKENDS_CFILES): Add elf32-frv.c
	(cpu-frv.lo): New target.
	(elf32-frv.lo): New target.
	* cpu-frv.c: New file.
	* elf32-frv.c: New file.

Index: bfd/Makefile.am
===================================================================
RCS file: /cvs/src/src/bfd/Makefile.am,v
retrieving revision 1.90
diff -c -p -d -u -p -r1.90 Makefile.am
--- bfd/Makefile.am	8 Jun 2002 23:23:08 -0000	1.90
+++ bfd/Makefile.am	10 Jun 2002 22:02:36 -0000
@@ -58,6 +58,7 @@ ALL_MACHINES = \
 	cpu-d30v.lo \
 	cpu-dlx.lo \
 	cpu-fr30.lo \
+	cpu-frv.lo \
 	cpu-h8300.lo \
 	cpu-h8500.lo \
 	cpu-hppa.lo \
@@ -107,6 +108,7 @@ ALL_MACHINES_CFILES = \
 	cpu-d30v.c \
 	cpu-dlx.c \
 	cpu-fr30.c \
+	cpu-frv.c \
 	cpu-h8300.c \
 	cpu-h8500.c \
 	cpu-hppa.c \
@@ -202,6 +204,7 @@ BFD32_BACKENDS = \
 	elf32-d30v.lo \
 	elf32-dlx.lo \
 	elf32-fr30.lo \
+	elf32-frv.lo \
 	elf32-gen.lo \
 	elf32-h8300.lo \
 	elf32-hppa.lo \
@@ -357,6 +360,7 @@ BFD32_BACKENDS_CFILES = \
 	elf32-d30v.c \
 	elf32-dlx.c \
 	elf32-fr30.c \
+	elf32-frv.c \
 	elf32-gen.c \
 	elf32-h8300.c \
 	elf32-hppa.c \
@@ -830,7 +834,6 @@ DISTCLEANFILES = $(BUILD_CFILES) $(BUILD
 config.status: $(srcdir)/configure $(srcdir)/config.bfd $(srcdir)/configure.host
 	$(SHELL) ./config.status --recheck
 
-
 # What appears below is generated by a hacked mkdep using gcc -MM.
 
 # DO NOT DELETE THIS LINE -- mkdep uses it.
@@ -886,6 +889,7 @@ cpu-d10v.lo: cpu-d10v.c $(INCDIR)/filena
 cpu-d30v.lo: cpu-d30v.c $(INCDIR)/filenames.h
 cpu-dlx.lo: cpu-dlx.c $(INCDIR)/filenames.h
 cpu-fr30.lo: cpu-fr30.c $(INCDIR)/filenames.h
+cpu-frv.lo: cpu-frv.c $(INCDIR)/filenames.h
 cpu-h8300.lo: cpu-h8300.c $(INCDIR)/filenames.h
 cpu-h8500.lo: cpu-h8500.c $(INCDIR)/filenames.h
 cpu-hppa.lo: cpu-hppa.c $(INCDIR)/filenames.h
@@ -1108,6 +1112,10 @@ elf32-dlx.lo: elf32-dlx.c $(INCDIR)/file
 elf32-fr30.lo: elf32-fr30.c $(INCDIR)/filenames.h elf-bfd.h \
   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/elf/fr30.h $(INCDIR)/elf/reloc-macros.h \
+  elf32-target.h
+elf32-frv.lo: elf32-frv.c elf-bfd.h $(INCDIR)/elf/common.h \
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+  $(INCDIR)/elf/frv.h $(INCDIR)/elf/reloc-macros.h \
   elf32-target.h
 elf32-gen.lo: elf32-gen.c $(INCDIR)/filenames.h elf-bfd.h \
   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
Index: bfd/archures.c
===================================================================
RCS file: /cvs/src/src/bfd/archures.c,v
retrieving revision 1.50
diff -c -p -d -u -p -r1.50 archures.c
--- bfd/archures.c	28 May 2002 14:05:10 -0000	1.50
+++ bfd/archures.c	10 Jun 2002 22:02:36 -0000
@@ -247,6 +247,13 @@ DESCRIPTION
 .#define bfd_mach_am33		330
 .  bfd_arch_fr30,
 .#define bfd_mach_fr30		0x46523330
+.  bfd_arch_frv,
+.#define bfd_mach_frv		0
+.#define bfd_mach_frvsimple	1
+.#define bfd_mach_fr300		300
+.#define bfd_mach_fr400		400
+.#define bfd_mach_frvtomcat	499	{* fr500 prototype *}
+.#define bfd_mach_fr500		500
 .  bfd_arch_mcore,
 .  bfd_arch_ia64,      {* HP/Intel ia64 *}
 .#define bfd_mach_ia64_elf64	0
@@ -315,6 +322,7 @@ extern const bfd_arch_info_type bfd_d10v
 extern const bfd_arch_info_type bfd_d30v_arch;
 extern const bfd_arch_info_type bfd_dlx_arch;
 extern const bfd_arch_info_type bfd_fr30_arch;
+extern const bfd_arch_info_type bfd_frv_arch;
 extern const bfd_arch_info_type bfd_h8300_arch;
 extern const bfd_arch_info_type bfd_h8500_arch;
 extern const bfd_arch_info_type bfd_hppa_arch;
@@ -369,6 +377,7 @@ static const bfd_arch_info_type * const 
     &bfd_d30v_arch,
     &bfd_dlx_arch,
     &bfd_fr30_arch,
+    &bfd_frv_arch,
     &bfd_h8300_arch,
     &bfd_h8500_arch,
     &bfd_hppa_arch,
Index: bfd/config.bfd
===================================================================
RCS file: /cvs/src/src/bfd/config.bfd,v
retrieving revision 1.100
diff -c -p -d -u -p -r1.100 config.bfd
--- bfd/config.bfd	8 Jun 2002 23:23:08 -0000	1.100
+++ bfd/config.bfd	10 Jun 2002 22:02:37 -0000
@@ -281,6 +281,10 @@ case "${targ}" in
     targ_defvec=bfd_elf32_fr30_vec
     ;;
 
+  frv-*-elf)
+    targ_defvec=bfd_elf32_frv_vec
+    ;;
+
 
   h8300*-*-elf)
     targ_defvec=bfd_elf32_h8300_vec
Index: bfd/configure.in
===================================================================
RCS file: /cvs/src/src/bfd/configure.in,v
retrieving revision 1.101
diff -c -p -d -u -p -r1.101 configure.in
--- bfd/configure.in	8 Jun 2002 23:23:08 -0000	1.101
+++ bfd/configure.in	10 Jun 2002 22:02:38 -0000
@@ -534,6 +534,7 @@ do
     # This list is alphabetized to make it easy to compare
     # with the two vector lists in targets.c.  For the same reason,
     # use one entry per line, even though this leads to long lines.
+    bfd_elf32_frv_vec)		tb="$tb elf32-frv.lo elf32.lo $elf" ;;
     a29kcoff_big_vec)		tb="$tb coff-a29k.lo cofflink.lo" ;;
     a_out_adobe_vec)		tb="$tb aout-adobe.lo aout32.lo" ;;
     aout0_big_vec)		tb="$tb aout0.lo aout32.lo" ;;
Index: bfd/cpu-frv.c
===================================================================
RCS file: bfd/cpu-frv.c
diff -N bfd/cpu-frv.c
--- bfd/cpu-frv.c	1 Jan 1970 00:00:00 -0000
+++ bfd/cpu-frv.c	10 Jun 2002 22:02:38 -0000
@@ -0,0 +1,64 @@
+/* BFD support for the FRV processor.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+enum {
+  I_frv_generic,
+  I_frv_simple,
+  I_frv_500,
+  I_frv_300,
+};
+
+#define FRV_ARCH(MACHINE, NAME, DEFAULT, NEXT)				\
+{									\
+  32,	                        /* 32 bits in a word */			\
+  32,	                        /* 32 bits in an address */		\
+  8,	                        /* 8 bits in a byte */			\
+  bfd_arch_frv,			/* architecture */			\
+  MACHINE,			/* which machine */			\
+  "frv",			/* architecture name */			\
+  NAME,				/* machine name */			\
+  4,				/* default alignment */			\
+  DEFAULT,			/* is this the default? */		\
+  bfd_default_compatible,	/* architecture comparison fn */	\
+  bfd_default_scan,		/* string to architecture convert fn */	\
+  NEXT				/* next in list */			\
+}
+
+static const bfd_arch_info_type arch_info_300
+  = FRV_ARCH (bfd_mach_fr300,   "fr300",   false, (bfd_arch_info_type *)0);
+
+static const bfd_arch_info_type arch_info_400
+  = FRV_ARCH (bfd_mach_fr400, "fr400", false, &arch_info_300);
+
+static const bfd_arch_info_type arch_info_500
+  = FRV_ARCH (bfd_mach_fr500, "fr500", false, &arch_info_400);
+
+static const bfd_arch_info_type arch_info_simple
+  = FRV_ARCH (bfd_mach_frvsimple, "simple", false, &arch_info_500);
+
+static const bfd_arch_info_type arch_info_tomcat
+  = FRV_ARCH (bfd_mach_frvtomcat, "tomcat", false, &arch_info_simple);
+
+const bfd_arch_info_type bfd_frv_arch
+  = FRV_ARCH (bfd_mach_frv, "frv", true, &arch_info_tomcat);
+
Index: bfd/elf32-frv.c
===================================================================
RCS file: bfd/elf32-frv.c
diff -N bfd/elf32-frv.c
--- bfd/elf32-frv.c	1 Jan 1970 00:00:00 -0000
+++ bfd/elf32-frv.c	10 Jun 2002 22:02:38 -0000
@@ -0,0 +1,1406 @@
+/* FRV-specific support for 32-bit ELF.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/frv.h"
+
+/* Forward declarations.  */
+static bfd_reloc_status_type elf32_frv_relocate_lo16
+  PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_hi16
+  PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_label24
+  PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_gprel12
+  PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_gprelu12
+  PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_gprello
+  PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static bfd_reloc_status_type elf32_frv_relocate_gprelhi
+  PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static reloc_howto_type *frv_reloc_type_lookup
+  PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void frv_info_to_howto_rela 
+  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+static boolean elf32_frv_relocate_section 
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean elf32_frv_add_symbol_hook
+  PARAMS (( bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, const char **, flagword *, asection **, bfd_vma *));
+static bfd_reloc_status_type frv_final_link_relocate
+  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));
+static boolean elf32_frv_gc_sweep_hook
+  PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
+static asection * elf32_frv_gc_mark_hook
+  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
+static boolean elf32_frv_check_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
+static int elf32_frv_machine PARAMS ((bfd *));
+static boolean elf32_frv_object_p PARAMS ((bfd *));
+static boolean frv_elf_set_private_flags PARAMS ((bfd *, flagword));
+static boolean frv_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean frv_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean frv_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
+
+static reloc_howto_type elf32_frv_howto_table [] =
+{
+  /* This reloc does nothing.  */
+  HOWTO (R_FRV_NONE,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_NONE",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* A 32 bit absolute relocation.  */
+  HOWTO (R_FRV_32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_32",		/* name */
+	 false,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* A 16 bit pc-relative relocation.  */
+  HOWTO (R_FRV_LABEL16,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_LABEL16",	/* name */
+	 false,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 true),		        /* pcrel_offset */
+
+  /* A 24-bit pc-relative relocation.  */
+  HOWTO (R_FRV_LABEL24,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_LABEL24",	/* name */
+	 false,			/* partial_inplace */
+	 0x7e03ffff,		/* src_mask */
+	 0x7e03ffff,		/* dst_mask */
+	 true),		        /* pcrel_offset */
+
+  HOWTO (R_FRV_LO16,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_LO16",		/* name */
+	false,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_HI16,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_HI16",		/* name */
+	 false,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_GPREL12,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_GPREL12",       /* name */
+	 false,			/* partial_inplace */
+	 0xfff,		        /* src_mask */
+	 0xfff,		        /* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_GPRELU12,        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_GPRELU12",      /* name */
+	 false,			/* partial_inplace */
+	 0xfff,		        /* src_mask */
+	 0x3f03f,	        /* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_GPREL32,         /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_GPREL32",	/* name */
+	 false,			/* partial_inplace */
+	 0xffffffff,            /* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_GPRELHI,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_GPRELHI",	/* name */
+	 false,			/* partial_inplace */
+	 0xffff,		        /* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),	        /* pcrel_offset */
+
+  HOWTO (R_FRV_GPRELLO,	        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_FRV_GPRELLO",	/* name */
+	 false,			/* partial_inplace */
+	 0xffff,		        /* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),	        /* pcrel_offset */
+};
+
+/* GNU extension to record C++ vtable hierarchy.  */
+static reloc_howto_type elf32_frv_vtinherit_howto =
+  HOWTO (R_FRV_GNU_VTINHERIT,   /* type */
+         0,                     /* rightshift */
+         2,                     /* size (0 = byte, 1 = short, 2 = long) */
+         0,                     /* bitsize */
+         false,                 /* pc_relative */
+         0,                     /* bitpos */
+         complain_overflow_dont, /* complain_on_overflow */
+         NULL,                  /* special_function */
+         "R_FRV_GNU_VTINHERIT", /* name */
+         false,                 /* partial_inplace */
+         0,                     /* src_mask */
+         0,                     /* dst_mask */
+         false);                /* pcrel_offset */
+
+  /* GNU extension to record C++ vtable member usage.  */
+static reloc_howto_type elf32_frv_vtentry_howto =
+  HOWTO (R_FRV_GNU_VTENTRY,     /* type */
+         0,                     /* rightshift */
+         2,                     /* size (0 = byte, 1 = short, 2 = long) */
+         0,                     /* bitsize */
+         false,                 /* pc_relative */
+         0,                     /* bitpos */
+         complain_overflow_dont, /* complain_on_overflow */
+         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
+         "R_FRV_GNU_VTENTRY",   /* name */
+         false,                 /* partial_inplace */
+         0,                     /* src_mask */
+         0,                     /* dst_mask */
+         false);                /* pcrel_offset */
+
+/* Map BFD reloc types to FRV ELF reloc types.  */
+#if 0
+struct frv_reloc_map
+{
+  unsigned int bfd_reloc_val;
+  unsigned int frv_reloc_val;
+};
+
+static const struct frv_reloc_map frv_reloc_map [] =
+{
+  { BFD_RELOC_NONE,           R_FRV_NONE },
+  { BFD_RELOC_32,             R_FRV_32 },
+  { BFD_RELOC_FRV_LABEL16,    R_FRV_LABEL16 },
+  { BFD_RELOC_FRV_LABEL24,    R_FRV_LABEL24 },
+  { BFD_RELOC_FRV_LO16,       R_FRV_LO16 },
+  { BFD_RELOC_FRV_HI16,       R_FRV_HI16 },
+  { BFD_RELOC_FRV_GPREL12,    R_FRV_GPREL12 },
+  { BFD_RELOC_FRV_GPRELU12,   R_FRV_GPRELU12 },
+  { BFD_RELOC_FRV_GPREL32,    R_FRV_GPREL32 },
+  { BFD_RELOC_FRV_GPRELHI,    R_FRV_GPRELHI },
+  { BFD_RELOC_FRV_GPRELLO,    R_FRV_GPRELLO },
+  { BFD_RELOC_VTABLE_INHERIT, R_FRV_GNU_VTINHERIT },
+  { BFD_RELOC_VTABLE_ENTRY,   R_FRV_GNU_VTENTRY },
+};
+#endif
+
+/* Handle an FRV small data reloc.  */
+
+static bfd_reloc_status_type
+elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation, contents, value)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *relocation;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+  bfd_vma gp;
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
+
+  gp = (h->u.def.value
+	+ h->u.def.section->output_section->vma
+	+ h->u.def.section->output_offset);
+
+  value -= input_section->output_section->vma;
+  value -= (gp - input_section->output_section->vma);
+
+  insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
+
+  value += relocation->r_addend;
+
+  if ((long) value > 0x7ff || (long) value < -0x800)
+    return bfd_reloc_overflow;
+
+  bfd_put_32 (input_bfd,
+	      (insn & 0xfffff000) | (value & 0xfff),
+	      contents + relocation->r_offset);
+
+  return bfd_reloc_ok;
+}
+
+/* Handle an FRV small data reloc. for the u12 field.  */
+
+static bfd_reloc_status_type
+elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation, contents, value)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *relocation;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+  bfd_vma gp;
+  struct bfd_link_hash_entry *h;
+  bfd_vma mask;
+
+  h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
+
+  gp = (h->u.def.value
+	+ h->u.def.section->output_section->vma
+	+ h->u.def.section->output_offset);
+ 
+  value -= input_section->output_section->vma;
+  value -= (gp - input_section->output_section->vma);
+
+  insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
+
+  value += relocation->r_addend;
+
+  if ((long) value > 0x7ff || (long) value < -0x800)
+    return bfd_reloc_overflow;
+
+  /* The high 6 bits go into bits 17-12. The low 6 bits go into bits 5-0.  */
+  mask = 0x3f03f;
+  insn = (insn & ~mask) | ((value & 0xfc0) << 12) | (value & 0x3f);
+
+  bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
+
+  return bfd_reloc_ok;
+}
+
+/* Handle an FRV ELF HI16 reloc.  */
+
+static bfd_reloc_status_type
+elf32_frv_relocate_hi16 (input_bfd, relhi, contents, value)
+     bfd *input_bfd;
+     Elf_Internal_Rela *relhi;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+
+  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
+
+  value += relhi->r_addend;
+  value = ((value >> 16) & 0xffff);
+
+  insn = (insn & 0xffff0000) | value;
+
+  if ((long) value > 0xffff || (long) value < -0x10000)
+    return bfd_reloc_overflow;
+
+  bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
+  return bfd_reloc_ok;
+
+}
+static bfd_reloc_status_type
+elf32_frv_relocate_lo16 (input_bfd, rello, contents, value)
+     bfd *input_bfd;
+     Elf_Internal_Rela *rello;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+
+  insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
+
+  value += rello->r_addend;
+  value = value & 0xffff;
+
+  insn = (insn & 0xffff0000) | value;
+
+  if ((long) value > 0xffff || (long) value < -0x10000)
+    return bfd_reloc_overflow;
+
+  bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
+  return bfd_reloc_ok;
+}
+
+/* Perform the relocation for the CALL label24 instruction.  */
+
+static bfd_reloc_status_type
+elf32_frv_relocate_label24 (input_bfd, input_section, rello, contents, value)
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *rello;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+  bfd_vma label6;
+  bfd_vma label18;
+
+  /* The format for the call instruction is:
+
+    0 000000 0001111 000000000000000000 
+      label6 opcode  label18
+
+    The branch calculation is: pc + (4*label24)
+    where label24 is the concatenation of label6 and label18.  */
+
+  /* Grab the instruction.  */
+  insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
+
+  value -= input_section->output_section->vma + input_section->output_offset;
+  value -= rello->r_offset;
+  value += rello->r_addend;
+
+  value = value >> 2;
+
+  label6  = value & 0xfc0000;
+  label6  = label6 << 7;
+
+  label18 = value & 0x3ffff;
+
+  insn = insn & 0x803c0000;
+  insn = insn | label6;
+  insn = insn | label18;
+
+  bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
+
+  return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation, contents, value)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *relocation;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+  bfd_vma gp;
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
+
+  gp = (h->u.def.value
+        + h->u.def.section->output_section->vma
+        + h->u.def.section->output_offset);
+
+  value -= input_section->output_section->vma;
+  value -= (gp - input_section->output_section->vma);
+  value += relocation->r_addend;
+  value = ((value >> 16) & 0xffff);
+
+  if ((long) value > 0xffff || (long) value < -0x10000)
+    return bfd_reloc_overflow;
+
+  insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
+  insn = (insn & 0xffff0000) | value;
+
+  bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
+  return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation, contents, value)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *relocation;
+     bfd_byte *contents;
+     bfd_vma value;
+{
+  bfd_vma insn;
+  bfd_vma gp;
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true);
+
+  gp = (h->u.def.value
+        + h->u.def.section->output_section->vma
+        + h->u.def.section->output_offset);
+
+  value -= input_section->output_section->vma;
+  value -= (gp - input_section->output_section->vma);
+  value += relocation->r_addend;
+  value = value & 0xffff;
+
+  if ((long) value > 0xffff || (long) value < -0x10000)
+    return bfd_reloc_overflow;
+
+  insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
+  insn = (insn & 0xffff0000) | value;
+
+  bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
+
+ return bfd_reloc_ok;
+}
+
+static reloc_howto_type *
+frv_reloc_type_lookup (abfd, code)
+     bfd * abfd ATTRIBUTE_UNUSED;
+     bfd_reloc_code_real_type code;
+{
+  switch (code)
+    {
+    default:
+      break;
+
+    case BFD_RELOC_NONE:
+      return &elf32_frv_howto_table[ (int) R_FRV_NONE];
+  
+    case BFD_RELOC_32:
+    case BFD_RELOC_CTOR:
+      return &elf32_frv_howto_table[ (int) R_FRV_32];
+
+    case BFD_RELOC_FRV_LABEL16:
+      return &elf32_frv_howto_table[ (int) R_FRV_LABEL16];
+
+    case BFD_RELOC_FRV_LABEL24:
+      return &elf32_frv_howto_table[ (int) R_FRV_LABEL24];
+
+    case BFD_RELOC_FRV_LO16:
+      return &elf32_frv_howto_table[ (int) R_FRV_LO16];
+
+    case BFD_RELOC_FRV_HI16:
+      return &elf32_frv_howto_table[ (int) R_FRV_HI16];
+
+    case BFD_RELOC_FRV_GPREL12:
+      return &elf32_frv_howto_table[ (int) R_FRV_GPREL12];
+
+    case BFD_RELOC_FRV_GPRELU12:
+      return &elf32_frv_howto_table[ (int) R_FRV_GPRELU12];
+
+    case BFD_RELOC_FRV_GPREL32:
+      return &elf32_frv_howto_table[ (int) R_FRV_GPREL32];
+
+    case BFD_RELOC_FRV_GPRELHI:
+      return &elf32_frv_howto_table[ (int) R_FRV_GPRELHI];
+
+    case BFD_RELOC_FRV_GPRELLO:
+      return &elf32_frv_howto_table[ (int) R_FRV_GPRELLO];
+
+    case BFD_RELOC_VTABLE_INHERIT:
+      return &elf32_frv_vtinherit_howto;
+
+    case BFD_RELOC_VTABLE_ENTRY:
+      return &elf32_frv_vtentry_howto;
+    }
+
+  return NULL;
+}
+
+/* Set the howto pointer for an FRV ELF reloc.  */
+
+static void
+frv_info_to_howto_rela (abfd, cache_ptr, dst)
+     bfd * abfd ATTRIBUTE_UNUSED;
+     arelent * cache_ptr;
+     Elf32_Internal_Rela * dst;
+{
+  unsigned int r_type;
+
+  r_type = ELF32_R_TYPE (dst->r_info);
+  switch (r_type)
+    {
+    case R_FRV_GNU_VTINHERIT:
+      cache_ptr->howto = &elf32_frv_vtinherit_howto;
+      break;
+
+    case R_FRV_GNU_VTENTRY:
+      cache_ptr->howto = &elf32_frv_vtentry_howto;
+      break;
+
+    default:
+      cache_ptr->howto = & elf32_frv_howto_table [r_type];
+      break;
+    }
+}
+
+/* Perform a single relocation.  By default we use the standard BFD
+   routines, but a few relocs, we have to do them ourselves.  */
+
+static bfd_reloc_status_type
+frv_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
+     reloc_howto_type *  howto;
+     bfd *               input_bfd;
+     asection *          input_section;
+     bfd_byte *          contents;
+     Elf_Internal_Rela * rel;
+     bfd_vma             relocation;
+{
+  return _bfd_final_link_relocate (howto, input_bfd, input_section,
+				   contents, rel->r_offset, relocation,
+				   rel->r_addend);
+}
+
+
+/* Relocate an FRV ELF section.
+   There is some attempt to make this function usable for many architectures,
+   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
+   if only to serve as a learning tool.
+
+   The RELOCATE_SECTION function is called by the new ELF backend linker
+   to handle the relocations for a section.
+
+   The relocs are always passed as Rela structures; if the section
+   actually uses Rel structures, the r_addend field will always be
+   zero.
+
+   This function is responsible for adjusting the section contents as
+   necessary, and (if using Rela relocs and generating a relocateable
+   output file) adjusting the reloc addend as necessary.
+
+   This function does not have to worry about setting the reloc
+   address or the reloc symbol index.
+
+   LOCAL_SYMS is a pointer to the swapped in local symbols.
+
+   LOCAL_SECTIONS is an array giving the section in the input file
+   corresponding to the st_shndx field of each local symbol.
+
+   The global hash table entry for the global symbols can be found
+   via elf_sym_hashes (input_bfd).
+
+   When generating relocateable output, this function must handle
+   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
+   going to be the section symbol corresponding to the output
+   section, which means that the addend must be adjusted
+   accordingly.  */
+
+static boolean
+elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
+			   contents, relocs, local_syms, local_sections)
+     bfd *                   output_bfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *  info;
+     bfd *                   input_bfd;
+     asection *              input_section;
+     bfd_byte *              contents;
+     Elf_Internal_Rela *     relocs;
+     Elf_Internal_Sym *      local_syms;
+     asection **             local_sections;
+{
+  Elf_Internal_Shdr *           symtab_hdr;
+  struct elf_link_hash_entry ** sym_hashes;
+  Elf_Internal_Rela *           rel;
+  Elf_Internal_Rela *           relend;
+
+  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+  relend     = relocs + input_section->reloc_count;
+
+  for (rel = relocs; rel < relend; rel ++)
+    {
+      reloc_howto_type *           howto;
+      unsigned long                r_symndx;
+      Elf_Internal_Sym *           sym;
+      asection *                   sec;
+      struct elf_link_hash_entry * h;
+      bfd_vma                      relocation;
+      bfd_reloc_status_type        r;
+      const char *                 name = NULL;
+      int                          r_type;
+      
+      r_type = ELF32_R_TYPE (rel->r_info);
+      
+      if (   r_type == R_FRV_GNU_VTINHERIT
+	  || r_type == R_FRV_GNU_VTENTRY)
+	continue;
+      
+      r_symndx = ELF32_R_SYM (rel->r_info);
+
+      if (info->relocateable)
+	{
+	  /* This is a relocateable link.  We don't have to change
+             anything, unless the reloc is against a section symbol,
+             in which case we have to adjust according to where the
+             section symbol winds up in the output section.  */
+	  if (r_symndx < symtab_hdr->sh_info)
+	    {
+	      sym = local_syms + r_symndx;
+	      
+	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+		{
+		  sec = local_sections [r_symndx];
+		  rel->r_addend += sec->output_offset + sym->st_value;
+		}
+	    }
+
+	  continue;
+	}
+
+      /* This is a final link.  */
+      howto  = elf32_frv_howto_table + ELF32_R_TYPE (rel->r_info);
+      h      = NULL;
+      sym    = NULL;
+      sec    = NULL;
+      
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  sym = local_syms + r_symndx;
+	  sec = local_sections [r_symndx];
+	  relocation = (sec->output_section->vma
+			+ sec->output_offset
+			+ sym->st_value);
+	  
+	  name = bfd_elf_string_from_elf_section
+	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
+	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
+	}
+      else
+	{
+	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+	  
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  name = h->root.root.string;
+	  
+	  if (h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	    {
+	      sec = h->root.u.def.section;
+	      relocation = (h->root.u.def.value
+			    + sec->output_section->vma
+			    + sec->output_offset);
+	    }
+	  else if (h->root.type == bfd_link_hash_undefweak)
+	    {
+	      relocation = 0;
+	    }
+	  else
+	    {
+	      if (! ((*info->callbacks->undefined_symbol)
+		     (info, h->root.root.string, input_bfd,
+		      input_section, rel->r_offset, true)))
+		return false;
+	      relocation = 0;
+	    }
+	}
+      
+     if (r_type == R_FRV_HI16)
+       r = elf32_frv_relocate_hi16 (input_bfd, rel, contents, relocation);
+
+     else if (r_type == R_FRV_LO16)
+       r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
+
+     else if (r_type == R_FRV_LABEL24)
+       r = elf32_frv_relocate_label24 (input_bfd, input_section, rel, contents, relocation);
+
+     else if (r_type == R_FRV_GPREL12)
+       r = elf32_frv_relocate_gprel12 (info, input_bfd, input_section, rel, contents, relocation);
+
+     else if (r_type == R_FRV_GPRELU12)
+       r = elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, rel, contents, relocation);
+
+     else if (r_type == R_FRV_GPRELLO)
+       r = elf32_frv_relocate_gprello (info, input_bfd, input_section, rel, contents, relocation);
+
+     else if (r_type == R_FRV_GPRELHI)
+       r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel, contents, relocation);
+
+     else
+       r = frv_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation);
+
+      if (r != bfd_reloc_ok)
+	{
+	  const char * msg = (const char *) NULL;
+
+	  switch (r)
+	    {
+	    case bfd_reloc_overflow:
+	      r = info->callbacks->reloc_overflow
+		(info, name, howto->name, (bfd_vma) 0,
+		 input_bfd, input_section, rel->r_offset);
+	      break;
+	      
+	    case bfd_reloc_undefined:
+	      r = info->callbacks->undefined_symbol
+		(info, name, input_bfd, input_section, rel->r_offset, true);
+	      break;
+	      
+	    case bfd_reloc_outofrange:
+	      msg = _("internal error: out of range error");
+	      break;
+
+	    case bfd_reloc_notsupported:
+	      msg = _("internal error: unsupported relocation error");
+	      break;
+
+	    case bfd_reloc_dangerous:
+	      msg = _("internal error: dangerous relocation");
+	      break;
+
+	    default:
+	      msg = _("internal error: unknown error");
+	      break;
+	    }
+
+	  if (msg)
+	    r = info->callbacks->warning
+	      (info, msg, name, input_bfd, input_section, rel->r_offset);
+
+	  if (! r)
+	    return false;
+	}
+    }
+
+  return true;
+}
+
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+elf32_frv_gc_mark_hook (abfd, info, rel, h, sym)
+     bfd *                        abfd;
+     struct bfd_link_info *       info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *          rel;
+     struct elf_link_hash_entry * h;
+     Elf_Internal_Sym *           sym;
+{
+  if (h != NULL)
+    {
+      switch (ELF32_R_TYPE (rel->r_info))
+	{
+	case R_FRV_GNU_VTINHERIT:
+	case R_FRV_GNU_VTENTRY:
+	  break;
+
+	default:
+	  switch (h->root.type)
+	    {
+	    default:
+	      break;
+
+	    case bfd_link_hash_defined:
+	    case bfd_link_hash_defweak:
+	      return h->root.u.def.section;
+
+	    case bfd_link_hash_common:
+	      return h->root.u.c.p->section;
+	    }
+	}
+    }
+  else
+    {
+      if (!(elf_bad_symtab (abfd)
+	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+		&& sym->st_shndx != SHN_COMMON))
+	return bfd_section_from_elf_index (abfd, sym->st_shndx);
+    }
+
+  return NULL;
+}
+
+/* Update the got entry reference counts for the section being removed.  */
+
+static boolean
+elf32_frv_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;
+{
+  return true;
+}
+
+
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it to put .comm items in .scomm, and not .comm.  */
+
+/*ARGSUSED*/
+static boolean
+elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep ATTRIBUTE_UNUSED;
+     flagword *flagsp ATTRIBUTE_UNUSED;
+     asection **secp;
+     bfd_vma *valp;
+{
+  if (sym->st_shndx == SHN_COMMON
+      && !info->relocateable
+      && (int)sym->st_size <= (int)bfd_get_gp_size (abfd))
+    {
+      /* Common symbols less than or equal to -G nn bytes are
+	 automatically put into .sbss.  */
+
+      asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
+
+      if (scomm == NULL)
+	{
+	  scomm = bfd_make_section (abfd, ".scommon");
+	  if (scomm == NULL
+	      || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
+						       | SEC_IS_COMMON
+						       | SEC_LINKER_CREATED)))
+	    return false;
+	}
+
+      *secp = scomm;
+      *valp = sym->st_size;
+    }
+
+  return true;
+}
+/* Look through the relocs for a section during the first phase.
+   Since we don't do .gots or .plts, we just need to consider the
+   virtual table relocs for gc.  */
+ 
+static boolean
+elf32_frv_check_relocs (abfd, info, sec, relocs)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *sec;
+     const Elf_Internal_Rela *relocs;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *rel_end;
+ 
+  if (info->relocateable)
+    return true;
+ 
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (abfd);
+  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+  if (!elf_bad_symtab (abfd))
+    sym_hashes_end -= symtab_hdr->sh_info;
+ 
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      struct elf_link_hash_entry *h;
+      unsigned long r_symndx;
+ 
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx < symtab_hdr->sh_info)
+        h = NULL;
+      else
+        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 
+      switch (ELF32_R_TYPE (rel->r_info))
+        {
+        /* This relocation describes the C++ object vtable hierarchy.
+           Reconstruct it for later use during GC.  */
+        case R_FRV_GNU_VTINHERIT:
+          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+            return false;
+          break;
+ 
+        /* This relocation describes which C++ vtable entries are actually
+           used.  Record for later use during GC.  */
+        case R_FRV_GNU_VTENTRY:
+          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+            return false;
+          break;
+        }
+    }
+ 
+  return true;
+}
+
+
+/* Return the machine subcode from the ELF e_flags header.  */
+
+static int
+elf32_frv_machine (abfd)
+     bfd *abfd;
+{
+  switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK)
+    {
+    default:		    break;
+    case EF_FRV_CPU_FR500:  return bfd_mach_fr500;
+    case EF_FRV_CPU_FR400:  return bfd_mach_fr400;
+    case EF_FRV_CPU_FR300:  return bfd_mach_fr300;
+    case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
+    case EF_FRV_CPU_TOMCAT: return bfd_mach_frvtomcat;
+    }
+
+  return bfd_mach_frv;
+}
+
+/* Set the right machine number for a FRV ELF file.  */
+
+static boolean
+elf32_frv_object_p (abfd)
+     bfd *abfd;
+{
+  bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
+  return true;
+}
+
+/* Function to set the ELF flag bits.  */
+
+static boolean
+frv_elf_set_private_flags (abfd, flags)
+     bfd *abfd;
+     flagword flags;
+{
+  elf_elfheader (abfd)->e_flags = flags;
+  elf_flags_init (abfd) = true;
+  return true;
+}
+
+/* Copy backend specific data from one object module to another.  */
+
+static boolean
+frv_elf_copy_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
+  BFD_ASSERT (!elf_flags_init (obfd)
+	      || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
+
+  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+  elf_flags_init (obfd) = true;
+  return true;
+}
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static boolean
+frv_elf_merge_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  flagword old_flags, old_partial;
+  flagword new_flags, new_partial;
+  boolean error = false;
+  char new_opt[80];
+  char old_opt[80];
+
+  new_opt[0] = old_opt[0] = '\0';
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  old_flags = elf_elfheader (obfd)->e_flags;
+
+#ifdef DEBUG
+  (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
+			 old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
+			 bfd_get_filename (ibfd));
+#endif
+
+  if (!elf_flags_init (obfd))			/* First call, no flags set.  */
+    {
+      elf_flags_init (obfd) = true;
+      old_flags = new_flags;
+    }
+
+  else if (new_flags == old_flags)		/* Compatible flags are ok.  */
+    ;
+
+  else						/* Possibly incompatible flags.  */
+    {
+      /* Warn if different # of gprs are used.  Note, 0 means nothing is
+         said about the size of gprs.  */
+      new_partial = (new_flags & EF_FRV_GPR_MASK);
+      old_partial = (old_flags & EF_FRV_GPR_MASK);
+      if (new_partial == old_partial)
+	;
+
+      else if (new_partial == 0)
+	;
+
+      else if (old_partial == 0)
+	old_flags |= new_partial;
+
+      else
+	{
+	  switch (new_partial)
+	    {
+	    default:		strcat (new_opt, " -mgpr-??"); break;
+	    case EF_FRV_GPR_32: strcat (new_opt, " -mgpr-32"); break;
+	    case EF_FRV_GPR_64: strcat (new_opt, " -mgpr-64"); break;
+	    }
+
+	  switch (old_partial)
+	    {
+	    default:		strcat (old_opt, " -mgpr-??"); break;
+	    case EF_FRV_GPR_32: strcat (old_opt, " -mgpr-32"); break;
+	    case EF_FRV_GPR_64: strcat (old_opt, " -mgpr-64"); break;
+	    }
+	}
+
+      /* Warn if different # of fprs are used.  Note, 0 means nothing is
+         said about the size of fprs.  */
+      new_partial = (new_flags & EF_FRV_FPR_MASK);
+      old_partial = (old_flags & EF_FRV_FPR_MASK);
+      if (new_partial == old_partial)
+	;
+
+      else if (new_partial == 0)
+	;
+
+      else if (old_partial == 0)
+	old_flags |= new_partial;
+
+      else
+	{
+	  switch (new_partial)
+	    {
+	    default:		  strcat (new_opt, " -mfpr-?");      break;
+	    case EF_FRV_FPR_32:   strcat (new_opt, " -mfpr-32");     break;
+	    case EF_FRV_FPR_64:   strcat (new_opt, " -mfpr-64");     break;
+	    case EF_FRV_FPR_NONE: strcat (new_opt, " -msoft-float"); break;
+	    }
+
+	  switch (old_partial)
+	    {
+	    default:		  strcat (old_opt, " -mfpr-?");      break;
+	    case EF_FRV_FPR_32:   strcat (old_opt, " -mfpr-32");     break;
+	    case EF_FRV_FPR_64:   strcat (old_opt, " -mfpr-64");     break;
+	    case EF_FRV_FPR_NONE: strcat (old_opt, " -msoft-float"); break;
+	    }
+	}
+
+      /* Warn if different dword support was used.  Note, 0 means nothing is
+         said about the dword support.  */
+      new_partial = (new_flags & EF_FRV_DWORD_MASK);
+      old_partial = (old_flags & EF_FRV_DWORD_MASK);
+      if (new_partial == old_partial)
+	;
+
+      else if (new_partial == 0)
+	;
+
+      else if (old_partial == 0)
+	old_flags |= new_partial;
+
+      else
+	{
+	  switch (new_partial)
+	    {
+	    default:		   strcat (new_opt, " -mdword-?");  break;
+	    case EF_FRV_DWORD_YES: strcat (new_opt, " -mdword");    break;
+	    case EF_FRV_DWORD_NO:  strcat (new_opt, " -mno-dword"); break;
+	    }
+
+	  switch (old_partial)
+	    {
+	    default:		   strcat (old_opt, " -mdword-?");  break;
+	    case EF_FRV_DWORD_YES: strcat (old_opt, " -mdword");    break;
+	    case EF_FRV_DWORD_NO:  strcat (old_opt, " -mno-dword"); break;
+	    }
+	}
+
+      /* Or in flags that accumulate (ie, if one module uses it, mark that the
+	 feature is used.  */
+      old_flags |= new_flags & (EF_FRV_DOUBLE
+				| EF_FRV_MEDIA
+				| EF_FRV_MULADD
+				| EF_FRV_NON_PIC_RELOCS);
+
+      /* If any module was compiled without -G0, clear the G0 bit.  */
+      old_flags = ((old_flags & ~ EF_FRV_G0)
+		   | (old_flags & new_flags & EF_FRV_G0));
+
+      /* If any module was compiled without -mnopack, clear the mnopack bit.  */
+      old_flags = ((old_flags & ~ EF_FRV_NOPACK)
+		   | (old_flags & new_flags & EF_FRV_NOPACK));
+
+      /* We don't have to do anything if the pic flags are the same, or the new
+         module(s) were compiled with -mlibrary-pic.  */
+      new_partial = (new_flags & EF_FRV_PIC_FLAGS);
+      old_partial = (old_flags & EF_FRV_PIC_FLAGS);
+      if ((new_partial == old_partial) || ((new_partial & EF_FRV_LIBPIC) != 0))
+	;
+
+      /* If the old module(s) were compiled with -mlibrary-pic, copy in the pic
+         flags if any from the new module.  */
+      else if ((old_partial & EF_FRV_LIBPIC) != 0)
+	old_flags = (old_flags & ~ EF_FRV_PIC_FLAGS) | new_partial;
+
+      /* If we have mixtures of -fpic and -fPIC, or in both bits.  */
+      else if (new_partial != 0 && old_partial != 0)
+	old_flags |= new_partial;
+
+      /* One module was compiled for pic and the other was not, see if we have
+         had any relocations that are not pic-safe.  */
+      else
+	{
+	  if ((old_flags & EF_FRV_NON_PIC_RELOCS) == 0)
+	    old_flags |= new_partial;
+	  else
+	    {
+	      old_flags &= ~ EF_FRV_PIC_FLAGS;
+#ifndef FRV_NO_PIC_ERROR
+	      error = true;
+	      (*_bfd_error_handler)
+		(_("%s: compiled with %s and linked with modules that use non-pic relocations"),
+		 bfd_get_filename (ibfd),
+		 (new_flags & EF_FRV_BIGPIC) ? "-fPIC" : "-fpic");
+#endif
+	    }
+	}
+
+      /* Warn if different cpu is used (allow a specific cpu to override
+	 the generic cpu).  */
+      new_partial = (new_flags & EF_FRV_CPU_MASK);
+      old_partial = (old_flags & EF_FRV_CPU_MASK);
+      if (new_partial == old_partial)
+	;
+
+      else if (new_partial == EF_FRV_CPU_GENERIC)
+	;
+
+      else if (old_partial == EF_FRV_CPU_GENERIC)
+	old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
+
+      else
+	{
+	  switch (new_partial)
+	    {
+	    default:		     strcat (new_opt, " -mcpu=?");      break;
+	    case EF_FRV_CPU_GENERIC: strcat (new_opt, " -mcpu=frv");    break;
+	    case EF_FRV_CPU_SIMPLE:  strcat (new_opt, " -mcpu=simple"); break;
+	    case EF_FRV_CPU_FR500:   strcat (new_opt, " -mcpu=fr500");  break;
+	    case EF_FRV_CPU_FR400:   strcat (new_opt, " -mcpu=fr400");  break;
+	    case EF_FRV_CPU_FR300:   strcat (new_opt, " -mcpu=fr300");  break;
+	    case EF_FRV_CPU_TOMCAT:  strcat (new_opt, " -mcpu=tomcat"); break;
+	    }
+
+	  switch (old_partial)
+	    {
+	    default:		     strcat (old_opt, " -mcpu=?");      break;
+	    case EF_FRV_CPU_GENERIC: strcat (old_opt, " -mcpu=frv");    break;
+	    case EF_FRV_CPU_SIMPLE:  strcat (old_opt, " -mcpu=simple"); break;
+	    case EF_FRV_CPU_FR500:   strcat (old_opt, " -mcpu=fr500");  break;
+	    case EF_FRV_CPU_FR400:   strcat (old_opt, " -mcpu=fr400");  break;
+	    case EF_FRV_CPU_FR300:   strcat (old_opt, " -mcpu=fr300");  break;
+	    case EF_FRV_CPU_TOMCAT:  strcat (old_opt, " -mcpu=tomcat"); break;
+	    }
+	}
+      
+      /* Print out any mismatches from above.  */
+      if (new_opt[0])
+	{
+	  error = true;
+	  (*_bfd_error_handler)
+	    (_("%s: compiled with %s and linked with modules compiled with %s"),
+	     bfd_get_filename (ibfd), new_opt, old_opt);
+	}
+
+      /* Warn about any other mismatches */
+      new_partial = (new_flags & ~ EF_FRV_ALL_FLAGS);
+      old_partial = (old_flags & ~ EF_FRV_ALL_FLAGS);
+      if (new_partial != old_partial)
+	{
+	  old_flags |= new_partial;
+	  error = true;
+	  (*_bfd_error_handler)
+	    (_("%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"),
+	     bfd_get_filename (ibfd), (long)new_partial, (long)old_partial);
+	}
+    }
+
+  /* If the cpu is -mcpu=simple, then set the -mnopack bit.  */
+  if ((old_flags & EF_FRV_CPU_MASK) == EF_FRV_CPU_SIMPLE)
+    old_flags |= EF_FRV_NOPACK;
+
+  /* Update the old flags now with changes made above.  */
+  old_partial = elf_elfheader (obfd)->e_flags & EF_FRV_CPU_MASK;
+  elf_elfheader (obfd)->e_flags = old_flags;
+  if (old_partial != (old_flags & EF_FRV_CPU_MASK))
+    bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
+
+  if (error)
+    bfd_set_error (bfd_error_bad_value);
+
+  return !error;
+}
+
+
+boolean
+frv_elf_print_private_bfd_data (abfd, ptr)
+     bfd *abfd;
+     PTR ptr;
+{
+  FILE *file = (FILE *) ptr;
+  flagword flags;
+
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  flags = elf_elfheader (abfd)->e_flags;
+  fprintf (file, _("private flags = 0x%lx:"), (long)flags);
+
+  switch (flags & EF_FRV_CPU_MASK)
+    {
+    default:							break;
+    case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple");	break;
+    case EF_FRV_CPU_FR500:  fprintf (file, " -mcpu=fr500");	break;
+    case EF_FRV_CPU_FR400:  fprintf (file, " -mcpu=fr400");	break;
+    case EF_FRV_CPU_FR300:  fprintf (file, " -mcpu=fr300");	break;
+    case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat");	break;
+    }
+
+  switch (flags & EF_FRV_GPR_MASK)
+    {
+    default:							break;
+    case EF_FRV_GPR_32: fprintf (file, " -mgpr-32");		break;
+    case EF_FRV_GPR_64: fprintf (file, " -mgpr-64");		break;
+    }
+
+  switch (flags & EF_FRV_FPR_MASK)
+    {
+    default:							break;
+    case EF_FRV_FPR_32:   fprintf (file, " -mfpr-32");		break;
+    case EF_FRV_FPR_64:   fprintf (file, " -mfpr-64");		break;
+    case EF_FRV_FPR_NONE: fprintf (file, " -msoft-float");	break;
+    }
+
+  switch (flags & EF_FRV_DWORD_MASK)
+    {
+    default:							break;
+    case EF_FRV_DWORD_YES: fprintf (file, " -mdword");		break;
+    case EF_FRV_DWORD_NO:  fprintf (file, " -mno-dword");	break;
+    }
+
+  if (flags & EF_FRV_DOUBLE)
+    fprintf (file, " -mdouble");
+
+  if (flags & EF_FRV_MEDIA)
+    fprintf (file, " -mmedia");
+
+  if (flags & EF_FRV_MULADD)
+    fprintf (file, " -mmuladd");
+
+  if (flags & EF_FRV_PIC)
+    fprintf (file, " -fpic");
+
+  if (flags & EF_FRV_BIGPIC)
+    fprintf (file, " -fPIC");
+
+  if (flags & EF_FRV_NON_PIC_RELOCS)
+    fprintf (file, " non-pic relocations");
+
+  if (flags & EF_FRV_G0)
+    fprintf (file, " -G0");
+
+  fputc ('\n', file);
+  return true;
+}
+
+
+#define ELF_ARCH		bfd_arch_frv
+#define ELF_MACHINE_CODE	EM_CYGNUS_FRV
+#define ELF_MAXPAGESIZE		0x1000
+
+#define TARGET_BIG_SYM          bfd_elf32_frv_vec
+#define TARGET_BIG_NAME		"elf32-frv"
+
+#define elf_info_to_howto_rel			NULL
+#define elf_info_to_howto			frv_info_to_howto_rela
+#define elf_backend_relocate_section		elf32_frv_relocate_section
+#define elf_backend_gc_mark_hook		elf32_frv_gc_mark_hook
+#define elf_backend_gc_sweep_hook		elf32_frv_gc_sweep_hook
+#define elf_backend_check_relocs                elf32_frv_check_relocs
+#define elf_backend_object_p			elf32_frv_object_p
+#define elf_backend_add_symbol_hook             elf32_frv_add_symbol_hook
+
+#define elf_backend_can_gc_sections		1
+
+#define bfd_elf32_bfd_reloc_type_lookup		frv_reloc_type_lookup
+#define bfd_elf32_bfd_set_private_flags		frv_elf_set_private_flags
+#define bfd_elf32_bfd_copy_private_bfd_data	frv_elf_copy_private_bfd_data
+#define bfd_elf32_bfd_merge_private_bfd_data	frv_elf_merge_private_bfd_data
+#define bfd_elf32_bfd_print_private_bfd_data	frv_elf_print_private_bfd_data
+
+#include "elf32-target.h"
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.60
diff -c -p -d -u -p -r1.60 reloc.c
--- bfd/reloc.c	30 May 2002 22:01:28 -0000	1.60
+++ bfd/reloc.c	10 Jun 2002 22:02:38 -0000
@@ -2079,6 +2079,27 @@ ENUMX
 ENUMX
   BFD_RELOC_MIPS_JALR
 COMMENT
+ENUM
+  BFD_RELOC_FRV_LABEL16
+ENUMX
+  BFD_RELOC_FRV_LABEL24
+ENUMX
+  BFD_RELOC_FRV_LO16
+ENUMX
+  BFD_RELOC_FRV_HI16
+ENUMX
+  BFD_RELOC_FRV_GPREL12
+ENUMX
+  BFD_RELOC_FRV_GPRELU12
+ENUMX
+  BFD_RELOC_FRV_GPREL32
+ENUMX
+  BFD_RELOC_FRV_GPRELHI
+ENUMX
+  BFD_RELOC_FRV_GPRELLO
+ENUMDOC
+  Fujitsu Frv Relocations.
+COMMENT
 COMMENT
 ENUMDOC
   MIPS ELF relocations.
Index: bfd/targets.c
===================================================================
RCS file: /cvs/src/src/bfd/targets.c,v
retrieving revision 1.66
diff -c -p -d -u -p -r1.66 targets.c
--- bfd/targets.c	8 Jun 2002 23:23:08 -0000	1.66
+++ bfd/targets.c	10 Jun 2002 22:02:38 -0000
@@ -513,6 +513,7 @@ extern const bfd_target bfd_elf32_d10v_v
 extern const bfd_target bfd_elf32_d30v_vec;
 extern const bfd_target bfd_elf32_dlx_big_vec;
 extern const bfd_target bfd_elf32_fr30_vec;
+extern const bfd_target bfd_elf32_frv_vec;
 extern const bfd_target bfd_elf32_h8300_vec;
 extern const bfd_target bfd_elf32_hppa_linux_vec;
 extern const bfd_target bfd_elf32_hppa_vec;
@@ -772,6 +773,7 @@ static const bfd_target * const _bfd_tar
 	&bfd_elf32_d30v_vec,
 	&bfd_elf32_dlx_big_vec,
 	&bfd_elf32_fr30_vec,
+	&bfd_elf32_frv_vec,
 	&bfd_elf32_h8300_vec,
 	&bfd_elf32_hppa_linux_vec,
 	&bfd_elf32_hppa_vec,
Index: bfd/po/SRC-POTFILES.in
===================================================================
RCS file: /cvs/src/src/bfd/po/SRC-POTFILES.in,v
retrieving revision 1.13
diff -c -p -d -u -p -r1.13 SRC-POTFILES.in
--- bfd/po/SRC-POTFILES.in	6 Jun 2002 00:29:22 -0000	1.13
+++ bfd/po/SRC-POTFILES.in	10 Jun 2002 22:02:38 -0000
@@ -67,6 +67,7 @@ cpu-d10v.c
 cpu-d30v.c
 cpu-dlx.c
 cpu-fr30.c
+cpu-frv.c
 cpu-h8300.c
 cpu-h8500.c
 cpu-hppa.c
@@ -127,6 +128,7 @@ elf32-d10v.c
 elf32-d30v.c
 elf32-dlx.c
 elf32-fr30.c
+elf32-frv.c
 elf32-gen.c
 elf32-h8300.c
 elf32-hppa.c
Index: binutils/NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.24
diff -c -p -d -u -p -r1.24 NEWS
--- binutils/NEWS	20 Feb 2002 10:46:54 -0000	1.24
+++ binutils/NEWS	11 Jun 2002 20:44:57 -0000
@@ -1,4 +1,6 @@
 -*- text -*-
+Support for the Fujitsu FRV architecture added by Red Hat. Models for FR400 and
+FR500 included.
 
 Changes in version 2.12:
 
Index: binutils/Makefile.am
===================================================================
RCS file: /cvs/src/src/binutils/Makefile.am,v
retrieving revision 1.33
diff -c -p -d -u -p -r1.33 Makefile.am
--- binutils/Makefile.am	8 Jun 2002 08:44:16 -0000	1.33
+++ binutils/Makefile.am	10 Jun 2002 22:02:38 -0000
@@ -501,6 +501,7 @@ readelf.o: readelf.c ../bfd/bfd.h $(INCD
   $(INCDIR)/elf/reloc-macros.h $(INCDIR)/elf/arc.h $(INCDIR)/elf/arm.h \
   $(INCDIR)/elf/avr.h $(INCDIR)/elf/cris.h $(INCDIR)/elf/d10v.h \
   $(INCDIR)/elf/d30v.h $(INCDIR)/elf/dlx.h $(INCDIR)/elf/fr30.h \
+  $(INCDIR)/elf/frv.h \
   $(INCDIR)/elf/h8.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/i386.h \
   $(INCDIR)/elf/i860.h $(INCDIR)/elf/i960.h $(INCDIR)/elf/ia64.h \
   $(INCDIR)/elf/m32r.h $(INCDIR)/elf/m68k.h $(INCDIR)/elf/mcore.h \
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.161
diff -c -p -d -u -p -r1.161 readelf.c
--- binutils/readelf.c	7 Jun 2002 16:42:31 -0000	1.161
+++ binutils/readelf.c	10 Jun 2002 22:02:39 -0000
@@ -58,6 +58,7 @@
 #include "elf/d30v.h"
 #include "elf/dlx.h"
 #include "elf/fr30.h"
+#include "elf/frv.h"
 #include "elf/h8.h"
 #include "elf/hppa.h"
 #include "elf/i386.h"
@@ -633,6 +634,7 @@ guess_is_rela (e_machine)
     case EM_CYGNUS_MN10300:
     case EM_FR30:
     case EM_CYGNUS_FR30:
+    case EM_CYGNUS_FRV:
     case EM_SH:
     case EM_ALPHA:
     case EM_MCORE:
@@ -1031,6 +1033,10 @@ dump_relocations (file, rel_offset, rel_
 	  rtype = elf_fr30_reloc_type (type);
 	  break;
 
+        case EM_CYGNUS_FRV:
+          rtype = elf_frv_reloc_type (type);
+          break;
+
 	case EM_MCORE:
 	  rtype = elf_mcore_reloc_type (type);
 	  break;
@@ -1508,6 +1514,7 @@ get_machine_name (e_machine)
     case EM_MN10200:		return "mn10200";
     case EM_CYGNUS_FR30:
     case EM_FR30:		return "Fujitsu FR30";
+    case EM_CYGNUS_FRV:	        return "Fujitsu FR-V";
     case EM_PJ_OLD:
     case EM_PJ:                 return "picoJava";
     case EM_MMA:		return "Fujitsu Multimedia Accelerator";
Index: gas/NEWS
===================================================================
RCS file: /cvs/src/src/gas/NEWS,v
retrieving revision 1.28
diff -c -p -d -u -p -r1.28 NEWS
--- gas/NEWS	28 May 2002 14:20:42 -0000	1.28
+++ gas/NEWS	11 Jun 2002 20:44:57 -0000
@@ -1,4 +1,7 @@
 -*- text -*-
+Support for the Fujitsu FRV architecture added by Red Hat. Models for FR400 and
+FR500 included.
+
 Support for DLX processor added.
 
 GASP has now been deprecated and will be removed in a future release.  Use the
Index: gas/Makefile.am
===================================================================
RCS file: /cvs/src/src/gas/Makefile.am,v
retrieving revision 1.59
diff -c -p -d -u -p -r1.59 Makefile.am
--- gas/Makefile.am	8 Jun 2002 08:45:03 -0000	1.59
+++ gas/Makefile.am	10 Jun 2002 22:02:39 -0000
@@ -47,6 +47,7 @@ CPU_TYPES = \
 	d30v \
 	dlx \
 	fr30 \
+	frv \
 	h8300 \
 	h8500 \
 	hppa \
@@ -236,6 +237,7 @@ TARGET_CPU_CFILES = \
 	config/tc-d30v.c \
 	config/tc-dlx.c \
 	config/tc-fr30.c \
+	config/tc-frv.c \
 	config/tc-h8300.c \
 	config/tc-h8500.c \
 	config/tc-hppa.c \
@@ -284,6 +286,7 @@ TARGET_CPU_HFILES = \
 	config/tc-d30v.h \
 	config/tc-dlx.h \
 	config/tc-fr30.h \
+	config/tc-frv.h \
 	config/tc-h8300.h \
 	config/tc-h8500.h \
 	config/tc-hppa.h \
@@ -1067,6 +1070,18 @@ DEPTC_fr30_elf = $(INCDIR)/symcat.h $(sr
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   $(srcdir)/../opcodes/fr30-desc.h $(INCDIR)/opcode/cgen.h \
   $(srcdir)/../opcodes/fr30-opc.h cgen.h
+DEPTC_frv_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
+  $(srcdir)/config/tc-frv.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h \
+  subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/frv-desc.h \
+  $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/frv-opc.h \
+  cgen.h
+DEPTC_frv_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-frv.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  $(srcdir)/../opcodes/frv-desc.h $(INCDIR)/opcode/cgen.h \
+  $(srcdir)/../opcodes/frv-opc.h cgen.h
 DEPTC_h8300_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
   $(srcdir)/config/tc-h8300.h $(INCDIR)/coff/internal.h \
   $(INCDIR)/coff/h8300.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \
@@ -1577,6 +1592,15 @@ DEPOBJ_fr30_elf = $(INCDIR)/symcat.h $(s
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   struc-symbol.h $(INCDIR)/aout/aout64.h
+DEPOBJ_frv_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
+  $(srcdir)/config/tc-frv.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+  subsegs.h
+DEPOBJ_frv_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-frv.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  struc-symbol.h $(INCDIR)/aout/aout64.h
 DEPOBJ_h8300_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
   $(srcdir)/config/tc-h8300.h $(INCDIR)/coff/internal.h \
   $(INCDIR)/coff/h8300.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \
@@ -2015,6 +2039,12 @@ DEP_fr30_coff = $(srcdir)/config/obj-cof
 DEP_fr30_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
   $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h
+DEP_frv_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-frv.h \
+  $(INCDIR)/symcat.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+  $(INCDIR)/bfdlink.h
+DEP_frv_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-frv.h
 DEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
   $(INCDIR)/symcat.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h \
   $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.107
diff -c -p -d -u -p -r1.107 configure.in
--- gas/configure.in	9 Jun 2002 00:45:41 -0000	1.107
+++ gas/configure.in	10 Jun 2002 22:02:40 -0000
@@ -218,6 +218,7 @@ changequote([,])dnl
 
 
       fr30-*-*)		    fmt=elf bfd_gas=yes ;;
+      frv-*-*)		    fmt=elf bfd_gas=yes ;;
 
       hppa-*-linux-gnu*)    case ${cpu} in
 				hppa*64*)
@@ -580,6 +581,9 @@ changequote([,])dnl
 	using_cgen=yes
 	;;
 
+      frv)
+	using_cgen=yes
+	;;
       m68k)
 	case ${extra_objects} in
 	*m68k-parse.o*) ;;
Index: gas/config/tc-frv.c
===================================================================
RCS file: gas/config/tc-frv.c
diff -N gas/config/tc-frv.c
--- gas/config/tc-frv.c	1 Jan 1970 00:00:00 -0000
+++ gas/config/tc-frv.c	10 Jun 2002 22:02:41 -0000
@@ -0,0 +1,1606 @@
+/* tc-frv.c -- Assembler for the Fujitsu FRV.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include "as.h"
+#include "dwarf2dbg.h"
+#include "subsegs.h"     
+#include "symcat.h"
+#include "opcodes/frv-desc.h"
+#include "opcodes/frv-opc.h"
+#include "cgen.h"
+#include "libbfd.h"
+#include "elf/common.h"
+#include "elf/frv.h"
+
+/* Structure to hold all of the different components describing
+   an individual instruction.  */
+typedef struct
+{
+  const CGEN_INSN *	insn;
+  const CGEN_INSN *	orig_insn;
+  CGEN_FIELDS		fields;
+#if CGEN_INT_INSN_P
+  CGEN_INSN_INT         buffer [1];
+#define INSN_VALUE(buf) (*(buf))
+#else
+  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
+#define INSN_VALUE(buf) (buf)
+#endif
+  char *		addr;
+  fragS *		frag;
+  int                   num_fixups;
+  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
+  int                   indices [MAX_OPERAND_INSTANCES];
+}
+frv_insn;
+
+enum vliw_insn_type
+{
+  VLIW_GENERIC_TYPE,		/* Don't care about this insn.  */
+  VLIW_BRANCH_TYPE,		/* A Branch.  */
+  VLIW_LABEL_TYPE,		/* A Label.  */
+  VLIW_NOP_TYPE,		/* A NOP.  */
+  VLIW_BRANCH_HAS_NOPS		/* A Branch that requires NOPS.  */
+};
+
+/* We're going to use these in the fr_subtype field to mark 
+   whether to keep inserted nops.  */
+
+#define NOP_KEEP 1		/* Keep these NOPS.  */
+#define NOP_DELETE 2		/* Delete these NOPS.  */
+
+#define DO_COUNT    true
+#define DONT_COUNT  false
+
+/* A list of insns within a VLIW insn.  */
+struct vliw_insn_list
+{
+  /*  The type of this insn.  */
+  enum vliw_insn_type	type;
+
+  /*  The corresponding gas insn information.  */
+  const CGEN_INSN	*insn;
+
+  /*  For branches and labels, the symbol that is referenced.  */
+  symbolS		*sym;
+
+  /*  For branches, the frag containing the single nop that was generated.  */
+  fragS			*snop_frag;
+
+  /*  For branches, the frag containing the double nop that was generated.  */
+  fragS			*dnop_frag;
+
+  /*  Pointer to raw data for this insn.  */
+  char			*address;
+
+  /* Next insn in list.  */
+  struct vliw_insn_list *next;
+};
+
+static struct vliw_insn_list single_nop_insn = {
+   VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
+
+static struct vliw_insn_list double_nop_insn = {
+   VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
+
+struct vliw_chain
+{
+  int			num;
+  int			insn_count;
+  struct vliw_insn_list *insn_list;
+  struct vliw_chain     *next;
+};
+
+static struct vliw_chain	*vliw_chain_top;
+static struct vliw_chain	*current_vliw_chain;
+static struct vliw_chain	*previous_vliw_chain;
+static struct vliw_insn_list	*current_vliw_insn;
+
+const char comment_chars[]        = ";";
+const char line_comment_chars[]   = "#";
+const char line_separator_chars[] = ""; 
+const char EXP_CHARS[]            = "eE";
+const char FLT_CHARS[]            = "dD";
+
+static FRV_VLIW vliw;
+
+/* Default machine */
+
+#ifdef  DEFAULT_CPU_FRV
+#define DEFAULT_MACHINE bfd_mach_frv
+#define DEFAULT_FLAGS	EF_FRV_CPU_GENERIC
+
+#else
+#ifdef  DEFAULT_CPU_FR300
+#define DEFAULT_MACHINE	bfd_mach_fr300
+#define DEFAULT_FLAGS	EF_FRV_CPU_FR300
+
+#else
+#ifdef	DEFAULT_CPU_SIMPLE
+#define	DEFAULT_MACHINE bfd_mach_frvsimple
+#define DEFAULT_FLAGS	EF_FRV_CPU_SIMPLE
+
+#else
+#ifdef	DEFAULT_CPU_TOMCAT
+#define	DEFAULT_MACHINE bfd_mach_frvtomcat
+#define DEFAULT_FLAGS	EF_FRV_CPU_TOMCAT
+
+#else
+#ifdef  DEFAULT_CPU_FR400
+#define DEFAULT_MACHINE	bfd_mach_fr400
+#define DEFAULT_FLAGS	EF_FRV_CPU_FR400
+
+#else
+#define DEFAULT_MACHINE	bfd_mach_fr500
+#define DEFAULT_FLAGS	EF_FRV_CPU_FR500
+#endif
+#endif
+#endif
+#endif
+#endif
+
+static unsigned long frv_mach = bfd_mach_frv;
+
+/* Flags to set in the elf header */
+static flagword frv_flags = DEFAULT_FLAGS;
+
+static int frv_user_set_flags_p = 0;
+static int frv_pic_p = 0;
+static const char *frv_pic_flag = (const char *)0;
+
+/* Print tomcat-specific debugging info.  */
+static int tomcat_debug = 0;
+
+/* Tomcat-specific NOP statistics.  */
+static int tomcat_stats = 0;
+static int tomcat_doubles = 0;
+static int tomcat_singles = 0;
+
+/* Forward reference to static functions */
+static void frv_set_flags		PARAMS ((int));
+static void frv_pic_ptr			PARAMS ((int));
+static void frv_frob_file_section	PARAMS ((bfd *, asection *, PTR));
+
+/* The target specific pseudo-ops which we support.  */
+const pseudo_typeS md_pseudo_table[] =
+{
+  { "eflags",	frv_set_flags,		0 },
+  { "word",	cons,			4 },
+  { "picptr",	frv_pic_ptr,		4 },
+  { "file",	dwarf2_directive_file,	0 },
+  { "loc",	dwarf2_directive_loc,	0 },
+  { NULL, 	NULL,			0 }
+};
+
+
+#define FRV_SHORTOPTS "G:"
+const char * md_shortopts = FRV_SHORTOPTS;
+
+#define OPTION_GPR_32		(OPTION_MD_BASE)
+#define OPTION_GPR_64		(OPTION_MD_BASE + 1)
+#define OPTION_FPR_32		(OPTION_MD_BASE + 2)
+#define OPTION_FPR_64		(OPTION_MD_BASE + 3)
+#define OPTION_SOFT_FLOAT	(OPTION_MD_BASE + 4)
+#define OPTION_DWORD_YES	(OPTION_MD_BASE + 5)
+#define OPTION_DWORD_NO		(OPTION_MD_BASE + 6)
+#define OPTION_DOUBLE		(OPTION_MD_BASE + 7)
+#define OPTION_NO_DOUBLE	(OPTION_MD_BASE + 8)
+#define OPTION_MEDIA		(OPTION_MD_BASE + 9)
+#define OPTION_NO_MEDIA		(OPTION_MD_BASE + 10)
+#define OPTION_CPU		(OPTION_MD_BASE + 11)
+#define OPTION_PIC		(OPTION_MD_BASE + 12)
+#define OPTION_BIGPIC		(OPTION_MD_BASE + 13)
+#define OPTION_LIBPIC		(OPTION_MD_BASE + 14)
+#define OPTION_MULADD		(OPTION_MD_BASE + 15)
+#define OPTION_NO_MULADD	(OPTION_MD_BASE + 16)
+#define OPTION_TOMCAT_DEBUG	(OPTION_MD_BASE + 17)
+#define OPTION_TOMCAT_STATS	(OPTION_MD_BASE + 18)
+#define OPTION_PACK	        (OPTION_MD_BASE + 19)
+#define OPTION_NO_PACK	        (OPTION_MD_BASE + 20)
+
+struct option md_longopts[] =
+{
+  { "mgpr-32",		no_argument,		NULL, OPTION_GPR_32        },
+  { "mgpr-64",		no_argument,		NULL, OPTION_GPR_64        },
+  { "mfpr-32",		no_argument,		NULL, OPTION_FPR_32        },
+  { "mfpr-64",		no_argument,		NULL, OPTION_FPR_64        },
+  { "mhard-float",	no_argument,		NULL, OPTION_FPR_64        },
+  { "msoft-float",	no_argument,		NULL, OPTION_SOFT_FLOAT    },
+  { "mdword",		no_argument,		NULL, OPTION_DWORD_YES     },
+  { "mno-dword",	no_argument,		NULL, OPTION_DWORD_NO      },
+  { "mdouble",		no_argument,		NULL, OPTION_DOUBLE        },
+  { "mno-double",	no_argument,		NULL, OPTION_NO_DOUBLE     },
+  { "mmedia",		no_argument,		NULL, OPTION_MEDIA         },
+  { "mno-media",	no_argument,		NULL, OPTION_NO_MEDIA      },
+  { "mcpu",		required_argument,	NULL, OPTION_CPU           },
+  { "mpic",		no_argument,		NULL, OPTION_PIC           },
+  { "mPIC",		no_argument,		NULL, OPTION_BIGPIC        },
+  { "mlibrary-pic",	no_argument,		NULL, OPTION_LIBPIC        },
+  { "mmuladd",		no_argument,		NULL, OPTION_MULADD        },
+  { "mno-muladd",	no_argument,		NULL, OPTION_NO_MULADD     },
+  { "mtomcat-debug",    no_argument,            NULL, OPTION_TOMCAT_DEBUG  },
+  { "mtomcat-stats",	no_argument,		NULL, OPTION_TOMCAT_STATS  },
+  { "mpack",        	no_argument,		NULL, OPTION_PACK          },
+  { "mno-pack",        	no_argument,		NULL, OPTION_NO_PACK       },
+  { NULL,		no_argument,		NULL, 0                 },
+};
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+/* What value to give to bfd_set_gp_size.  */
+static int g_switch_value = 8;
+
+int
+md_parse_option (c, arg)
+     int    c;
+     char * arg;
+{
+  switch (c)
+    {
+    default:
+      return 0;
+
+    case 'G':
+      g_switch_value = atoi (arg);
+      if (! g_switch_value)
+	frv_flags |= EF_FRV_G0;
+      break;
+
+    case OPTION_GPR_32:
+      frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
+      break;
+
+    case OPTION_GPR_64:
+      frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
+      break;
+
+    case OPTION_FPR_32:
+      frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
+      break;
+
+    case OPTION_FPR_64:
+      frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
+      break;
+
+    case OPTION_SOFT_FLOAT:
+      frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
+      break;
+
+    case OPTION_DWORD_YES:
+      frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
+      break;
+
+    case OPTION_DWORD_NO:
+      frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
+      break;
+
+    case OPTION_DOUBLE:
+      frv_flags |= EF_FRV_DOUBLE;
+      break;
+
+    case OPTION_NO_DOUBLE:
+      frv_flags &= ~EF_FRV_DOUBLE;
+      break;
+
+    case OPTION_MEDIA:
+      frv_flags |= EF_FRV_MEDIA;
+      break;
+
+    case OPTION_NO_MEDIA:
+      frv_flags &= ~EF_FRV_MEDIA;
+      break;
+
+    case OPTION_MULADD:
+      frv_flags |= EF_FRV_MULADD;
+      break;
+
+    case OPTION_NO_MULADD:
+      frv_flags &= ~EF_FRV_MULADD;
+      break;
+
+    case OPTION_PACK:
+      frv_flags &= ~EF_FRV_NOPACK;
+      break;
+
+    case OPTION_NO_PACK:
+      frv_flags |= EF_FRV_NOPACK;
+      break;
+
+    case OPTION_CPU:
+      {
+	char *p;
+	int cpu_flags = EF_FRV_CPU_GENERIC;
+
+	/* Identify the processor type */
+	p = arg;
+	if (strcmp (p, "frv") == 0)
+	  {
+	    cpu_flags = EF_FRV_CPU_GENERIC;
+	    frv_mach = bfd_mach_frv;
+	  }
+
+	else if (strcmp (p, "fr500") == 0)
+	  {
+	    cpu_flags = EF_FRV_CPU_FR500;
+	    frv_mach = bfd_mach_fr500;
+	  }
+
+	else if (strcmp (p, "fr400") == 0)
+	  {
+	    cpu_flags = EF_FRV_CPU_FR400;
+	    frv_mach = bfd_mach_fr400;
+	  }
+
+	else if (strcmp (p, "fr300") == 0)
+	  {
+	    cpu_flags = EF_FRV_CPU_FR300;
+	    frv_mach = bfd_mach_fr300;
+	  }
+
+	else if (strcmp (p, "simple") == 0)
+	  {
+	    cpu_flags = EF_FRV_CPU_SIMPLE;
+	    frv_mach = bfd_mach_frvsimple;
+	    frv_flags |= EF_FRV_NOPACK;
+	  }
+
+        else if (strcmp (p, "tomcat") == 0)
+          {
+            cpu_flags = EF_FRV_CPU_TOMCAT;
+            frv_mach = bfd_mach_frvtomcat;
+          }
+
+	else
+	  {
+	    as_fatal ("Unknown cpu -mcpu=%s", arg);
+	    return 0;
+	  }
+
+	frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
+      }
+      break;
+
+    case OPTION_PIC:
+      frv_flags |= EF_FRV_PIC;
+      frv_pic_p = 1;
+      frv_pic_flag = "-fpic";
+      break;
+
+    case OPTION_BIGPIC:
+      frv_flags |= EF_FRV_BIGPIC;
+      frv_pic_p = 1;
+      frv_pic_flag = "-fPIC";
+      break;
+
+    case OPTION_LIBPIC:
+      frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
+      frv_pic_p = 1;
+      frv_pic_flag = "-mlibrary-pic";
+      g_switch_value = 0;
+      break;
+
+    case OPTION_TOMCAT_DEBUG:
+      tomcat_debug = 1;
+      break;
+
+    case OPTION_TOMCAT_STATS:
+      tomcat_stats = 1;
+      break;
+    }
+
+  return 1;
+}
+
+void
+md_show_usage (stream)
+  FILE * stream;
+{
+  fprintf (stream, _("FRV specific command line options:\n"));
+  fprintf (stream, _("-G n         Data >= n bytes is in small data area\n"));
+  fprintf (stream, _("-mgpr-32     Note 32 gprs are used\n"));
+  fprintf (stream, _("-mgpr-64     Note 64 gprs are used\n"));
+  fprintf (stream, _("-mfpr-32     Note 32 fprs are used\n"));
+  fprintf (stream, _("-mfpr-64     Note 64 fprs are used\n"));
+  fprintf (stream, _("-msoft-float Note software fp is used\n"));
+  fprintf (stream, _("-mdword      Note stack is aligned to a 8 byte boundary\n"));
+  fprintf (stream, _("-mno-dword   Note stack is aligned to a 4 byte boundary\n"));
+  fprintf (stream, _("-mdouble     Note fp double insns are used\n"));
+  fprintf (stream, _("-mmedia      Note media insns are used\n"));
+  fprintf (stream, _("-mmuladd     Note multiply add/subtract insns are used\n"));
+  fprintf (stream, _("-mpack       Note instructions are packed\n"));
+  fprintf (stream, _("-mno-pack    Do not allow instructions to be packed\n"));
+  fprintf (stream, _("-mpic        Note small position independent code\n"));
+  fprintf (stream, _("-mPIC        Note large position independent code\n"));
+  fprintf (stream, _("-mlibrary-pic Compile library for large position indepedent code\n"));
+  fprintf (stream, _("-mcpu={fr500|fr400|fr300|frv|simple|tomcat}\n"));
+  fprintf (stream, _("             Record the cpu type\n"));
+  fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
+  fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
+} 
+
+
+void
+md_begin ()
+{
+  /* Initialize the `cgen' interface.  */
+  
+  /* Set the machine number and endian.  */
+  gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
+					 CGEN_CPU_OPEN_ENDIAN,
+					 CGEN_ENDIAN_BIG,
+					 CGEN_CPU_OPEN_END);
+  frv_cgen_init_asm (gas_cgen_cpu_desc);
+
+  /* This is a callback from cgen to gas to parse operands.  */
+  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
+
+  /* Set the ELF flags if desired. */
+  if (frv_flags)
+    bfd_set_private_flags (stdoutput, frv_flags);
+
+  /* Set the machine type */
+  bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
+
+  /* Set up gp size so we can put local common items in .sbss */
+  bfd_set_gp_size (stdoutput, g_switch_value);
+
+  frv_vliw_reset (& vliw, frv_mach, frv_flags);
+}
+
+int chain_num = 0;
+
+struct vliw_insn_list *
+frv_insert_vliw_insn (count)
+      boolean count;
+{
+  struct vliw_insn_list *vliw_insn_list_entry;
+  struct vliw_chain     *vliw_chain_entry;
+
+  if (current_vliw_chain == NULL)
+    {
+      vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+      vliw_chain_entry->insn_count = 0;
+      vliw_chain_entry->insn_list  = NULL;
+      vliw_chain_entry->next       = NULL;
+      vliw_chain_entry->num        = chain_num++;
+
+      if (!vliw_chain_top)
+	vliw_chain_top = vliw_chain_entry;
+      current_vliw_chain = vliw_chain_entry;
+      if (previous_vliw_chain)
+	previous_vliw_chain->next = vliw_chain_entry;
+    }
+
+  vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
+  vliw_insn_list_entry->type      = VLIW_GENERIC_TYPE;
+  vliw_insn_list_entry->insn      = NULL;
+  vliw_insn_list_entry->sym       = NULL;
+  vliw_insn_list_entry->snop_frag = NULL;
+  vliw_insn_list_entry->dnop_frag = NULL;
+  vliw_insn_list_entry->next      = NULL;
+
+  if (count)
+    current_vliw_chain->insn_count++;
+
+  if (current_vliw_insn)
+    current_vliw_insn->next = vliw_insn_list_entry;
+  current_vliw_insn = vliw_insn_list_entry;
+
+  if (!current_vliw_chain->insn_list)
+    current_vliw_chain->insn_list = current_vliw_insn;
+
+  return vliw_insn_list_entry;
+}
+
+  /* Identify the following cases:
+ 
+     1) A VLIW insn that contains both a branch and the branch destination.
+        This requires the insertion of two vliw instructions before the
+        branch.  The first consists of two nops.  The second consists of
+        a single nop.
+ 
+     2) A single instruction VLIW insn which is the destination of a branch
+        that is in the next VLIW insn.  This requires the insertion of a vliw
+        insn containing two nops before the branch.
+ 
+     3) A double instruction VLIW insn which contains the destination of a
+        branch that is in the next VLIW insn.  This requires the insertion of
+        a VLIW insn containing a single nop before the branch.
+ 
+     4) A single instruction VLIW insn which contains branch destination (x),
+        followed by a single instruction VLIW insn which does not contain
+        the branch to (x), followed by a VLIW insn which does contain the branch
+        to (x).  This requires the insertion of a VLIW insn containing a single
+        nop before the VLIW instruction containing the branch.
+ 
+  */
+#define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
+#define FRV_NOP_PACK   0x00880000  /* ori.p  gr0,0,gr0 */
+#define FRV_NOP_NOPACK 0x80880000  /* ori    gr0,0,gr0 */
+
+/* Check a vliw insn for an insn of type containing the sym passed in label_sym.  */
+
+static struct vliw_insn_list *
+frv_find_in_vliw (vliw_insn_type, this_chain, label_sym)
+    enum vliw_insn_type vliw_insn_type;
+    struct vliw_chain *this_chain;
+    symbolS *label_sym;
+{
+
+  struct vliw_insn_list *the_insn;
+
+  if (!this_chain)
+    return NULL;
+
+  for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
+    {
+      if (the_insn->type == vliw_insn_type
+	  && the_insn->sym == label_sym)
+	return the_insn;
+    }
+
+  return NULL;
+}
+
+enum vliw_nop_type
+{
+  /* A Vliw insn containing a single nop insn.  */
+  VLIW_SINGLE_NOP,
+  
+  /* A Vliw insn containing two nop insns.  */
+  VLIW_DOUBLE_NOP,
+
+  /* Two vliw insns.  The first containing two nop insns.  
+     The second contain a single nop insn.  */
+  VLIW_DOUBLE_THEN_SINGLE_NOP
+};
+
+static void
+frv_debug_tomcat (start_chain)
+   struct vliw_chain *start_chain;
+{
+   struct vliw_chain *this_chain;
+   struct vliw_insn_list *this_insn;
+   int i = 1;
+
+  for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
+    {
+      fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
+
+      for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
+	{
+	  if (this_insn->type == VLIW_LABEL_TYPE)
+	    fprintf (stderr, "Label Value: %d\n", (int) this_insn->sym);
+	  else if (this_insn->type == VLIW_BRANCH_TYPE)
+	    fprintf (stderr, "%s to %d\n", this_insn->insn->base->name, (int) this_insn->sym);
+	  else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
+	    fprintf (stderr, "nop'd %s to %d\n", this_insn->insn->base->name, (int) this_insn->sym);
+	  else if (this_insn->type == VLIW_NOP_TYPE)
+	    fprintf (stderr, "Nop\n");
+	  else
+	    fprintf (stderr, "	%s\n", this_insn->insn->base->name);
+	}
+   }
+}
+
+
+static void
+frv_adjust_vliw_count (this_chain)
+    struct vliw_chain *this_chain;
+{
+  struct vliw_insn_list *this_insn;
+
+  this_chain->insn_count = 0;
+
+  for (this_insn = this_chain->insn_list;
+       this_insn;
+       this_insn = this_insn->next)
+    {
+      if (this_insn->type != VLIW_LABEL_TYPE)
+  	this_chain->insn_count++;
+    }
+
+}
+
+/* Insert the desired nop combination in the vliw chain before insert_before_insn.
+   Rechain the vliw insn.  */
+
+
+static struct vliw_chain *
+frv_tomcat_shuffle (this_nop_type, vliw_to_split, insert_before_insn)
+   enum vliw_nop_type    this_nop_type;
+   struct vliw_chain     *vliw_to_split;
+   struct vliw_insn_list *insert_before_insn;
+{
+
+  boolean pack_prev = false;
+  struct vliw_chain *return_me = NULL;
+  struct vliw_insn_list *prev_insn = NULL;
+  struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
+
+  struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+  struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+  struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
+  struct vliw_chain *curr_vliw = vliw_chain_top;
+  struct vliw_chain *prev_vliw = NULL;
+
+  while (curr_insn && curr_insn != insert_before_insn)
+    {
+      /* We can't set the packing bit on a label.  If we have the case
+	 label 1:
+	 label 2:
+	 label 3:
+	   branch that needs nops
+	Then don't set pack bit later.  */
+
+      if (curr_insn->type != VLIW_LABEL_TYPE)
+	pack_prev = true;
+      prev_insn = curr_insn;
+      curr_insn = curr_insn->next;
+    } 
+
+  while (curr_vliw && curr_vliw != vliw_to_split)
+    {
+      prev_vliw = curr_vliw;
+      curr_vliw = curr_vliw->next;
+    }
+
+  switch (this_nop_type)
+    {
+    case VLIW_SINGLE_NOP:
+      if (!prev_insn)
+	{
+	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
+	if (prev_vliw)
+	  prev_vliw->next = single_nop;
+	else
+	  vliw_chain_top = single_nop;
+	single_nop->next = vliw_to_split;
+	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+	return_me = vliw_to_split;
+	}
+      else
+	{
+	  /* Set the packing bit on the previous insn.  */
+	  if (pack_prev)
+	    {
+	      unsigned char *buffer = prev_insn->address;
+	      buffer[0] |= 0x80;
+	    }
+	  /* The branch is in the middle.  Split this vliw insn into first
+	     and second parts.  Insert the NOP inbetween.  */
+
+          second_part->insn_list = insert_before_insn;
+	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+          second_part->next      = vliw_to_split->next;
+ 	  frv_adjust_vliw_count (second_part);
+
+          single_nop->next       = second_part;
+ 
+          vliw_to_split->next    = single_nop;
+          prev_insn->next        = NULL;
+ 
+          return_me = second_part;
+	  frv_adjust_vliw_count (vliw_to_split);
+	}
+      break;
+
+    case VLIW_DOUBLE_NOP:
+      if (!prev_insn)
+	{
+	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
+        if (prev_vliw)
+          prev_vliw->next = double_nop;
+        else
+          vliw_chain_top = double_nop;
+
+	double_nop->next = vliw_to_split;
+	return_me = vliw_to_split;
+	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+	}
+      else
+	{
+	  /* Set the packing bit on the previous insn.  */
+	  if (pack_prev)
+	    {
+	      unsigned char *buffer = prev_insn->address;
+	      buffer[0] |= 0x80;
+	    }
+
+	/* The branch is in the middle.  Split this vliw insn into first
+	   and second parts.  Insert the NOP inbetween.  */
+          second_part->insn_list = insert_before_insn;
+	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+          second_part->next      = vliw_to_split->next;
+ 	  frv_adjust_vliw_count (second_part);
+ 
+          double_nop->next       = second_part;
+ 
+          vliw_to_split->next    = single_nop;
+          prev_insn->next        = NULL;
+ 	  frv_adjust_vliw_count (vliw_to_split);
+ 
+          return_me = second_part;
+	}
+      break;
+
+    case VLIW_DOUBLE_THEN_SINGLE_NOP:
+      double_nop->next = single_nop;
+      double_nop->insn_count = 2;
+      double_nop->insn_list = &double_nop_insn;
+      single_nop->insn_count = 1;
+      single_nop->insn_list = &single_nop_insn;
+
+      if (!prev_insn)
+	{
+	  /* The branch is the first insn in this vliw.  Don't split the vliw.  Insert
+	     the nops prior to this vliw.  */
+          if (prev_vliw)
+            prev_vliw->next = double_nop;
+          else
+            vliw_chain_top = double_nop;
+ 
+	  single_nop->next = vliw_to_split;
+	  return_me = vliw_to_split;
+	  vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+	}
+      else
+	{
+	  /* Set the packing bit on the previous insn.  */
+	  if (pack_prev)
+	    {
+	      unsigned char *buffer = prev_insn->address;
+	      buffer[0] |= 0x80;
+	    }
+
+	  /* The branch is in the middle of this vliw insn.  Split into first and
+	     second parts.  Insert the nop vliws in between.  */  
+	  second_part->insn_list = insert_before_insn;
+	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
+	  second_part->next      = vliw_to_split->next;
+ 	  frv_adjust_vliw_count (second_part);
+
+	  single_nop->next       = second_part;
+
+	  vliw_to_split->next	 = double_nop;
+	  prev_insn->next	 = NULL;
+ 	  frv_adjust_vliw_count (vliw_to_split);
+
+	  return_me = second_part;
+	}
+      break;
+    }
+
+  return return_me;
+}
+
+static void
+frv_tomcat_analyze_vliw_chains ()
+{
+  struct vliw_chain *vliw1 = NULL;
+  struct vliw_chain *vliw2 = NULL;
+  struct vliw_chain *vliw3 = NULL;
+
+  struct vliw_insn_list *this_insn = NULL;
+  struct vliw_insn_list *temp_insn = NULL;
+
+  /* We potentially need to look at three VLIW insns to determine if the
+     workaround is required.  Set them up.  Ignore existing nops during analysis. */
+
+#define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
+  if (VLIW1 && VLIW1->next)			 \
+    VLIW2 = VLIW1->next;			 \
+  else						 \
+    VLIW2 = NULL;				 \
+  if (VLIW2 && VLIW2->next)			 \
+    VLIW3 = VLIW2->next;			 \
+  else						 \
+    VLIW3 = NULL
+
+  vliw1 = vliw_chain_top;
+
+workaround_top:
+
+  FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
+
+  if (!vliw1)
+    return;
+
+  if (vliw1->insn_count == 1)
+    {
+      /* check vliw1 for a label. */
+      if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
+	{
+	  temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
+	  if (temp_insn)
+	    {
+	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
+	      temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
+	      vliw1 = vliw1->next;
+	      if (tomcat_stats)
+		tomcat_doubles++;
+	      goto workaround_top;
+	    }
+	  else if (vliw2 
+		   && vliw2->insn_count == 1
+		   && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
+	    {
+	      temp_insn->snop_frag->fr_subtype = NOP_KEEP;
+	      vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
+	      if (tomcat_stats)
+		tomcat_singles++;
+	      goto workaround_top;
+	    }
+	}
+    }
+
+  if (vliw1->insn_count == 2)
+    {
+      struct vliw_insn_list *this_insn;
+ 
+      /* check vliw1 for a label. */
+      for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
+	{
+	  if (this_insn->type == VLIW_LABEL_TYPE)
+	    {
+	      if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym, temp_insn)) != NULL)
+		{
+		  temp_insn->snop_frag->fr_subtype = NOP_KEEP;
+		  vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
+		  if (tomcat_stats)
+		    tomcat_singles++;
+		}
+	      else
+		vliw1 = vliw1->next;
+              goto workaround_top;
+            }
+	}
+    }
+  /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
+  for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
+    {
+      /* Don't look at labels or nops.  */
+      while (this_insn
+	     && (this_insn->type == VLIW_LABEL_TYPE
+                 || this_insn->type == VLIW_NOP_TYPE
+		 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
+	this_insn = this_insn->next;
+
+      if (!this_insn)
+        {
+	  vliw1 = vliw2;
+	  goto workaround_top;
+	}
+
+      if (frv_is_branch_insn (this_insn->insn))
+	{
+	  if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym, temp_insn)) != NULL)
+	    {
+	      /* Insert [nop/nop] [nop] before branch.  */
+	      this_insn->snop_frag->fr_subtype = NOP_KEEP;
+	      this_insn->dnop_frag->fr_subtype = NOP_KEEP;
+	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
+	      goto workaround_top;
+	    }
+	}
+
+
+    }
+  /* This vliw insn checks out okay.  Take a look at the next one.  */
+  vliw1 = vliw1->next;
+  goto workaround_top;
+}
+
+void
+frv_tomcat_workaround ()
+{
+  if (frv_mach != bfd_mach_frvtomcat)
+    return;
+
+  if (tomcat_debug)
+    frv_debug_tomcat (vliw_chain_top);
+
+  frv_tomcat_analyze_vliw_chains ();
+
+  if (tomcat_stats)
+    {
+      fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
+      fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
+    }
+}
+
+void
+md_assemble (str)
+     char * str;
+{
+  frv_insn insn;
+  char *errmsg;
+  int packing_constraint;
+  finished_insnS  finished_insn;
+  fragS *double_nop_frag = NULL;
+  fragS *single_nop_frag = NULL;
+  struct vliw_insn_list *vliw_insn_list_entry = NULL;
+
+  /* Initialize GAS's cgen interface for a new instruction.  */
+  gas_cgen_init_parse ();
+
+  insn.insn = frv_cgen_assemble_insn
+    (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
+  
+  if (!insn.insn)
+    {
+      as_bad (errmsg);
+      return;
+    }
+  
+  /* If the cpu is tomcat, then we need to insert nops to workaround
+     hardware limitations.  We need to keep track of each vliw unit
+     and examine the length of the unit and the individual insns
+     within the unit to determine the number and location of the
+     required nops.  */
+  if (frv_mach == bfd_mach_frvtomcat)
+    {
+      /* If we've just finished a VLIW insn OR this is a branch,
+	 then start up a new frag.  Fill it with nops.  We will get rid
+	 of those that are not required after we've seen all of the 
+	 instructions but before we start resolving fixups.  */
+      if ( !FRV_IS_NOP (insn)
+	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
+	{
+	  char *buffer;
+
+	  frag_wane (frag_now);
+	  frag_new (0);
+	  double_nop_frag = frag_now;
+	  buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
+	  md_number_to_chars (buffer, FRV_NOP_PACK, 4);
+	  md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
+
+	  frag_wane (frag_now);
+	  frag_new (0);
+	  single_nop_frag = frag_now;
+	  buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
+	  md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
+	}
+
+      vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
+      vliw_insn_list_entry->insn   = insn.insn;
+      if (frv_is_branch_insn (insn.insn))
+	vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
+
+      if ( !FRV_IS_NOP (insn)
+	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
+	{
+	  vliw_insn_list_entry->snop_frag = single_nop_frag;
+	  vliw_insn_list_entry->dnop_frag = double_nop_frag;
+	}
+    }
+
+  /* Make sure that this insn does not violate the VLIW packing constraints.  */
+  /* -mno-pack disallows any packing whatsoever.  */
+  if (frv_flags & EF_FRV_NOPACK)
+    {
+      if (! insn.fields.f_pack)
+	{
+	  as_bad (_("VLIW packing used for -mno-pack"));
+	  return;
+	}
+    }
+  /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
+     instructions, don't do vliw checking.  */
+  else if (frv_mach != bfd_mach_frv)
+    {
+      packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
+      if (insn.fields.f_pack)
+	frv_vliw_reset (& vliw, frv_mach, frv_flags);
+      if (packing_constraint)
+	{
+	  as_bad (_("VLIW packing constraint violation"));
+	  return;
+	}
+    }
+
+  /* Doesn't really matter what we pass for RELAX_P here.  */
+  gas_cgen_finish_insn (insn.insn, insn.buffer,
+			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
+
+
+  /* If the cpu is tomcat, then we need to insert nops to workaround
+     hardware limitations.  We need to keep track of each vliw unit
+     and examine the length of the unit and the individual insns
+     within the unit to determine the number and location of the
+     required nops.  */
+  if (frv_mach == bfd_mach_frvtomcat)
+    {
+      if (vliw_insn_list_entry)
+        vliw_insn_list_entry->address = finished_insn.addr;
+      else
+	abort();
+
+      if (insn.fields.f_pack)
+	{
+	  /* We've completed a VLIW insn.  */
+	  previous_vliw_chain = current_vliw_chain;
+	  current_vliw_chain = NULL;
+	  current_vliw_insn  = NULL;
+        } 
+    }
+}
+
+/* The syntax in the manual says constants begin with '#'.
+   We just ignore it.  */
+
+void 
+md_operand (expressionP)
+     expressionS * expressionP;
+{
+  if (* input_line_pointer == '#')
+    {
+      input_line_pointer ++;
+      expression (expressionP);
+    }
+}
+
+valueT
+md_section_align (segment, size)
+     segT   segment;
+     valueT size;
+{
+  int align = bfd_get_section_alignment (stdoutput, segment);
+  return ((size + (1 << align) - 1) & (-1 << align));
+}
+
+symbolS *
+md_undefined_symbol (name)
+  char * name ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* Interface to relax_segment.  */
+
+/* FIXME: Build table by hand, get it working, then machine generate.  */
+const relax_typeS md_relax_table[] =
+{
+  {1, 1, 0, 0},
+  {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
+  {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
+  {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
+};
+
+long
+frv_relax_frag (fragP, stretch)
+     fragS   *fragP ATTRIBUTE_UNUSED;
+     long    stretch ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* Return an initial guess of the length by which a fragment must grow to
+   hold a branch to reach its destination.
+   Also updates fr_type/fr_subtype as necessary.
+
+   Called just before doing relaxation.
+   Any symbol that is now undefined will not become defined.
+   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+   Although it may not be explicit in the frag, pretend fr_var starts with a
+   0 value.  */
+
+int
+md_estimate_size_before_relax (fragP, segment)
+     fragS * fragP;
+     segT    segment ATTRIBUTE_UNUSED;
+{
+  switch (fragP->fr_subtype)
+    {
+    case NOP_KEEP:
+      return fragP->fr_var;
+
+    default:
+    case NOP_DELETE:
+      return 0;
+    }     
+} 
+
+/* *fragP has been relaxed to its final size, and now needs to have
+   the bytes inside it modified to conform to the new size.
+
+   Called after relaxation is finished.
+   fragP->fr_type == rs_machine_dependent.
+   fragP->fr_subtype is the subtype of what the address relaxed to.  */
+
+void
+md_convert_frag (abfd, sec, fragP)
+  bfd *   abfd ATTRIBUTE_UNUSED;
+  segT    sec ATTRIBUTE_UNUSED;
+  fragS * fragP;
+{
+  switch (fragP->fr_subtype)
+    {
+    default:
+    case NOP_DELETE:
+      return;
+
+    case NOP_KEEP:
+      fragP->fr_fix = fragP->fr_var;
+      fragP->fr_var = 0;
+      return;   
+    }
+}
+
+/* Functions concerning relocs.  */
+
+/* The location from which a PC relative jump should be calculated,
+   given a PC relative reloc.  */
+
+long
+md_pcrel_from_section (fixP, sec)
+     fixS * fixP;
+     segT   sec;
+{
+  if (fixP->fx_addsy != (symbolS *) NULL
+      && (! S_IS_DEFINED (fixP->fx_addsy)
+	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+    {
+      /* The symbol is undefined (or is defined but not in this section).
+	 Let the linker figure it out.  */
+      return 0;
+    }
+
+  return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
+}
+
+/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
+   Returns BFD_RELOC_NONE if no reloc type can be found.
+   *FIXP may be modified if desired.  */
+
+bfd_reloc_code_real_type
+md_cgen_lookup_reloc (insn, operand, fixP)
+     const CGEN_INSN *    insn ATTRIBUTE_UNUSED;
+     const CGEN_OPERAND * operand;
+     fixS *               fixP;
+{
+  switch (operand->type)
+    {
+    case FRV_OPERAND_LABEL16:
+      fixP->fx_pcrel = true;
+      return BFD_RELOC_FRV_LABEL16;
+
+    case FRV_OPERAND_LABEL24:
+      fixP->fx_pcrel = true;
+      return BFD_RELOC_FRV_LABEL24;
+
+    case FRV_OPERAND_UHI16:
+    case FRV_OPERAND_ULO16:
+    case FRV_OPERAND_SLO16:
+
+      /* The relocation type should be recorded in opinfo */
+      if (fixP->fx_cgen.opinfo != 0)
+        return fixP->fx_cgen.opinfo;
+      break;
+
+    case FRV_OPERAND_D12:
+    case FRV_OPERAND_S12:
+      return BFD_RELOC_FRV_GPREL12;
+
+    case FRV_OPERAND_U12:
+      return BFD_RELOC_FRV_GPRELU12;
+
+    default: 
+      break;
+    }
+  return BFD_RELOC_NONE;
+}
+
+
+/* See whether we need to force a relocation into the output file.
+   This is used to force out switch and PC relative relocations when
+   relaxing.  */
+
+int
+frv_force_relocation (fix)
+     fixS * fix;
+{
+  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+      || fix->fx_r_type == BFD_RELOC_FRV_GPREL12
+      || fix->fx_r_type == BFD_RELOC_FRV_GPRELU12)
+    return 1;
+
+  return 0;
+}
+
+/* Write a value out to the object file, using the appropriate endianness.  */
+
+void
+frv_md_number_to_chars (buf, val, n)
+     char * buf;
+     valueT val;
+     int    n;
+{
+  number_to_chars_bigendian (buf, val, n);
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
+   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
+*/
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+     char   type;
+     char * litP;
+     int *  sizeP;
+{
+  int              i;
+  int              prec;
+  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
+  char *           t;
+  char *           atof_ieee ();
+
+  switch (type)
+    {
+    case 'f':
+    case 'F':
+    case 's':
+    case 'S':
+      prec = 2;
+      break;
+
+    case 'd':
+    case 'D':
+    case 'r':
+    case 'R':
+      prec = 4;
+      break;
+
+   /* FIXME: Some targets allow other format chars for bigger sizes here.  */
+
+    default:
+      * sizeP = 0;
+      return _("Bad call to md_atof()");
+    }
+
+  t = atof_ieee (input_line_pointer, type, words);
+  if (t)
+    input_line_pointer = t;
+  * sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+  for (i = 0; i < prec; i++)
+    {
+      md_number_to_chars (litP, (valueT) words[i],
+			  sizeof (LITTLENUM_TYPE));
+      litP += sizeof (LITTLENUM_TYPE);
+    }
+     
+  return 0;
+}
+
+boolean
+frv_fix_adjustable (fixP)
+   fixS * fixP;
+{
+  bfd_reloc_code_real_type reloc_type;
+
+  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
+    {
+      const CGEN_INSN *insn = NULL;
+      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
+      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
+      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
+    }
+  else
+    reloc_type = fixP->fx_r_type;
+
+  if (fixP->fx_addsy == NULL)
+    return 1;
+  
+  /* Prevent all adjustments to global symbols. */
+  if (S_IS_EXTERN (fixP->fx_addsy))
+    return 0;
+  
+  if (S_IS_WEAK (fixP->fx_addsy))
+    return 0;
+  
+  /* We need the symbol name for the VTABLE entries */
+  if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
+      || reloc_type == BFD_RELOC_VTABLE_ENTRY
+      || reloc_type == BFD_RELOC_FRV_GPREL12
+      || reloc_type == BFD_RELOC_FRV_GPRELU12)
+    return 0;
+
+  return 1;
+}
+
+/* Allow user to set flags bits.  */
+void
+frv_set_flags (arg)
+     int arg ATTRIBUTE_UNUSED;
+{
+  flagword new_flags = get_absolute_expression ();
+  flagword new_mask = ~ (flagword)0;
+
+  frv_user_set_flags_p = 1;
+  if (*input_line_pointer == ',')
+    {
+      ++input_line_pointer;
+      new_mask = get_absolute_expression ();
+    }
+
+  frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
+  bfd_set_private_flags (stdoutput, frv_flags);
+}
+
+/* Frv specific function to handle 4 byte initializations for pointers that are
+   considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
+   is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
+   BFD_RELOC_32 at that time.  */
+
+void
+frv_pic_ptr (nbytes)
+     int nbytes;
+{
+  expressionS exp;
+  char *p;
+
+  if (nbytes != 4)
+    abort ();
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+#ifdef md_cons_align
+  md_cons_align (nbytes);
+#endif
+
+  do
+    {
+      expression (&exp);
+
+      p = frag_more (4);
+      memset (p, 0, 4);
+      fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
+		   BFD_RELOC_CTOR);
+    }
+  while (*input_line_pointer++ == ',');
+
+  input_line_pointer--;			/* Put terminator back into stream. */
+  demand_empty_rest_of_line ();
+}
+
+
+
+#ifdef DEBUG
+#define DPRINTF1(A)	fprintf (stderr, A)
+#define DPRINTF2(A,B)	fprintf (stderr, A, B)
+#define DPRINTF3(A,B,C)	fprintf (stderr, A, B, C)
+
+#else
+#define DPRINTF1(A)
+#define DPRINTF2(A,B)
+#define DPRINTF3(A,B,C)
+#endif
+
+/* Go through a the sections looking for relocations that are problematical for
+   pic.  If not pic, just note that this object can't be linked with pic.  If
+   it is pic, see if it needs to be marked so that it will be fixed up, or if
+   not possible, issue an error.  */
+
+static void
+frv_frob_file_section (abfd, sec, ptr)
+     bfd *abfd;
+     asection *sec;
+     PTR ptr ATTRIBUTE_UNUSED;
+{
+  segment_info_type *seginfo = seg_info (sec);
+  fixS *fixp;
+  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
+  flagword flags = bfd_get_section_flags (abfd, sec);
+
+  /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
+     since we can fix those up by hand.  */
+  int known_section_p = (sec->name
+			 && sec->name[0] == '.'
+			 && ((sec->name[1] == 'c'
+			      && strcmp (sec->name, ".ctor") == 0)
+			     || (sec->name[1] == 'd'
+				 && strcmp (sec->name, ".dtor") == 0)
+			     || (sec->name[1] == 'g'
+				 && strcmp (sec->name, ".gcc_except_table") == 0)));
+
+  DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
+  if ((flags & SEC_ALLOC) == 0)
+    {
+      DPRINTF1 ("\tSkipping non-loaded section\n");
+      return;
+    }
+
+  for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
+    {
+      symbolS *s = fixp->fx_addsy;
+      bfd_reloc_code_real_type reloc;
+      int non_pic_p;
+      int opindex;
+      const CGEN_OPERAND *operand;
+      const CGEN_INSN *insn = fixp->fx_cgen.insn;
+
+      if (fixp->fx_done)
+	{
+	  DPRINTF1 ("\tSkipping reloc that has already been done\n");
+	  continue;
+	}
+
+      if (fixp->fx_pcrel)
+	{
+	  DPRINTF1 ("\tSkipping reloc that is PC relative\n");
+	  continue;
+	}
+
+      if (! s)
+	{
+	  DPRINTF1 ("\tSkipping reloc without symbol\n");
+	  continue;
+	}
+
+      if (fixp->fx_r_type < BFD_RELOC_UNUSED)
+	{
+	  opindex = -1;
+	  reloc = fixp->fx_r_type;
+	}
+      else
+	{
+	  opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
+	  operand = cgen_operand_lookup_by_num (cd, opindex);
+	  reloc = md_cgen_lookup_reloc (insn, operand, fixp);
+	}
+
+      DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
+
+      non_pic_p = 0;
+      switch (reloc)
+	{
+	default:
+	  break;
+
+	case BFD_RELOC_32:
+	  /* Skip relocations in known sections (.ctors, .dtors, and
+	     .gcc_except_table) since we can fix those up by hand.  Also
+	     skip forward references to constants.  Also skip a difference
+	     of two symbols, which still uses the BFD_RELOC_32 at this
+	     point.  */
+	  if (! known_section_p
+	      && S_GET_SEGMENT (s) != absolute_section
+	      && !fixp->fx_subsy
+	      && (flags & (SEC_READONLY | SEC_CODE)) == 0)
+	    {
+	      non_pic_p = 1;
+	    }
+	  break;
+
+	  /* FIXME -- should determine if any of the GP relocation really uses
+	     gr16 (which is not pic safe) or not.  Right now, assume if we
+	     aren't being compiled with -mpic, the usage is non pic safe, but
+	     is safe with -mpic.  */
+	case BFD_RELOC_FRV_GPREL12:
+	case BFD_RELOC_FRV_GPRELU12:
+	case BFD_RELOC_FRV_GPREL32:
+	case BFD_RELOC_FRV_GPRELHI:
+	case BFD_RELOC_FRV_GPRELLO:
+	  non_pic_p = ! frv_pic_p;
+	  break;
+
+	case BFD_RELOC_FRV_LO16:
+	case BFD_RELOC_FRV_HI16:
+	  if (S_GET_SEGMENT (s) != absolute_section)
+	    non_pic_p = 1;
+	  break;
+
+	case BFD_RELOC_VTABLE_INHERIT:
+	case BFD_RELOC_VTABLE_ENTRY:
+	  non_pic_p = 1;
+	  break;
+
+	  /* If this is a blessed BFD_RELOC_32, convert it back to the normal
+             relocation.  */
+	case BFD_RELOC_CTOR:
+	  fixp->fx_r_type = BFD_RELOC_32;
+	  break;
+	}
+
+      if (non_pic_p)
+	{
+	  DPRINTF1 (" (Non-pic relocation)\n");
+	  if (frv_pic_p)
+	    as_warn_where (fixp->fx_file, fixp->fx_line,
+			   _("Relocation %s is not safe for %s"),
+			   bfd_get_reloc_code_name (reloc), frv_pic_flag);
+
+	  else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
+	    {
+	      frv_flags |= EF_FRV_NON_PIC_RELOCS;
+	      bfd_set_private_flags (abfd, frv_flags);
+	    }
+	}
+#ifdef DEBUG
+      else
+	DPRINTF1 ("\n");
+#endif
+    }
+}
+
+/* After all of the symbols have been adjusted, go over the file looking
+   for any relocations that pic won't support.  */
+
+void
+frv_frob_file ()
+{
+  bfd_map_over_sections (stdoutput, frv_frob_file_section, (PTR)0);
+}
+
+void
+frv_frob_label (this_label)
+    symbolS *this_label;
+{
+  struct vliw_insn_list *vliw_insn_list_entry;
+
+  if (frv_mach != bfd_mach_frvtomcat)
+    return;
+
+  if (now_seg != text_section)
+    return;
+
+  vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
+  vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
+  vliw_insn_list_entry->sym  = this_label; 
+}
+
+fixS *
+frv_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
+     fragS *              frag;
+     int                  where;
+     const CGEN_INSN *    insn;
+     int                  length;
+     const CGEN_OPERAND * operand;
+     int                  opinfo;
+     expressionS *        exp;
+{
+  fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
+                                           operand, opinfo, exp);
+
+  if (frv_mach == bfd_mach_frvtomcat
+      && current_vliw_insn
+      && current_vliw_insn->type == VLIW_BRANCH_TYPE
+      && exp != NULL)
+    current_vliw_insn->sym = exp->X_add_symbol;
+    
+  return fixP;
+}
Index: gas/config/tc-frv.h
===================================================================
RCS file: gas/config/tc-frv.h
diff -N gas/config/tc-frv.h
--- gas/config/tc-frv.h	1 Jan 1970 00:00:00 -0000
+++ gas/config/tc-frv.h	10 Jun 2002 22:02:41 -0000
@@ -0,0 +1,89 @@
+/* tc-frv.h -- Header file for tc-frv.c.
+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA. */
+
+#define TC_FRV
+
+#ifndef BFD_ASSEMBLER
+/* leading space so will compile with cc */
+ #error FRV support requires BFD_ASSEMBLER
+#endif
+
+#define LISTING_HEADER "FRV GAS "
+
+/* The target BFD architecture.  */
+#define TARGET_ARCH bfd_arch_frv
+
+#define TARGET_FORMAT "elf32-frv"
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+long md_pcrel_from_section PARAMS ((struct fix *, segT));
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+
+/* Permit temporary numeric labels.  */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK		/* .-foo gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely.  */
+#define WORKING_DOT_WORD
+
+#define md_apply_fix3 gas_cgen_md_apply_fix3
+
+extern void frv_tomcat_workaround PARAMS ((void));
+#define md_cleanup frv_tomcat_workaround
+
+#define md_number_to_chars frv_md_number_to_chars
+
+extern long frv_relax_frag PARAMS ((fragS *, long));
+#define md_relax_frag(segment, fragP, stretch) frv_relax_frag(fragP, stretch)
+
+#define obj_fix_adjustable(fixP) frv_fix_adjustable (fixP)
+extern boolean frv_fix_adjustable PARAMS ((struct fix *));
+
+#ifdef OBJ_ELF
+/* This arranges for gas/write.c to not apply a relocation if
+   obj_fix_adjustable() says it is not adjustable.  */
+#define TC_FIX_ADJUSTABLE(fixP) obj_fix_adjustable (fixP)
+#endif
+
+/* When relaxing, we need to emit various relocs we otherwise wouldn't.  */
+#define TC_FORCE_RELOCATION(fix) frv_force_relocation (fix)
+extern int frv_force_relocation PARAMS ((struct fix *));
+
+#undef GAS_CGEN_MAX_FIXUPS
+#define GAS_CGEN_MAX_FIXUPS 1
+
+void frv_frob_label PARAMS ((symbolS *));
+#define tc_frob_label(sym) frv_frob_label(sym)
+
+#define tc_gen_reloc gas_cgen_tc_gen_reloc
+
+#define md_cgen_record_fixup_exp frv_cgen_record_fixup_exp
+
+/* Call md_pcrel_from_section(), not md_pcrel_from().  */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+/* After all of the symbols have been adjusted, go over the file looking
+   for any relocations that pic won't support.  */
+#define tc_frob_file() frv_frob_file ()
+extern void frv_frob_file	PARAMS ((void));
Index: gas/po/POTFILES.in
===================================================================
RCS file: /cvs/src/src/gas/po/POTFILES.in,v
retrieving revision 1.16
diff -c -p -d -u -p -r1.16 POTFILES.in
--- gas/po/POTFILES.in	31 May 2002 04:25:51 -0000	1.16
+++ gas/po/POTFILES.in	10 Jun 2002 22:02:41 -0000
@@ -60,6 +60,8 @@ config/tc-dlx.c
 config/tc-dlx.h
 config/tc-fr30.c
 config/tc-fr30.h
+config/tc-frv.c
+config/tc-frv.h
 config/tc-h8300.c
 config/tc-h8300.h
 config/tc-h8500.c
Index: include/dis-asm.h
===================================================================
RCS file: /cvs/src/src/include/dis-asm.h,v
retrieving revision 1.34
diff -c -p -d -u -p -r1.34 dis-asm.h
--- include/dis-asm.h	28 May 2002 14:08:14 -0000	1.34
+++ include/dis-asm.h	10 Jun 2002 22:02:43 -0000
@@ -236,6 +236,7 @@ extern int print_insn_w65		PARAMS ((bfd_
 extern int print_insn_xstormy16		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_sh64		PARAMS ((bfd_vma, disassemble_info *));
 extern int print_insn_sh64x_media	PARAMS ((bfd_vma, disassemble_info *));
+extern int print_insn_frv		PARAMS ((bfd_vma, disassemble_info *));
 
 extern disassembler_ftype arc_get_disassembler PARAMS ((void *));
 extern disassembler_ftype cris_get_disassembler PARAMS ((bfd *));
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.45
diff -c -p -d -u -p -r1.45 common.h
--- include/elf/common.h	6 Jun 2002 09:59:38 -0000	1.45
+++ include/elf/common.h	10 Jun 2002 22:02:43 -0000
@@ -244,6 +244,8 @@ Foundation, Inc., 59 Temple Place - Suit
 
 #define EM_XSTORMY16	        0xad45
 
+/* FRV magic number - no EABI available??.  */
+#define EM_CYGNUS_FRV		0x5441
 /* See the above comment before you add a new EM_* value here.  */
 
 /* Values for e_version.  */
Index: include/elf/frv.h
===================================================================
RCS file: include/elf/frv.h
diff -N include/elf/frv.h
--- include/elf/frv.h	1 Jan 1970 00:00:00 -0000
+++ include/elf/frv.h	10 Jun 2002 22:02:43 -0000
@@ -0,0 +1,95 @@
+/* FRV ELF support for BFD.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _ELF_FRV_H
+#define _ELF_FRV_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocations.  */
+START_RELOC_NUMBERS (elf_frv_reloc_type)
+  RELOC_NUMBER (R_FRV_NONE, 0)
+  RELOC_NUMBER (R_FRV_32, 1)
+  RELOC_NUMBER (R_FRV_LABEL16, 2)
+  RELOC_NUMBER (R_FRV_LABEL24, 3)
+  RELOC_NUMBER (R_FRV_LO16, 4)
+  RELOC_NUMBER (R_FRV_HI16, 5)
+  RELOC_NUMBER (R_FRV_GPREL12, 6)
+  RELOC_NUMBER (R_FRV_GPRELU12, 7)
+  RELOC_NUMBER (R_FRV_GPREL32, 8)
+  RELOC_NUMBER (R_FRV_GPRELHI, 9)
+  RELOC_NUMBER (R_FRV_GPRELLO, 10)
+  RELOC_NUMBER (R_FRV_GNU_VTINHERIT, 200)
+  RELOC_NUMBER (R_FRV_GNU_VTENTRY, 201)
+END_RELOC_NUMBERS(R_FRV_max)
+
+/* Processor specific flags for the ELF header e_flags field.  */
+						/* gpr support */
+#define EF_FRV_GPR_MASK		0x00000003	/* mask for # of gprs */
+#define EF_FRV_GPR_32		0x00000001	/* -mgpr-32 */
+#define EF_FRV_GPR_64		0x00000002	/* -mgpr-64 */
+
+						/* fpr support */
+#define EF_FRV_FPR_MASK		0x0000000c	/* mask for # of fprs */
+#define EF_FRV_FPR_32		0x00000004	/* -mfpr-32 */
+#define EF_FRV_FPR_64		0x00000008	/* -mfpr-64 */
+#define EF_FRV_FPR_NONE		0x0000000c	/* -msoft-float */
+
+						/* double word support */
+#define EF_FRV_DWORD_MASK	0x00000030	/* mask for dword support */
+#define EF_FRV_DWORD_YES	0x00000010	/* use double word insns */
+#define EF_FRV_DWORD_NO		0x00000020	/* don't use double word insn*/
+
+#define EF_FRV_DOUBLE		0x00000040	/* -mdouble */
+#define EF_FRV_MEDIA		0x00000080	/* -mmedia */
+
+#define EF_FRV_PIC		0x00000100	/* -fpic */
+#define EF_FRV_NON_PIC_RELOCS	0x00000200	/* used non pic safe relocs */
+
+#define EF_FRV_MULADD		0x00000400	/* -mmuladd */
+#define EF_FRV_BIGPIC		0x00000800	/* -fPIC */
+#define	EF_FRV_LIBPIC		0x00001000	/* -mlibrary-pic */
+#define EF_FRV_G0		0x00002000	/* -G 0, no small data ptr */
+#define EF_FRV_NOPACK		0x00004000	/* -mnopack */
+
+#define	EF_FRV_CPU_MASK		0xff000000	/* specific cpu bits */
+#define EF_FRV_CPU_GENERIC	0x00000000	/* generic FRV */
+#define EF_FRV_CPU_FR500	0x01000000	/* FRV500 */
+#define EF_FRV_CPU_FR300	0x02000000	/* FRV300 */
+#define EF_FRV_CPU_SIMPLE	0x03000000	/* SIMPLE */
+#define EF_FRV_CPU_TOMCAT	0x04000000	/* Tomcat, FR500 prototype */
+#define EF_FRV_CPU_FR400	0x05000000	/* FRV400 */
+
+						/* Mask of PIC related bits */
+#define	EF_FRV_PIC_FLAGS	(EF_FRV_PIC | EF_FRV_LIBPIC | EF_FRV_BIGPIC)
+
+						/* Mask of all flags */
+#define EF_FRV_ALL_FLAGS	(EF_FRV_GPR_MASK | \
+				 EF_FRV_FPR_MASK | \
+				 EF_FRV_DWORD_MASK | \
+				 EF_FRV_DOUBLE | \
+				 EF_FRV_MEDIA | \
+				 EF_FRV_PIC_FLAGS | \
+				 EF_FRV_NON_PIC_RELOCS | \
+				 EF_FRV_MULADD | \
+				 EF_FRV_G0 | \
+				 EF_FRV_NOPACK | \
+				 EF_FRV_CPU_MASK)
+
+#endif /* _ELF_FRV_H */
Index: ld/NEWS
===================================================================
RCS file: /cvs/src/src/ld/NEWS,v
retrieving revision 1.23
diff -c -p -d -u -p -r1.23 NEWS
--- ld/NEWS	30 May 2002 02:58:04 -0000	1.23
+++ ld/NEWS	11 Jun 2002 20:44:57 -0000
@@ -1,4 +1,7 @@
 -*- text -*-
+Support for the Fujitsu FRV architecture added by Red Hat. Models for FR400 and
+FR500 included.
+
 Changes in version 2.13:
 
 * DEC VAX ELF support, by Matt Thomas.
Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.101
diff -c -p -d -u -p -r1.101 Makefile.am
--- ld/Makefile.am	4 Jun 2002 02:57:42 -0000	1.101
+++ ld/Makefile.am	10 Jun 2002 22:02:43 -0000
@@ -159,6 +159,7 @@ ALL_EMULATIONS = \
 	eelf32ebmip.o \
 	eelf32elmip.o \
 	eelf32fr30.o \
+	eelf32frv.o \
 	eelf32i370.o \
 	eelf32l4300.o \
 	eelf32lmip.o \
@@ -526,6 +527,9 @@ eelf32vax.c: $(srcdir)/emulparams/elf32v
 eelf32fr30.c: $(srcdir)/emulparams/elf32fr30.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32fr30 "$(tdir_fr30)"
+eelf32frv.c: $(srcdir)/emulparams/elf32frv.sh \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} elf32frv "$(tdir_frv)"
 eelf32mcore.c: $(srcdir)/emulparams/elf32mcore.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32mcore "$(tdir_mcore)"
Index: ld/configure.tgt
===================================================================
RCS file: /cvs/src/src/ld/configure.tgt,v
retrieving revision 1.95
diff -c -p -d -u -p -r1.95 configure.tgt
--- ld/configure.tgt	5 Jun 2002 19:54:28 -0000	1.95
+++ ld/configure.tgt	10 Jun 2002 22:02:43 -0000
@@ -481,6 +481,7 @@ tic80-*-*)		targ_emul=tic80coff ;;
 v850-*-*)		targ_emul=v850 ;;
 v850e-*-*)		targ_emul=v850 ;;
 v850ea-*-*)		targ_emul=v850 ;;
+frv-*-*)		targ_emul=elf32frv ;;
 w65-*-*)		targ_emul=w65 ;;
 xstormy16-*-*)		targ_emul=elf32xstormy16 ;;
 fr30-*-*)		targ_emul=elf32fr30 ;;
Index: ld/emulparams/elf32frv.sh
===================================================================
RCS file: ld/emulparams/elf32frv.sh
diff -N ld/emulparams/elf32frv.sh
--- ld/emulparams/elf32frv.sh	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/elf32frv.sh	10 Jun 2002 22:02:43 -0000
@@ -0,0 +1,20 @@
+MACHINE=
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf32-frv"
+TEXT_START_ADDR=0x10000
+ARCH=frv
+MAXPAGESIZE=256
+ENTRY=_start
+EMBEDDED=yes
+OTHER_EXCLUDE_FILES='*frvend.o'
+OTHER_BSS_END_SYMBOLS='__end = .;'
+DATA_START_SYMBOLS='__data_start = . ;'
+OTHER_RELOCATING_SECTIONS='
+  PROVIDE (_stack = 0x200000);
+  PROVIDE (__stack = 0x200000);'
+OTHER_GOT_SYMBOLS='
+  . = ALIGN(8);  _gp = . + 2048;
+  PROVIDE (gp = _gp);'
+OTHER_READONLY_SECTIONS='
+  .rofixup        : { *(.rofixup) }
+'
Index: opcodes/Makefile.am
===================================================================
RCS file: /cvs/src/src/opcodes/Makefile.am,v
retrieving revision 1.52
diff -c -p -d -u -p -r1.52 Makefile.am
--- opcodes/Makefile.am	31 May 2002 04:27:35 -0000	1.52
+++ opcodes/Makefile.am	10 Jun 2002 22:02:46 -0000
@@ -26,6 +26,7 @@ LIBIBERTY = ../libiberty/libiberty.a
 HFILES = \
 	arm-opc.h \
 	fr30-desc.h fr30-opc.h \
+	frv-desc.h frv-opc.h \
 	h8500-opc.h \
 	ia64-asmtab.h \
 	ia64-opc.h \
@@ -66,6 +67,11 @@ CFILES = \
 	fr30-dis.c \
 	fr30-ibld.c \
 	fr30-opc.c \
+	frv-asm.c \
+	frv-desc.c \
+	frv-dis.c \
+	frv-ibld.c \
+	frv-opc.c \
 	h8300-dis.c \
 	h8500-dis.c \
 	hppa-dis.c \
@@ -168,6 +174,11 @@ ALL_MACHINES = \
 	fr30-dis.lo \
 	fr30-ibld.lo \
 	fr30-opc.lo \
+	frv-asm.lo \
+	frv-desc.lo \
+	frv-dis.lo \
+	frv-ibld.lo \
+	frv-opc.lo \
 	h8300-dis.lo \
 	h8500-dis.lo \
 	hppa-dis.lo \
@@ -301,7 +312,7 @@ uninstall_libopcodes:
 	rm -f $(DESTDIR)$(bfdincludedir)/dis-asm.h
 
 CLEANFILES = \
-	stamp-m32r stamp-fr30 stamp-openrisc \
+	stamp-m32r stamp-fr30 stamp-frv stamp-openrisc \
 	stamp-xstormy16 \
 	libopcodes.a stamp-lib dep.sed DEP DEPA DEP1 DEP2
 
@@ -321,11 +332,13 @@ CGENDEPS = ../cgen/stamp-cgen \
 if CGEN_MAINT
 M32R_DEPS = stamp-m32r
 FR30_DEPS = stamp-fr30
+FRV_DEPS = stamp-frv
 OPENRISC_DEPS = stamp-openrisc
 XSTORMY16_DEPS = stamp-xstormy16
 else
 M32R_DEPS =
 FR30_DEPS =
+FRV_DEPS =
 OPENRISC_DEPS = 
 XSTORMY16_DEPS = 
 endif
@@ -348,6 +361,11 @@ $(srcdir)/fr30-desc.h $(srcdir)/fr30-des
 stamp-fr30: $(CGENDEPS) $(CPUDIR)/fr30.cpu $(CPUDIR)/fr30.opc
 	$(MAKE) run-cgen arch=fr30 prefix=fr30 options= extrafiles=
 
+$(srcdir)/frv-desc.h $(srcdir)/frv-desc.c $(srcdir)/frv-opc.h $(srcdir)/frv-opc.c $(srcdir)/frv-ibld.c $(srcdir)/frv-asm.c $(srcdir)/frv-dis.c: $(FRV_DEPS)
+	@true
+stamp-frv: $(CGENDEPS) $(CPUDIR)/frv.cpu $(CPUDIR)/frv.opc
+	$(MAKE) run-cgen arch=frv prefix=frv options= extrafiles=
+
 $(srcdir)/openrisc-desc.h $(srcdir)/openrisc-desc.c $(srcdir)/openrisc-opc.h $(srcdir)/openrisc-opc.c $(srcdir)/openrisc-ibld.c $(srcdir)/openrisc-asm.c $(srcdir)/openrisc-dis.c: $(OPENRISC_DEPS)
 	@true
 stamp-openrisc: $(CGENDEPS) $(CPUDIR)/openrisc.cpu $(CPUDIR)/openrisc.opc
@@ -495,6 +513,23 @@ fr30-ibld.lo: fr30-ibld.c sysdep.h confi
 fr30-opc.lo: fr30-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \
   $(BFD_H) $(INCDIR)/symcat.h fr30-desc.h $(INCDIR)/opcode/cgen.h \
   fr30-opc.h $(INCDIR)/libiberty.h
+frv-asm.lo: frv-asm.c sysdep.h config.h $(BFD_H) \
+  $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h frv-desc.h \
+  $(INCDIR)/opcode/cgen.h frv-opc.h opintl.h
+frv-desc.lo: frv-desc.c sysdep.h config.h $(BFD_H) \
+  $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h frv-desc.h \
+  $(INCDIR)/opcode/cgen.h frv-opc.h opintl.h
+frv-dis.lo: frv-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+  $(BFD_H) $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h frv-desc.h $(INCDIR)/opcode/cgen.h \
+  frv-opc.h opintl.h
+frv-ibld.lo: frv-ibld.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+  $(BFD_H) $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h frv-desc.h $(INCDIR)/opcode/cgen.h \
+  frv-opc.h opintl.h
+frv-opc.lo: frv-opc.c sysdep.h config.h $(BFD_H) \
+  $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h frv-desc.h \
+  $(INCDIR)/opcode/cgen.h frv-opc.h
 h8300-dis.lo: h8300-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/opcode/h8300.h $(INCDIR)/dis-asm.h $(BFD_H) \
   $(INCDIR)/symcat.h opintl.h
Index: opcodes/configure.in
===================================================================
RCS file: /cvs/src/src/opcodes/configure.in,v
retrieving revision 1.38
diff -c -p -d -u -p -r1.38 configure.in
--- opcodes/configure.in	4 Jun 2002 02:57:44 -0000	1.38
+++ opcodes/configure.in	10 Jun 2002 22:02:46 -0000
@@ -238,6 +238,7 @@ if test x${all_targets} = xfalse ; then
 	bfd_we32k_arch)		;;
 	bfd_xstormy16_arch)	ta="$ta xstormy16-asm.lo xstormy16-desc.lo xstormy16-dis.lo xstormy16-ibld.lo xstormy16-opc.lo" using_cgen=yes ;;
 	bfd_z8k_arch)		ta="$ta z8k-dis.lo" ;;
+	bfd_frv_arch)           ta="$ta frv-asm.lo frv-desc.lo frv-dis.lo frv-ibld.lo frv-opc.lo" using_cgen=yes ;;
 
 	"")			;;
 	*)		AC_MSG_ERROR(*** unknown target architecture $arch) ;;
Index: opcodes/disassemble.c
===================================================================
RCS file: /cvs/src/src/opcodes/disassemble.c,v
retrieving revision 1.34
diff -c -p -d -u -p -r1.34 disassemble.c
--- opcodes/disassemble.c	28 May 2002 14:08:47 -0000	1.34
+++ opcodes/disassemble.c	10 Jun 2002 22:02:46 -0000
@@ -66,6 +66,7 @@ Foundation, Inc., 59 Temple Place - Suit
 #define ARCH_w65
 #define ARCH_xstormy16
 #define ARCH_z8k
+#define ARCH_frv
 #define INCLUDE_SHMEDIA
 #endif
 
@@ -334,6 +335,11 @@ disassembler (abfd)
 #ifdef ARCH_vax
     case bfd_arch_vax:
       disassemble = print_insn_vax;
+      break;
+#endif
+#ifdef ARCH_frv
+    case bfd_arch_frv:
+      disassemble = print_insn_frv;
       break;
 #endif
     default:
Index: opcodes/po/POTFILES.in
===================================================================
RCS file: /cvs/src/src/opcodes/po/POTFILES.in,v
retrieving revision 1.20
diff -c -p -d -u -p -r1.20 POTFILES.in
--- opcodes/po/POTFILES.in	31 May 2002 04:27:37 -0000	1.20
+++ opcodes/po/POTFILES.in	10 Jun 2002 22:02:47 -0000
@@ -26,6 +26,13 @@ fr30-dis.c
 fr30-ibld.c
 fr30-opc.c
 fr30-opc.h
+frv-asm.c
+frv-desc.c
+frv-desc.h
+frv-dis.c
+frv-ibld.c
+frv-opc.c
+frv-opc.h
 h8300-dis.c
 h8500-dis.c
 h8500-opc.h

Attachment: frv.binutils.gen.patch.tgz
Description: application/compressed


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