This is the mail archive of the binutils@sourceware.org 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 port] Toshiba Media Processor (MeP)


Hi,

On behalf of Red Hat I would like to contribute a port of bfd, opcodes, gas, ld and binutils to the Toshiba Media architecture (MeP). The port has been maintained at Red Hat and available from Toshiba since 2001. We would now like to contribute the project to the FSF sources.

I will be maintaining this port.

Attached is a patch for existing files, the contents of new files and ChangeLog entries.

Seeking approval to commit.

Thanks,
Dave
bfd/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:
	2006-12-19  Dave Brolley  <brolley@redhat.com>

	* elf32-mep.c: Fix problems with DEBUG printfs.
	* elflink.h (elf_link_input_bfd): Always setup finfo->internal_syms.

	2006-10-17  Nick Clifton  <nickc@redhat.com>

	* elf32-mep.c (mep_elf_print_private_bfd_data): Remove redundant
	check against 0.

	2006-09-25  Dave Brolley  <brolley@redhat.com>

	* elf32-mep.c (mep_elf_print_private_bfd_data): Check that
	(long)partial_flags is non-negative before using it as an
	array index.

	2004-06-24  Dave Brolley  <brolley@redhat.com>

	* elf32-mep.c: Regenerated by MeP-Integrator.

	2005-04-22  Richard Sandiford  <rsandifo@redhat.com>

	* elf32-mep.c (mep_elf_merge_private_bfd_data): Allow two objects
	to be linked together if one of them uses the EF_MEP_LIBRARY flag.
	Give priority to flag sets in which EF_MEP_LIBRARY is not set.

	2005-04-05  Richard Sandiford  <rsandifo@redhat.com>

	* elf32-mep.c (config_names): Reduce divergence from MeP-Integrator
	output.

	2004-08-03  Richard Sandiford  <rsandifo@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Fix overflow check for
	R_MEP_PCABS24A2.

	2004-06-24  Dave Brolley  <brolley@redhat.com>

	* archures.c (bfd_mach_mep_h1): #define as 0x6831.
	* bfd-in2.h: Regenerated.

	2004-06-21  Dave Brolley  <brolley@redhat.com>

	* elf32-mep.c (mep_elf_copy_private_bfd_data): Remove assertion about
	flags being identical.
	(mep_elf_merge_private_bfd_data): Handle existence of multiple CGEN
	MACHs.
	(mep_elf_print_private_bfd_data): Ditto.
	(config_names): Give the machine at index 0 the name "basic".
	(core_names): New table.
	(elf32_mep_machine): New function.
	(mep_elf_object_p): Call bfd_default_set_arch_mach.
	* cpu-mep.c (bfd_h1_arch): Define it and link it into the chain.
	* archures.c (bfd_mach_mep_h1): Define it.
	* bfd-in2.h: Regenerated.

	2003-07-19  Nick Clifton  <nickc@redhat.com>

	* elf32-mep.c: Convert to ISO C.

	2002-04-09  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Allow impossible
	relocations to undefined weak functions.

	2002-02-08  Frank Ch. Eigler  <fche@redhat.com>

        * cpu-mep.c (mep_compatible): Remove: only one bfd_mach used now.
        * elf32-mep.c (elf32_mep_machine): Ditto.

	2001-12-12  Ben Elliston  <bje@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Do not adjust the pc
	prior to applying a pc-relative relocation.

	2001-10-02  Nick Clifton  <nickc@cambridge.redhat.com>

	* elf32-mep.c: Add missing prototypes.

	2001-10-01  Frank Ch. Eigler  <fche@redhat.com>

	* elf32-mep.c (mep_elf_merge_private_bfd_data): Enforce endianness
	compatibility.

	2001-09-28  Richard Henderson  <rth@redhat.com>

	* elf32-mep.c (mep_elf_section_flags): New.
	(mep_elf_fake_sections): New.
	(elf_backend_section_flags): New.
	(elf_backend_fake_sections): New.

	2001-09-27  Nick Clifton  <nickc@cambridge.redhat.com>

	* elf32-mep.c: Add missing function prototypes.
	Fix compile time warnings.  Improve formatting.
	* mep_relocs.pl: Improve formatting in generated code.

	2001-09-21  Nick Clifton  <nickc@cambridge.redhat.com>

	* cpu-mep.c: Add missing function prototype.

	2001-07-25  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Adjust calculation of PC
	to be endian-sensitive.

	2001-07-17  Richard Henderson  <rth@redhat.com>

	* elf32-mep.c (mep_final_link_relocate) [R_MEP_HI16S]: Correctly
	compensate for high bit set in R_MEP_LOW16.

	2001-07-12  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Don't do overflow
	checking on VT relocs.
	(mep_elf_merge_private_bfd_data): Return true if we chose not to
	merge the data.
	
	2001-07-09  DJ Delorie  <dj@redhat.com>

	* cpu-mep.c (mep_compatible): New, base compatibility on
	conflicting configurations.
	(bfd_mep_arch): Use a macro and wrap with comments for the config
	tool.
	* elf32-mep.c (elf32_mep_machine): Take bfd_mach directly from
	flags.
	(mep_elf_merge_private_bfd_data): Merge configurations sanely.
	(config_names): New.
	(mep_elf_print_private_bfd_data): Print config name if possible.

	2001-06-25  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_reloc_type_lookup): Add vtable special cases,
	regenerate others.
	* reloc.c: Regenerate with new elf/mep.h relocs.
	* libbfd.h: Likewise.
	* bfd-in2.h: Likewise.
	
	2001-06-25  Ben Elliston  <bje@redhat.com>

	* elf32-mep.c (mep_reloc): Mark unused parameters as such.
	(mep_final_link_relocate): Remove unused local variables.

	2001-06-06  DJ Delorie  <dj@redhat.com>

	* config.bfd (mep-*-elf): Add bfd_elf32_mep_little_vec.
	* configure.in: Ditto.
	* configure: Ditto.
	* mep-relocs.pl: Support both endians.
	* elf32-mep.c: Regenerate; add little endian targets.

	2001-05-31  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_elf_relocate_section): Fix error message.

	2001-05-21  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_final_link_relocate): Fix pcrel logic.

	2001-05-10  DJ Delorie  <dj@redhat.com>

	* mep-relocs.pl: Detect no-overflow relocs better.
	* elf32-mep.c: Regenerate.  HI16U, HI16S have correct shifts and
	those and LOW16 are no-overflow now.

	2001-05-03  DJ Delorie  <dj@redhat.com>

	* mep-relocs.pl: New, generates reloc-handling code for
	elf32-mep.c.
	* elf32-mep.c: Regenerate.

	2001-05-02  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c (mep_elf_howto_table): Fix size fields.
	(mep_lookup_global, mep_tpoff_base, mep_sdaoff_base): New,
	support %tpoff() and %sdaoff() relocs.
	(mep_final_link_reloc): Add support for MeP relocs.
	(mep_elf_relocate_section): Support %tpoff() and %sdaoff().

	2001-05-01  DJ Delorie  <dj@redhat.com>

	* elf32-mep.c: Use RELA only.
	(mep_elf_howto_table): Add MeP-specific relocs.
	(mep_reloc_type_lookup): Map relocs.
	* reloc.c: Add MeP-specific relocs.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.

	2001-04-03  Ben Elliston  <bje@redhat.com>

	* Makefile.am (ALL_MACHINES): Add cpu-mep.lo.
	(ALL_MACHINES_CFILES): Add cpu-mep.c.
	(BFD32_BACKENDS): Add elf32-mep.lo.
	(BFD32_BACKENDS_CFILES): Add elf32-mep.c.
	(cpu-mep.lo): New target.
	* Makefile.in: Regenerate.
	* config.bfd: Handle mep-*-elf.
	* archures.c (bfd_architecture): Add bfd_{arch,mach}_mep.
	(bfd_archures_list): Add bfd_mep_arch.
	* configure.in: Handle bfd_elf32_mep_vec.
	* configure: Regenerate.
	* targets.c (bfd_elf32_mep_vec): Declare.
	(bfd_target_vector): Add bfd_elf32_mep_vec.
	* elf.c (prep_headers): Set e_machine to EM_CYGNUS_MEP.
	* cpu-mep.c: New file.
	* elf32-mep.c: Likewise.
	* bfd-in2.h: Regenerate.
	* po/POTFILES.in: Likewise.
	
binutils/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:
	2003-10-29  Dave Brolley  <brolley@redhat.com>

	* configure.in: Define SKIP_ZEROES and SKIP_ZEROES_AT_END for mep.
	* configure: Regenerated.

	2002-02-14  Graydon Hoare  <graydon@redhat.com>

	* objdump.c (objdump_print_addr_with_sym): Back out last
	change; leave in vendor branch.

	2002-02-11  Graydon Hoare  <graydon@redhat.com>

	* objdump.c (objdump_print_addr_with_sym): Add "0x" prefix
	in output.

	2001-04-03  Ben Elliston  <bje@redhat.com>

	* readelf.c: Include "elf/mep.h".
	(guess_is_rela): Handle EM_CYGNUS_MEP.
	(get_machine_name): Ditto.
	(dump_relocations): Ditto.

gas/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:
	2005-08-22  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (mep_machine): Handle EF_MEP_CPU_C4.
	* testsuite/gas/mep/complex-relocs.exp: Use -mconfig=simple.

	2005-04-22  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (library_flag): New variable.
	(OPTION_LIBRARY): New macro.
	(md_longopts): Add -mlibrary.
	(md_parse_option): Handle it.
	(md_begin): Include library_flag in the ELF header flags.

	2005-04-15  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (OPTION_COP32): New macro.
	(md_longopts): Add -mcop32.
	(md_parse_option): Handle it.
	(md_show_usage): Mention it.

	2005-04-12  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (md_estimate_size_before_relax): Generalize VLIW
	code to handle all VLIW sections, not just .vtext.

	2005-02-16  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c: Rename CGEN_ISA_MASK to CGEN_BITSET. Rename
	cgen_isa_mask_* to cgen_bitset_*.

	2004-10-06  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (mep_parse_operand): New function.
	(md_begin): Use it instead of gas_cgen_parse_operand.

	2004-09-30  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (mep_force_relocation): Allow pc-relative fixups
	against global symbols to be resolved at assembly time.

	2004-06-21  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (mep_machine): New function.
	(md_begin): Call mep_machine to get bfd machine. Store the cpu in the
	elf flags.

	2004-03-09  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (mep_cgen_assemble_cop_insn): Call
	mep_cgen_insn_supported before accepting the insn.

	2004-02-25  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (OPTION_UCI): Removed.
	(OPTION_NOUCI): Removed.
	(OPTION_DSP): Removed.
	(OPTION_NODSP): Removed.
	(md_longopts): Remove muci, mno-uci, mdsp, mno-dsp.
	(md_parse_option): Remove hnadling of OPTION_UCI, OPTION_NOUCI,
	OPTION_DSP and OPTION_NODSP.
	(md_show_usage): Remove description of muci, mno-uci, mdsp,
	mno-dsp.

	2003-11-20  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.h (TC_CGEN_MAX_RELAX): New macro.

	2003-11-19  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (md_estimate_size_before_relax): Don't
	update the insn in the frag if the new subtype insn index is -1.

	2003-11-13  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_convert_frag): Calculate new insn properly.

	2003-11-13  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.c (md_pcrel_from_section): Remove code that worked
	around write.c's handling of MD_APPLY_SYM_VALUE.

	2003-11-13  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_relax_table): Use correct relaxation cutoffs.

	2003-11-10  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_relax_table): Add relaxation for beqi,
	bnei (expand to abs24), bgei, blti, bcpeq, bcpne, and bcpat.
	(subtype_mappings): Likewise.
	(md_estimate_size_before_relax): Don't rely on beqi being
	after beqz (etc).
	(md_convert_frag): Add expansions for the above.

	2003-10-19  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-mep.h (MD_APPLY_SYM_VALUE): Return 0.
	* config/tc-mep.c (mep_apply_fix3): Only adjust valP if the final
	fixup value is known.

	2003-10-09  Stan Cox  <scox@redhat.com>

	* config/tc-mep.c (mep_apply_fix3): Make BFD_RELOC_MEP_GPREL case
	the default case.

	2003-09-16  Jim Blandy  <jimb@redhat.com>

	* config/tc-mep.c (md_show_usage): As of version 3.3, GCC no
	longer tolerates unescaped newlines in string literals.

	2003-08-01  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (mep_apply_fix3): Adjust the low order bit of the
	BFD_RELOC_MEP_HI16S reloc to account for a signed operand in
	%lo (BFD_RELOC_MEP_LOW16).

	2003-07-14  Nick Clifton  <nickc@redhat.com>

	* config/tc-mep.c: Remove inclusion of <ctype.h>

	2003-05-27  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_longopts): Add -mdebug.
	(md_parse_option): Likewise.

	2003-05-16  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (mep_apply_fix3): New function.
	* config/tc-mep.h (md_apply_fix3): Now defined as mep_apply_fix3.
	(mep_apply_fix3): New prototype.

	2003-04-29  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_check_for_disabled_registers): Check only
	16-bit insns.

	2003-04-22  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_noregerr): New, attach to pseudo-op .noregerr.
	(mep_check_for_disabled_registers): Skip if .noregerr.

	2003-04-21  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_check_for_disabled_registers): Support
	!CGEN_INT_INSN_P also.

	2003-04-17  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_check_for_disabled_registers): New.
	(md_assemble): Call it.

	2002-02-10  Stan Cox  <scox@redhat.com>

	* config/tc-mep.c (mep_cgen_assemble_cop_insn): Call CGEN_PARSE_FN.
	(md_estimate_size_before_relax):  For vliw32, treat bsr12 as bsr24,
	beqz as beqi, bnez as bnei.
	(md_check_parallel32_scheduling): Likewise.

	2002-01-27  Stan Cox  <scox@redhat.com>

	* config/tc-mep.c (mep_cgen_assemble_cop_insn): New.
	(md_assemble): Use it.
	(mep_process_saved_insns): Bracket with gas_cgen_{save,restore}_fixups.

	2002-12-13  Dave Brolley  <brolley@redhat.com>

	* config/tc-mep.c (md_assemble): Allocate an isa for use by
	gas_cgen_cpu_desc. Use support functions to manipulate it.

	2002-09-21  Nick Clifton  <nickc@redhat.com>

	* config/tc-mep.c (mep_fix_adjustable): Remove extern and weak
	tests.
	(mep_force_relocation): Use S_FORCE_RELOC.
	* config/tc-mep.h (obj_fix_adjustable): Rename to tc_fix_adjustable.
	[Based on work done by Alan Modra]

	2002-07-26  Jim Wilson  <wilson@redhat.com>

	* config/tc-mep.c (md_convert_frag, case MEP_INSN_BEQ): Check for
	out-of-range addends, and fall through to MEP_INSN_JMP case.

	2002-05-23  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_relax_table): Adjust offsets.
	(mep_prepare_relax_scan): Adjust for opcode size.
	* config/tc-mep.h (md_prepare_scan): Adjust prototype.

	2002-03-18  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_process_saved_insns): Note that the
	bytes generated go with the previous line, not the current
	line.

	2002-03-08  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (mep_switch_to_vliw_mode): Disallow .vliw unless
	VLIW is enabled.

	2002-03-08  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c: Add various -m options.
	(md_parse_options): Remember them.
	(md_show_usage): Document them.
	(md_begin): Process them.

	2002-02-08  Frank Ch. Eigler  <fche@redhat.com>

	* config/tc-mep.c (target_vliw64): Remove constant parameter.
	(md_begin): Use eflags, not bfd_mach, to identify configuration.
	(md_assemble): Reorganize for per-core configuration.
	(mep_check_parallel*_scheduling): Ditto.

	2002-01-24  Graydon Hoare  <graydon@redhat.com>

	* config/tc-mep.c (md_cgen_lookup_reloc): Switch MEP_OPERAND_SIMM16
	from BFD_RELOC_MEP_16 to BFD_RELOC_RELC, to handle fact that SIMM16
	is signed.

	2001-12-10  Ben Elliston  <bje@redhat.com>

	* config/tc-mep.c (md_convert_frag): Don't fiddle the addends.

	2001-12-10  Ben Elliston  <bje@redhat.com>

	* config/tc-mep.h (OBJ_COMPLEX_RELC): Fix comment to conform to
	the GNU coding standard.

	2001-12-05  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (mep_flush_pending_output): Change to return an int.
	Return 1 for use with TC_START_SYMBOL.
	* config/tc-mep.h: Update prototype for mep_flush_pending_output and
	Define TC_START_SYMBOL.

	2001-11-28  Nick Clifton  <nickc@cambridge.redhat.com>

	* config/tc-mep.c: Update reference to md_apply_fix3.
	* config/tc-mep.h (MD_APPLY_FIX3): Remove.
	(TC_HANDLE_FX_DONE): Remove.
	* config/tc-mips.h (TC_HANDLES_FX_DONE): Remove.

	2001-11-18  Frank Ch. Eigler  <fche@redhat.com>

	* config/tc-mep.h (GAS_CGEN_MAX_FIXUPS): Define as 10.

	2001-11-14  John Healy  <jhealy@redhat.com>

	* config/tc-mep.h: Define md_flush_pending_output.  Add prototype
	for mep_flush_pending_output.
	* config/tc-mep.c (mep_flush_pending_output): New routine.
	(mep_switch_to_core_mode): Process saved insns before switching

	2001-10-29  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (mep_check_parallel32_scheduling): Add check for
        IS_CORE_INSN attribute when determining whether an insn is a core
        or copro insn.
        (mep_check_parallel64_scheduling): Ditto

	2001-10-25  graydon hoare  <graydon@redhat.com>

	* config/tc-mep.c (md_begin): Open CPU with MEP_COP_ISA.

	2001-10-24  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (target_vliw64): Initialized to 1.

	2001-10-22  graydon hoare  <graydon@redhat.com>

	* config/tc-mep.c (md_parse_option): Switch VLIW64/32 behavior
	based on -mconfig option.
	(mep_check_parallel_scheduling): Likewise.

	2001-10-11  John Healy  <jhealy@redhat.com>

	* tc-mep.c (mep_check_parallel64_scheduling): Clear insn buffer before
	assembling nop that is longer than 32 bits.

	2001-10-05  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (md_assemble): Removed old kludge for handling
        comv insn in vliw mode.
	(md_assemble): Clear top 64 bytes of insn.buffer before assembling.
	(mep_check_parallel_scheduling): Forced into 64-bit mode when in
	vliw mode for now.

	2001-10-04  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (mep_check_parallel_scheduling): Forced into
        32-bit mode when in vliw mode for now.

	2001-10-01  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (mep_check_parallel32_scheduling): Wrote body
	of function.

	2001-09-28  Richard Henderson  <rth@redhat.com>

	* config/tc-mep.c (mep_check_parallel32_scheduling,
	mep_check_parallel64_scheduling): Prototype.
	(target_address_for): Remove unused variable.

	* config/tc-mep.c: Reindent.

	2001-09-28  Richard Henderson  <rth@redhat.com>

	* config/obj-elf.c: Include elf/mep.h.
	* config/tc-mep.c: Prototype some functions.
	(mep_elf_section_change_hook): Remove.
	(mep_s_vtext): Remove vliw/core hackery.
	(mep_switch_to_core_mode): Don't change sections.
	(mep_switch_to_vliw_mode): Likewise.
	(mep_elf_section_letter): New.
	(mep_elf_section_flags): New.
	(mep_vtext_section): Rename from mep_create_vtext_section.
	* config/tc-mep.h: Cleanup prototypes.
	(md_elf_section_letter): New.
	(md_elf_section_flags): New.
	(ELF_TC_SPECIAL_SECTIONS): New.
	(md_elf_section_change_hook): Remove.

	2001-09-27  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c: Removed debugging printfs from various places.

	2001-09-27  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (md_assemble): Moved all vliw group verification
	checking to separate functions, fixed a problem with saved insn
	counting.
	(mep_check_parallel_scheduling): Calls proper routine based on mode.
	(mep_check_parallel32_scheduling): New routine.
	(mep_check_parallel64_scheduling): New routine.
	(mep_save_insn): Added fixup saving.

	2001-09-12  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (target_address_for): Remove r_address
	workaround.

	2001-08-15  Ben Elliston  <bje@redhat.com>

	* config/tc-mep.c (md_assemble): Remove unused local vars.

	2001-07-25  Richard Henderson  <rth@redhat.com>

	* config/tc-mep.c (target_address_for): Don't crash looking up
	resolved local symbols.

	2001-07-23  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c: Cleaned up some old comments.

	2001-07-12  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (mep_elf_section_change_hook): Renamed from
	mep_elf_section_change_data_hook.  Using this hook simplify
	section change tracking.
	(mep_s_text): Removed.
	(mep_s_data): Removed.
	(md_pseud_table): Removed entries for .text and .data.
	* config/tc-mep.c: Removed prototypes for mep_s_text and mep_s_data.
	Defeined md_elf_section_change_hook.  Removed definition for
	md_elf_section_change_data_hook.  Added prototype for
	mep_elf_section_change_hook.

	2001-07-10  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c: Added flag to setion_data structure and new
	vtext_section variable.
	(md_pseudo_table): Added entries for .data, .text and .vtext.
	(md_begin): Added intializations for name field of section_data
	structures and the flag to indicate that vliw mode has not been used.
	(mep_elf_section_change_data_hook): New routine to track section
	changes that are done using the .section directive.
	(mep_s_data): New routine to handle .data directive.
	(mep_s_text): New routine to handle .text directive.
	(mep_s_vtext): New routine to handle the new .vtext directive.
	(mep_switch_to_core_mode): Renamed from switch_to_core_mode.  Added
	code to track section changes across core/vliw mode switches and
	switch back to the section that was in use last time core mode
	was in use.
	(mep_switch_to_core_mode): Renamed from switch_to_vliw_mode.  Added
	code to track section changes across core/vliw mode switches and
	switch back to the section that was in use last time vliw mode
	was in use.  Also added code to detect the first transition into
	vliw mode and create and switch to the .vtext section, which is
	the default section (the counterpart of core mode's .text section) in
        vliw mode.
	(mep_create_vtext_section): The code that actually creates the
	.vtext section.
	(switch_to_core_mode): Renamed to mep_switch_to_core_mode.
	(switch_to_vliw_mode): Renamed to mep_switch_to_vliw_mode.
	* config/tc-mep.h: Changed prototypes for mode switching functions
	to refelct the new names.  Added prototypes for mep_s_data,
	mep_s_text, mep_s_vtext, mep_create_vtext_section,
	mep_elf_section_change_data_hook, and obj_elf_change_section.  Added
	definitions for VTEXT_SECTION_NAME and md_elf_section_change_data_hook.

	2001-07-09  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_begin): Set bfd_mach from config, not a
	static value.

	2001-07-06  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (OPTION_CONFIG): New.
	(md_longopts): Add -mconfig
	(md_parse_option): Support OPTION_CONFIG.
	(md_show_usage): List configurations if any.
	(md_begin): Set the bfd's private flags to the configuration
	number.

	2001-07-05  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (md_begin): Added initialization of stored fixups
	array.
	(md_assemble): Added crude processing for vliw mode.
	(mep_unrecognized_line): New routine for handling leading + required
	for instruction parallelization in vliw mode.
	(mep_save_insn): New routine.
	(mep_cleanup): New routine.
	(mep_process_saved_insns): New routine.
	(mep_check_parallel_scheduling): New routine.
	* config/tc-mep.h: Defined tc_unrecognized_line and md_cleanup.  Added
	prototypes for mep_unrecognized_line, mep_save_insn, mep_cleaup,
	mep_process_saved_insns and mep_check_parallel_scheduling.

	2001-06-20  Frank Ch. Eigler  <fche@redhat.com>

	* config/tc-mep.h: Define OBJ_COMPLEX_RELC.

	2001-06-19  John Healy  <jhealy@redhat.com>

	* config/tc-mep.h: Added enum EXP_PAR_INSN.
	* config/tc-mep.c (md_assemble): Fleshed out skeleton for vliw
	mode processing and added error generation when a leading '+' is
	encountered in core mode.

	2001-06-19  John Healy  <jhealy@redhat.com>

	* config/tc-mep (md_assemble_single_insn): Removed.
	(md_assemble_insn_pair): Removed.
	(md_assemble): Replaced normal assemble for core mode and added
	simple preliminary top-level skeleton for vliw mode processing.
	Instructions preceeded by a '+' are now detected in vliw mode.
	(mep_unrecognized_line): New routine.  It's called each time
	a line is encountered that can't be parsed.  This is where
	leading '+' signs are detected.
	* config/tc-mep.h: Added prototype for mep_unrecognized_line and
	defined tc_unrecognized_line macro.  Also removed prototypes for
	md_assemble_single_insn and md_assemble_insn_pair.

	2001-06-14  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (assemble_single_insn): New routine that is
	responsible for assembling a single (i.e. non-core/cop pair)
	instruction. Essentially contains the previous contents of
	md_assemble.
	(assemble_insn_pair): New routine (just a stub so far) to be used
	for assembling core/copro instruction pairs in vliw mode.
	(md_assemble): Added framework for handling core and vliw modes.
	Moved most of the contents to assemble_single_insn().
	* config/tc-mep.h: Added prototypes for assemble_single_insn
	and assemble_insn_pair.

	2001-06-14  John Healy  <jhealy@redhat.com>

	* config/tc-mep.c (pseudo_table): Added .vliw and .core pseudo-ops.
	(switch_to_core_mode): New routine.
	(switch_to_vliw_mode): New routine.
	Added new variable "mode" to track core/vliw mode switches.
	* config/tc-mep.h: Added prototypes for switch_to_core_mode()
	and switch_to_vliw_mode().

	2001-06-13  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.h (md_prepare_relax_scan): Define.
	* config/tc-mep.c (md_relax_table): Add entries for BEQZ and BNEZ.
	They relax to BEQI and BNEI.
	(md_prepare_relax_scan): New.  Avoid auto-relaxing due to externs;
	we handle that specially ourselves.
	(md_convert_frag): Add code for beqz/bnez to beqi/bnei.

	2001-06-12  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.h (md_prepare_relax_scan): Define.
	* config/tc-mep.c (md_relax_table): Add entries for beqz->beqi and
	bnez->bnei conversions.
	(subtype_mappings): Ditto.
	(mep_prepare_relax_scan): New.  If relaxing for an unresolved
	symbol, set the "aim" to zero to prevent the location of the
	opcode from causing unwanted relaxation (subtype_mappings handles
	that).
	(md_convert_frag): Add conversions for beqz, bnez, beqi, and bnei.

	2001-06-06  DJ Delorie  <dj@redhat.com>

	* configure.in (mep-*-elf): Set default endianness.
	* configure (mep-*-elf): Ditto.
	* config/tc-mep.h (TARGET_FORMAT): Support both big and little
	endian.
	* config/tc-mep.c (md_longopts): Add -EB and -EL options.
	(md_parse_option): Parse them.
	(md_show_usage): Document them.
	(md_begin): Set endianness.
	(md_convert_frag): Support both endians.
	(md_number_to_chars): Ditto.

	* config/tc-mep.c (subtype_mappings): Don't expand bra/beq to jmp
	for external symbols.

	2001-05-31  DJ Delorie  <dj@redhat.com>

	* config/tc-mep (me_pcrel_from_section): Fix bug in pcrel branches
	between segments in the same object.

	2001-05-18  Ben Elliston  <bje@redhat.com>

	* Makefile.am (CPU_TYPES): Add mep.
	* Makefile.in: Regenerate.

	2001-05-03  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (insn_to_subtype): Add prototype, fix type of i.
	(md_convert_frag): Calculate fix size and location correctly.
	(md_pcrel_from_section): Let cgen do the adjustments.
	(md_cgen_lookup_reloc): Make sure we don't move the reloc more
	than once.

	* config/tc-mep.c: Comments start with `#' as per spec (or ';'
	at BOL), `;' used for line separator.

	2001-05-03  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c (md_convert_frag): Don't rely on fx_fix to
	say how big the opcode is, but specify them for each fixup
	type explicitly.  Add default case to silence warnings.

	2001-05-01  DJ Delorie  <dj@redhat.com>

	* config/tc-mep.c: Rename stuff from iq2000 to mep.
	(md_relax_table): New.
	(md_estimate_size_before_relaxing): Support bra->beq->jmp and
	bsr12->bsr24 relaxing.
	(md_convert_frag): Ditto.
	(md_cgen_lookup_reloc): Add MeP-specific relocs.
	* config/tc-mep.h: Rename stuff from iq2000 to mep.
	(TC_GENERIC_RELAX_TABLE): Define.
	(md_operand): Define.

	2001-04-03  Ben Elliston  <bje@redhat.com>

	* configure.in: Handle mep-elf target.
	* configure: Regenerate.
	* config/tc-mep.c: New file.
	* config/tc-mep.h: Likewise.

include/elf/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following Changes:	
	2005-08-22  Dave Brolley  <brolley@redhat.com>

	* mep.h (EF_MEP_CPU_C4): New macro.
	(EF_MEP_CPU_H1): Change to 0x10000000.

	2005-04-22  Richard Sandiford  <rsandifo@redhat.com>

	* mep.h (EF_MEP_LIBRARY): New flag.
	(EF_MEP_ALL_FLAGS): Update accordingly.

	2004-06-21  Dave Brolley  <brolley@redhat.com>

	* mep.h (EF_MEP_CPU_MASK, EF_MEP_CPU_MEP, EF_MEP_CPU_C2) 
	(EF_MEP_CPU_C3, EF_MEP_CPU_H1, EF_MEP_INDEX_MASK) 
	(EF_MEP_ALL_FLAGS): New macros.

	2001-09-28  Richard Henderson  <rth@redhat.com>

	* mep.h (SHF_MEP_VLIW, SEC_MEP_VLIW): New.

	2001-07-12  DJ Delorie  <dj@redhat.com>

	* mep.h (R_MEP_GNU_VTINHERIT, R_MEP_GNU_VTENTRY): Mark as no-overflow.

	2001-06-25  DJ Delorie  <dj@redhat.com>

	* mep.h: Add vtable relocs.

	2001-05-10  DJ Delorie  <dj@redhat.com>

	* mep.h: Fix bit offsets for HI16*, make them no-overflow.  Add
	comment about mep-relocs.pl.

	2001-05-01  DJ Delorie  <dj@redhat.com>

	* mep.h: Add MeP-specific relocs.

	2001-03-22  Ben Elliston  <bje@redhat.com>

	* mep.h: New file.

	2001-03-20  Ben Elliston  <bje@redhat.com>

	* common.h (EM_CYGNUS_MEP): Define.

include/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:
	2001-03-26  Ben Elliston  <bje@redhat.com>

	* dis-asm.h (print_insn_mep): Declare.

ld/testsuite/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following Changes:
	2006-12-08  Dave Brolley  <brolley@redhat.com>

	* ld-undefined/undefined.exp: XFAIL the undefined test
	for mep-*-*.

	2002-04-09  DJ Delorie  <dj@redhat.com>

	* ld-mep: New, with content.

ld/ChangeLog:
2007-01-15  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:
	2006-12-08  Dave Brolley  <brolley@redhat.com>

	* emulparams/elf32mep.sh (OTHER_SDATA_SECTIONS): PROVIDE
	__sdabase here.
	 (OTHER_READONLY_SECTIONS): Set __stack here...
	(OTHER_END_SYMBOLS): ...not here.

	2005-07-29  Dave Brolley  <brolley@redhat.com>

	* emulparams/elf32mep.sh (SCRIPT_NAME): Set to 'mep'.
	(OTHER_SDATA_SECTIONS): Add code to check for overflow of tiny
	sections.
	* Makefile.am (eelf32mep.c): Use scripttempl.mep.sc.
	* Makefile.in: Regenerate.
	* scripttempl/mep.sc: New file.

	2003-05-21  Richard Sandiford  <rsandifo@redhat.com>

	* emulparams/elf32mep.sh (TEMPLATE_NAME): Define.

	2003-05-02  Dave Brolley  <brolley@redhat.com>

	* emulparams/elf32mep.sh (OTHER_READONLY_SECTIONS): Remove
	__stack[1-11].

	2003-02-06  Dave Brolley  <brolley@redhat.com>

	* emulparams/elf32mep.sh (OTHER_READONLY_SECTIONS): Support 12 modules.
	Correct stack alignment.

	2002-06-10  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh (OTHER_TEXT_SECTIONS): Change .vfar to
	.vftext.

	2002-05-29  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh (OTHER_TEXT_SECTIONS): Add .vfar.

	2002-05-01  Graydon Hoare  <graydon@redhat.com>

       * emulparams/elf32mep.sh (OTHER_READONLY_SECTIONS): Add .rostacktab.

       2002-05-06  Dave Brolley  <brolley@redhat.com>

	* emulparams/elf32mep.sh (OTHER_END_SYMBOLS): Use to define __stack,
	__heap and __heap_end.

	2002-03-19  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh (OTHER_BSS_SECTIONS): Check size of near segment.

	2002-02-19  Frank Ch. Eigler  <fche@redhat.com>

	* emulparams/elf32mep.sh: Add .based/.tiny size limit assertions.

	2001-10-29  Frank Ch. Eigler  <fche@redhat.com>

	* emulparams/elf32mep.sh (__heap, __heap_end): Provide start/end
	symbols for heap -- see also libgloss/mep/sbrk.c.

	2001-10-25  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh (OTHER_TEXT_SECTIONS): Support .srodata.

	* emulparams/elf32mep.sh (OTHER_BSS_SECTIONS): Provide start/end
	symbols for farbss.

	* emulparams/elf32mep.sh (OTHER_TEXT_SECTIONS): Support .frodata.

	2001-06-11  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh (OTHER_TEXT_SECTIONS): Merge far
	functions.
	(OTHER_READWRITE_SECTIONS): Include .gnu.linkonce.*.

	2001-05-23  Anthony Green  <green@redhat.com>

	* emulparams/elf32mep.sh (DATA_START_SYMBOLS): Define.

	2001-05-31  DJ Delorie  <dj@redhat.com>

	* emulparams/elf32mep.sh: Move stack, add __sdabase and __tpbase
	symbols, add .based, .far, and .farbss sections.

	2001-05-02  DJ Delorie  <dj@redhat.com>

	* configure.tgt: Change target_emul to targ_emul.

	2001-04-03  Ben Elliston  <bje@redhat.com>

	* Makefile.am (ALL_EMULATIONS): Add eelf32mep.o.
	(eelf32mep.c): New target.
	* Makefile.in: Regenerate.
	* configure.tgt: Handle mep-*-elf.
	* emulparams/elf32mep.sh: New file.

? bfd/cpu-mep.c
? bfd/elf32-mep.c
? bfd/mep-relocs.pl
? gas/config/tc-mep.c
? gas/config/tc-mep.h
? gas/testsuite/gas/mep
? include/elf/mep.h
? ld/emulparams/elf32mep.sh
? ld/scripttempl/mep.sc
? ld/testsuite/ld-mep
? opcodes/mep-asm.c
? opcodes/mep-desc.c
? opcodes/mep-desc.h
? opcodes/mep-dis.c
? opcodes/mep-ibld.c
? opcodes/mep-opc.c
? opcodes/mep-opc.h
Index: bfd/Makefile.am
===================================================================
RCS file: /cvs/src/src/bfd/Makefile.am,v
retrieving revision 1.183
diff -c -p -r1.183 Makefile.am
*** bfd/Makefile.am	25 Oct 2006 06:49:19 -0000	1.183
--- bfd/Makefile.am	11 Jan 2007 19:09:35 -0000
*************** ALL_MACHINES = \
*** 91,96 ****
--- 91,97 ----
  	cpu-m10300.lo \
  	cpu-maxq.lo \
  	cpu-mcore.lo \
+ 	cpu-mep.lo \
  	cpu-mips.lo \
  	cpu-mmix.lo \
  	cpu-mt.lo \
*************** ALL_MACHINES_CFILES = \
*** 155,160 ****
--- 156,162 ----
  	cpu-m10300.c \
  	cpu-maxq.c \
  	cpu-mcore.c \
+ 	cpu-mep.c \
  	cpu-mips.c \
  	cpu-mmix.c \
  	cpu-mt.c \
*************** BFD32_BACKENDS = \
*** 266,271 ****
--- 268,274 ----
  	elf-m10200.lo \
  	elf-m10300.lo \
  	elf32-mcore.lo \
+ 	elf32-mep.lo \
  	elfxx-mips.lo \
  	elf32-mips.lo \
  	elf32-mt.lo \
*************** BFD32_BACKENDS_CFILES = \
*** 442,447 ****
--- 445,451 ----
  	elf-m10200.c \
  	elf-m10300.c \
  	elf32-mcore.c \
+ 	elf32-mep.c \
  	elfxx-mips.c \
  	elf32-mips.c \
  	elf32-mt.c \
*************** cpu-m10200.lo: cpu-m10200.c $(INCDIR)/fi
*** 1064,1069 ****
--- 1068,1074 ----
  cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-maxq.lo: cpu-maxq.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+ cpu-mep.lo: cpu-mep.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-mt.lo: cpu-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
*************** elf32-mcore.lo: elf32-mcore.c $(INCDIR)/
*** 1406,1411 ****
--- 1411,1420 ----
    $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
    $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/mcore.h \
    $(INCDIR)/elf/reloc-macros.h elf32-target.h
+ elf32-mep.lo: elf32-mep.c elf-bfd.h $(INCDIR)/elf/common.h \
+   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+   $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h \
+   elf32-target.h
  elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
    $(INCDIR)/libiberty.h elf-bfd.h $(INCDIR)/elf/common.h \
    $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
Index: bfd/archures.c
===================================================================
RCS file: /cvs/src/src/bfd/archures.c,v
retrieving revision 1.122
diff -c -p -r1.122 archures.c
*** bfd/archures.c	8 Jan 2007 18:42:36 -0000	1.122
--- bfd/archures.c	11 Jan 2007 19:09:35 -0000
*************** DESCRIPTION
*** 318,323 ****
--- 318,326 ----
  .#define bfd_mach_fr500		500
  .#define bfd_mach_fr550		550
  .  bfd_arch_mcore,
+ .  bfd_arch_mep,
+ .#define bfd_mach_mep		1
+ .#define bfd_mach_mep_h1	0x6831
  .  bfd_arch_ia64,      {* HP/Intel ia64 *}
  .#define bfd_mach_ia64_elf64	64
  .#define bfd_mach_ia64_elf32	32
*************** extern const bfd_arch_info_type bfd_m68k
*** 456,461 ****
--- 459,465 ----
  extern const bfd_arch_info_type bfd_m88k_arch;
  extern const bfd_arch_info_type bfd_maxq_arch;
  extern const bfd_arch_info_type bfd_mcore_arch;
+ extern const bfd_arch_info_type bfd_mep_arch;
  extern const bfd_arch_info_type bfd_mips_arch;
  extern const bfd_arch_info_type bfd_mmix_arch;
  extern const bfd_arch_info_type bfd_mn10200_arch;
*************** static const bfd_arch_info_type * const 
*** 525,530 ****
--- 529,535 ----
      &bfd_m88k_arch,
      &bfd_maxq_arch,
      &bfd_mcore_arch,
+     &bfd_mep_arch,
      &bfd_mips_arch,
      &bfd_mmix_arch,
      &bfd_mn10200_arch,
Index: bfd/config.bfd
===================================================================
RCS file: /cvs/src/src/bfd/config.bfd,v
retrieving revision 1.222
diff -c -p -r1.222 config.bfd
*** bfd/config.bfd	8 Jan 2007 17:21:48 -0000	1.222
--- bfd/config.bfd	11 Jan 2007 19:09:35 -0000
*************** case "${targ}" in
*** 840,845 ****
--- 840,850 ----
      targ_selvecs="mcore_pe_big_vec mcore_pe_little_vec mcore_pei_big_vec mcore_pei_little_vec"
      ;;
  
+   mep-*-elf)
+     targ_defvec=bfd_elf32_mep_vec
+     targ_selvecs=bfd_elf32_mep_little_vec
+     ;;
+ 
    mips*-big-*)
      targ_defvec=ecoff_big_vec
      targ_selvecs=ecoff_little_vec
Index: bfd/configure.in
===================================================================
RCS file: /cvs/src/src/bfd/configure.in,v
retrieving revision 1.218
diff -c -p -r1.218 configure.in
*** bfd/configure.in	16 Dec 2006 11:24:05 -0000	1.218
--- bfd/configure.in	11 Jan 2007 19:09:35 -0000
*************** do
*** 650,655 ****
--- 650,657 ----
      bfd_elf32_m88k_vec)		tb="$tb elf32-m88k.lo elf32.lo $elf" ;;
      bfd_elf32_mcore_big_vec)	tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
      bfd_elf32_mcore_little_vec)	tb="$tb elf32-mcore.lo elf32.lo $elf" ;;
+     bfd_elf32_mep_vec)		tb="$tb elf32-mep.lo elf32.lo $elf" ;;
+     bfd_elf32_mep_little_vec)	tb="$tb elf32-mep.lo elf32.lo $elf" ;;
      bfd_elf32_mn10200_vec)	tb="$tb elf-m10200.lo elf32.lo $elf" ;;
      bfd_elf32_mn10300_vec)	tb="$tb elf-m10300.lo elf32.lo $elf" ;;
      bfd_elf32_mt_vec)           tb="$tb elf32-mt.lo elf32.lo $elf" ;;
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.160
diff -c -p -r1.160 reloc.c
*** bfd/reloc.c	3 Nov 2006 00:58:10 -0000	1.160
--- bfd/reloc.c	11 Jan 2007 19:09:37 -0000
*************** ENUMDOC
*** 3701,3706 ****
--- 3701,3750 ----
    Motorola Mcore relocations.
  
  ENUM
+   BFD_RELOC_MEP_8
+ ENUMX
+   BFD_RELOC_MEP_16
+ ENUMX
+   BFD_RELOC_MEP_32
+ ENUMX
+   BFD_RELOC_MEP_PCREL8A2
+ ENUMX
+   BFD_RELOC_MEP_PCREL12A2
+ ENUMX
+   BFD_RELOC_MEP_PCREL17A2
+ ENUMX
+   BFD_RELOC_MEP_PCREL24A2
+ ENUMX
+   BFD_RELOC_MEP_PCABS24A2
+ ENUMX
+   BFD_RELOC_MEP_LOW16
+ ENUMX
+   BFD_RELOC_MEP_HI16U
+ ENUMX
+   BFD_RELOC_MEP_HI16S
+ ENUMX
+   BFD_RELOC_MEP_GPREL
+ ENUMX
+   BFD_RELOC_MEP_TPREL
+ ENUMX
+   BFD_RELOC_MEP_TPREL7
+ ENUMX
+   BFD_RELOC_MEP_TPREL7A2
+ ENUMX
+   BFD_RELOC_MEP_TPREL7A4
+ ENUMX
+   BFD_RELOC_MEP_UIMM24
+ ENUMX
+   BFD_RELOC_MEP_ADDR24A4
+ ENUMX
+   BFD_RELOC_MEP_GNU_VTINHERIT
+ ENUMX
+   BFD_RELOC_MEP_GNU_VTENTRY
+ ENUMDOC
+   Toshiba Media Processor Relocations.
+ COMMENT
+ 
+ ENUM
    BFD_RELOC_MMIX_GETA
  ENUMX
    BFD_RELOC_MMIX_GETA_1
Index: bfd/targets.c
===================================================================
RCS file: /cvs/src/src/bfd/targets.c,v
retrieving revision 1.156
diff -c -p -r1.156 targets.c
*** bfd/targets.c	30 Oct 2006 23:25:50 -0000	1.156
--- bfd/targets.c	11 Jan 2007 19:09:37 -0000
*************** extern const bfd_target bfd_elf32_m68k_v
*** 609,614 ****
--- 609,616 ----
  extern const bfd_target bfd_elf32_m88k_vec;
  extern const bfd_target bfd_elf32_mcore_big_vec;
  extern const bfd_target bfd_elf32_mcore_little_vec;
+ extern const bfd_target bfd_elf32_mep_vec;
+ extern const bfd_target bfd_elf32_mep_little_vec;
  extern const bfd_target bfd_elf32_mn10200_vec;
  extern const bfd_target bfd_elf32_mn10300_vec;
  extern const bfd_target bfd_elf32_mt_vec;
*************** static const bfd_target * const _bfd_tar
*** 934,939 ****
--- 936,942 ----
  	&bfd_elf32_m88k_vec,
  	&bfd_elf32_mcore_big_vec,
  	&bfd_elf32_mcore_little_vec,
+ 	&bfd_elf32_mep_vec,
  	&bfd_elf32_mn10200_vec,
  	&bfd_elf32_mn10300_vec,
  	&bfd_elf32_mt_vec,
Index: binutils/Makefile.am
===================================================================
RCS file: /cvs/src/src/binutils/Makefile.am,v
retrieving revision 1.78
diff -c -p -r1.78 Makefile.am
*** binutils/Makefile.am	25 Oct 2006 06:49:20 -0000	1.78
--- binutils/Makefile.am	11 Jan 2007 19:09:37 -0000
*************** readelf.o: readelf.c dwarf.h ../bfd/bfd.
*** 552,558 ****
    $(INCDIR)/elf/i370.h $(INCDIR)/elf/i860.h $(INCDIR)/elf/i960.h \
    $(INCDIR)/elf/ia64.h $(INCDIR)/elf/ip2k.h $(INCDIR)/elf/iq2000.h \
    $(INCDIR)/elf/m32c.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/m68k.h \
!   $(INCDIR)/elf/m68hc11.h $(INCDIR)/elf/mcore.h $(INCDIR)/elf/mips.h \
    $(INCDIR)/elf/mmix.h $(INCDIR)/elf/mn10200.h $(INCDIR)/elf/mn10300.h \
    $(INCDIR)/elf/mt.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/or32.h \
    $(INCDIR)/elf/pj.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/ppc64.h \
--- 552,559 ----
    $(INCDIR)/elf/i370.h $(INCDIR)/elf/i860.h $(INCDIR)/elf/i960.h \
    $(INCDIR)/elf/ia64.h $(INCDIR)/elf/ip2k.h $(INCDIR)/elf/iq2000.h \
    $(INCDIR)/elf/m32c.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/m68k.h \
!   $(INCDIR)/elf/m68hc11.h $(INCDIR)/elf/mcore.h \
!   $(INCDIR)/elf/mep.h $(INCDIR)/elf/mips.h \
    $(INCDIR)/elf/mmix.h $(INCDIR)/elf/mn10200.h $(INCDIR)/elf/mn10300.h \
    $(INCDIR)/elf/mt.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/or32.h \
    $(INCDIR)/elf/pj.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/ppc64.h \
Index: binutils/configure.in
===================================================================
RCS file: /cvs/src/src/binutils/configure.in,v
retrieving revision 1.69
diff -c -p -r1.69 configure.in
*** binutils/configure.in	8 Jan 2007 17:21:49 -0000	1.69
--- binutils/configure.in	11 Jan 2007 19:09:37 -0000
*************** changequote([,])dnl
*** 315,320 ****
--- 315,323 ----
    	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
  	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MCORE_ELF"
  	  ;;
+   	mep-*)
+ 	  OBJDUMP_DEFS="-DSKIP_ZEROES=256 -DSKIP_ZEROES_AT_END=0"
+ 	  ;;
  	esac
      fi
  done
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.356
diff -c -p -r1.356 readelf.c
*** binutils/readelf.c	8 Jan 2007 18:42:36 -0000	1.356
--- binutils/readelf.c	11 Jan 2007 19:09:38 -0000
***************
*** 112,117 ****
--- 112,118 ----
  #include "elf/m68k.h"
  #include "elf/m68hc11.h"
  #include "elf/mcore.h"
+ #include "elf/mep.h"
  #include "elf/mips.h"
  #include "elf/mmix.h"
  #include "elf/mn10200.h"
*************** guess_is_rela (unsigned long e_machine)
*** 615,620 ****
--- 616,622 ----
      case EM_M32C:
      case EM_M32R:
      case EM_MCORE:
+     case EM_CYGNUS_MEP:
      case EM_MMIX:
      case EM_MN10200:
      case EM_CYGNUS_MN10200:
*************** dump_relocations (FILE *file,
*** 1167,1172 ****
--- 1169,1178 ----
  	case EM_BLACKFIN:
  	  rtype = elf_bfin_reloc_type (type);
  	  break;
+ 
+ 	case EM_CYGNUS_MEP:
+ 	  rtype = elf_mep_reloc_type (type);
+ 	  break;
  	}
  
        if (rtype == NULL)
*************** get_machine_name (unsigned e_machine)
*** 1762,1767 ****
--- 1768,1774 ----
      case EM_NIOS32:		return "Altera Nios";
      case EM_ALTERA_NIOS2:	return "Altera Nios II";
      case EM_XC16X:		return "Infineon Technologies xc16x";
+     case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
      default:
        snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
        return buff;
Index: gas/Makefile.am
===================================================================
RCS file: /cvs/src/src/gas/Makefile.am,v
retrieving revision 1.139
diff -c -p -r1.139 Makefile.am
*** gas/Makefile.am	14 Dec 2006 18:33:28 -0000	1.139
--- gas/Makefile.am	11 Jan 2007 19:09:39 -0000
*************** CPU_TYPES = \
*** 68,73 ****
--- 68,74 ----
  	m68k \
  	maxq \
  	mcore \
+ 	mep \
  	mips \
  	mmix \
  	mn10200 \
*************** TARGET_CPU_CFILES = \
*** 258,263 ****
--- 259,265 ----
  	config/tc-m68hc11.c \
  	config/tc-m68k.c \
  	config/tc-mcore.c \
+ 	config/tc-mep.c \
  	config/tc-mips.c \
  	config/tc-mmix.c \
  	config/tc-mn10200.c \
*************** TARGET_CPU_HFILES = \
*** 311,316 ****
--- 313,319 ----
  	config/tc-m68hc11.h \
  	config/tc-m68k.h \
  	config/tc-mcore.h \
+ 	config/tc-mep.h \
  	config/tc-mips.h \
  	config/tc-mmix.h \
  	config/tc-mn10200.h \
*************** DEPTC_i386_multi = $(DEPTC_i386_aout) $(
*** 1426,1431 ****
--- 1429,1448 ----
  DEPTC_mips_multi = $(DEPTC_mips_coff) $(DEPTC_mips_ecoff) \
    $(DEPTC_mips_elf)
  DEPTC_cris_multi = $(DEPTC_cris_aout) $(DEPTC_cris_elf)
+ DEPTC_mep_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
+   $(srcdir)/config/tc-mep.h $(INCDIR)/coff/internal.h \
+   $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h dwarf2dbg.h \
+   subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/mep-desc.h \
+   $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/mep-opc.h \
+   cgen.h $(INCDIR)/elf/common.h $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h \
+   $(BFDDIR)/libbfd.h $(INCDIR)/safe-ctype.h
+ DEPTC_mep_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-mep.h \
+   dwarf2dbg.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/mep-desc.h \
+   $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/mep-opc.h \
+   cgen.h $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h \
+   $(BFDDIR)/libbfd.h $(INCDIR)/safe-ctype.h
  DEPOBJ_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
    ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
    $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
*************** DEPOBJ_i386_multi = $(DEPOBJ_i386_aout) 
*** 1782,1787 ****
--- 1799,1814 ----
  DEPOBJ_mips_multi = $(DEPOBJ_mips_coff) $(DEPOBJ_mips_ecoff) \
    $(DEPOBJ_mips_elf)
  DEPOBJ_cris_multi = $(DEPOBJ_cris_aout) $(DEPOBJ_cris_elf)
+ DEPOBJ_mep_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
+   $(srcdir)/config/tc-mep.h $(INCDIR)/coff/internal.h \
+   $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+   subsegs.h $(INCDIR)/safe-ctype.h
+ DEPOBJ_mep_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-mep.h \
+   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+   $(INCDIR)/elf/mep.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/aout/aout64.h \
+   $(INCDIR)/safe-ctype.h
  DEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
    ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
  DEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
*************** DEP_i386_multi = $(DEP_i386_aout) $(DEP_
*** 2078,2083 ****
--- 2105,2117 ----
  DEP_mips_multi = $(DEP_mips_coff) $(DEP_mips_ecoff) \
    $(DEP_mips_elf)
  DEP_cris_multi = $(DEP_cris_aout) $(DEP_cris_elf)
+ DEP_mep_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mep.h \
+   $(INCDIR)/symcat.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+   $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h
+ DEP_mep_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-mep.h \
+   $(INCDIR)/safe-ctype.h
  BMKDEP = #DO NOT PUT ANYTHING BETWEEN THIS LINE AND THE MATCHING WARNING ABOVE.
  #MKDEP    DO NOT PUT ANYTHING BETWEEN THIS LINE AND THE MATCHING WARNING BELOW.
  app.o: app.c
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.195
diff -c -p -r1.195 configure.in
*** gas/configure.in	11 Dec 2006 15:09:43 -0000	1.195
--- gas/configure.in	11 Jan 2007 19:09:40 -0000
*************** changequote([,])dnl
*** 304,309 ****
--- 304,313 ----
  	esac
  	;;
  
+       mep)
+ 	using_cgen=yes
+ 	;;
+ 
        mips)
  	echo ${extra_objects} | grep -s "itbl-parse.o"
  	if test $? -ne 0 ; then
Index: gas/configure.tgt
===================================================================
RCS file: /cvs/src/src/gas/configure.tgt,v
retrieving revision 1.32
diff -c -p -r1.32 configure.tgt
*** gas/configure.tgt	8 Jan 2007 17:21:49 -0000	1.32
--- gas/configure.tgt	11 Jan 2007 19:09:40 -0000
*************** case ${cpu} in
*** 52,57 ****
--- 52,58 ----
    m6811|m6812|m68hc12)	cpu_type=m68hc11 ;;
    m683??)		cpu_type=m68k ;;
    maxq)			cpu_type=maxq ;;
+   mep-*-elf)		cpu_type=mep endian=big ;;
    mips*el)		cpu_type=mips endian=little ;;
    mips*)		cpu_type=mips endian=big ;;
    mt)                   cpu_type=mt endian=big ;;
*************** case ${generic_target} in
*** 257,262 ****
--- 258,265 ----
  
    maxq-*-coff)      			fmt=coff bfd_gas=yes ;;
  
+   mep-*-elf)				fmt=elf ;;
+ 
    mcore-*-elf)				fmt=elf ;;
    mcore-*-pe)				fmt=coff em=pe bfd_gas=yes ;;
  
Index: gas/config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.99
diff -c -p -r1.99 obj-elf.c
*** gas/config/obj-elf.c	22 Nov 2006 03:35:36 -0000	1.99
--- gas/config/obj-elf.c	11 Jan 2007 19:09:50 -0000
***************
*** 57,62 ****
--- 57,66 ----
  #include "elf/x86-64.h"
  #endif
  
+ #ifdef TC_MEP
+ #include "elf/mep.h"
+ #endif
+ 
  static void obj_elf_line (int);
  static void obj_elf_size (int);
  static void obj_elf_type (int);
Index: gas/testsuite/gas/all/gas.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/all/gas.exp,v
retrieving revision 1.42
diff -c -p -r1.42 gas.exp
*** gas/testsuite/gas/all/gas.exp	8 Jan 2007 17:21:49 -0000	1.42
--- gas/testsuite/gas/all/gas.exp	11 Jan 2007 19:09:50 -0000
*************** gas_test "p2425.s" ""   "" "pcrel values
*** 16,22 ****
  # The ".space" directive is taken care of in the C54x-specific tests, so fail
  #  here 
  #
! if { [istarget hppa*-*-*] || [istarget *c54x*-*-*] } then {
      setup_xfail *-*-*
      fail "simplifiable double subtraction"
  } else {
--- 16,25 ----
  # The ".space" directive is taken care of in the C54x-specific tests, so fail
  #  here 
  #
! # The test also doesn't work on mep targets, since they use RELC, and it
! # will avoid simplifying the expression since it conservatively assumes
! # ugly expressions can be saved until link-time.
! if { [istarget hppa*-*-*] || [istarget *c54x*-*-*] || [istarget mep*-*-*]} then {
      setup_xfail *-*-*
      fail "simplifiable double subtraction"
  } else {
Index: include/dis-asm.h
===================================================================
RCS file: /cvs/src/src/include/dis-asm.h,v
retrieving revision 1.65
diff -c -p -r1.65 dis-asm.h
*** include/dis-asm.h	31 Oct 2006 20:21:56 -0000	1.65
--- include/dis-asm.h	11 Jan 2007 19:10:16 -0000
*************** extern "C" {
*** 35,41 ****
  #include <stdio.h>
  #include "bfd.h"
  
! typedef int (*fprintf_ftype) (void *, const char*, ...) ATTRIBUTE_FPTR_PRINTF_2;
  
  enum dis_insn_type
  {
--- 35,41 ----
  #include <stdio.h>
  #include "bfd.h"
  
!   typedef int (*fprintf_ftype) (void *, const char*, ...) /*ATTRIBUTE_FPTR_PRINTF_2*/;
  
  enum dis_insn_type
  {
*************** extern int print_insn_m88k		(bfd_vma, di
*** 251,256 ****
--- 251,257 ----
  extern int print_insn_maxq_big		(bfd_vma, disassemble_info *);
  extern int print_insn_maxq_little	(bfd_vma, disassemble_info *);
  extern int print_insn_mcore		(bfd_vma, disassemble_info *);
+ extern int print_insn_mep		(bfd_vma, disassemble_info *);
  extern int print_insn_mmix		(bfd_vma, disassemble_info *);
  extern int print_insn_mn10200		(bfd_vma, disassemble_info *);
  extern int print_insn_mn10300		(bfd_vma, disassemble_info *);
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.80
diff -c -p -r1.80 common.h
*** include/elf/common.h	25 Oct 2006 06:49:18 -0000	1.80
--- include/elf/common.h	11 Jan 2007 19:10:16 -0000
***************
*** 280,285 ****
--- 280,287 ----
  /* NIOS magic number - no EABI available.  */
  #define EM_NIOS32		0xFEBB
  
+ #define EM_CYGNUS_MEP		0xF00D  /* Toshiba MeP */
+ 
  /* See the above comment before you add a new EM_* value here.  */
  
  /* Values for e_version.  */
Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.227
diff -c -p -r1.227 Makefile.am
*** ld/Makefile.am	12 Dec 2006 14:31:48 -0000	1.227
--- ld/Makefile.am	11 Jan 2007 19:10:16 -0000
*************** ALL_EMULATIONS = \
*** 177,182 ****
--- 177,183 ----
  	eelf32lppcsim.o \
  	eelf32m32c.o \
  	eelf32mcore.o \
+ 	eelf32mep.o \
  	eelf32mipswindiss.o \
  	eelf32mt.o \
  	eelf32openrisc.o \
*************** eelf32frvfd.c: $(srcdir)/emulparams/elf3
*** 692,697 ****
--- 693,701 ----
  eelf32mcore.c: $(srcdir)/emulparams/elf32mcore.sh \
    $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32mcore "$(tdir_mcore)"
+ eelf32mep.c: $(srcdir)/emulparams/elf32mep.sh \
+   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/mep.sc ${GEN_DEPENDS}
+ 	${GENSCRIPTS} elf32mep "$(tdir_mep)"
  em32relf.c: $(srcdir)/emulparams/m32relf.sh \
    $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} m32relf "$(tdir_m32r)"
Index: ld/configure.tgt
===================================================================
RCS file: /cvs/src/src/ld/configure.tgt,v
retrieving revision 1.202
diff -c -p -r1.202 configure.tgt
*** ld/configure.tgt	8 Jan 2007 17:21:50 -0000	1.202
--- ld/configure.tgt	11 Jan 2007 19:10:19 -0000
*************** mcore-*-pe)		targ_emul=mcorepe ;
*** 321,326 ****
--- 321,327 ----
  			targ_extra_ofiles="deffilep.o pe-dll.o" ;;
  mcore-*-elf)		targ_emul=elf32mcore
  			;;
+ mep-*-elf)		targ_emul=elf32mep ;;
  mips*-*-pe)		targ_emul=mipspe ;
  			targ_extra_ofiles="deffilep.o pe-dll.o" ;;
  mips*-dec-ultrix*)	targ_emul=mipslit ;;
Index: ld/testsuite/ld-undefined/undefined.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-undefined/undefined.exp,v
retrieving revision 1.25
diff -c -p -r1.25 undefined.exp
*** ld/testsuite/ld-undefined/undefined.exp	20 May 2005 19:09:54 -0000	1.25
--- ld/testsuite/ld-undefined/undefined.exp	11 Jan 2007 19:10:20 -0000
*************** set ml "undefined.c:9: undefined referen
*** 119,124 ****
--- 119,125 ----
  # hence the xfails below.
  
  setup_xfail mcore-*-elf
+ setup_xfail mep-*-*
  setup_xfail mips-sgi-irix6*
  setup_xfail "sh64-*-*"
  
Index: opcodes/Makefile.am
===================================================================
RCS file: /cvs/src/src/opcodes/Makefile.am,v
retrieving revision 1.103
diff -c -p -r1.103 Makefile.am
*** opcodes/Makefile.am	25 Oct 2006 06:49:20 -0000	1.103
--- opcodes/Makefile.am	11 Jan 2007 19:10:22 -0000
*************** HFILES = \
*** 39,44 ****
--- 39,45 ----
  	m32c-desc.h m32c-opc.h \
  	m32r-desc.h m32r-opc.h \
  	mcore-opc.h \
+ 	mep-desc.h mep-opc.h \
  	mt-desc.h mt-opc.h \
  	openrisc-desc.h openrisc-opc.h \
  	score-opc.h \
*************** CFILES = \
*** 132,137 ****
--- 133,143 ----
  	m88k-dis.c \
  	maxq-dis.c \
  	mcore-dis.c \
+ 	mep-asm.c \
+ 	mep-desc.c \
+ 	mep-dis.c \
+ 	mep-ibld.c \
+ 	mep-opc.c \
  	mips-dis.c \
  	mips-opc.c \
  	mips16-opc.c \
*************** ALL_MACHINES = \
*** 270,275 ****
--- 276,286 ----
  	m10300-opc.lo \
  	maxq-dis.lo \
  	mcore-dis.lo \
+ 	mep-asm.lo \
+ 	mep-desc.lo \
+ 	mep-dis.lo \
+ 	mep-ibld.lo \
+ 	mep-opc.lo \
  	mips-dis.lo \
  	mips-opc.lo \
  	mips16-opc.lo \
*************** uninstall_libopcodes:
*** 399,405 ****
  
  CLEANFILES = \
  	stamp-ip2k stamp-m32c stamp-m32r stamp-fr30 stamp-frv \
! 	stamp-openrisc stamp-iq2000 stamp-mt stamp-xstormy16 stamp-xc16x\
  	libopcodes.a stamp-lib dep.sed DEP DEPA DEP1 DEP2
  
  
--- 410,416 ----
  
  CLEANFILES = \
  	stamp-ip2k stamp-m32c stamp-m32r stamp-fr30 stamp-frv \
! 	stamp-openrisc stamp-iq2000 stamp-mep stamp-mt stamp-xstormy16 stamp-xc16x\
  	libopcodes.a stamp-lib dep.sed DEP DEPA DEP1 DEP2
  
  
*************** CGENDEPS = \
*** 415,421 ****
  	$(CGENDIR)/opc-opinst.scm \
  	cgen-asm.in cgen-dis.in cgen-ibld.in
  
! CGEN_CPUS = fr30 frv ip2k m32c m32r mt openrisc xc16x xstormy16
  
  if CGEN_MAINT
  IP2K_DEPS = stamp-ip2k
--- 426,432 ----
  	$(CGENDIR)/opc-opinst.scm \
  	cgen-asm.in cgen-dis.in cgen-ibld.in
  
! CGEN_CPUS = fr30 frv ip2k m32c m32r mep mt openrisc xc16x xstormy16
  
  if CGEN_MAINT
  IP2K_DEPS = stamp-ip2k
*************** M32C_DEPS = stamp-m32c
*** 423,428 ****
--- 434,440 ----
  M32R_DEPS = stamp-m32r
  FR30_DEPS = stamp-fr30
  FRV_DEPS = stamp-frv
+ MEP_DEPS = stamp-mep
  MT_DEPS = stamp-mt
  OPENRISC_DEPS = stamp-openrisc
  IQ2000_DEPS = stamp-iq2000
*************** M32C_DEPS =
*** 434,439 ****
--- 446,452 ----
  M32R_DEPS =
  FR30_DEPS =
  FRV_DEPS =
+ MEP_DEPS =
  MT_DEPS =
  OPENRISC_DEPS = 
  IQ2000_DEPS = 
*************** stamp-frv: $(CGENDEPS) $(srcdir)/../cpu/
*** 507,512 ****
--- 520,531 ----
  	$(MAKE) run-cgen arch=frv prefix=frv options= \
  		archfile=$(srcdir)/../cpu/frv.cpu opcfile=$(srcdir)/../cpu/frv.opc extrafiles=
  
+ $(srcdir)/mep-desc.h $(srcdir)/mep-desc.c $(srcdir)/mep-opc.h $(srcdir)/mep-opc.c $(srcdir)/mep-ibld.c $(srcdir)/mep-asm.c $(srcdir)/mep-dis.c: $(MEP_DEPS)
+ 	@true
+ stamp-mep: $(CGENDEPS) $(CPUDIR)/mep.cpu $(CPUDIR)/mep-default.cpu $(CPUDIR)/mep-core.cpu $(CPUDIR)/mep-h1.cpu $(CPUDIR)/mep-ext-cop.cpu $(CPUDIR)/mep-sample-ucidsp.cpu $(CPUDIR)/mep-rhcop.cpu $(CPUDIR)/mep-fmax.cpu $(CPUDIR)/mep.opc
+ 	$(MAKE) run-cgen arch=mep prefix=mep options= \
+ 		archfile=$(CPUDIR)/mep.cpu opcfile=$(CPUDIR)/mep.opc extrafiles=
+ 
  $(srcdir)/mt-desc.h $(srcdir)/mt-desc.c $(srcdir)/mt-opc.h $(srcdir)/mt-opc.c $(srcdir)/mt-ibld.c $(srcdir)/mt-asm.c $(srcdir)/mt-dis.c: $(MT_DEPS)
  	@true
  stamp-mt: $(CGENDEPS) $(srcdir)/../cpu/mt.cpu $(srcdir)/../cpu/mt.opc
*************** maxq-dis.lo: maxq-dis.c sysdep.h config.
*** 928,933 ****
--- 947,969 ----
  mcore-dis.lo: mcore-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \
    mcore-opc.h $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/ansidecl.h \
    $(INCDIR)/symcat.h
+ mep-asm.lo: mep-asm.c sysdep.h config.h $(BFD_H) \
+   $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h mep-desc.h \
+   $(INCDIR)/opcode/cgen.h mep-opc.h opintl.h
+ mep-desc.lo: mep-desc.c sysdep.h config.h $(BFD_H) \
+   $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h mep-desc.h \
+   $(INCDIR)/opcode/cgen.h mep-opc.h opintl.h
+ mep-dis.lo: mep-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+   $(BFD_H) $(INCDIR)/ansidecl.h \
+   $(INCDIR)/symcat.h mep-desc.h $(INCDIR)/opcode/cgen.h \
+   mep-opc.h opintl.h
+ mep-ibld.lo: mep-ibld.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+   $(BFD_H) $(INCDIR)/ansidecl.h \
+   $(INCDIR)/symcat.h mep-desc.h $(INCDIR)/opcode/cgen.h \
+   mep-opc.h opintl.h
+ mep-opc.lo: mep-opc.c sysdep.h config.h $(BFD_H) \
+   $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h mep-desc.h \
+   $(INCDIR)/opcode/cgen.h mep-opc.h
  mips-dis.lo: mips-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \
    $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \
    $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mips.h \
Index: opcodes/configure.in
===================================================================
RCS file: /cvs/src/src/opcodes/configure.in,v
retrieving revision 1.73
diff -c -p -r1.73 configure.in
*** opcodes/configure.in	25 Oct 2006 06:49:20 -0000	1.73
--- opcodes/configure.in	11 Jan 2007 19:10:23 -0000
*************** if test x${all_targets} = xfalse ; then
*** 184,189 ****
--- 184,190 ----
  	bfd_m88k_arch)		ta="$ta m88k-dis.lo" ;;
  	bfd_maxq_arch)		ta="$ta maxq-dis.lo" ;;
  	bfd_mcore_arch)		ta="$ta mcore-dis.lo" ;;
+ 	bfd_mep_arch)		ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
  	bfd_mips_arch)		ta="$ta mips-dis.lo mips-opc.lo mips16-opc.lo" ;;
  	bfd_mmix_arch)		ta="$ta mmix-dis.lo mmix-opc.lo" ;;
  	bfd_mn10200_arch)	ta="$ta m10200-dis.lo m10200-opc.lo" ;;
Index: opcodes/disassemble.c
===================================================================
RCS file: /cvs/src/src/opcodes/disassemble.c,v
retrieving revision 1.64
diff -c -p -r1.64 disassemble.c
*** opcodes/disassemble.c	25 Oct 2006 06:49:20 -0000	1.64
--- opcodes/disassemble.c	11 Jan 2007 19:10:23 -0000
***************
*** 50,55 ****
--- 50,56 ----
  #define ARCH_m88k
  #define ARCH_maxq
  #define ARCH_mcore
+ #define ARCH_mep
  #define ARCH_mips
  #define ARCH_mmix
  #define ARCH_mn10200
*************** disassembler (abfd)
*** 261,266 ****
--- 262,272 ----
        disassemble = print_insn_mcore;
        break;
  #endif
+ #ifdef ARCH_mep
+     case bfd_arch_mep:
+       disassemble = print_insn_mep;
+       break;
+ #endif
  #ifdef ARCH_mips
      case bfd_arch_mips:
        if (bfd_big_endian (abfd))
*************** disassemble_init_for_target (struct disa
*** 476,481 ****
--- 482,493 ----
        info->skip_zeroes = 32;
        break;
  #endif
+ #ifdef ARCH_mep
+     case bfd_arch_mep:
+       info->skip_zeroes = 256;
+       info->skip_zeroes_at_end = 0;
+       break;
+ #endif
  #ifdef ARCH_m32c
      case bfd_arch_m32c:
        info->endian = BFD_ENDIAN_BIG;
/* BFD support for the Toshiba Media Engine Processor.
   Copyright (C) 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"

#define MA(x, n, def, y) { 32, 32, 8, bfd_arch_mep, x, "mep", n, \
	2, def, bfd_default_compatible, bfd_default_scan, y }

static const bfd_arch_info_type bfd_h1_arch = MA (bfd_mach_mep_h1, "h1", FALSE, NULL);
const bfd_arch_info_type bfd_mep_arch = MA (bfd_mach_mep, "mep", TRUE, & bfd_h1_arch);
/* tc-mep.h -- Header file for tc-mep.c.
   Copyright (C) 2001, 2002, 2005 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, 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA. */

#define TC_MEP

/* Support computed relocations.  */
#define OBJ_COMPLEX_RELC

/* Support many operands per instruction.  */
#define GAS_CGEN_MAX_FIXUPS 10

#define LISTING_HEADER "MEP GAS "

/* The target BFD architecture.  */
#define TARGET_ARCH bfd_arch_mep

#define TARGET_FORMAT (target_big_endian ? "elf32-mep" : "elf32-mep-little")

/* This is the default.  */
#define TARGET_BYTES_BIG_ENDIAN 1

/* Permit temporary numeric labels. */
#define LOCAL_LABELS_FB 1

/* .-foo gets turned into PC relative relocs.  */
#define DIFF_EXPR_OK

/* We don't need to handle .word strangely.  */
#define WORKING_DOT_WORD

/* Values passed to md_apply_fix don't include the symbol value.  */
#define MD_APPLY_SYM_VALUE(FIX) 0

#define MD_APPLY_FIX
#define md_apply_fix mep_apply_fix
extern void mep_apply_fix (struct fix *, valueT *, segT);

/* 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 (struct fix *, segT);

#define tc_frob_file() mep_frob_file ()
extern void mep_frob_file (void);

#define tc_fix_adjustable(fixP) mep_fix_adjustable (fixP)
extern bfd_boolean mep_fix_adjustable (struct fix *);

/* After creating a fixup for an instruction operand, we need
   to check for HI16 relocs and queue them up for later sorting.  */
#define md_cgen_record_fixup_exp  mep_cgen_record_fixup_exp

/* When relaxing, we need to emit various relocs we otherwise wouldn't.  */
#define TC_FORCE_RELOCATION(fix) mep_force_relocation (fix)
extern int mep_force_relocation (struct fix *);

#define tc_gen_reloc gas_cgen_tc_gen_reloc

extern void gas_cgen_md_operand (expressionS *);
#define md_operand(x) gas_cgen_md_operand (x)

#define md_flush_pending_output() mep_flush_pending_output()
extern int mep_flush_pending_output(void);

extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table

/* Account for inserting a jmp after the insn.  */
#define TC_CGEN_MAX_RELAX(insn, len) ((len) + 4)

extern void mep_prepare_relax_scan (fragS *, offsetT *, relax_substateT);
#define md_prepare_relax_scan(FRAGP, ADDR, AIM, STATE, TYPE) \
	mep_prepare_relax_scan (FRAGP, &AIM, STATE)

#define skip_whitespace(str) while (*(str) == ' ') ++(str)

/* Support for core/vliw mode switching.  */
#define CORE 0
#define VLIW 1
#define MAX_PARALLEL_INSNS 56 /* From email from Toshiba.  */
#define VTEXT_SECTION_NAME ".vtext"

/* Needed to process pending instructions when a label is encountered.  */
#define TC_START_LABEL(ch, ptr)    ((ch == ':') && mep_flush_pending_output ())

#define tc_unrecognized_line(c) mep_unrecognized_line (c)
extern int mep_unrecognized_line (int);
#define md_cleanup mep_cleanup
extern void mep_cleanup (void);

#define md_elf_section_letter		mep_elf_section_letter
extern int mep_elf_section_letter (int, char **);
#define md_elf_section_flags		mep_elf_section_flags
extern flagword mep_elf_section_flags  (flagword, int, int);

#define ELF_TC_SPECIAL_SECTIONS \
  { VTEXT_SECTION_NAME, SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR|SHF_MEP_VLIW },

/* The values of the following enum are for use with parinsnum, which 
   is a variable in md_assemble that keeps track of whether or not the
   next instruction is expected to be the first or second instrucion in
   a parallelization group.  */
typedef enum exp_par_insn_{FIRST, SECOND} EXP_PAR_INSN;
/* MeP-specific support for 32-bit ELF.
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/mep.h"
#include "libiberty.h"

/* Forward declarations.  */

/* Private relocation functions.  */

#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
  {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }

#define N complain_overflow_dont
#define S complain_overflow_signed
#define U complain_overflow_unsigned

static bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
					void *, asection *, bfd *, char **);

static reloc_howto_type mep_elf_howto_table [] =
{
  /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
  MEPREL (R_MEP_NONE,     0,  0, 0, 0, 0, N, 0),
  /* MEPRELOC:HOWTO */
  /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
  MEPREL (R_MEP_8,        0,  8, 0, 0, 0, U, 0xff),
  MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
  MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
  MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
  MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
  MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
  MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
  MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
  MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
  MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
  MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
  MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
  MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
  MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
  MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
  MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
  MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
  MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
  MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
  MEPREL (R_MEP_GNU_VTENTRY,1,  0,16,32, 0, N, 0x0000),
  /* MEPRELOC:END */
};

#define VALID_MEP_RELOC(N) ((N) >= 0 \
  && (N) < ARRAY_SIZE (mep_elf_howto_table)

#undef OD
#undef OS
#undef OU


static bfd_reloc_status_type
mep_reloc
    (bfd *               abfd ATTRIBUTE_UNUSED,
     arelent *           reloc_entry ATTRIBUTE_UNUSED,
     struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
     void *              data ATTRIBUTE_UNUSED,
     asection *          input_section ATTRIBUTE_UNUSED,
     bfd *               output_bfd ATTRIBUTE_UNUSED,
     char **             error_message ATTRIBUTE_UNUSED)
{
  return bfd_reloc_ok;
}



#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
#define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
#else
#define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
#endif

static reloc_howto_type *
mep_reloc_type_lookup
    (bfd * abfd ATTRIBUTE_UNUSED,
     bfd_reloc_code_real_type code)
{
  unsigned int type = 0;

  switch (code)
    {
    MAP(NONE);
    case BFD_RELOC_8:
      type = R_MEP_8;
      break;
    case BFD_RELOC_16:
      type = R_MEP_16;
      break;
    case BFD_RELOC_32:
      type = R_MEP_32;
      break;
    case BFD_RELOC_VTABLE_ENTRY:
      type = R_MEP_GNU_VTENTRY;
      break;
    case BFD_RELOC_VTABLE_INHERIT:
      type = R_MEP_GNU_VTINHERIT;
      break;

    /* MEPRELOC:MAP */
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
    MAP(8);
    MAP(16);
    MAP(32);
    MAP(PCREL8A2);
    MAP(PCREL12A2);
    MAP(PCREL17A2);
    MAP(PCREL24A2);
    MAP(PCABS24A2);
    MAP(LOW16);
    MAP(HI16U);
    MAP(HI16S);
    MAP(GPREL);
    MAP(TPREL);
    MAP(TPREL7);
    MAP(TPREL7A2);
    MAP(TPREL7A4);
    MAP(UIMM24);
    MAP(ADDR24A4);
    MAP(GNU_VTINHERIT);
    MAP(GNU_VTENTRY);
    /* MEPRELOC:END */

    default:
      /* Pacify gcc -Wall.  */
      fprintf (stderr, "mep: no reloc for code %d\n", code);
      return NULL;
    }

  if (mep_elf_howto_table[type].type != type)
    {
      fprintf (stderr, "MeP: howto %d has type %d\n", type, mep_elf_howto_table[type].type);
      abort ();
    }

  return mep_elf_howto_table + type;
}

#undef MAP


/* Perform a single relocation.  */

static struct bfd_link_info *mep_info;
static int warn_tp = 0, warn_sda = 0;

static bfd_vma
mep_lookup_global
    (char *    name,
     bfd_vma   ofs,
     bfd_vma * cache,
     int *     warn)
{
  struct bfd_link_hash_entry *h;

  if (*cache || *warn)
    return *cache;

  h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
  if (h == 0 || h->type != bfd_link_hash_defined)
    {
      *warn = ofs + 1;
      return 0;
    }
  *cache = (h->u.def.value
	  + h->u.def.section->output_section->vma
	  + h->u.def.section->output_offset);
  return *cache;
}

static bfd_vma
mep_tpoff_base (bfd_vma ofs)
{
  static bfd_vma cache = 0;
  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
}

static bfd_vma
mep_sdaoff_base (bfd_vma ofs)
{
  static bfd_vma cache = 0;
  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
}

static bfd_reloc_status_type
mep_final_link_relocate
    (reloc_howto_type *  howto,
     bfd *               input_bfd,
     asection *          input_section,
     bfd_byte *          contents,
     Elf_Internal_Rela * rel,
     bfd_vma             relocation)
{
  unsigned long u;
  long s;
  unsigned char *byte;
  bfd_vma pc;
  bfd_reloc_status_type r = bfd_reloc_ok;
  int e2, e4;

  if (bfd_big_endian (input_bfd))
    {
      e2 = 0;
      e4 = 0;
    }
  else
    {
      e2 = 1;
      e4 = 3;
    }

  pc = (input_section->output_section->vma
	+ input_section->output_offset
	+ rel->r_offset);

  s = relocation + rel->r_addend;

  byte = (unsigned char *)contents + rel->r_offset;

  if (howto->type == R_MEP_PCREL24A2
      && s == 0
      && pc >= 0x800000)
    {
      /* This is an unreachable branch to an undefined weak function.
	 Silently ignore it, since the opcode can't do that but should
	 never be executed anyway.  */
      return bfd_reloc_ok;
    }

  if (howto->pc_relative)
    s -= pc;

  u = (unsigned long) s;

  switch (howto->type)
    {
    /* MEPRELOC:APPLY */
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
    case R_MEP_8: /* 76543210 */
      if (u > 255) r = bfd_reloc_overflow;
      byte[0] = (u & 0xff);
      break;
    case R_MEP_16: /* fedcba9876543210 */
      if (u > 65535) r = bfd_reloc_overflow;
      byte[0^e2] = ((u >> 8) & 0xff);
      byte[1^e2] = (u & 0xff);
      break;
    case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
      byte[0^e4] = ((u >> 24) & 0xff);
      byte[1^e4] = ((u >> 16) & 0xff);
      byte[2^e4] = ((u >> 8) & 0xff);
      byte[3^e4] = (u & 0xff);
      break;
    case R_MEP_PCREL8A2: /* --------7654321- */
      if (-128 > s || s > 127) r = bfd_reloc_overflow;
      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
      break;
    case R_MEP_PCREL12A2: /* ----ba987654321- */
      if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
      byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
      break;
    case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
      if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
      byte[2^e2] = ((s >> 9) & 0xff);
      byte[3^e2] = ((s >> 1) & 0xff);
      break;
    case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
      if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
      byte[2^e2] = ((s >> 16) & 0xff);
      byte[3^e2] = ((s >> 8) & 0xff);
      break;
    case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
      if ((u ^ pc) > 16777215) r = bfd_reloc_overflow;
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
      byte[2^e2] = ((u >> 16) & 0xff);
      byte[3^e2] = ((u >> 8) & 0xff);
      break;
    case R_MEP_LOW16: /* ----------------fedcba9876543210 */
      byte[2^e2] = ((u >> 8) & 0xff);
      byte[3^e2] = (u & 0xff);
      break;
    case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
      byte[2^e2] = ((u >> 24) & 0xff);
      byte[3^e2] = ((u >> 16) & 0xff);
      break;
    case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
      if (s & 0x8000)
	s += 0x10000;
      byte[2^e2] = ((s >> 24) & 0xff);
      byte[3^e2] = ((s >> 16) & 0xff);
      break;
    case R_MEP_GPREL: /* ----------------fedcba9876543210 */
      s -= mep_sdaoff_base(rel->r_offset);
      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
      byte[2^e2] = ((s >> 8) & 0xff);
      byte[3^e2] = (s & 0xff);
      break;
    case R_MEP_TPREL: /* ----------------fedcba9876543210 */
      s -= mep_tpoff_base(rel->r_offset);
      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
      byte[2^e2] = ((s >> 8) & 0xff);
      byte[3^e2] = (s & 0xff);
      break;
    case R_MEP_TPREL7: /* ---------6543210 */
      u -= mep_tpoff_base(rel->r_offset);
      if (u > 127) r = bfd_reloc_overflow;
      byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
      break;
    case R_MEP_TPREL7A2: /* ---------654321- */
      u -= mep_tpoff_base(rel->r_offset);
      if (u > 127) r = bfd_reloc_overflow;
      byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
      break;
    case R_MEP_TPREL7A4: /* ---------65432-- */
      u -= mep_tpoff_base(rel->r_offset);
      if (u > 127) r = bfd_reloc_overflow;
      byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
      break;
    case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
      if (u > 16777215) r = bfd_reloc_overflow;
      byte[1^e2] = (u & 0xff);
      byte[2^e2] = ((u >> 16) & 0xff);
      byte[3^e2] = ((u >> 8) & 0xff);
      break;
    case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
      if (u > 16777215) r = bfd_reloc_overflow;
      byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
      byte[2^e2] = ((u >> 16) & 0xff);
      byte[3^e2] = ((u >> 8) & 0xff);
      break;
    case R_MEP_GNU_VTINHERIT: /* ---------------- */
      break;
    case R_MEP_GNU_VTENTRY: /* ---------------- */
      break;
    /* MEPRELOC:END */
    default:
      abort ();
    }

  return r;
}

/* Set the howto pointer for a MEP ELF reloc.  */

static void
mep_info_to_howto_rela
    (bfd *               abfd ATTRIBUTE_UNUSED,
     arelent *           cache_ptr,
     Elf_Internal_Rela * dst)
{
  unsigned int r_type;

  static reloc_howto_type complex_reloc_installation_howto =
    HOWTO(R_RELC,0,0,0,0,0,complain_overflow_dont, 0, "RELOC_RELC",FALSE,0,0,0);

  r_type = ELF32_R_TYPE (dst->r_info);
  if (r_type == 0xff)
    cache_ptr->howto = & complex_reloc_installation_howto;
  else
    cache_ptr->howto = & mep_elf_howto_table [r_type];
}

/* 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 bfd_boolean
mep_elf_check_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;
  struct elf_link_hash_entry ** sym_hashes_end;
  const Elf_Internal_Rela *     rel;
  const Elf_Internal_Rela *     rel_end;

  if (info->relocatable)
    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];
    }
  return TRUE;
}


/* Relocate a MEP 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 relocatable
   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 relocatable 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 bfd_boolean
mep_elf_relocate_section
    (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;

  mep_info = info;

  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);

      r_symndx = ELF32_R_SYM (rel->r_info);

      if (info->relocatable)
	{
	  /* This is a relocatable 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  = mep_elf_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 = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);

	  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;
#if 0
	  fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
		   sec->name, name, sym->st_name,
		   sec->output_section->vma, sec->output_offset,
		   sym->st_value, rel->r_addend);
#endif
	}
      else
	{
	  h = sym_hashes [r_symndx];

	  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);
#if 0
	      fprintf (stderr,
		       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
		       sec->name, name, h->root.u.def.value,
		       sec->output_section->vma, sec->output_offset, relocation);
#endif
	    }
	  else if (h->root.type == bfd_link_hash_undefweak)
	    {
#if 0
	      fprintf (stderr, "undefined: sec: %s, name: %s\n",
		       sec->name, name);
#endif
	      relocation = 0;
	    }
	  else
	    {
	      if (! ((*info->callbacks->undefined_symbol)
		     (info, h->root.root.string, input_bfd,
		      input_section, rel->r_offset,
		      (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
		return FALSE;
#if 0
	      fprintf (stderr, "unknown: name: %s\n", name);
#endif
	      relocation = 0;
	    }
	}

      switch (r_type)
	{
	default:
	  r = mep_final_link_relocate (howto, input_bfd, input_section,
					 contents, rel, relocation);
	  break;
	}

      if (r != bfd_reloc_ok)
	{
	  const char * msg = (const char *) NULL;

	  switch (r)
	    {
	    case bfd_reloc_overflow:
	      r = info->callbacks->reloc_overflow
		(info, (h ? &h->root : NULL), 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;
	}
    }

  if (warn_tp)
    info->callbacks->undefined_symbol
      (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
  if (warn_sda)
    info->callbacks->undefined_symbol
      (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
  if (warn_sda || warn_tp)
    return FALSE;

  return TRUE;
}


/* Update the got entry reference counts for the section being
   removed.  */

static bfd_boolean
mep_elf_gc_sweep_hook
    (bfd *                     abfd ATTRIBUTE_UNUSED,
     struct bfd_link_info *    info ATTRIBUTE_UNUSED,
     asection *                sec ATTRIBUTE_UNUSED,
     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
{
  return TRUE;
}

/* Return the section that should be marked against GC for a given
   relocation.  */

static asection *
mep_elf_gc_mark_hook
    (asection *                   sec,
     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))
	{
	default:
	  switch (h->root.type)
	    {
	    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;

	    default:
	      break;
	    }
	}
    }
  else
    {
      if (!(elf_bad_symtab (sec->owner)
	    && 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 (sec->owner, sym->st_shndx);
    }

  return NULL;
}


/* Function to set the ELF flag bits.  */

static bfd_boolean
mep_elf_set_private_flags (bfd *    abfd,
			   flagword flags)
{
  elf_elfheader (abfd)->e_flags = flags;
  elf_flags_init (abfd) = TRUE;
  return TRUE;
}

static bfd_boolean
mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
{
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return TRUE;

  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 bfd_boolean
mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
{
  static bfd *last_ibfd = 0;
  flagword old_flags, new_flags;
  flagword old_partial, new_partial;

  /* Check if we have the same endianess.  */
  if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
    return FALSE;

  new_flags = elf_elfheader (ibfd)->e_flags;
  old_flags = elf_elfheader (obfd)->e_flags;

#ifdef DEBUG
  _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
#endif

    /* First call, no flags set.  */
    if (!elf_flags_init (obfd))
    {
      elf_flags_init (obfd) = TRUE;
      old_flags = new_flags;
    }
  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
    {
      /* Non-library flags trump library flags.  The choice doesn't really
	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
      if (old_flags & EF_MEP_LIBRARY)
	old_flags = new_flags;
    }
  else
    {
      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
	 mach.  */
      new_partial = (new_flags & EF_MEP_CPU_MASK);
      old_partial = (old_flags & EF_MEP_CPU_MASK);
      if (new_partial == old_partial)
	;
      else if (new_partial == EF_MEP_CPU_MEP)
	;
      else if (old_partial == EF_MEP_CPU_MEP)
	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
      else
	{
	  _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
	  bfd_set_error (bfd_error_invalid_target);
	  return FALSE;
	}

      /* Make sure they're for the same me_module.  Allow basic config to
	 mix with any other.  */
      new_partial = (new_flags & EF_MEP_INDEX_MASK);
      old_partial = (old_flags & EF_MEP_INDEX_MASK);
      if (new_partial == old_partial)
	;
      else if (new_partial == 0)
	;
      else if (old_partial == 0)
	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
      else
	{
	  _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
	  bfd_set_error (bfd_error_invalid_target);
	  return FALSE;
	}
    }

  elf_elfheader (obfd)->e_flags = old_flags;
  last_ibfd = ibfd;
  return TRUE;
}

/* This will be edited by the MeP configration tool.  */
static const char * config_names[] =
{
  "basic"
  /* start-mepcfgtool */
  ,"simple"
  ,"fmax"
  /* end-mepcfgtool */
};

static const char * core_names[] =
{
  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
};

static bfd_boolean
mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
{
  FILE *   file = (FILE *) ptr;
  flagword flags, partial_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);

  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
  if (partial_flags < ARRAY_SIZE (core_names))
    fprintf (file, "  core: %s", core_names[(long)partial_flags]);

  partial_flags = flags & EF_MEP_INDEX_MASK;
  if (partial_flags < ARRAY_SIZE (config_names))
    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);

  fputc ('\n', file);

  return TRUE;
}

/* Return the machine subcode from the ELF e_flags header.  */

static int
elf32_mep_machine (bfd * abfd)
{
  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
    {
    default: break;
    case EF_MEP_CPU_C2: return bfd_mach_mep;
    case EF_MEP_CPU_C3: return bfd_mach_mep;
    case EF_MEP_CPU_C4: return bfd_mach_mep;
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
    }

  return bfd_mach_mep;
}

static bfd_boolean
mep_elf_object_p (bfd * abfd)
{
  /* Irix 5 and 6 is broken.  Object file symbol tables are not always
     sorted correctly such that local symbols precede global symbols,
     and the sh_info field in the symbol table is not always right.  */
  /* This is needed for the RELC support code.  */
  elf_bad_symtab (abfd) = TRUE;
  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
  return TRUE;
}

static bfd_boolean
mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
{
  if (hdr->sh_flags & SHF_MEP_VLIW)
    * flags |= SEC_MEP_VLIW;
  return TRUE;
}

static bfd_boolean
mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
		       Elf_Internal_Shdr * hdr,
		       asection *          sec)
{
  if (sec->flags & SEC_MEP_VLIW)
    hdr->sh_flags |= SHF_MEP_VLIW;
  return TRUE;
}

#define ELF_ARCH		bfd_arch_mep
#define ELF_MACHINE_CODE	EM_CYGNUS_MEP
#define ELF_MAXPAGESIZE		0x1000

#define TARGET_BIG_SYM		bfd_elf32_mep_vec
#define TARGET_BIG_NAME		"elf32-mep"

#define TARGET_LITTLE_SYM	bfd_elf32_mep_little_vec
#define TARGET_LITTLE_NAME	"elf32-mep-little"

#define elf_info_to_howto_rel			NULL
#define elf_info_to_howto			mep_info_to_howto_rela
#define elf_backend_relocate_section		mep_elf_relocate_section
#define elf_backend_gc_mark_hook		mep_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook		mep_elf_gc_sweep_hook
#define elf_backend_check_relocs                mep_elf_check_relocs
#define elf_backend_object_p		        mep_elf_object_p
#define elf_backend_section_flags		mep_elf_section_flags
#define elf_backend_fake_sections		mep_elf_fake_sections

#define elf_backend_can_gc_sections		1

#define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
#define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
#define bfd_elf32_bfd_copy_private_bfd_data	mep_elf_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
#define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data

/* We use only the RELA entries.  */
#define USE_RELA

#include "elf32-target.h"
MACHINE=
SCRIPT_NAME=mep
OUTPUT_FORMAT="elf32-mep"
TEXT_START_ADDR=0x1000
ARCH=mep
MAXPAGESIZE=256
ENTRY=_start
EMBEDDED=yes
TEMPLATE_NAME=elf32
DATA_START_SYMBOLS='__data_start = . ;'
OTHER_GOT_SYMBOLS='
  . = ALIGN(4);
  __sdabase = . + 0x8000;
  .srodata : { *(.srodata) *(.srodata.*) *(.gnu.linkonce.srd.*) }
'
OTHER_SDATA_SECTIONS='
  PROVIDE (__sdabase = .);
  __assert_tiny_size = ASSERT ((. < __sdabase) || ((. - __sdabase) <= 0x8000),
			      "tiny section overflow");
'
OTHER_READONLY_SECTIONS='
  __stack = 0x001ffff0;
  __stack_size = 0x100000;
  __stack0  = (__stack - (0 *  (__stack_size / 1)) + 15) / 16 * 16;

  .rostacktab : 
  {
    /* Emit a table describing the location of the different stacks.
       Only 1 processor in the default configuration.  */
    . = ALIGN(4);
    __stack_table = .;
    LONG (__stack0);
  }
'
OTHER_END_SYMBOLS='
  PROVIDE (__heap = _end);
  PROVIDE (__heap_end = 0);
'
OTHER_TEXT_SECTIONS='
  *(.ftext) *(.ftext.*) *(.gnu.linkonce.ft.*)
  . = ALIGN(8);
  *(.vftext) *(.vftext.*) *(.gnu.linkonce.vf.*)
  *(.frodata) *(.frodata.*) *(.gnu.linkonce.frd.*)
'
OTHER_READWRITE_SECTIONS='
  . = ALIGN(4);
  __tpbase = .;
  .based : { *(.based) *(.based.*) *(.gnu.linkonce.based.*) }
  __assert_based_size = ASSERT ((. - __tpbase) <= 0x80, "based section overflow");
  .far : { *(.far) *(.far.*) *(.gnu.linkonce.far.*) }
'
OTHER_BSS_SECTIONS='
  __assert_near_size = ASSERT (. <= 0x1000000, "near section overflow");
  .farbss : { PROVIDE (__farbss_start = .); *(.farbss) *(.farbss.*) PROVIDE (__farbss_end = .); }
'
/* Toshiba MeP ELF support for BFD.
   Copyright (C) 2001, 2004, 2005 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_MEP_H
#define _ELF_MEP_H

/* Bits in the sh_flags field of Elf32_Shdr:  */

#define SHF_MEP_VLIW		0x10000000	/* contains vliw code */

/* This bit is reserved by BFD for processor specific stuff.  Name
   it properly so that we can easily stay consistent elsewhere.  */
#define SEC_MEP_VLIW		SEC_TIC54X_BLOCK

#include "elf/reloc-macros.h"

/* Note: The comments in this file are used by bfd/mep-relocs.pl to
   build parts of bfd/elf32-mep.c.  */

/* Relocations.  */
START_RELOC_NUMBERS (elf_mep_reloc_type)

  RELOC_NUMBER (R_MEP_NONE, 0)

  RELOC_NUMBER (R_MEP_8, 1)		/* 7654 3210                               U */
  RELOC_NUMBER (R_MEP_16, 2)		/* fedc ba98 7654 3210                     U */
  RELOC_NUMBER (R_MEP_32, 3)		/* vuts rqpo nmlk jihg fedc ba98 7654 3210 U */

  RELOC_NUMBER (R_MEP_PCREL8A2, 4)	/* ---- ---- 7654 321-                     S PC-REL */
  RELOC_NUMBER (R_MEP_PCREL12A2, 5)	/* ---- ba98 7654 321-                     S PC-REL */
  RELOC_NUMBER (R_MEP_PCREL17A2, 6)	/* ---- ---- ---- ---- gfed cba9 8765 4321 S PC-REL */
  RELOC_NUMBER (R_MEP_PCREL24A2, 7)	/* ---- -765 4321 ---- nmlk jihg fedc ba98 S PC-REL */
  RELOC_NUMBER (R_MEP_PCABS24A2, 8)	/* ---- -765 4321 ---- nmlk jihg fedc ba98 U */

  RELOC_NUMBER (R_MEP_LOW16, 9)		/* ---- ---- ---- ---- fedc ba98 7654 3210 U no-overflow */
  RELOC_NUMBER (R_MEP_HI16U, 10)	/* ---- ---- ---- ---- vuts rqpo nmlk jihg U no-overflow */
  RELOC_NUMBER (R_MEP_HI16S, 11)	/* ---- ---- ---- ---- vuts rqpo nmlk jihg S no-overflow */
  RELOC_NUMBER (R_MEP_GPREL, 12)	/* ---- ---- ---- ---- fedc ba98 7654 3210 S GP-REL*/
  RELOC_NUMBER (R_MEP_TPREL, 13)	/* ---- ---- ---- ---- fedc ba98 7654 3210 S TP-REL*/

  RELOC_NUMBER (R_MEP_TPREL7, 14)	/* ---- ---- -654 3210                     U TP-REL */
  RELOC_NUMBER (R_MEP_TPREL7A2, 15)	/* ---- ---- -654 321-                     U TP-REL */
  RELOC_NUMBER (R_MEP_TPREL7A4, 16)	/* ---- ---- -654 32--                     U TP-REL */

  RELOC_NUMBER (R_MEP_UIMM24, 17)	/* ---- ---- 7654 3210 nmlk jihg fedc ba98 U */
  RELOC_NUMBER (R_MEP_ADDR24A4, 18)	/* ---- ---- 7654 32-- nmlk jihg fedc ba98 U */

  RELOC_NUMBER (R_MEP_GNU_VTINHERIT, 19) /* ---- ---- ---- ----                     U no-overflow */
  RELOC_NUMBER (R_MEP_GNU_VTENTRY, 20)   /* ---- ---- ---- ----                     U no-overflow */

END_RELOC_NUMBERS(R_MEP_max)

#define	EF_MEP_CPU_MASK		0xff000000	/* specific cpu bits */
#define EF_MEP_CPU_MEP          0x00000000	/* generic MEP */
#define EF_MEP_CPU_C2   	0x01000000	/* MEP c2 */
#define EF_MEP_CPU_C3   	0x02000000	/* MEP c3 */
#define EF_MEP_CPU_C4   	0x04000000	/* MEP c4 */
#define EF_MEP_CPU_H1   	0x10000000	/* MEP h1 */

#define EF_MEP_LIBRARY		0x00000100	/* Built as a library */

#define EF_MEP_INDEX_MASK       0x000000ff      /* Configuration index */

#define EF_MEP_ALL_FLAGS	0xff0001ff

#endif /* _ELF_MEP_H */
#
# Unusual variables checked by this code:
#	NOP - four byte opcode for no-op (defaults to 0)
#	NO_SMALL_DATA - no .sbss/.sbss2/.sdata/.sdata2 sections if not
#		empty.
#	SMALL_DATA_CTOR - .ctors contains small data.
#	SMALL_DATA_DTOR - .dtors contains small data.
#	DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
#	INITIAL_READONLY_SECTIONS - at start of text segment
#	OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
#		(e.g., .PARISC.milli)
#	OTHER_TEXT_SECTIONS - these get put in .text when relocating
#	OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
#		(e.g., .PARISC.global)
#	OTHER_RELRO_SECTIONS - other than .data.rel.ro ...
#		(e.g. PPC32 .fixup, .got[12])
#	OTHER_BSS_SECTIONS - other than .bss .sbss ...
#	OTHER_SECTIONS - at the end
#	EXECUTABLE_SYMBOLS - symbols that must be defined for an
#		executable (e.g., _DYNAMIC_LINK)
#       TEXT_START_ADDR - the first byte of the text segment, after any
#               headers.
#       TEXT_BASE_ADDRESS - the first byte of the text segment.
#	TEXT_START_SYMBOLS - symbols that appear at the start of the
#		.text section.
#	DATA_START_SYMBOLS - symbols that appear at the start of the
#		.data section.
#	OTHER_GOT_SYMBOLS - symbols defined just before .got.
#	OTHER_GOT_SECTIONS - sections just after .got.
#	OTHER_SDATA_SECTIONS - sections just after .sdata.
#	OTHER_BSS_SYMBOLS - symbols that appear at the start of the
#		.bss section besides __bss_start.
#	DATA_PLT - .plt should be in data segment, not text segment.
#	PLT_BEFORE_GOT - .plt just before .got when .plt is in data segement.
#	BSS_PLT - .plt should be in bss segment
#	TEXT_DYNAMIC - .dynamic in text segment, not data segment.
#	EMBEDDED - whether this is for an embedded system. 
#	SHLIB_TEXT_START_ADDR - if set, add to SIZEOF_HEADERS to set
#		start address of shared library.
#	INPUT_FILES - INPUT command of files to always include
#	WRITABLE_RODATA - if set, the .rodata section should be writable
#	INIT_START, INIT_END -  statements just before and just after
# 	combination of .init sections.
#	FINI_START, FINI_END - statements just before and just after
# 	combination of .fini sections.
#	STACK_ADDR - start of a .stack section.
#	OTHER_END_SYMBOLS - symbols to place right at the end of the script.
#	SEPARATE_GOTPLT - if set, .got.plt should be separate output section,
#		so that .got can be in the RELRO area.  It should be set to
#		the number of bytes in the beginning of .got.plt which can be
#		in the RELRO area as well.
#
# When adding sections, do note that the names of some sections are used
# when specifying the start address of the next.
#

#  Many sections come in three flavours.  There is the 'real' section,
#  like ".data".  Then there are the per-procedure or per-variable
#  sections, generated by -ffunction-sections and -fdata-sections in GCC,
#  and useful for --gc-sections, which for a variable "foo" might be
#  ".data.foo".  Then there are the linkonce sections, for which the linker
#  eliminates duplicates, which are named like ".gnu.linkonce.d.foo".
#  The exact correspondences are:
#
#  Section	Linkonce section
#  .text	.gnu.linkonce.t.foo
#  .rodata	.gnu.linkonce.r.foo
#  .data	.gnu.linkonce.d.foo
#  .bss		.gnu.linkonce.b.foo
#  .sdata	.gnu.linkonce.s.foo
#  .sbss	.gnu.linkonce.sb.foo
#  .sdata2	.gnu.linkonce.s2.foo
#  .sbss2	.gnu.linkonce.sb2.foo
#  .debug_info	.gnu.linkonce.wi.foo
#  .tdata	.gnu.linkonce.td.foo
#  .tbss	.gnu.linkonce.tb.foo
#
#  Each of these can also have corresponding .rel.* and .rela.* sections.

test -z "$ENTRY" && ENTRY=_start
test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
test -z "${ELFSIZE}" && ELFSIZE=32
test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
test "$LD_FLAG" = "N" && DATA_ADDR=.
test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT
DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_RELRO_END=""
DATA_SEGMENT_RELRO_GOTPLT_END=""
DATA_SEGMENT_END=""
if test -n "${COMMONPAGESIZE}"; then
  DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
  DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
  if test -n "${SEPARATE_GOTPLT}"; then
    DATA_SEGMENT_RELRO_GOTPLT_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT}, .);"
  else
    DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (0, .);"
  fi
fi
INTERP=".interp       ${RELOCATING-0} : { *(.interp) }"
PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
if test -z "$GOT"; then
  if test -z "$SEPARATE_GOTPLT"; then
    GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
  else
    GOT=".got          ${RELOCATING-0} : { *(.got) }"
    GOTPLT="${RELOCATING+${DATA_SEGMENT_RELRO_GOTPLT_END}}
  .got.plt      ${RELOCATING-0} : { *(.got.plt) }"
  fi
fi
DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }"
STACKNOTE="/DISCARD/ : { *(.note.GNU-stack) }"
if test -z "${NO_SMALL_DATA}"; then
  SBSS=".sbss         ${RELOCATING-0} :
  {
    ${RELOCATING+PROVIDE (__sbss_start = .);}
    ${RELOCATING+PROVIDE (___sbss_start = .);}
    ${CREATE_SHLIB+*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)}
    *(.dynsbss)
    *(.sbss${RELOCATING+ .sbss.* .gnu.linkonce.sb.*})
    *(.scommon)
    ${RELOCATING+PROVIDE (__sbss_end = .);}
    ${RELOCATING+PROVIDE (___sbss_end = .);}
  }"
  SBSS2=".sbss2        ${RELOCATING-0} : { *(.sbss2${RELOCATING+ .sbss2.* .gnu.linkonce.sb2.*}) }"
  SDATA="/* We want the small data sections together, so single-instruction offsets
     can access them all, and initialized data all before uninitialized, so
     we can shorten the on-disk segment size.  */
  .sdata        ${RELOCATING-0} : 
  {
    ${RELOCATING+${SDATA_START_SYMBOLS}}
    ${CREATE_SHLIB+*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)}
    *(.sdata${RELOCATING+ .sdata.* .gnu.linkonce.s.*})
  }"
  SDATA2=".sdata2       ${RELOCATING-0} : { *(.sdata2${RELOCATING+ .sdata2.* .gnu.linkonce.s2.*}) }"
  REL_SDATA=".rel.sdata    ${RELOCATING-0} : { *(.rel.sdata${RELOCATING+ .rel.sdata.* .rel.gnu.linkonce.s.*}) }
  .rela.sdata   ${RELOCATING-0} : { *(.rela.sdata${RELOCATING+ .rela.sdata.* .rela.gnu.linkonce.s.*}) }"
  REL_SBSS=".rel.sbss     ${RELOCATING-0} : { *(.rel.sbss${RELOCATING+ .rel.sbss.* .rel.gnu.linkonce.sb.*}) }
  .rela.sbss    ${RELOCATING-0} : { *(.rela.sbss${RELOCATING+ .rela.sbss.* .rela.gnu.linkonce.sb.*}) }"
  REL_SDATA2=".rel.sdata2   ${RELOCATING-0} : { *(.rel.sdata2${RELOCATING+ .rel.sdata2.* .rel.gnu.linkonce.s2.*}) }
  .rela.sdata2  ${RELOCATING-0} : { *(.rela.sdata2${RELOCATING+ .rela.sdata2.* .rela.gnu.linkonce.s2.*}) }"
  REL_SBSS2=".rel.sbss2    ${RELOCATING-0} : { *(.rel.sbss2${RELOCATING+ .rel.sbss2.* .rel.gnu.linkonce.sb2.*}) }
  .rela.sbss2   ${RELOCATING-0} : { *(.rela.sbss2${RELOCATING+ .rela.sbss2.* .rela.gnu.linkonce.sb2.*}) }"
else
  NO_SMALL_DATA=" "
fi
test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" "
CTOR=".ctors        ${CONSTRUCTING-0} : 
  {
    ${CONSTRUCTING+${CTOR_START}}
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */

    KEEP (*crtbegin*.o(.ctors))

    /* We don't want to include the .ctor section from
       from the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */

    KEEP (*(EXCLUDE_FILE (*crtend*.o $OTHER_EXCLUDE_FILES) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    ${CONSTRUCTING+${CTOR_END}}
  }"
DTOR=".dtors        ${CONSTRUCTING-0} :
  {
    ${CONSTRUCTING+${DTOR_START}}
    KEEP (*crtbegin*.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend*.o $OTHER_EXCLUDE_FILES) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    ${CONSTRUCTING+${DTOR_END}}
  }"
STACK="  .stack        ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} :
  {
    ${RELOCATING+_stack = .;}
    *(.stack)
  }"

# if this is for an embedded system, don't add SIZEOF_HEADERS.
if [ -z "$EMBEDDED" ]; then
   test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR} + SIZEOF_HEADERS"
else
   test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}"
fi

cat <<EOF
OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
	      "${LITTLE_OUTPUT_FORMAT}")
OUTPUT_ARCH(${OUTPUT_ARCH})
ENTRY(${ENTRY})

${RELOCATING+${LIB_SEARCH_DIRS}}
${RELOCATING+/* Do we need any of these for elf?
   __DYNAMIC = 0; ${STACKZERO+${STACKZERO}} ${SHLIB_PATH+${SHLIB_PATH}}  */}
${RELOCATING+${EXECUTABLE_SYMBOLS}}
${RELOCATING+${INPUT_FILES}}
${RELOCATING- /* For some reason, the Solaris linker makes bad executables
  if gld -r is used and the intermediate file has sections starting
  at non-zero addresses.  Could be a Solaris ld bug, could be a GNU ld
  bug.  But for now assigning the zero vmas works.  */}

SECTIONS
{
  /* Read-only sections, merged into text segment: */
  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + SIZEOF_HEADERS;}}
  ${CREATE_PIE+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + SIZEOF_HEADERS;}}
  ${CREATE_SHLIB-${INTERP}}
  ${INITIAL_READONLY_SECTIONS}
  ${TEXT_DYNAMIC+${DYNAMIC}}
  .hash         ${RELOCATING-0} : { *(.hash) }
  .dynsym       ${RELOCATING-0} : { *(.dynsym) }
  .dynstr       ${RELOCATING-0} : { *(.dynstr) }
  .gnu.version  ${RELOCATING-0} : { *(.gnu.version) }
  .gnu.version_d ${RELOCATING-0}: { *(.gnu.version_d) }
  .gnu.version_r ${RELOCATING-0}: { *(.gnu.version_r) }

EOF
if [ "x$COMBRELOC" = x ]; then
  COMBRELOCCAT=cat
else
  COMBRELOCCAT="cat > $COMBRELOC"
fi
eval $COMBRELOCCAT <<EOF
  .rel.init     ${RELOCATING-0} : { *(.rel.init) }
  .rela.init    ${RELOCATING-0} : { *(.rela.init) }
  .rel.text     ${RELOCATING-0} : { *(.rel.text${RELOCATING+ .rel.text.* .rel.gnu.linkonce.t.*}) }
  .rela.text    ${RELOCATING-0} : { *(.rela.text${RELOCATING+ .rela.text.* .rela.gnu.linkonce.t.*}) }
  .rel.fini     ${RELOCATING-0} : { *(.rel.fini) }
  .rela.fini    ${RELOCATING-0} : { *(.rela.fini) }
  .rel.rodata   ${RELOCATING-0} : { *(.rel.rodata${RELOCATING+ .rel.rodata.* .rel.gnu.linkonce.r.*}) }
  .rela.rodata  ${RELOCATING-0} : { *(.rela.rodata${RELOCATING+ .rela.rodata.* .rela.gnu.linkonce.r.*}) }
  ${OTHER_READONLY_RELOC_SECTIONS}
  .rel.data.rel.ro ${RELOCATING-0} : { *(.rel.data.rel.ro${RELOCATING+*}) }
  .rela.data.rel.ro ${RELOCATING-0} : { *(.rel.data.rel.ro${RELOCATING+*}) }
  .rel.data     ${RELOCATING-0} : { *(.rel.data${RELOCATING+ .rel.data.* .rel.gnu.linkonce.d.*}) }
  .rela.data    ${RELOCATING-0} : { *(.rela.data${RELOCATING+ .rela.data.* .rela.gnu.linkonce.d.*}) }
  .rel.tdata	${RELOCATING-0} : { *(.rel.tdata${RELOCATING+ .rel.tdata.* .rel.gnu.linkonce.td.*}) }
  .rela.tdata	${RELOCATING-0} : { *(.rela.tdata${RELOCATING+ .rela.tdata.* .rela.gnu.linkonce.td.*}) }
  .rel.tbss	${RELOCATING-0} : { *(.rel.tbss${RELOCATING+ .rel.tbss.* .rel.gnu.linkonce.tb.*}) }
  .rela.tbss	${RELOCATING-0} : { *(.rela.tbss${RELOCATING+ .rela.tbss.* .rela.gnu.linkonce.tb.*}) }
  .rel.ctors    ${RELOCATING-0} : { *(.rel.ctors) }
  .rela.ctors   ${RELOCATING-0} : { *(.rela.ctors) }
  .rel.dtors    ${RELOCATING-0} : { *(.rel.dtors) }
  .rela.dtors   ${RELOCATING-0} : { *(.rela.dtors) }
  .rel.got      ${RELOCATING-0} : { *(.rel.got) }
  .rela.got     ${RELOCATING-0} : { *(.rela.got) }
  ${OTHER_GOT_RELOC_SECTIONS}
  ${REL_SDATA}
  ${REL_SBSS}
  ${REL_SDATA2}
  ${REL_SBSS2}
  .rel.bss      ${RELOCATING-0} : { *(.rel.bss${RELOCATING+ .rel.bss.* .rel.gnu.linkonce.b.*}) }
  .rela.bss     ${RELOCATING-0} : { *(.rela.bss${RELOCATING+ .rela.bss.* .rela.gnu.linkonce.b.*}) }
EOF
if [ -n "$COMBRELOC" ]; then
cat <<EOF
  .rel.dyn      ${RELOCATING-0} :
    {
EOF
sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/      \1/' $COMBRELOC
cat <<EOF
    }
  .rela.dyn     ${RELOCATING-0} :
    {
EOF
sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/      \1/' $COMBRELOC
cat <<EOF
    }
EOF
fi
cat <<EOF
  .rel.plt      ${RELOCATING-0} : { *(.rel.plt) }
  .rela.plt     ${RELOCATING-0} : { *(.rela.plt) }
  ${OTHER_PLT_RELOC_SECTIONS}

  .init         ${RELOCATING-0} : 
  { 
    ${RELOCATING+${INIT_START}}
    KEEP (*(.init))
    ${RELOCATING+${INIT_END}}
  } =${NOP-0}

  ${DATA_PLT-${BSS_PLT-${PLT}}}
  .text         ${RELOCATING-0} :
  {
    ${RELOCATING+${TEXT_START_SYMBOLS}}
    *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
    KEEP (*(.text.*personality*))
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
    ${RELOCATING+${OTHER_TEXT_SECTIONS}}
  } =${NOP-0}
  .fini         ${RELOCATING-0} :
  {
    ${RELOCATING+${FINI_START}}
    KEEP (*(.fini))
    ${RELOCATING+${FINI_END}}
  } =${NOP-0}
  ${RELOCATING+PROVIDE (__etext = .);}
  ${RELOCATING+PROVIDE (_etext = .);}
  ${RELOCATING+PROVIDE (etext = .);}
  ${WRITABLE_RODATA-${RODATA}}
  .rodata1      ${RELOCATING-0} : { *(.rodata1) }
  ${CREATE_SHLIB-${SDATA2}}
  ${CREATE_SHLIB-${SBSS2}}
  ${OTHER_READONLY_SECTIONS}
  .eh_frame_hdr : { *(.eh_frame_hdr) }
  .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }

  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
  ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}

  /* Exception handling  */
  .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }

  /* Thread Local Storage sections  */
  .tdata	${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
  .tbss		${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }

  .preinit_array   ${RELOCATING-0} : { KEEP (*(.preinit_array)) }
  .init_array   ${RELOCATING-0} : { KEEP (*(.init_array)) }
  .fini_array   ${RELOCATING-0} : { KEEP (*(.fini_array)) }

  ${SMALL_DATA_CTOR-${RELOCATING+${CTOR}}}
  ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}}
  .jcr          ${RELOCATING-0} : { KEEP (*(.jcr)) }

  ${RELOCATING+${DATARELRO}}
  ${OTHER_RELRO_SECTIONS}
  ${TEXT_DYNAMIC-${DYNAMIC}}
  ${NO_SMALL_DATA+${RELRO_NOW+${GOT}}}
  ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
  ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT+${GOTPLT}}}}
  ${RELOCATING+${DATA_SEGMENT_RELRO_END}}
  ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT-${GOT}}}}

  ${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}}

  .data         ${RELOCATING-0} :
  {
    ${RELOCATING+${DATA_START_SYMBOLS}}
    *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
    KEEP (*(.gnu.linkonce.d.*personality*))
    ${CONSTRUCTING+SORT(CONSTRUCTORS)}
  }
  .data1        ${RELOCATING-0} : { *(.data1) }
  ${WRITABLE_RODATA+${RODATA}}
  ${OTHER_READWRITE_SECTIONS}
  ${SMALL_DATA_CTOR+${RELOCATING+${CTOR}}}
  ${SMALL_DATA_DTOR+${RELOCATING+${DTOR}}}
  ${DATA_PLT+${PLT_BEFORE_GOT+${PLT}}}
  ${RELOCATING+${OTHER_GOT_SYMBOLS}}
  ${NO_SMALL_DATA-${GOT}}
  ${OTHER_GOT_SECTIONS}
  ${SDATA}
  ${OTHER_SDATA_SECTIONS}
  ${RELOCATING+_edata = .;}
  ${RELOCATING+PROVIDE (edata = .);}
  ${RELOCATING+__bss_start = .;}
  ${RELOCATING+${OTHER_BSS_SYMBOLS}}
  ${SBSS}
  ${BSS_PLT+${PLT}}
  .bss          ${RELOCATING-0} :
  {
   *(.dynbss)
   *(.bss${RELOCATING+ .bss.* .gnu.linkonce.b.*})
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.  */
   ${RELOCATING+. = ALIGN(${ALIGNMENT});}
  }
  ${OTHER_BSS_SECTIONS}
  ${RELOCATING+. = ALIGN(${ALIGNMENT});}
  ${RELOCATING+_end = .;}
  ${RELOCATING+${OTHER_BSS_END_SYMBOLS}}
  ${RELOCATING+PROVIDE (end = .);}
  ${RELOCATING+${DATA_SEGMENT_END}}

  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }

  .comment       0 : { *(.comment) }

  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */

  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }

  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }

  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }

  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }

  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

  ${STACK_ADDR+${STACK}}
  ${OTHER_SECTIONS}
  ${RELOCATING+${OTHER_END_SYMBOLS}}
  ${RELOCATING+${STACKNOTE}}
}
EOF
#!/usr/bin/perl
# -*- perl -*-
#
# Toshiba MeP Media Engine Relocation Generator
# Copyright (C) 2001 Red Hat, Inc.
# This file is part of BFD.
# Originally written by DJ Delorie <dj@redhat.com>
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */


# Usage: Run this anywhere inside your source tree.  It will read
# include/elf/mep.h and scan the comments therein.  It will renumber
# the relocs to be sequential (this is needed so that bfd/elf32-mep.h
# works) if needed.  It will then update the reloc list in bfd/reloc.c
# and the howto, mapping, and apply routines in bfd/elf32-mep.c.  You
# can then regenerate bfd-in2.h and check everything in.

# FIXME: After the relocation list is finalized, change this to
# *verify* the reloc list, rather than resequence it.

while (! -f "include/elf/mep.h" && ! -f "bfd/reloc.c") {
    chdir "..";
    $pwd = `pwd`;
    if ($pwd !~ m@/.*/@) {
	print STDERR "Cannot find include/elf/mep.h or bfd/reloc.h\n";
	exit 1;
    }
}
$pwd = `pwd`;
print "srctop is $pwd";

printf "Reading include/elf/mep.h ...\n";
open(MEPH, "include/elf/mep.h");
open(MEPHO, "> include/elf/mep.h.new") || die("mep.h.new create: $!");
$val = 0;
while (<MEPH>) {
    if (($pre,$rel,$rest) = /(.*RELOC_NUMBER \()([^,]+), *\d+(.*)/) {
	$rest =~ s/[\r\n]+$//;
	print (MEPHO "$pre$rel, $val$rest\n") || die("mep.h.new write: $!");
	$val ++;
	$rel =~ s/R_MEP_//;
	push(@relocs, $rel);

	$rest =~ s@.*/\* @@;
	($pattern, $sign, $attrs) = $rest =~ m@(.*) ([US]) (.*)\*/@;
	$pattern =~ s/ //g;
	push(@pattern, $pattern);
	push(@sign, $sign);
	push(@attrs, $attrs);

	printf "%4d $rel p=`$pattern' s=`$sign' a=`$attrs'\n", $#pattern;

    } else {
	print(MEPHO) || die("mep.h.new write: $!");
    }
}
close(MEPH);
close(MEPHO) || die("mep.h.new close: $!");

&swapfile("include/elf/mep.h");

redo_file ("bfd/reloc.c",
	   "",
	   "ENUMDOC\n  Toshiba Media Processor Relocations.\n\nCOMMENT\n",
	   "ENUM\n  BFD_RELOC_MEP_%s\n",
	   "");

$autogen = "    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */\n";

redo_file ("bfd/elf32-mep.c",
	   "MEPRELOC:HOWTO",
	   $autogen,
	   "MEPRELOC:END",
	   "",
	   "&emit_howto();",
	   "MEPRELOC:MAP",
	   $autogen,
	   "MEPRELOC:END",
	   "",
	   "    MAP(%s);\n",
	   "MEPRELOC:APPLY",
	   $autogen,
	   "MEPRELOC:END",
	   "",
	   "&emit_apply();",
	   );

sub mask2shifts {
    my ($mask) = @_;
    my ($bits, $left, $right, $ci, $c, $cv);
    $bits = 0;
    $left = 0;
    $right = 32;
    for ($ci=0; $ci<length($mask); $ci++) {
	$c = substr($mask, $ci, 1);
	$left++;
	next if $c eq '-';
	$left = 0;
	$cv = ord($c) - ord('0');
	$cv -= ord('a') - ord('9') - 1 if $cv > 9;
	$right = $cv unless $right < $cv;
	$bits = $cv+1 unless $bits > $cv+1;
    }
    $mask =~ tr/-/1/c;
    $mask =~ tr/-/0/;
    ($rmask = $mask) =~ tr/01/10/;
    $mask = unpack("H*", pack("B*", $mask));
    $rmask = unpack("H*", pack("B*", $rmask));
    return ($bits, $left, $right, $mask, $rmask);
}

sub emit_howto {
    for ($i=1; $i<=$#relocs; $i++) {
	$mask = $pattern[$i];

	if (length($mask) == 8)     { $bytesize = 0; }
	elsif (length($mask) == 16) { $bytesize = 1; }
	elsif (length($mask) == 32) { $bytesize = 2; }

	($bits, $left, $right, $mask) = mask2shifts ($mask);
	$bits[$i] = $bits;
	$pcrel = 0;
	$pcrel = 1 if $attrs[$i] =~ /pc-rel/i;
	$overflow = $sign[$i];
	$overflow = 'N' if $attrs[$i] =~ /no-overflow/;

	$c = "$relocs[$i],";
	printf(NEW "  MEPREL (R_MEP_%-10s%d,%3d,%2d,%2d,%2d,%2s, 0x%s),\n",
	       $c, $bytesize, $bits, $left, $right, $pcrel, $overflow, $mask);
    }
}

sub emit_apply {
    for ($i=1; $i<=$#relocs; $i++) {
	$v = "u";
	$v = "s" if $sign[$i] =~ /S/;
	if (length($pattern[$i]) == 8) {
	    $e = ''; # no endian swap for bytes
	} elsif ($pattern[$i] =~ /-/ || length($pattern[$i]) == 16) {
	    $e = '^e2'; # endian swap - 2byte words only
	} else {
	    $e = '^e4' # endian swap for data
	}
	print NEW "    case R_MEP_$relocs[$i]: /* $pattern[$i] */\n";
	if ($attrs[$i] =~ /tp-rel/i) {
	    print NEW "      $v -= mep_tpoff_base(rel->r_offset);\n";
	}
	if ($attrs[$i] =~ /gp-rel/i) {
	    print NEW "      $v -= mep_sdaoff_base(rel->r_offset);\n";
	}
	if ($attrs[$i] !~ /no-overflow/ && $bits[$i] < 32) {
	    if ($v eq "u") {
		$max = (1 << $bits[$i]) - 1;
		print NEW "      if (u > $max) r = bfd_reloc_overflow;\n";
	    } else {
		$min = -(1 << ($bits[$i]-1));
		$max = (1 << ($bits[$i]-1)) - 1;
		print NEW "      if ($min > s || s > $max) r = bfd_reloc_overflow;\n";
	    }
	}
	for ($b=0; $b<length($pattern[$i]); $b += 8) {
	    $mask = substr($pattern[$i], $b, 8);
	    ($bits, $left, $right, $mask, $rmask) = mask2shifts ($mask);
	    if ($left > $right) { $left -= $right; $right = 0; }
	    else { $right -= $left; $left = 0; }

	    if ($mask ne "00") {
		$bb = $b / 8;
		print NEW "      byte[$bb$e] = ";
		print NEW "(byte[$bb$e] & 0x$rmask) | " if $rmask ne "00";
		if ($left) {
		    print NEW "(($v << $left) & 0x$mask)";
		} elsif ($right) {
		    print NEW "(($v >> $right) & 0x$mask)";
		} else {
		    print NEW "($v & 0x$mask)";
		}
		print NEW ";\n";
	    }
	}
	print NEW "      break;\n";
    }
}


#-----------------------------------------------------------------------------

sub redo_file {
    my ($file, @control) = @_;
    open(OLD, $file);
    open(NEW, "> $file.new") || die("$file.new create: $!");

    print "Scanning file $file ...\n";

    while (1) {
	$start = shift @control;
	$prefix = shift @control;
	$end = shift @control;
	$suffix = shift @control;
	$pattern = shift @control;

	if (!$start) {
	    print NEW while <OLD>;
	    last;
	}

	print "  looking for $start\n";
	while (<OLD>) {
	    print NEW;
	    last if /\Q$start\E/;
	}
	print "can't find $start\n" unless $_;
	last unless $_;

	print NEW $prefix;
	if ($pattern =~ /^\&/) {
	    eval $pattern;
	    die("$pattern: $@") if $@;
	} else {
	    for $i (1..$#relocs) {
		printf (NEW "$pattern", $relocs[$i]) || die("$file.new write: $!");
		$pattern =~ s/^ENUM\n/ENUMX\n/;
	    }
	}
	print NEW $suffix;
	while (<OLD>) {
	    last if /\Q$end\E/;
	}
	print NEW;
    }

    close(OLD);
    close(NEW) || die("$file.new close: $!");
    &swapfile($file);
}

#-----------------------------------------------------------------------------

sub swapfile {
    my ($f) = @_;
    if ( ! -f "$f.save") {
	system "cp $f $f.save";
    }
    open(ORIG, $f);
    open(NEW, "$f.new");
    while (<ORIG>) {
	$n = <NEW>;
	if ($n ne $_) {
	    close(ORIG);
	    close(NEW);
	    print "  Updating $f\n";
	    rename "$f", "$f.old";
	    rename "$f.new", "$f";
	    return;
	}
    }
    close(ORIG);
    close(NEW);
    print "  No change to $f\n";
    unlink "$f.new";
}
/* tc-mep.c -- Assembler for the Toshiba Media Processor.
   Copyright (C) 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.  */

#include <stdio.h>
#include "as.h"
#include "dwarf2dbg.h"
#include "subsegs.h"
#include "symcat.h"
#include "opcodes/mep-desc.h"
#include "opcodes/mep-opc.h"
#include "cgen.h"
#include "elf/common.h"
#include "elf/mep.h"
#include "libbfd.h"
#include "xregex.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];
} mep_insn;

static int mode = CORE; /* Start in core mode. */
static int pluspresent = 0;
static int allow_disabled_registers = 0;
static int library_flag = 0;

/* We're going to need to store all of the instructions along with
   their fixups so that we can parallelization grouping rules. */

static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
static int num_insns_saved = 0;

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 void mep_switch_to_vliw_mode (int);
static void mep_switch_to_core_mode (int);
static void mep_s_vtext (int);
static void mep_noregerr (int);

/* The target specific pseudo-ops which we support.  */
const pseudo_typeS md_pseudo_table[] =
{
  { "word",	cons,	                        4 },
  { "file",	(void (*) (int)) dwarf2_directive_file,   	0 },
  { "loc",	dwarf2_directive_loc,   	0 },
  { "vliw", 	mep_switch_to_vliw_mode,	0 },
  { "core", 	mep_switch_to_core_mode,	0 },
  { "vtext", 	mep_s_vtext,             	0 },
  { "noregerr",	mep_noregerr,	             	0 },
  { NULL, 	NULL,		        	0 }
};

/* Relocations against symbols are done in two
   parts, with a HI relocation and a LO relocation.  Each relocation
   has only 16 bits of space to store an addend.  This means that in
   order for the linker to handle carries correctly, it must be able
   to locate both the HI and the LO relocation.  This means that the
   relocations must appear in order in the relocation table.

   In order to implement this, we keep track of each unmatched HI
   relocation.  We then sort them so that they immediately precede the
   corresponding LO relocation. */

struct mep_hi_fixup
{
  struct mep_hi_fixup * next;	/* Next HI fixup.  */
  fixS * fixp;			/* This fixup.  */
  segT seg;			/* The section this fixup is in.  */
};

/* The list of unmatched HI relocs.  */
static struct mep_hi_fixup * mep_hi_fixup_list;


#define OPTION_EB		(OPTION_MD_BASE + 0)
#define OPTION_EL		(OPTION_MD_BASE + 1)
#define OPTION_CONFIG		(OPTION_MD_BASE + 2)
#define OPTION_AVERAGE		(OPTION_MD_BASE + 3)
#define OPTION_NOAVERAGE	(OPTION_MD_BASE + 4)
#define OPTION_MULT		(OPTION_MD_BASE + 5)
#define OPTION_NOMULT		(OPTION_MD_BASE + 6)
#define OPTION_DIV		(OPTION_MD_BASE + 7)
#define OPTION_NODIV		(OPTION_MD_BASE + 8)
#define OPTION_BITOPS		(OPTION_MD_BASE + 9)
#define OPTION_NOBITOPS		(OPTION_MD_BASE + 10)
#define OPTION_LEADZ		(OPTION_MD_BASE + 11)
#define OPTION_NOLEADZ		(OPTION_MD_BASE + 12)
#define OPTION_ABSDIFF		(OPTION_MD_BASE + 13)
#define OPTION_NOABSDIFF	(OPTION_MD_BASE + 14)
#define OPTION_MINMAX		(OPTION_MD_BASE + 15)
#define OPTION_NOMINMAX		(OPTION_MD_BASE + 16)
#define OPTION_CLIP		(OPTION_MD_BASE + 17)
#define OPTION_NOCLIP		(OPTION_MD_BASE + 18)
#define OPTION_SATUR		(OPTION_MD_BASE + 19)
#define OPTION_NOSATUR		(OPTION_MD_BASE + 20)
#define OPTION_COP32		(OPTION_MD_BASE + 21)
#define OPTION_REPEAT		(OPTION_MD_BASE + 25)
#define OPTION_NOREPEAT		(OPTION_MD_BASE + 26)
#define OPTION_DEBUG		(OPTION_MD_BASE + 27)
#define OPTION_NODEBUG		(OPTION_MD_BASE + 28)
#define OPTION_LIBRARY		(OPTION_MD_BASE + 29)

struct option md_longopts[] = {
  { "EB",          no_argument, NULL, OPTION_EB},
  { "EL",          no_argument, NULL, OPTION_EL},
  { "mconfig",     required_argument, NULL, OPTION_CONFIG},
  { "maverage",    no_argument, NULL, OPTION_AVERAGE},
  { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
  { "mmult",       no_argument, NULL, OPTION_MULT},
  { "mno-mult",    no_argument, NULL, OPTION_NOMULT},
  { "mdiv",        no_argument, NULL, OPTION_DIV},
  { "mno-div",     no_argument, NULL, OPTION_NODIV},
  { "mbitops",     no_argument, NULL, OPTION_BITOPS},
  { "mno-bitops",  no_argument, NULL, OPTION_NOBITOPS},
  { "mleadz",      no_argument, NULL, OPTION_LEADZ},
  { "mno-leadz",   no_argument, NULL, OPTION_NOLEADZ},
  { "mabsdiff",    no_argument, NULL, OPTION_ABSDIFF},
  { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
  { "mminmax",     no_argument, NULL, OPTION_MINMAX},
  { "mno-minmax",  no_argument, NULL, OPTION_NOMINMAX},
  { "mclip",       no_argument, NULL, OPTION_CLIP},
  { "mno-clip",    no_argument, NULL, OPTION_NOCLIP},
  { "msatur",      no_argument, NULL, OPTION_SATUR},
  { "mno-satur",   no_argument, NULL, OPTION_NOSATUR},
  { "mcop32",	   no_argument, NULL, OPTION_COP32},
  { "mdebug",      no_argument, NULL, OPTION_DEBUG},
  { "mno-debug",   no_argument, NULL, OPTION_NODEBUG},
  { "mlibrary",    no_argument, NULL, OPTION_LIBRARY},
  { NULL, 0, NULL, 0 } };
size_t md_longopts_size = sizeof (md_longopts);

const char * md_shortopts = "";
static int optbits = 0;
static int optbitset = 0;

int
md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
{
  int i, idx;
  switch (c)
    {
    case OPTION_EB:
      target_big_endian = 1;
      break;
    case OPTION_EL:
      target_big_endian = 0;
      break;
    case OPTION_CONFIG:
      idx = 0;
      for (i=1; mep_config_map[i].name; i++)
	if (strcmp (mep_config_map[i].name, arg) == 0)
	  {
	    idx = i;
	    break;
	  }
      if (!idx)
	{
	  fprintf (stderr, "Error: unknown configuration %s\n", arg);
	  return 0;
	}
      mep_config_index = idx;
      target_big_endian = mep_config_map[idx].big_endian;
      break;
    case OPTION_AVERAGE:
      optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
      break;
    case OPTION_NOAVERAGE:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
      break;
    case OPTION_MULT:
      optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
      break;
    case OPTION_NOMULT:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
      break;
    case OPTION_DIV:
      optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
      break;
    case OPTION_NODIV:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
      break;
    case OPTION_BITOPS:
      optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
      break;
    case OPTION_NOBITOPS:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
      break;
    case OPTION_LEADZ:
      optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
      break;
    case OPTION_NOLEADZ:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
      break;
    case OPTION_ABSDIFF:
      optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
      break;
    case OPTION_NOABSDIFF:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
      break;
    case OPTION_MINMAX:
      optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
      break;
    case OPTION_NOMINMAX:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
      break;
    case OPTION_CLIP:
      optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
      break;
    case OPTION_NOCLIP:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
      break;
    case OPTION_SATUR:
      optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
      break;
    case OPTION_NOSATUR:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
      break;
    case OPTION_COP32:
      optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
      break;
    case OPTION_DEBUG:
      optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
      break;
    case OPTION_NODEBUG:
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
      break;
    case OPTION_LIBRARY:
      library_flag = EF_MEP_LIBRARY;
      break;
    case OPTION_REPEAT:
    case OPTION_NOREPEAT:
      break;
    default:
      return 0;
    }
  return 1;
}

void
md_show_usage (FILE *stream)
{
  fprintf (stream, _("MeP specific command line options:\n\
  -EB                     assemble for a big endian system (default)\n\
  -EL                     assemble for a little endian system\n\
  -mconfig=<name>         specify a chip configuration to use\n\
  -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
  -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
  -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
                          enable/disable the given opcodes\n\
\n\
  If -mconfig is given, the other -m options modify it.  Otherwise,\n\
  if no -m options are given, all core opcodes are enabled;\n\
  if any enabling -m options are given, only those are enabled;\n\
  if only disabling -m options are given, only those are disabled.\n\
"));
  if (mep_config_map[1].name)
    {
      int i;
      fprintf (stream, "  -mconfig=STR            specify the configuration to use\n");
      fprintf (stream, "  Configurations:");
      for (i=0; mep_config_map[i].name; i++)
	fprintf (stream, " %s", mep_config_map[i].name);
      fprintf (stream, "\n");
    }
}



static void
mep_check_for_disabled_registers (mep_insn *insn)
{
  static int initted = 0;
  static int has_mul_div = 0;
  static int has_cop = 0;
  static int has_debug = 0;
  unsigned int b, r;

  if (allow_disabled_registers)
    return;

#if !CGEN_INT_INSN_P
  if (target_big_endian)
    b = insn->buffer[0] * 256 + insn->buffer[1];
  else
    b = insn->buffer[1] * 256 + insn->buffer[0];
#else
  b = insn->buffer[0];
#endif

  if ((b & 0xfffff00e) == 0x7008 /* stc */
      || (b & 0xfffff00e) == 0x700a /* ldc */)
    {
      if (!initted)
	{
	  initted = 1;
	  if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
	      || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
	    has_mul_div = 1;
	  if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
	    has_debug = 1;
	  if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
	    has_cop = 1;
	}

      r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
      switch (r)
	{
	case 7: /* $hi */
	case 8: /* $lo */
	  if (!has_mul_div)
	    as_bad ("$hi and $lo are disabled when MUL and DIV are off");
	  break;
	case 12: /* $mb0 */
	case 13: /* $me0 */
	case 14: /* $mb1 */
	case 15: /* $me1 */
	  if (!has_cop)
	    as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
	  break;
	case 24: /* $dbg */
	case 25: /* $depc */
	  if (!has_debug)
	    as_bad ("$dbg and $depc are disabled when DEBUG is off");
	  break;
	}
    }
}

static int
mep_machine (void)
{
  switch (MEP_CPU)
    {
    default: break;
    case EF_MEP_CPU_C2: return bfd_mach_mep;
    case EF_MEP_CPU_C3: return bfd_mach_mep;
    case EF_MEP_CPU_C4: return bfd_mach_mep;
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
    }

  return bfd_mach_mep;
}

/* The MeP version of the cgen parse_operand function.  The only difference
   from the standard version is that we want to avoid treating '$foo' and
   '($foo...)' as references to a symbol called '$foo'.  The chances are
   that '$foo' is really a misspelt register.  */

static const char *
mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
		   const char **strP, int opindex, int opinfo,
		   enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
{
  if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
    {
      const char *next;

      next = *strP;
      while (*next == '(')
	next++;
      if (*next == '$')
	return "Not a valid literal";
    }
  return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
				 resultP, valueP);
}

void
md_begin ()
{
  /* Initialize the `cgen' interface.  */

  /* If the user specifies no options, we default to allowing
     everything.  If the user specifies any enabling options, we
     default to allowing only what is specified.  If the user
     specifies only disabling options, we only disable what is
     specified.  If the user specifies options and a config, the
     options modify the config.  */
  if (optbits && mep_config_index == 0)
    MEP_OMASK = optbits;
  else
    MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;

  /* Set the machine number and endian.  */
  gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
					 CGEN_CPU_OPEN_ENDIAN,
					 target_big_endian
					 ? CGEN_ENDIAN_BIG
					 : CGEN_ENDIAN_LITTLE,
					 CGEN_CPU_OPEN_ISAS, 0,
					 CGEN_CPU_OPEN_END);
  mep_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, mep_parse_operand);

  /* Identify the architecture.  */
  bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());

  /* Store the configuration number and core.  */
  bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);

  /* Initialize the array we'll be using to store fixups.  */
  gas_cgen_initialize_saved_fixups_array();
}

/* Variant of mep_cgen_assemble_insn.  Assemble insn STR of cpu CD as a 
   coprocessor instruction, if possible, into FIELDS, BUF, and INSN.  */

static const CGEN_INSN *
mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
			    const char *str,
			    CGEN_FIELDS *fields,
			    CGEN_INSN_BYTES_PTR buf,
			    const struct cgen_insn *pinsn)
{
  const char *start;
  CGEN_INSN_LIST *ilist;
  const char *errmsg = NULL;

  /* The instructions are stored in hashed lists. */
  ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc, 
				CGEN_INSN_MNEMONIC (pinsn));

  start = str;
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    {
      const CGEN_INSN *insn = ilist->insn;
      if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn), 
		  CGEN_INSN_MNEMONIC (pinsn)) == 0
	  && MEP_INSN_COP_P (ilist->insn)
	  && mep_cgen_insn_supported (cd, insn))
	{
	  str = start;

	  /* skip this insn if str doesn't look right lexically */
	  if (CGEN_INSN_RX (insn) != NULL &&
	      regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
	    continue;

	  /* Allow parse/insert handlers to obtain length of insn.  */
	  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);

	  errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
	  if (errmsg != NULL)
	    continue;
	  
	  errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
					      (bfd_vma) 0);
	  if (errmsg != NULL)
	    continue;

	  return insn;
	}
    }
  return pinsn;
}

static void
mep_save_insn (mep_insn insn)
{
  /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
  if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
    {
      as_fatal("index into saved_insns[] out of bounds.");
      return;
    }
  saved_insns[num_insns_saved] = insn;
  gas_cgen_save_fixups(num_insns_saved);
  num_insns_saved++;
}

static void
mep_check_parallel32_scheduling (void)
{
  int insn0iscopro, insn1iscopro, insn0length, insn1length;

  /* More than two instructions means that either someone is referring to
     an internally parallel core or an internally parallel coprocessor,
     neither of which are supported at this time.  */
  if ( num_insns_saved > 2 )
    as_fatal("Internally paralled cores and coprocessors not supported.");

  /* If there are no insns saved, that's ok.  Just return.  This will
     happen when mep_process_saved_insns is called when the end of the
     source file is reached and there are no insns left to be processed.  */
  if (num_insns_saved == 0)
    return;

  /* Check some of the attributes of the first insn.  */
  insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
  insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);

  if (num_insns_saved == 2)
    {
      /* Check some of the attributes of the first insn.  */
      insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
      insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);

      if ((insn0iscopro && !insn1iscopro)
          || (insn1iscopro && !insn0iscopro))
	{
          /* We have one core and one copro insn.  If their sizes
             add up to 32, then the combination is valid.  */
	  if (insn0length + insn1length == 32)
	    return;
          else
	    as_bad ("core and copro insn lengths must total 32 bits.");
	}
      else
        as_bad ("vliw group must consist of 1 core and 1 copro insn."); 
    }
  else
    {
      /* If we arrive here, we have one saved instruction.  There are a
	 number of possible cases:

	 1.  The instruction is a 32 bit core or coprocessor insn and
             can be executed by itself.  Valid.

         2.  The instrucion is a core instruction for which a cop nop
             exists.  In this case, insert the cop nop into the saved
             insn array after the core insn and return.  Valid.

         3.  The instruction is a coprocessor insn for which a core nop
             exists.  In this case, move the coprocessor insn to the
             second element of the array and put the nop in the first
	     element then return.  Valid.

         4. The instruction is a core or coprocessor instruction for
            which there is no matching coprocessor or core nop to use
	    to form a valid vliw insn combination.  In this case, we
	    we have to abort.  */

      if (insn0length > 32)
	as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");

      if (insn0length == 32)
	return;

      /* Insn is smaller than datapath.  If there are no matching
         nops for this insn, then terminate assembly.  */
      if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
                                CGEN_INSN_VLIW32_NO_MATCHING_NOP))
	as_fatal ("No valid nop.");

      /* At this point we know that we have a single 16-bit insn that has 
	 a matching nop.  We have to assemble it and put it into the saved 
         insn and fixup chain arrays. */

      if (insn0iscopro)
	{
          char *errmsg;
          mep_insn insn;
         
          /* Move the insn and it's fixups to the second element of the
             saved insns arrary and insert a 16 bit core nope into the
             first element. */
             insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
                                                 &insn.fields, insn.buffer,
                                                 &errmsg);
             if (!insn.insn)
               {
                 as_bad ("%s", errmsg);
                 return;
               }

             /* Move the insn in element 0 to element 1 and insert the
                 nop into element 0.  Move the fixups in element 0 to
                 element 1 and save the current fixups to element 0.  
                 Really there aren't any fixups at this point because we're
                 inserting a nop but we might as well be general so that
                 if there's ever a need to insert a general insn, we'll
                 have an example. */
              saved_insns[1] = saved_insns[0];
              saved_insns[0] = insn;
              num_insns_saved++;
              gas_cgen_swap_fixups (0);
              gas_cgen_save_fixups (1);
	}
      else
	{
          char * errmsg;
          mep_insn insn;
	  int insn_num = saved_insns[0].insn->base->num;

	  /* Use 32 bit branches and skip the nop.  */
	  if (insn_num == MEP_INSN_BSR12
	      || insn_num == MEP_INSN_BEQZ
	      || insn_num == MEP_INSN_BNEZ)
	    return;

          /* Insert a 16-bit coprocessor nop.  Note that at the time */
          /* this was done, no 16-bit coprocessor nop was defined.   */
	  insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
					      &insn.fields, insn.buffer,
					      &errmsg);
          if (!insn.insn)
            {
              as_bad ("%s", errmsg);
              return;
            }

          /* Now put the insn and fixups into the arrays.  */
          mep_save_insn (insn);
	}
    }
}

static void
mep_check_parallel64_scheduling (void)
{
  int insn0iscopro, insn1iscopro, insn0length, insn1length;

  /* More than two instructions means that someone is referring to an
     internally parallel core or an internally parallel coprocessor.  */
  /* These are not currently supported.  */
  if (num_insns_saved > 2)
    as_fatal ("Internally parallel cores of coprocessors not supported.");

  /* If there are no insns saved, that's ok.  Just return.  This will
     happen when mep_process_saved_insns is called when the end of the
     source file is reached and there are no insns left to be processed.  */
  if (num_insns_saved == 0)
    return;

  /* Check some of the attributes of the first insn.  */
  insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
  insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);

  if (num_insns_saved == 2)
    {
      /* Check some of the attributes of the first insn. */
      insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
      insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);

      if ((insn0iscopro && !insn1iscopro)
	  || (insn1iscopro && !insn0iscopro))
	{
	  /* We have one core and one copro insn.  If their sizes
	     add up to 64, then the combination is valid.  */
	  if (insn0length + insn1length == 64)
            return;
	  else
            as_bad ("core and copro insn lengths must total 64 bits.");
	}
      else
        as_bad ("vliw group must consist of 1 core and 1 copro insn.");
    }
  else
    {
      /* If we arrive here, we have one saved instruction.  There are a
	 number of possible cases:

         1.  The instruction is a 64 bit coprocessor insn and can be
             executed by itself.  Valid.

         2.  The instrucion is a core instruction for which a cop nop
             exists.  In this case, insert the cop nop into the saved
             insn array after the core insn and return.  Valid.

         3.  The instruction is a coprocessor insn for which a core nop
             exists.  In this case, move the coprocessor insn to the
             second element of the array and put the nop in the first
             element then return.  Valid.

         4.  The instruction is a core or coprocessor instruction for
             which there is no matching coprocessor or core nop to use
             to form a valid vliw insn combination.  In this case, we
	     we have to abort.  */

      /* If the insn is 64 bits long, it can run alone.  The size check
	 is done indepependantly of whether the insn is core or copro
	 in case 64 bit coprocessor insns are added later.  */
      if (insn0length == 64)
        return;

      /* Insn is smaller than datapath.  If there are no matching
	 nops for this insn, then terminate assembly.  */
      if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
				CGEN_INSN_VLIW64_NO_MATCHING_NOP))
	as_fatal ("No valid nop.");

      if (insn0iscopro)
	{
	  char *errmsg;
	  mep_insn insn;
          int i;

          /* Initialize the insn buffer.  */
          for (i = 0; i < 64; i++)
             insn.buffer[i] = '\0';

	  /* We have a coprocessor insn.  At this point in time there
	     are is 32-bit core nop.  There is only a 16-bit core
	     nop.  The idea is to allow for a relatively arbitrary
	     coprocessor to be specified.  We aren't looking at
	     trying to cover future changes in the core at this time
	     since it is assumed that the core will remain fairly
	     static.  If there ever are 32 or 48 bit core nops added,
	     they will require entries below.  */

	  if (insn0length == 48)
	    {
	      /* Move the insn and fixups to the second element of the
		 arrays then assemble and insert a 16 bit core nop.  */
	      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
						  & insn.fields, insn.buffer,
						  & errmsg);
	    }
          else
            {
              /* If this is reached, then we have a single coprocessor
                 insn that is not 48 bits long, but for which the assembler
                 thinks there is a matching core nop.  If a 32-bit core
                 nop has been added, then make the necessary changes and
                 handle its assembly and insertion here.  Otherwise,
                 go figure out why either:
              
                 1. The assembler thinks that there is a 32-bit core nop
                    to match a 32-bit coprocessor insn, or
                 2. The assembler thinks that there is a 48-bit core nop
                    to match a 16-bit coprocessor insn.  */

              as_fatal ("Assembler expects a non-existent core nop.");
            }

	 if (!insn.insn)
	   {
	     as_bad ("%s", errmsg);
	     return;
	   }

         /* Move the insn in element 0 to element 1 and insert the
            nop into element 0.  Move the fixups in element 0 to
            element 1 and save the current fixups to element 0. 
	    Really there aren't any fixups at this point because we're
	    inserting a nop but we might as well be general so that
	    if there's ever a need to insert a general insn, we'll
	    have an example. */

         saved_insns[1] = saved_insns[0];
         saved_insns[0] = insn;
         num_insns_saved++;
         gas_cgen_swap_fixups(0);
         gas_cgen_save_fixups(1);

	}
      else
	{
	  char * errmsg;
	  mep_insn insn;
          int i;

          /* Initialize the insn buffer */
          for (i = 0; i < 64; i++)
             insn.buffer[i] = '\0';

	  /* We have a core insn.  We have to handle all possible nop
	     lengths.  If a coprocessor doesn't have a nop of a certain
	     length but there exists core insns that when combined with
	      a nop of that length would fill the datapath, those core
	      insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
	      attribute.  That will ensure that when used in a way that
	      requires a nop to be inserted, assembly will terminate
	      before reaching this section of code.  This guarantees
	      that cases below which would result in the attempted
	      insertion of nop that doesn't exist will never be entered.  */
	  if (insn0length == 16)
	    {
	      /* Insert 48 bit coprocessor nop.          */
	      /* Assemble it and put it into the arrays. */
	      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
						  &insn.fields, insn.buffer,
						  &errmsg);
	    }
	  else if (insn0length == 32)
	    {
	      /* Insert 32 bit coprocessor nop. */
	      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
						  &insn.fields, insn.buffer,
						  &errmsg);
	    }
	  else if (insn0length == 48)
	    {
	      /* Insert 16 bit coprocessor nop. */
	      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
						  &insn.fields, insn.buffer,
						  &errmsg);
	    }
	  else
	    /* Core insn has an invalid length.  Something has gone wrong. */
	    as_fatal ("Core insn has invalid length!  Something is wrong!");

	  if (!insn.insn)
	    {
	      as_bad ("%s", errmsg);
	      return;
	    }

	  /* Now put the insn and fixups into the arrays.  */
	  mep_save_insn (insn);
	}
    }
}

/* The scheduling functions are just filters for invalid combinations.
   If there is a violation, they terminate assembly.  Otherise they
   just fall through.  Succesful combinations cause no side effects
   other than valid nop insertion.  */

static void
mep_check_parallel_scheduling (void)
{
  /* This is where we will eventually read the config information
     and choose which scheduling checking function to call.  */   
  if (MEP_VLIW64)
    mep_check_parallel64_scheduling ();
  else
    mep_check_parallel32_scheduling ();
}

static void
mep_process_saved_insns (void)
{
  int i;

  gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);

  /* We have to check for valid scheduling here. */
  mep_check_parallel_scheduling ();

  /* If the last call didn't cause assembly to terminate, we have
     a valid vliw insn/insn pair saved. Restore this instructions'
     fixups and process the insns. */
  for (i = 0;i<num_insns_saved;i++)
    {
      gas_cgen_restore_fixups (i);
      gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
			    CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
			    1, NULL);
    }
  gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);

  /* Clear the fixups and reset the number insn saved to 0. */
  gas_cgen_initialize_saved_fixups_array ();
  num_insns_saved = 0;
  listing_prev_line ();
}

void
md_assemble (char * str)
{
  static CGEN_BITSET* isas = NULL;
  char * errmsg;

  /* Initialize GAS's cgen interface for a new instruction.  */
  gas_cgen_init_parse ();

  /* There are two possible modes: core and vliw.  We have to assemble
     differently for each.

     Core Mode:  We assemble normally.  All instructions are on a
                 single line and are made up of one mnemonic and one
                 set of operands.
     VLIW Mode:  Vliw combinations are indicated as follows:

		       core insn
		     + copro insn

                 We want to handle the general case where more than
                 one instruction can be preceeded by a +.  This will
                 happen later if we add support for internally parallel
                 coprocessors.  We'll make the parsing nice and general
                 so that it can handle an arbitrary number of insns
                 with leading +'s.  The actual checking for valid
                 combinations is done elsewhere.  */

  /* Initialize the isa to refer to the core.  */
  if (isas == NULL)
    isas = cgen_bitset_copy (& MEP_CORE_ISA);
  else
    {
      cgen_bitset_clear (isas);
      cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
    }
  gas_cgen_cpu_desc->isas = isas;

  if (mode == VLIW)
    {
      /* VLIW mode.  */

      int thisInsnIsCopro = 0;
      mep_insn insn;
      int i;
      
      /* Initialize the insn buffer */
	
      if (! CGEN_INT_INSN_P)
         for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
            insn.buffer[i]='\0';

      /* Can't tell core / copro insns apart at parse time! */
      cgen_bitset_union (isas, & MEP_COP_ISA, isas);

      /* Assemble the insn so we can examine its attributes. */
      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
					  &insn.fields, insn.buffer,
					  &errmsg);
      if (!insn.insn)
	{
	  as_bad ("%s", errmsg);
	  return;
	}
      mep_check_for_disabled_registers (&insn);

      /* Check to see if it's a coprocessor instruction. */
      thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);

      if (!thisInsnIsCopro)
	{
	  insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
						  &insn.fields, insn.buffer,
						  insn.insn);
	  thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
	  mep_check_for_disabled_registers (&insn);
	}

      if (pluspresent)
	{
	  /* A plus was present. */
	  /* Check for a + with a core insn and abort if found. */
	  if (!thisInsnIsCopro)
	    {
	      as_fatal("A core insn cannot be preceeded by a +.\n");
	      return;
	    }

	  if (num_insns_saved > 0)
	    {
	      /* There are insns in the queue. Add this one. */
	      mep_save_insn (insn);
	    }
	  else
	    {
	      /* There are no insns in the queue and a plus is present.
		 This is a syntax error.  Let's not tolerate this.
		 We can relax this later if necessary.  */
	      as_bad (_("Invalid use of parallelization operator."));
	      return;
	    }
	}
      else
	{
	  /* No plus was present. */
	  if (num_insns_saved > 0)
	    {
	      /* There are insns saved and we came across an insn without a
		 leading +.  That's the signal to process the saved insns
		 before proceeding then treat the current insn as the first
		 in a new vliw group.  */
	      mep_process_saved_insns ();
	      num_insns_saved = 0;
	      /* mep_save_insn (insn); */
	    }
	  mep_save_insn (insn);
#if 0
	  else
	    {

              /* Core Insn. Add it to the beginning of the queue. */
              mep_save_insn (insn);
	      /* gas_cgen_save_fixups(num_insns_saved); */
	    }
#endif
	}

      pluspresent = 0;
    }
  else
    {
      /* Core mode.  */

      /* Only single instructions are assembled in core mode. */
      mep_insn insn;

      /* If a leading '+' was present, issue an error.
	 That's not allowed in core mode. */
      if (pluspresent)
	{
	  as_bad (_("Leading plus sign not allowed in core mode"));
	  return;
	}

      insn.insn = mep_cgen_assemble_insn
	(gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);

      if (!insn.insn)
	{
	  as_bad ("%s", errmsg);
	  return;
	}
      gas_cgen_finish_insn (insn.insn, insn.buffer,
			    CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
      mep_check_for_disabled_registers (&insn);
    }
}

valueT
md_section_align (segT segment, valueT size)
{
  int align = bfd_get_section_alignment (stdoutput, segment);
  return ((size + (1 << align) - 1) & (-1 << align));
}


symbolS *
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
{
  return 0;
}

/* Interface to relax_segment.  */


const relax_typeS md_relax_table[] =
{
  /* The fields are:
     1) most positive reach of this state,
     2) most negative reach of this state,
     3) how many bytes this mode will have in the variable part of the frag
     4) which index into the table to try if we can't fit into this one.  */
  /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
     jump to addresses with any bits 27..24 set.  So, we use beq as a
     17-bit pc-relative branch to avoid using jmp, just in case.  */

  /* 0 */ {     0,      0, 0, 0 }, /* unused */
  /* 1 */ {     0,      0, 0, 0 }, /* marker for "don't know yet" */

  /* 2 */ {  2047,  -2048, 0, 3 }, /* bsr12 */
  /* 3 */ {     0,      0, 2, 0 }, /* bsr16 */

  /* 4 */ {  2047,  -2048, 0, 5 }, /* bra */
  /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
  /* 6 */ {     0,      0, 2, 0 }, /* jmp24 */

  /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
  /* 8 */ {     0,      0, 4, 0 }, /* bnei/jmp */

  /* 9 */  {   127,   -128, 0, 10 }, /* beqz */
  /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
  /* 11 */ {     0,      0, 4,  0 }, /* bnei/jmp */

  /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
  /* 13 */ {     0,      0, 4,  0 }, /* beqi/jmp */

  /* 14 */ {   127,   -128, 0, 15 }, /* bnez */
  /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
  /* 16 */ {     0,      0, 4,  0 },  /* beqi/jmp */

  /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
  /* 18 */ {     0,      0, 4,  0 },
  /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
  /* 20 */ {     0,      0, 4,  0 },
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
  /* 20 */ {     0,      0, 4,  0 },
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
  /* 20 */ {     0,      0, 4,  0 },
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
  /* 20 */ {     0,      0, 4,  0 },
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
  /* 20 */ {     0,      0, 4,  0 }
};

/* Pseudo-values for 64 bit "insns" which are combinations of two 32
   bit insns.  */
typedef enum {
  MEP_PSEUDO64_NONE,
  MEP_PSEUDO64_16BITCC,
  MEP_PSEUDO64_32BITCC,
} MepPseudo64Values;

static struct {
  int insn;
  int growth;
  int insn_for_extern;
} subtype_mappings[] = {
  { 0, 0, 0 },
  { 0, 0, 0 },
  { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
  { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
  { MEP_INSN_BRA,   0, MEP_INSN_BRA   },
  { MEP_INSN_BEQ,   2, MEP_INSN_BEQ   },
  { MEP_INSN_JMP,   2, MEP_INSN_JMP   },
  { MEP_INSN_BEQI,  0, MEP_INSN_BEQI  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BEQZ,  0, MEP_INSN_BEQZ  },
  { MEP_INSN_BEQI,  2, MEP_INSN_BEQI  },
  { -1,             4, MEP_PSEUDO64_16BITCC },
  { MEP_INSN_BNEI,  0, MEP_INSN_BNEI  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BNEZ,  0, MEP_INSN_BNEZ  },
  { MEP_INSN_BNEI,  2, MEP_INSN_BNEI  },
  { -1,             4, MEP_PSEUDO64_16BITCC },
  { MEP_INSN_BGEI,  0, MEP_INSN_BGEI  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BLTI,  0, MEP_INSN_BLTI  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT  },
  { -1,             4, MEP_PSEUDO64_32BITCC },
  { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF  },
  { -1,             4, MEP_PSEUDO64_32BITCC }
};
#define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))

void
mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
{
  symbolS *symbolP = fragP->fr_symbol;
  if (symbolP && !S_IS_DEFINED (symbolP))
    *aim = 0;
  /* Adjust for MeP pcrel not being relative to the next opcode.  */
  *aim += 2 + md_relax_table[this_state].rlx_length;
}

static int
insn_to_subtype (int insn)
{
  unsigned int i;
  for (i=0; i<NUM_MAPPINGS; i++)
    if (insn == subtype_mappings[i].insn)
      return i;
  abort ();
}

/* 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
   and 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 (fragS * fragP, segT segment)
{
  if (fragP->fr_subtype == 1)
    fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);

  if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
    {
      int new_insn;

      new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
      fragP->fr_subtype = insn_to_subtype (new_insn);
    }

  if (MEP_VLIW && ! MEP_VLIW64
      && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
    {
      /* Use 32 bit branches for vliw32 so the vliw word is not split.  */
      switch (fragP->fr_cgen.insn->base->num)
	{
	case MEP_INSN_BSR12:
	  fragP->fr_subtype = insn_to_subtype 
	    (subtype_mappings[fragP->fr_subtype].insn_for_extern);
	  break;
	case MEP_INSN_BEQZ:
	  fragP->fr_subtype ++;
	  break;
	case MEP_INSN_BNEZ:
	  fragP->fr_subtype ++;
	  break;
	}
    }

  if (fragP->fr_cgen.insn->base
      && fragP->fr_cgen.insn->base->num
         != subtype_mappings[fragP->fr_subtype].insn)
    {
      int new_insn= subtype_mappings[fragP->fr_subtype].insn;
      if (new_insn != -1)
	{
	  fragP->fr_cgen.insn = (fragP->fr_cgen.insn
				 - fragP->fr_cgen.insn->base->num
				 + new_insn);
	}
    }

  return subtype_mappings[fragP->fr_subtype].growth;
}

/* *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.  */

static int
target_address_for (fragS *frag)
{
  int rv = frag->fr_offset;
  symbolS *sym = frag->fr_symbol;

  if (sym)
    rv += S_GET_VALUE (sym);

  return rv;
}

void
md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED, 
		 segT sec ATTRIBUTE_UNUSED,
		 fragS *fragP)
{
  int addend, rn, bit = 0;
  int operand;
  int where = fragP->fr_opcode - fragP->fr_literal;
  int e = target_big_endian ? 0 : 1;

  addend = target_address_for (fragP) - (fragP->fr_address + where);

  if (subtype_mappings[fragP->fr_subtype].insn == -1)
    {
      fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
      switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
	{
	case MEP_PSEUDO64_16BITCC:
	  fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
	  fragP->fr_opcode[2^e] = 0xd8;
	  fragP->fr_opcode[3^e] = 0x08;
	  fragP->fr_opcode[4^e] = 0;
	  fragP->fr_opcode[5^e] = 0;
	  where += 2;
	  break;
	case MEP_PSEUDO64_32BITCC:
	  if (fragP->fr_opcode[0^e] & 0x10)
	    fragP->fr_opcode[1^e] ^= 0x01;
	  else
	    fragP->fr_opcode[1^e] ^= 0x04;
	  fragP->fr_opcode[2^e] = 0;
	  fragP->fr_opcode[3^e] = 4;
	  fragP->fr_opcode[4^e] = 0xd8;
	  fragP->fr_opcode[5^e] = 0x08;
	  fragP->fr_opcode[6^e] = 0;
	  fragP->fr_opcode[7^e] = 0;
	  where += 4;
	  break;
	default:
	  abort ();
	}
      fragP->fr_cgen.insn = (fragP->fr_cgen.insn
			     - fragP->fr_cgen.insn->base->num
			     + MEP_INSN_JMP);
      operand = MEP_OPERAND_PCABS24A2;
    }
  else
    switch (fragP->fr_cgen.insn->base->num)
      {
      case MEP_INSN_BSR12:
	fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
	fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
	operand = MEP_OPERAND_PCREL12A2;
	break;

      case MEP_INSN_BSR24:
	fragP->fr_fix += 2;
	fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
	fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
	fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
	fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
	operand = MEP_OPERAND_PCREL24A2;
	break;

      case MEP_INSN_BRA:
	fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
	fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
	operand = MEP_OPERAND_PCREL12A2;
	break;

      case MEP_INSN_BEQ:
	/* The default relax_frag doesn't change the state if there is no
	   growth, so we must manually handle converting out-of-range BEQ
	   instructions to JMP.  */
	if (addend <= 65535 && addend >= -65536)
	  {
	    fragP->fr_fix += 2;
	    fragP->fr_opcode[0^e] = 0xe0;
	    fragP->fr_opcode[1^e] = 0x01;
	    fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
	    fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
	    operand = MEP_OPERAND_PCREL17A2;
	    break;
	  }
	/* ...FALLTHROUGH... */

      case MEP_INSN_JMP:
	addend = target_address_for (fragP);
	fragP->fr_fix += 2;
	fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
	fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
	fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
	fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
	operand = MEP_OPERAND_PCABS24A2;
	break;

      case MEP_INSN_BNEZ:
	bit = 1;
      case MEP_INSN_BEQZ:
	fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
	operand = MEP_OPERAND_PCREL8A2;
	break;

      case MEP_INSN_BNEI:
	bit = 4;
      case MEP_INSN_BEQI:
	if (subtype_mappings[fragP->fr_subtype].growth)
	  {
	    fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
	    rn = fragP->fr_opcode[0^e] & 0x0f;
	    fragP->fr_opcode[0^e] = 0xe0 | rn;
	    fragP->fr_opcode[1^e] = bit;
	  }
	fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
	fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
	operand = MEP_OPERAND_PCREL17A2;
	break;

      case MEP_INSN_BLTI:
      case MEP_INSN_BGEI:
      case MEP_INSN_BCPEQ:
      case MEP_INSN_BCPNE:
      case MEP_INSN_BCPAT:
      case MEP_INSN_BCPAF:
	/* No opcode change needed, just operand.  */
	fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
	fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
	operand = MEP_OPERAND_PCREL17A2;
	break;

      default:
	abort ();
      }

  if (S_GET_SEGMENT (fragP->fr_symbol) != sec
      || operand == MEP_OPERAND_PCABS24A2)
    {
      assert (fragP->fr_cgen.insn != 0);
      gas_cgen_record_fixup (fragP,
			     where,
			     fragP->fr_cgen.insn,
			     (fragP->fr_fix - where) * 8,
			     cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
							 operand),
			     fragP->fr_cgen.opinfo,
			     fragP->fr_symbol, fragP->fr_offset);
    }
}


/* Functions concerning relocs.  */

void
mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
  /* If we already know the fixup value, adjust it in the same
     way that the linker would have done.  */
  if (fixP->fx_addsy == 0)
    switch (fixP->fx_cgen.opinfo)
      {
      case BFD_RELOC_MEP_LOW16:
	*valP = ((long)(*valP & 0xffff)) << 16 >> 16;
	break;
      case BFD_RELOC_MEP_HI16U:
	*valP >>= 16;
	break;
      case BFD_RELOC_MEP_HI16S:
	*valP = (*valP + 0x8000) >> 16;
	break;
      }

  /* Now call cgen's md_aply_fix.  */
  gas_cgen_md_apply_fix (fixP, valP, seg);
}

long
md_pcrel_from_section (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 the address of the opcode - cgen adjusts for opcode size
     itself, to be consistent with the disassembler, which must do
     so.  */
  return fixP->fx_where + fixP->fx_frag->fr_address;
}

/* 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.  */

#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
#define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
#else
#define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n;
#endif

bfd_reloc_code_real_type
md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
		      const CGEN_OPERAND *operand,
		      fixS *fixP)
{
  enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
  static char printed[MEP_OPERAND_MAX] = { 0 };

  /* If there's a reloc here, it's because the parser saw a %foo() and
     is giving us the correct reloc to use, or because we converted to
     a different size reloc below and want to avoid "converting" more
     than once.  */
  if (reloc && reloc != BFD_RELOC_NONE)
    return reloc;

  switch (operand->type)
    {
      MAP (PCREL8A2);	/* beqz */
      MAP (PCREL12A2);	/* bsr16 */
      MAP (PCREL17A2);	/* beqi */
      MAP (PCREL24A2);	/* bsr24 */
      MAP (PCABS24A2);	/* jmp */
      MAP (UIMM24);	/* mov */
      MAP (ADDR24A4);	/* sw/lw */

    /* The rest of the relocs should be generated by the parser,
       for things such as %tprel(), etc. */
    case MEP_OPERAND_SIMM16:
#ifdef OBJ_COMPLEX_RELC
      /* coalescing this into RELOC_MEP_16 is actually a bug,
	 since it's a signed operand. let the relc code handle it. */
      return BFD_RELOC_RELC; 
#endif

    case MEP_OPERAND_UIMM16:
    case MEP_OPERAND_SDISP16:
    case MEP_OPERAND_CODE16:
      fixP->fx_where += 2;
      /* to avoid doing the above add twice */
      fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
      return BFD_RELOC_MEP_16;

    default:
#ifdef OBJ_COMPLEX_RELC
      /* this is not an error, yet. 
	 pass it to the linker. */
      return BFD_RELOC_RELC;
#endif
      if (printed[operand->type])
	return BFD_RELOC_NONE;
      printed[operand->type] = 1;

      as_bad_where (fixP->fx_file, fixP->fx_line,
		    _("Don't know how to relocate plain operands of type %s"),
		    operand->name);

      /* Print some helpful hints for the user.  */
      switch (operand->type)
	{
	case MEP_OPERAND_UDISP7:
	case MEP_OPERAND_UDISP7A2:
	case MEP_OPERAND_UDISP7A4:
	  as_bad_where (fixP->fx_file, fixP->fx_line,
			_("Perhaps you are missing %%tpoff()?"));
	  break;
	default:
	  break;
	}
      return BFD_RELOC_NONE;
    }
}

/* Called while parsing an instruction to create a fixup.
   We need to check for HI16 relocs and queue them up for later sorting.  */

fixS *
mep_cgen_record_fixup_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);
  return fixP;
}

/* Return BFD reloc type from opinfo field in a fixS.
   It's tricky using fx_r_type in mep_frob_file because the values
   are BFD_RELOC_UNUSED + operand number.  */
#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)

/* Sort any unmatched HI16 relocs so that they immediately precede
   the corresponding LO16 reloc.  This is called before md_apply_fix and
   tc_gen_reloc.  */

void
mep_frob_file ()
{
  struct mep_hi_fixup * l;

  for (l = mep_hi_fixup_list; l != NULL; l = l->next)
    {
      segment_info_type * seginfo;
      int pass;

      assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
	      || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);

      /* Check quickly whether the next fixup happens to be a matching low.  */
      if (l->fixp->fx_next != NULL
	  && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
	  && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
	  && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
	continue;

      /* Look through the fixups for this segment for a matching
         `low'.  When we find one, move the high just in front of it.
         We do this in two passes.  In the first pass, we try to find
         a unique `low'.  In the second pass, we permit multiple
         high's relocs for a single `low'.  */
      seginfo = seg_info (l->seg);
      for (pass = 0; pass < 2; pass++)
	{
	  fixS * f;
	  fixS * prev;

	  prev = NULL;
	  for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
	    {
	      /* Check whether this is a `low' fixup which matches l->fixp.  */
	      if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
		  && f->fx_addsy == l->fixp->fx_addsy
		  && f->fx_offset == l->fixp->fx_offset
		  && (pass == 1
		      || prev == NULL
		      || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
		      || prev->fx_addsy != f->fx_addsy
		      || prev->fx_offset !=  f->fx_offset))
		{
		  fixS ** pf;

		  /* Move l->fixp before f.  */
		  for (pf = &seginfo->fix_root;
		       * pf != l->fixp;
		       pf = & (* pf)->fx_next)
		    assert (* pf != NULL);

		  * pf = l->fixp->fx_next;

		  l->fixp->fx_next = f;
		  if (prev == NULL)
		    seginfo->fix_root = l->fixp;
		  else
		    prev->fx_next = l->fixp;

		  break;
		}

	      prev = f;
	    }

	  if (f != NULL)
	    break;

	  if (pass == 1)
	    as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
			   _("Unmatched high relocation"));
	}
    }
}

/* See whether we need to force a relocation into the output file. */

int
mep_force_relocation (fixS *fixp)
{
  if (   fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
	 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    return 1;

  /* Allow branches to global symbols to be resolved at assembly time.
     This is consistent with way relaxable branches are handled, since
     branches to both global and local symbols are relaxed.  It also
     corresponds to the assumptions made in md_pcrel_from_section.  */
  return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
}

/* Write a value out to the object file, using the appropriate endianness.  */

void
md_number_to_chars (char *buf, valueT val, int n)
{
  if (target_big_endian)
    number_to_chars_bigendian (buf, val, n);
  else
    number_to_chars_littleendian (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 (int type, char *litP, int *sizeP)
{
  int              i;
  int              prec;
  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
  char *           t;

  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;
}


bfd_boolean
mep_fix_adjustable (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_EXTERNAL (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)
    return 0;

  return 1;
}

int
mep_elf_section_letter (int letter, char **ptrmsg)
{
  if (letter == 'v')
    return SHF_MEP_VLIW;

  *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
  return 0;
}

flagword
mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
{
  if (attr & SHF_MEP_VLIW)
    flags |= SEC_MEP_VLIW;
  return flags;
}

/* In vliw mode, the default section is .vtext.  We have to be able
   to switch into .vtext using only the .vtext directive.  */

static segT
mep_vtext_section (void)
{
  static segT vtext_section;

  if (! vtext_section)
    {
      flagword applicable = bfd_applicable_section_flags (stdoutput);
      vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
      bfd_set_section_flags (stdoutput, vtext_section,
			     applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
					   | SEC_CODE | SEC_READONLY
					   | SEC_MEP_VLIW));
    }

  return vtext_section;
}

static void
mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
{
  int temp;

  /* Record previous_section and previous_subsection.  */
  obj_elf_section_change_hook ();

  temp = get_absolute_expression ();
  subseg_set (mep_vtext_section (), (subsegT) temp);
  demand_empty_rest_of_line ();
}

static void
mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
{
  mep_process_saved_insns ();
  pluspresent = 0;
  mode = CORE;
}

static void
mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
{
  if (! MEP_VLIW)
    as_bad (_(".vliw unavailable when VLIW is disabled."));
  mode = VLIW;
  /* Switch into .vtext here too. */
  /* mep_s_vtext(); */
}

/* This is an undocumented pseudo-op used to disable gas's
   "disabled_registers" check.  Used for code which checks for those
   registers at runtime.  */
static void
mep_noregerr (int i ATTRIBUTE_UNUSED)
{
  allow_disabled_registers = 1;
}

/* mep_unrecognized_line: This is called when a line that can't be parsed
   is encountered.  We use it to check for a leading '+' sign which indicates
   that the current instruction is a coprocessor instruction that is to be
   parallelized with a previous core insn.  This function accepts the '+' and
   rejects all other characters that might indicate garbage at the beginning
   of the line.  The '+' character gets lost as the calling loop continues,
   so we need to indicate that we saw it.  */

int
mep_unrecognized_line (int ch)
{
  switch (ch)
    {
    case '+':
      pluspresent = 1;
      return 1; /* '+' indicates an instruction to be parallelized. */
    default:
      return 0; /* If it's not a '+', the line can't be parsed. */
    }
}

void
mep_cleanup (void)
{
  /* Take care of any insns left to be parallelized when the file ends.
     This is mainly here to handle the case where the file ends with an
     insn preceeded by a + or the file ends unexpectedly.  */
  if (mode == VLIW)
    mep_process_saved_insns ();
}

int
mep_flush_pending_output (void)
{
  if (mode == VLIW)
    {
      mep_process_saved_insns ();
      pluspresent = 0;
    }

  return 1; 
}

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