diff -urN binutils-2.10.org/bfd/archures.c binutils-2.10/bfd/archures.c --- binutils-2.10.org/bfd/archures.c 2000-03-27 00:39:12.000000000 -0800 +++ binutils-2.10/bfd/archures.c 2011-03-20 03:53:01.000000000 -0700 @@ -186,6 +186,9 @@ .#define bfd_mach_v850 0 .#define bfd_mach_v850e 'E' .#define bfd_mach_v850ea 'A' +. bfd_arch_v810, {* NEC V810 *} +.#define bfd_mach_v810 0 +.#define bfd_mach_v830 3 . bfd_arch_arc, {* Argonaut RISC Core *} .#define bfd_mach_arc_base 0 . bfd_arch_m32r, {* Mitsubishi M32R/D *} @@ -274,6 +277,7 @@ extern const bfd_arch_info_type bfd_ns32k_arch; extern const bfd_arch_info_type bfd_w65_arch; extern const bfd_arch_info_type bfd_v850_arch; +extern const bfd_arch_info_type bfd_v810_arch; extern const bfd_arch_info_type bfd_fr30_arch; extern const bfd_arch_info_type bfd_mcore_arch; extern const bfd_arch_info_type bfd_avr_arch; @@ -314,6 +318,7 @@ &bfd_ns32k_arch, &bfd_w65_arch, &bfd_v850_arch, + &bfd_v810_arch, &bfd_fr30_arch, &bfd_mcore_arch, &bfd_avr_arch, diff -urN binutils-2.10.org/bfd/bfd-in2.h binutils-2.10/bfd/bfd-in2.h --- binutils-2.10.org/bfd/bfd-in2.h 2000-04-28 18:45:48.000000000 -0700 +++ binutils-2.10/bfd/bfd-in2.h 2011-03-20 03:53:01.000000000 -0700 @@ -1402,6 +1402,9 @@ #define bfd_mach_v850 0 #define bfd_mach_v850e 'E' #define bfd_mach_v850ea 'A' + bfd_arch_v810, /* NEC V810 */ +#define bfd_mach_v810 0 +#define bfd_mach_v830 3 bfd_arch_arc, /* Argonaut RISC Core */ #define bfd_mach_arc_base 0 bfd_arch_m32r, /* Mitsubishi M32R/D */ @@ -2256,6 +2259,27 @@ BFD_RELOC_V850_CALLT_16_16_OFFSET, +/* This is a 9-bit reloc */ + BFD_RELOC_V810_9_PCREL, + +/* This is a 26-bit reloc */ + BFD_RELOC_V810_26_PCREL, + +/* This is a 16 bit offset from the short data area pointer. */ + BFD_RELOC_V810_SDA_16_16_OFFSET, + +/* This is a 16 bit offset (of which only 15 bits are used) from the +short data area pointer. */ + BFD_RELOC_V810_SDA_15_16_OFFSET, + +/* This is a 16 bit offset from the zero data area pointer. */ + BFD_RELOC_V810_ZDA_16_16_OFFSET, + +/* This is a 16 bit offset (of which only 15 bits are used) from the +zero data area pointer. */ + BFD_RELOC_V810_ZDA_15_16_OFFSET, + + /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_32_PCREL, diff -urN binutils-2.10.org/bfd/config.bfd binutils-2.10/bfd/config.bfd --- binutils-2.10.org/bfd/config.bfd 2000-05-13 05:23:45.000000000 -0700 +++ binutils-2.10/bfd/config.bfd 2011-03-20 03:53:01.000000000 -0700 @@ -43,6 +43,7 @@ powerpc*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;; rs6000) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;; sparc*) targ_archs=bfd_sparc_arch ;; +v810*) targ_archs=bfd_v810_arch ;; v850*) targ_archs=bfd_v850_arch ;; z8k*) targ_archs=bfd_z8k_arch ;; *) targ_archs=bfd_${targ_cpu}_arch ;; @@ -759,6 +760,13 @@ ;; + v810-*-*) + targ_defvec=bfd_elf32_v810_vec + ;; + v830-*-*) + targ_defvec=bfd_elf32_v810_vec + ;; + v850-*-*) targ_defvec=bfd_elf32_v850_vec ;; diff -urN binutils-2.10.org/bfd/configure binutils-2.10/bfd/configure --- binutils-2.10.org/bfd/configure 2000-06-01 13:09:06.000000000 -0700 +++ binutils-2.10/bfd/configure 2011-03-20 03:53:01.000000000 -0700 @@ -5110,6 +5110,7 @@ bfd_elf32_sh_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo" ;; bfd_elf32_shl_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo" ;; bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elf32.lo $elf" ;; + bfd_elf32_v810_vec) tb="$tb elf32-v810.lo elf32.lo $elf" ;; bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;; bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf" target64=true ;; diff -urN binutils-2.10.org/bfd/configure.in binutils-2.10/bfd/configure.in --- binutils-2.10.org/bfd/configure.in 2000-06-01 13:09:07.000000000 -0700 +++ binutils-2.10/bfd/configure.in 2011-03-20 03:53:01.000000000 -0700 @@ -477,6 +477,7 @@ bfd_elf32_sh_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo" ;; bfd_elf32_shl_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo" ;; bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elf32.lo $elf" ;; + bfd_elf32_v810_vec) tb="$tb elf32-v810.lo elf32.lo $elf" ;; bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;; bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf" target64=true ;; diff -urN binutils-2.10.org/bfd/cpu-v810.c binutils-2.10/bfd/cpu-v810.c --- binutils-2.10.org/bfd/cpu-v810.c 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/bfd/cpu-v810.c 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,101 @@ +/* BFD support for the NEC V810 processor + Copyright 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#include + +static boolean +scan (info, string) + const struct bfd_arch_info * info; + const char * string; +{ + const char *ptr_src; + const char *ptr_tst; + unsigned long number; + enum bfd_architecture arch; + + /* First test for an exact match */ + if (strcasecmp (string, info->printable_name) == 0) + return true; + + /* See how much of the supplied string matches with the + architecture, eg the string m68k:68020 would match the m68k entry + up to the :, then we get left with the machine number */ + + for (ptr_src = string, ptr_tst = info->arch_name; + *ptr_src && *ptr_tst; + ptr_src++, ptr_tst++) + { + if (*ptr_src != *ptr_tst) break; + } + + /* Chewed up as much of the architecture as will match, skip any + colons */ + if (*ptr_src == ':') + ptr_src++; + + if (*ptr_src == 0) + { + /* nothing more, then only keep this one if it is the default + machine for this architecture */ + return info->the_default; + } + + number = 0; + while (isdigit ((unsigned char) *ptr_src)) + { + number = number * 10 + * ptr_src - '0'; + ptr_src++; + } + + switch (number) + { + case bfd_mach_v830: arch = bfd_arch_v810; break; + default: + return false; + } + + if (arch != info->arch) + return false; + + if (number != info->mach) + return false; + + return true; +} + +#define N(number, print, default, next) \ +{ 32, 32, 8, bfd_arch_v810, number, "v810", print, 2, default, \ + bfd_default_compatible, scan, next } + +#define NEXT NULL + +static const bfd_arch_info_type arch_info_struct[] = +{ + N (bfd_mach_v830, "v830", false, NULL) +}; + +#undef NEXT +#define NEXT &arch_info_struct[0] + +const bfd_arch_info_type bfd_v810_arch = + N (bfd_mach_v810, "v810", true, NEXT); diff -urN binutils-2.10.org/bfd/elf32-v810.c binutils-2.10/bfd/elf32-v810.c --- binutils-2.10.org/bfd/elf32-v810.c 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/bfd/elf32-v810.c 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,1811 @@ +/* V810-specific support for 32-bit ELF + Copyright (C) 1996, 1997, 1998, 1999 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. */ + + + +/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char + dependencies. As is the gas & simulator code or the v810. */ + + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/v810.h" + +static reloc_howto_type *v810_elf_reloc_type_lookup + PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); +static void v810_elf_info_to_howto_rel + PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *)); +static void v810_elf_info_to_howto_rela + PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); +static bfd_reloc_status_type v810_elf_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static boolean v810_elf_is_local_label_name + PARAMS ((bfd *, const char *)); +static boolean v810_elf_relocate_section + PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); +static bfd_reloc_status_type v810_elf_perform_relocation + PARAMS ((bfd *, int, bfd_vma, bfd_byte *)); +static boolean v810_elf_check_relocs + PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); +static void remember_hi16s_reloc + PARAMS ((bfd *, bfd_vma, bfd_byte *)); +static bfd_byte * find_remembered_hi16s_reloc + PARAMS ((bfd_vma, boolean *)); +static bfd_reloc_status_type v810_elf_final_link_relocate + PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, + bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int)); +static boolean v810_elf_object_p + PARAMS ((bfd *)); +static boolean v810_elf_fake_sections + PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); +static void v810_elf_final_write_processing + PARAMS ((bfd *, boolean)); +static boolean v810_elf_set_private_flags + PARAMS ((bfd *, flagword)); +static boolean v810_elf_copy_private_bfd_data + PARAMS ((bfd *, bfd *)); +static boolean v810_elf_merge_private_bfd_data + PARAMS ((bfd *, bfd *)); +static boolean v810_elf_print_private_bfd_data + PARAMS ((bfd *, PTR)); +static boolean v810_elf_section_from_bfd_section + PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *)); +static void v810_elf_symbol_processing + PARAMS ((bfd *, asymbol *)); +static boolean v810_elf_add_symbol_hook + PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, + const char **, flagword *, asection **, bfd_vma *)); +static boolean v810_elf_link_output_symbol_hook + PARAMS ((bfd *, struct bfd_link_info *, const char *, + Elf_Internal_Sym *, asection *)); +static boolean v810_elf_section_from_shdr + PARAMS ((bfd *, Elf_Internal_Shdr *, char *)); + +/* Note: It is REQUIRED that the 'type' value of each entry in this array + match the index of the entry in the array. */ +static reloc_howto_type v810_elf_howto_table[] = +{ + /* This reloc does nothing. */ + HOWTO (R_V810_NONE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_V810_NONE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* A PC relative 9 bit branch. */ + HOWTO (R_V810_9_PCREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 26, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_9_PCREL", /* name */ + false, /* partial_inplace */ + 0x00ffffff, /* src_mask */ + 0x00ffffff, /* dst_mask */ + true), /* pcrel_offset */ + + /* A PC relative 26 bit branch. */ + HOWTO (R_V810_26_PCREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 26, /* bitsize */ + true, /* pc_relative */ + 7, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_26_PCREL", /* name */ + false, /* partial_inplace */ + 0x03ffffff, /* src_mask */ + 0x03ffffff, /* dst_mask */ + true), /* pcrel_offset */ + + /* High 16 bits of symbol value. */ + HOWTO (R_V810_HI16_S, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_HI16_S", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* High 16 bits of symbol value. */ + HOWTO (R_V810_HI16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_HI16", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Low 16 bits of symbol value. */ + HOWTO (R_V810_LO16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_LO16", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Simple 32bit reloc. */ + HOWTO (R_V810_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_32", /* name */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Simple 16bit reloc. */ + HOWTO (R_V810_16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_V810_16", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Simple 8bit reloc. */ + HOWTO (R_V810_8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_V810_8", /* name */ + false, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + false), /* pcrel_offset */ + + /* 16 bit offset from the short data area pointer. */ + HOWTO (R_V810_SDA_16_16_OFFSET, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_SDA_16_16_OFFSET", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* 15 bit offset from the short data area pointer. */ + HOWTO (R_V810_SDA_15_16_OFFSET, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_SDA_15_16_OFFSET", /* name */ + false, /* partial_inplace */ + 0xfffe, /* src_mask */ + 0xfffe, /* dst_mask */ + false), /* pcrel_offset */ + + /* 16 bit offset from the zero data area pointer. */ + HOWTO (R_V810_ZDA_16_16_OFFSET, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_ZDA_16_16_OFFSET", /* name */ + false, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* 15 bit offset from the zero data area pointer. */ + HOWTO (R_V810_ZDA_15_16_OFFSET, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + v810_elf_reloc, /* special_function */ + "R_V810_ZDA_15_16_OFFSET", /* name */ + false, /* partial_inplace */ + 0xfffe, /* src_mask */ + 0xfffe, /* dst_mask */ + false), /* pcrel_offset */ + + /* GNU extension to record C++ vtable hierarchy */ + HOWTO (R_V810_GNU_VTINHERIT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_V810_GNU_VTINHERIT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* GNU extension to record C++ vtable member usage */ + HOWTO (R_V810_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_V810_GNU_VTENTRY", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + +}; + +/* Map BFD reloc types to V810 ELF reloc types. */ + +struct v810_elf_reloc_map +{ + /* BFD_RELOC_V810_CALLT_16_16_OFFSET is 258, which will not fix in an + unsigned char. */ + bfd_reloc_code_real_type bfd_reloc_val; + unsigned char elf_reloc_val; +}; + +static const struct v810_elf_reloc_map v810_elf_reloc_map[] = +{ + { BFD_RELOC_NONE, R_V810_NONE }, + { BFD_RELOC_V810_9_PCREL, R_V810_9_PCREL }, + { BFD_RELOC_V810_26_PCREL, R_V810_26_PCREL }, + { BFD_RELOC_HI16_S, R_V810_HI16_S }, + { BFD_RELOC_HI16, R_V810_HI16 }, + { BFD_RELOC_LO16, R_V810_LO16 }, + { BFD_RELOC_32, R_V810_32 }, + { BFD_RELOC_16, R_V810_16 }, + { BFD_RELOC_8, R_V810_8 }, + { BFD_RELOC_V810_SDA_16_16_OFFSET, R_V810_SDA_16_16_OFFSET }, + { BFD_RELOC_V810_SDA_15_16_OFFSET, R_V810_SDA_15_16_OFFSET }, + { BFD_RELOC_V810_ZDA_16_16_OFFSET, R_V810_ZDA_16_16_OFFSET }, + { BFD_RELOC_V810_ZDA_15_16_OFFSET, R_V810_ZDA_15_16_OFFSET }, + { BFD_RELOC_VTABLE_INHERIT, R_V810_GNU_VTINHERIT }, + { BFD_RELOC_VTABLE_ENTRY, R_V810_GNU_VTENTRY }, + +}; + + +/* Map a bfd relocation into the appropriate howto structure */ +static reloc_howto_type * +v810_elf_reloc_type_lookup (abfd, code) + bfd * abfd ATTRIBUTE_UNUSED; + bfd_reloc_code_real_type code; +{ + unsigned int i; + + for (i = 0; + i < sizeof (v810_elf_reloc_map) / sizeof (struct v810_elf_reloc_map); + i++) + { + if (v810_elf_reloc_map[i].bfd_reloc_val == code) + { + BFD_ASSERT (v810_elf_howto_table[v810_elf_reloc_map[i].elf_reloc_val].type == v810_elf_reloc_map[i].elf_reloc_val); + + return & v810_elf_howto_table[v810_elf_reloc_map[i].elf_reloc_val]; + } + } + + return NULL; +} + + +/* Set the howto pointer for an V810 ELF reloc. */ +static void +v810_elf_info_to_howto_rel (abfd, cache_ptr, dst) + bfd * abfd ATTRIBUTE_UNUSED; + arelent * cache_ptr; + Elf32_Internal_Rel * dst; +{ + unsigned int r_type; + + r_type = ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (r_type < (unsigned int) R_V810_max); + cache_ptr->howto = &v810_elf_howto_table[r_type]; +} + +/* Set the howto pointer for a V810 ELF reloc (type RELA). */ +static void +v810_elf_info_to_howto_rela (abfd, cache_ptr, dst) + bfd * abfd ATTRIBUTE_UNUSED; + arelent * cache_ptr; + Elf32_Internal_Rela *dst; +{ + unsigned int r_type; + + r_type = ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (r_type < (unsigned int) R_V810_max); + cache_ptr->howto = &v810_elf_howto_table[r_type]; +} + + +/* Look through the relocs for a section during the first phase, and + allocate space in the global offset table or procedure linkage + table. */ + +static boolean +v810_elf_check_relocs (abfd, info, sec, relocs) + bfd * abfd; + struct bfd_link_info * info; + asection * sec; + const Elf_Internal_Rela * relocs; +{ + boolean ret = true; + bfd *dynobj; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + asection *sreloc; + enum v810_reloc_type r_type; + int other = 0; + const char *common = (const char *)0; + + if (info->relocateable) + return true; + +#ifdef DEBUG + fprintf (stderr, "v810_elf_check_relocs called for section %s in %s\n", + bfd_get_section_name (abfd, sec), + bfd_get_filename (abfd)); +#endif + + dynobj = elf_hash_table (info)->dynobj; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + sreloc = NULL; + + rel_end = relocs + sec->reloc_count; + for (rel = relocs; rel < rel_end; rel++) + { + unsigned long r_symndx; + struct elf_link_hash_entry *h; + + 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]; + + r_type = (enum v810_reloc_type) ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + default: + case R_V810_NONE: + case R_V810_9_PCREL: + case R_V810_26_PCREL: + case R_V810_HI16_S: + case R_V810_HI16: + case R_V810_LO16: + case R_V810_32: + case R_V810_16: + case R_V810_8: + break; + + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ + case R_V810_GNU_VTINHERIT: + if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return false; + break; + + /* This relocation describes which C++ vtable entries are actually + used. Record for later use during GC. */ + case R_V810_GNU_VTENTRY: + if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return false; + break; + + case R_V810_SDA_16_16_OFFSET: + case R_V810_SDA_15_16_OFFSET: + other = V810_OTHER_SDA; + common = ".scommon"; + goto small_data_common; + + case R_V810_ZDA_16_16_OFFSET: + case R_V810_ZDA_15_16_OFFSET: + other = V810_OTHER_ZDA; + common = ".zcommon"; + /* fall through */ + +#define V810_OTHER_MASK (V810_OTHER_SDA | V810_OTHER_ZDA) + + small_data_common: + if (h) + { + h->other |= other; /* flag which type of relocation was used */ + if ((h->other & V810_OTHER_MASK) != (other & V810_OTHER_MASK) + && (h->other & V810_OTHER_ERROR) == 0) + { + const char * msg; + static char buff[200]; /* XXX */ + + switch (h->other & V810_OTHER_MASK) + { + default: + msg = _("Variable `%s' cannot occupy in multiple small data regions"); + break; + case V810_OTHER_SDA | V810_OTHER_ZDA: + msg = _("Variable `%s' cannot be in both small and zero data regions simultaneously"); + break; + } + + sprintf (buff, msg, h->root.root.string); + info->callbacks->warning (info, buff, h->root.root.string, + abfd, h->root.u.def.section, 0); + + bfd_set_error (bfd_error_bad_value); + h->other |= V810_OTHER_ERROR; + ret = false; + } + } + + if (h && h->root.type == bfd_link_hash_common + && h->root.u.c.p + && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON")) + { + asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common); + section->flags |= SEC_IS_COMMON; + } + +#ifdef DEBUG + fprintf (stderr, "v810_elf_check_relocs, found %s relocation for %s%s\n", + v810_elf_howto_table[ (int)r_type ].name, + (h && h->root.root.string) ? h->root.root.string : "", + (h->root.type == bfd_link_hash_common) ? ", symbol is common" : ""); +#endif + break; + } + } + + return ret; +} + +/* + * In the old version, when an entry was checked out from the table, + * it was deleted. This produced an error if the entry was needed + * more than once, as the second attempted retry failed. + * + * In the current version, the entry is not deleted, instead we set + * the field 'found' to true. If a second lookup matches the same + * entry, then we know that the hi16s reloc has already been updated + * and does not need to be updated a second time. + * + * TODO - TOFIX: If it is possible that we need to restore 2 different + * addresses from the same table entry, where the first generates an + * overflow, whilst the second do not, then this code will fail. + */ + +typedef struct hi16s_location +{ + bfd_vma addend; + bfd_byte * address; + unsigned long counter; + boolean found; + struct hi16s_location * next; +} +hi16s_location; + +static hi16s_location * previous_hi16s; +static hi16s_location * free_hi16s; +static unsigned long hi16s_counter; + +static void +remember_hi16s_reloc (abfd, addend, address) + bfd * abfd; + bfd_vma addend; + bfd_byte * address; +{ + hi16s_location * entry = NULL; + + /* Find a free structure. */ + if (free_hi16s == NULL) + free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s)); + + entry = free_hi16s; + free_hi16s = free_hi16s->next; + + entry->addend = addend; + entry->address = address; + entry->counter = hi16s_counter ++; + entry->found = false; + entry->next = previous_hi16s; + previous_hi16s = entry; + + /* Cope with wrap around of our counter. */ + if (hi16s_counter == 0) + { + /* XXX - Assume that all counter entries differ only in their low 16 bits. */ + for (entry = previous_hi16s; entry != NULL; entry = entry->next) + entry->counter &= 0xffff; + + hi16s_counter = 0x10000; + } + + return; +} + +static bfd_byte * +find_remembered_hi16s_reloc (addend, already_found) + bfd_vma addend; + boolean * already_found; +{ + hi16s_location * match = NULL; + hi16s_location * entry; + hi16s_location * previous = NULL; + hi16s_location * prev; + bfd_byte * addr; + + /* Search the table. Record the most recent entry that matches. */ + for (entry = previous_hi16s; entry; entry = entry->next) + { + if (entry->addend == addend + && (match == NULL || match->counter < entry->counter)) + { + previous = prev; + match = entry; + } + + prev = entry; + } + + if (match == NULL) + return NULL; + + /* Extract the address. */ + addr = match->address; + + /* Remeber if this entry has already been used before. */ + if (already_found) + * already_found = match->found; + + /* Note that this entry has now been used. */ + match->found = true; + + return addr; +} + +/* FIXME: The code here probably ought to be removed and the code in reloc.c + allowed to do its stuff instead. At least for most of the relocs, anwyay. */ +static bfd_reloc_status_type +v810_elf_perform_relocation (abfd, r_type, addend, address) + bfd * abfd; + int r_type; + bfd_vma addend; + bfd_byte * address; +{ + unsigned long insn; + bfd_signed_vma saddend = (bfd_signed_vma) addend; + + switch (r_type) + { + default: + /* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */ + return bfd_reloc_notsupported; + + case R_V810_32: + bfd_put_32 (abfd, addend, address); + return bfd_reloc_ok; + + case R_V810_26_PCREL: + if (saddend > 0x1ffffff || saddend < -0x2000000) + return bfd_reloc_overflow; + + if ((addend % 2) != 0) + return bfd_reloc_dangerous; + + insn = bfd_get_32 (abfd, address); + insn &= ~0xfffe03ff; + insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3ff0000) >> 16)); + bfd_put_32 (abfd, insn, address); + return bfd_reloc_ok; + + case R_V810_9_PCREL: + if (saddend > 0xff || saddend < -0x100) + return bfd_reloc_overflow; + + if ((addend % 2) != 0) + return bfd_reloc_dangerous; + + insn = bfd_get_16 (abfd, address); + insn &= ~ 0x01ff; + insn |= (addend & 0x1ff); + break; + + case R_V810_HI16: + addend += (bfd_get_16 (abfd, address) << 16); + addend = (addend >> 16); + insn = addend; + break; + + case R_V810_HI16_S: + /* Remember where this relocation took place. */ + remember_hi16s_reloc (abfd, addend, address); + + addend += (bfd_get_16 (abfd, address) << 16); + addend = (addend >> 16) + ((addend & 0x8000) != 0); + + /* This relocation cannot overflow. */ + if (addend > 0x7fff) + addend = 0; + + insn = addend; + break; + + case R_V810_LO16: + /* Calculate the sum of the value stored in the instruction and the + addend and check for overflow from the low 16 bits into the high + 16 bits. The assembler has already done some of this: If the + value stored in the instruction has its 15th bit set, (counting + from zero) then the assembler will have added 1 to the value + stored in the associated HI16S reloc. So for example, these + relocations: + + movhi hi( fred ), r0, r1 + movea lo( fred ), r1, r1 + + will store 0 in the value fields for the MOVHI and MOVEA instructions + and addend will be the address of fred, but for these instructions: + + movhi hi( fred + 0x123456), r0, r1 + movea lo( fred + 0x123456), r1, r1 + + the value stored in the MOVHI instruction will be 0x12 and the value + stored in the MOVEA instruction will be 0x3456. If however the + instructions were: + + movhi hi( fred + 0x10ffff), r0, r1 + movea lo( fred + 0x10ffff), r1, r1 + + then the value stored in the MOVHI instruction would be 0x11 (not + 0x10) and the value stored in the MOVEA instruction would be 0xffff. + Thus (assuming for the moment that the addend is 0), at run time the + MOVHI instruction loads 0x110000 into r1, then the MOVEA instruction + adds 0xffffffff (sign extension!) producing 0x10ffff. Similarly if + the instructions were: + + movhi hi( fred - 1), r0, r1 + movea lo( fred - 1), r1, r1 + + then 0 is stored in the MOVHI instruction and -1 is stored in the + MOVEA instruction. + + Overflow can occur if the addition of the value stored in the + instruction plus the addend sets the 15th bit when before it was clear. + This is because the 15th bit will be sign extended into the high part, + thus reducing its value by one, but since the 15th bit was originally + clear, the assembler will not have added 1 to the previous HI16S reloc + to compensate for this effect. For example: + + movhi hi( fred + 0x123456), r0, r1 + movea lo( fred + 0x123456), r1, r1 + + The value stored in HI16S reloc is 0x12, the value stored in the LO16 + reloc is 0x3456. If we assume that the address of fred is 0x00007000 + then the relocations become: + + HI16S: 0x0012 + (0x00007000 >> 16) = 0x12 + LO16: 0x3456 + (0x00007000 & 0xffff) = 0xa456 + + but when the instructions are executed, the MOVEA instruction's value + is signed extended, so the sum becomes: + + 0x00120000 + + 0xffffa456 + ------------ + 0x0011a456 but 'fred + 0x123456' = 0x0012a456 + + Note that if the 15th bit was set in the value stored in the LO16 + reloc, then we do not have to do anything: + + movhi hi( fred + 0x10ffff), r0, r1 + movea lo( fred + 0x10ffff), r1, r1 + + HI16S: 0x0011 + (0x00007000 >> 16) = 0x11 + LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff + + 0x00110000 + + 0x00006fff + ------------ + 0x00116fff = fred + 0x10ffff = 0x7000 + 0x10ffff + + + Overflow can also occur if the computation carries into the 16th bit + and it also results in the 15th bit having the same value as the 15th + bit of the original value. What happens is that the HI16S reloc + will have already examined the 15th bit of the original value and + added 1 to the high part if the bit is set. This compensates for the + sign extension of 15th bit of the result of the computation. But now + there is a carry into the 16th bit, and this has not been allowed for. + + So, for example if fred is at address 0xf000: + + movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] + movea lo( fred + 0xffff), r1, r1 + + HI16S: 0x0001 + (0x0000f000 >> 16) = 0x0001 + LO16: 0xffff + (0x0000f000 & 0xffff) = 0xefff (carry into bit 16 is lost) + + 0x00010000 + + 0xffffefff + ------------ + 0x0000efff but 'fred + 0xffff' = 0x0001efff + + Similarly, if the 15th bit remains clear, but overflow occurs into + the 16th bit then (assuming the address of fred is 0xf000): + + movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] + movea lo( fred + 0x7000), r1, r1 + + HI16S: 0x0000 + (0x0000f000 >> 16) = 0x0000 + LO16: 0x7000 + (0x0000f000 & 0xffff) = 0x6fff (carry into bit 16 is lost) + + 0x00000000 + + 0x00006fff + ------------ + 0x00006fff but 'fred + 0x7000' = 0x00016fff + + Note - there is no need to change anything if a carry occurs, and the + 15th bit changes its value from being set to being clear, as the HI16S + reloc will have already added in 1 to the high part for us: + + movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] + movea lo( fred + 0xffff), r1, r1 + + HI16S: 0x0001 + (0x00007000 >> 16) + LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff (carry into bit 16 is lost) + + 0x00010000 + + 0x00006fff (bit 15 not set, so the top half is zero) + ------------ + 0x00016fff which is right (assuming that fred is at 0x7000) + + but if the 15th bit goes from being clear to being set, then we must + once again handle overflow: + + movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] + movea lo( fred + 0x7000), r1, r1 + + HI16S: 0x0000 + (0x0000ffff >> 16) + LO16: 0x7000 + (0x0000ffff & 0xffff) = 0x6fff (carry into bit 16) + + 0x00000000 + + 0x00006fff (bit 15 not set, so the top half is zero) + ------------ + 0x00006fff which is wrong (assuming that fred is at 0xffff) + */ + + { + long result; + + insn = bfd_get_16 (abfd, address); + result = insn + addend; + +#define BIT15_SET(x) ((x) & 0x8000) +#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff) + + if ((BIT15_SET (result) && ! BIT15_SET (addend)) + || (OVERFLOWS (addend, insn) + && ((! BIT15_SET (insn)) || (BIT15_SET (addend))))) + { + boolean already_updated; + bfd_byte * hi16s_address = find_remembered_hi16s_reloc + (addend, & already_updated); + + /* Amend the matching HI16_S relocation. */ + if (hi16s_address != NULL) + { + if (! already_updated) + { + insn = bfd_get_16 (abfd, hi16s_address); + insn += 1; + bfd_put_16 (abfd, insn, hi16s_address); + } + } + else + { + fprintf (stderr, _("FAILED to find previous HI16 reloc\n")); + return bfd_reloc_overflow; + } + } + + /* Do not complain if value has top bit set, as this has been anticipated. */ + insn = result & 0xffff; + break; + } + + case R_V810_8: + addend += (char) bfd_get_8 (abfd, address); + + saddend = (bfd_signed_vma) addend; + + if (saddend > 0x7f || saddend < -0x80) + return bfd_reloc_overflow; + + bfd_put_8 (abfd, addend, address); + return bfd_reloc_ok; + + case R_V810_16: + + /* drop through */ + case R_V810_SDA_16_16_OFFSET: + case R_V810_ZDA_16_16_OFFSET: + addend += bfd_get_16 (abfd, address); + + saddend = (bfd_signed_vma) addend; + + if (saddend > 0x7fff || saddend < -0x8000) + return bfd_reloc_overflow; + + insn = addend; + break; + + case R_V810_SDA_15_16_OFFSET: + case R_V810_ZDA_15_16_OFFSET: + insn = bfd_get_16 (abfd, address); + addend += (insn & 0xfffe); + + saddend = (bfd_signed_vma) addend; + + if (saddend > 0x7ffe || saddend < -0x8000) + return bfd_reloc_overflow; + + if (addend & 1) + return bfd_reloc_dangerous; + + insn = (addend & ~1) | (insn & 1); + break; + + case R_V810_GNU_VTINHERIT: + case R_V810_GNU_VTENTRY: + return bfd_reloc_ok; + + } + + bfd_put_16 (abfd, insn, address); + return bfd_reloc_ok; +} + + +/* Insert the addend into the instruction. */ +static bfd_reloc_status_type +v810_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) + bfd * abfd ATTRIBUTE_UNUSED; + arelent * reloc; + asymbol * symbol; + PTR data ATTRIBUTE_UNUSED; + asection * isection; + bfd * obfd; + char ** err ATTRIBUTE_UNUSED; +{ + long relocation; + + /* If there is an output BFD, + and the symbol is not a section name (which is only defined at final link time), + and either we are not putting the addend into the instruction + or the addend is zero, so there is nothing to add into the instruction + then just fixup the address and return. */ + if (obfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (! reloc->howto->partial_inplace + || reloc->addend == 0)) + { + reloc->address += isection->output_offset; + return bfd_reloc_ok; + } +#if 0 + else if (obfd != NULL) + { + return bfd_reloc_continue; + } +#endif + + /* Catch relocs involving undefined symbols. */ + if (bfd_is_und_section (symbol->section) + && (symbol->flags & BSF_WEAK) == 0 + && obfd == NULL) + return bfd_reloc_undefined; + + /* We handle final linking of some relocs ourselves. */ + + /* Is the address of the relocation really within the section? */ + if (reloc->address > isection->_cooked_size) + return bfd_reloc_outofrange; + + /* Work out which section the relocation is targetted at and the + initial relocation command value. */ + + /* Get symbol value. (Common symbols are special.) */ + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + /* Convert input-section-relative symbol value to absolute + addend. */ + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + relocation += reloc->addend; + + if (reloc->howto->pc_relative == true) + { + /* Here the variable relocation holds the final address of the + symbol we are relocating against, plus any addend. */ + relocation -= isection->output_section->vma + isection->output_offset; + + /* Deal with pcrel_offset */ + relocation -= reloc->address; + } + + reloc->addend = relocation; + return bfd_reloc_ok; +} + + +/*ARGSUSED*/ +static boolean +v810_elf_is_local_label_name (abfd, name) + bfd * abfd ATTRIBUTE_UNUSED; + const char * name; +{ + return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.')) + || (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')); +} + + +/* Perform a relocation as part of a final link. */ +static bfd_reloc_status_type +v810_elf_final_link_relocate (howto, input_bfd, output_bfd, + input_section, contents, offset, value, + addend, info, sym_sec, is_local) + reloc_howto_type * howto; + bfd * input_bfd; + bfd * output_bfd ATTRIBUTE_UNUSED; + asection * input_section; + bfd_byte * contents; + bfd_vma offset; + bfd_vma value; + bfd_vma addend; + struct bfd_link_info * info; + asection * sym_sec; + int is_local ATTRIBUTE_UNUSED; +{ + unsigned long r_type = howto->type; + bfd_byte * hit_data = contents + offset; + + /* Adjust the value according to the relocation. */ + switch (r_type) + { + case R_V810_9_PCREL: + value -= (input_section->output_section->vma + + input_section->output_offset); + value -= offset; + break; + + case R_V810_26_PCREL: + value -= (input_section->output_section->vma + + input_section->output_offset + + offset); + break; + + case R_V810_HI16_S: + case R_V810_HI16: + case R_V810_LO16: + case R_V810_16: + case R_V810_32: + case R_V810_8: + break; + + case R_V810_ZDA_15_16_OFFSET: + case R_V810_ZDA_16_16_OFFSET: + if (sym_sec == NULL) + return bfd_reloc_undefined; + + /*value -= sym_sec->output_section->vma;*/ + break; + + case R_V810_SDA_15_16_OFFSET: + case R_V810_SDA_16_16_OFFSET: + { + unsigned long gp; + struct bfd_link_hash_entry * h; + + if (sym_sec == NULL) + return bfd_reloc_undefined; + + /* Get the value of __gp. */ + h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true); + if (h == (struct bfd_link_hash_entry *) NULL + || h->type != bfd_link_hash_defined) + return bfd_reloc_other; + + gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + + value -= sym_sec->output_section->vma; + value -= (gp - sym_sec->output_section->vma); + } + break; + + case R_V810_NONE: + case R_V810_GNU_VTINHERIT: + case R_V810_GNU_VTENTRY: + return bfd_reloc_ok; + + default: + return bfd_reloc_notsupported; + } + + /* Perform the relocation. */ + return v810_elf_perform_relocation (input_bfd, r_type, value + addend, hit_data); +} + + +/* Relocate an V810 ELF section. */ +static boolean +v810_elf_relocate_section (output_bfd, info, input_bfd, input_section, + contents, relocs, local_syms, local_sections) + bfd * output_bfd; + 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); + + if (sym_hashes == NULL) + { + info->callbacks->warning + (info, "no hash table available", NULL, input_bfd, input_section, 0); + + return false; + } + + /* Reset the list of remembered HI16S relocs to empty. */ + free_hi16s = previous_hi16s; + previous_hi16s = NULL; + hi16s_counter = 0; + + rel = relocs; + relend = relocs + input_section->reloc_count; + for (; rel < relend; rel++) + { + int r_type; + 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; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + + if (r_type == R_V810_GNU_VTENTRY + || r_type == R_V810_GNU_VTINHERIT) + continue; + + howto = v810_elf_howto_table + r_type; + + if (info->relocateable) + { + /* This is a relocateable link. We don't have to change + anything, unless the reloc is against a section symbol, + in which case we have to adjust according to where the + section symbol winds up in the output section. */ + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + sec = local_sections[r_symndx]; + rel->r_addend += sec->output_offset + sym->st_value; + } + } + + continue; + } + + /* This is a final link. */ + h = NULL; + sym = NULL; + sec = NULL; + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + relocation = (sec->output_section->vma + + sec->output_offset + + sym->st_value); +#if 0 + { + char * name; + name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); + name = (name == NULL) ? "" : name; +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 - symtab_hdr->sh_info]; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + 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, h->root.root.string, 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, h->root.root.string); +#endif + relocation = 0; + } + else + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, + input_section, rel->r_offset, true))) + return false; +#if 0 +fprintf (stderr, "unknown: name: %s\n", h->root.root.string); +#endif + relocation = 0; + } + } + + /* FIXME: We should use the addend, but the COFF relocations + don't. */ + r = v810_elf_final_link_relocate (howto, input_bfd, output_bfd, + input_section, + contents, rel->r_offset, + relocation, rel->r_addend, + info, sec, h == NULL); + + if (r != bfd_reloc_ok) + { + const char * name; + const char * msg = (const char *)0; + + if (h != NULL) + name = h->root.root.string; + else + { + name = (bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name)); + if (name == NULL || *name == '\0') + name = bfd_section_name (input_bfd, sec); + } + + switch (r) + { + case bfd_reloc_overflow: + if (! ((*info->callbacks->reloc_overflow) + (info, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset))) + return false; + break; + + case bfd_reloc_undefined: + if (! ((*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, + rel->r_offset, true))) + return false; + break; + + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + goto common_error; + + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation error"); + goto common_error; + + case bfd_reloc_dangerous: + msg = _("internal error: dangerous relocation"); + goto common_error; + + case bfd_reloc_other: + msg = _("could not locate special linker symbol __gp"); + goto common_error; + + case bfd_reloc_continue: + msg = _("could not locate special linker symbol __ep"); + goto common_error; + + case (bfd_reloc_dangerous + 1): + msg = _("could not locate special linker symbol __ctbp"); + goto common_error; + + default: + msg = _("internal error: unknown error"); + /* fall through */ + + common_error: + if (!((*info->callbacks->warning) + (info, msg, name, input_bfd, input_section, + rel->r_offset))) + return false; + break; + } + } + } + + return true; +} + +static boolean +v810_elf_gc_sweep_hook (abfd, info, sec, relocs) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + asection *sec ATTRIBUTE_UNUSED; + const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; +{ + /* No got and plt entries for v810-elf */ + return true; +} + +static asection * +v810_elf_gc_mark_hook (abfd, info, rel, h, sym) + bfd *abfd; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + Elf_Internal_Rela *rel; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; +{ + if (h != NULL) + { + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_V810_GNU_VTINHERIT: + case R_V810_GNU_VTENTRY: + break; + + 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 (abfd) + && ELF_ST_BIND (sym->st_info) != STB_LOCAL) + && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) + && sym->st_shndx != SHN_COMMON)) + { + return bfd_section_from_elf_index (abfd, sym->st_shndx); + } + } + return NULL; +} +/* Set the right machine number. */ +static boolean +v810_elf_object_p (abfd) + bfd *abfd; +{ + switch (elf_elfheader (abfd)->e_flags & EF_V810_ARCH) + { + default: + case E_V810_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v810, 0); break; + case E_V830_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v810, bfd_mach_v830); break; + } + return true; +} + +/* Store the machine number in the flags field. */ +static void +v810_elf_final_write_processing (abfd, linker) + bfd * abfd; + boolean linker ATTRIBUTE_UNUSED; +{ + unsigned long val; + + switch (bfd_get_mach (abfd)) + { + default: + case 0: val = E_V810_ARCH; break; + case bfd_mach_v830: val = E_V830_ARCH; break; + } + + elf_elfheader (abfd)->e_flags &=~ EF_V810_ARCH; + elf_elfheader (abfd)->e_flags |= val; +} + +/* Function to keep V810 specific file flags. */ +static boolean +v810_elf_set_private_flags (abfd, flags) + bfd * abfd; + flagword flags; +{ + BFD_ASSERT (!elf_flags_init (abfd) + || elf_elfheader (abfd)->e_flags == flags); + + elf_elfheader (abfd)->e_flags = flags; + elf_flags_init (abfd) = true; + return true; +} + +/* Copy backend specific data from one object module to another */ +static boolean +v810_elf_copy_private_bfd_data (ibfd, obfd) + bfd * ibfd; + bfd * obfd; +{ + if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return true; + + BFD_ASSERT (!elf_flags_init (obfd) + || (elf_elfheader (obfd)->e_flags + == elf_elfheader (ibfd)->e_flags)); + + elf_gp (obfd) = elf_gp (ibfd); + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + elf_flags_init (obfd) = true; + return true; +} + +/* Merge backend specific data from an object file to the output + object file when linking. */ +static boolean +v810_elf_merge_private_bfd_data (ibfd, obfd) + bfd * ibfd; + bfd * obfd; +{ + flagword out_flags; + flagword in_flags; + + if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return true; + + in_flags = elf_elfheader (ibfd)->e_flags; + out_flags = elf_elfheader (obfd)->e_flags; + + if (! elf_flags_init (obfd)) + { + /* If the input is the default architecture then do not + bother setting the flags for the output architecture, + instead allow future merges to do this. If no future + merges ever set these flags then they will retain their + unitialised values, which surprise surprise, correspond + to the default values. */ + if (bfd_get_arch_info (ibfd)->the_default) + return true; + + elf_flags_init (obfd) = true; + elf_elfheader (obfd)->e_flags = in_flags; + + if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) + && bfd_get_arch_info (obfd)->the_default) + { + return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); + } + + return true; + } + + /* Check flag compatibility. */ + if (in_flags == out_flags) + return true; + + if ((in_flags & EF_V810_ARCH) != (out_flags & EF_V810_ARCH) + && (in_flags & EF_V810_ARCH) != E_V810_ARCH) + _bfd_error_handler (_("%s: Architecture mismatch with previous modules"), + bfd_get_filename (ibfd)); + + return true; +} +/* Display the flags field */ + +static boolean +v810_elf_print_private_bfd_data (abfd, ptr) + bfd * abfd; + PTR ptr; +{ + FILE * file = (FILE *) ptr; + + BFD_ASSERT (abfd != NULL && ptr != NULL); + + _bfd_elf_print_private_bfd_data (abfd, ptr); + + /* xgettext:c-format */ + fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags); + + switch (elf_elfheader (abfd)->e_flags & EF_V810_ARCH) + { + default: + case E_V810_ARCH: fprintf (file, _("v810 architecture")); break; + case E_V830_ARCH: fprintf (file, _("v830 architecture")); break; + } + + fputc ('\n', file); + + return true; +} + +/* V810 ELF uses four common sections. One is the usual one, and the + others are for (small) objects in one of the special data areas: + small, tiny and zero. All the objects are kept together, and then + referenced via the gp register, the ep register or the r0 register + respectively, which yields smaller, faster assembler code. This + approach is copied from elf32-mips.c. */ + +static asection v810_elf_scom_section; +static asymbol v810_elf_scom_symbol; +static asymbol * v810_elf_scom_symbol_ptr; +static asection v810_elf_zcom_section; +static asymbol v810_elf_zcom_symbol; +static asymbol * v810_elf_zcom_symbol_ptr; + + +/* Given a BFD section, try to locate the corresponding ELF section + index. */ + +static boolean +v810_elf_section_from_bfd_section (abfd, hdr, sec, retval) + bfd * abfd ATTRIBUTE_UNUSED; + Elf32_Internal_Shdr * hdr ATTRIBUTE_UNUSED; + asection * sec; + int * retval; +{ + if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) + *retval = SHN_V810_SCOMMON; + else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0) + *retval = SHN_V810_ZCOMMON; + else + return false; + + return true; +} + +/* Handle the special V810 section numbers that a symbol may use. */ + +static void +v810_elf_symbol_processing (abfd, asym) + bfd * abfd; + asymbol * asym; +{ + elf_symbol_type * elfsym = (elf_symbol_type *) asym; + unsigned short index; + + index = elfsym->internal_elf_sym.st_shndx; + + /* If the section index is an "ordinary" index, then it may + refer to a v810 specific section created by the assembler. + Check the section's type and change the index it matches. + + FIXME: Should we alter the st_shndx field as well ? */ + + if (index < elf_elfheader(abfd)[0].e_shnum) + switch (elf_elfsections(abfd)[index]->sh_type) + { + case SHT_V810_SCOMMON: + index = SHN_V810_SCOMMON; + break; + + case SHT_V810_ZCOMMON: + index = SHN_V810_ZCOMMON; + break; + + default: + break; + } + + switch (index) + { + case SHN_V810_SCOMMON: + if (v810_elf_scom_section.name == NULL) + { + /* Initialize the small common section. */ + v810_elf_scom_section.name = ".scommon"; + v810_elf_scom_section.flags = SEC_IS_COMMON | SEC_ALLOC | SEC_DATA; + v810_elf_scom_section.output_section = & v810_elf_scom_section; + v810_elf_scom_section.symbol = & v810_elf_scom_symbol; + v810_elf_scom_section.symbol_ptr_ptr = & v810_elf_scom_symbol_ptr; + v810_elf_scom_symbol.name = ".scommon"; + v810_elf_scom_symbol.flags = BSF_SECTION_SYM; + v810_elf_scom_symbol.section = & v810_elf_scom_section; + v810_elf_scom_symbol_ptr = & v810_elf_scom_symbol; + } + asym->section = & v810_elf_scom_section; + asym->value = elfsym->internal_elf_sym.st_size; + break; + + case SHN_V810_ZCOMMON: + if (v810_elf_zcom_section.name == NULL) + { + /* Initialize the zcommon section. */ + v810_elf_zcom_section.name = ".zcommon"; + v810_elf_zcom_section.flags = SEC_IS_COMMON; + v810_elf_zcom_section.output_section = & v810_elf_zcom_section; + v810_elf_zcom_section.symbol = & v810_elf_zcom_symbol; + v810_elf_zcom_section.symbol_ptr_ptr = & v810_elf_zcom_symbol_ptr; + v810_elf_zcom_symbol.name = ".zcommon"; + v810_elf_zcom_symbol.flags = BSF_SECTION_SYM; + v810_elf_zcom_symbol.section = & v810_elf_zcom_section; + v810_elf_zcom_symbol_ptr = & v810_elf_zcom_symbol; + } + asym->section = & v810_elf_zcom_section; + asym->value = elfsym->internal_elf_sym.st_size; + break; + } +} + +/* Hook called by the linker routine which adds symbols from an object + file. We must handle the special v810 section numbers here. */ + +/*ARGSUSED*/ +static boolean +v810_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) + bfd * abfd; + struct bfd_link_info * info ATTRIBUTE_UNUSED; + const Elf_Internal_Sym * sym; + const char ** namep ATTRIBUTE_UNUSED; + flagword * flagsp ATTRIBUTE_UNUSED; + asection ** secp; + bfd_vma * valp; +{ + int index = sym->st_shndx; + + /* If the section index is an "ordinary" index, then it may + refer to a v810 specific section created by the assembler. + Check the section's type and change the index it matches. + + FIXME: Should we alter the st_shndx field as well ? */ + + if (index < elf_elfheader(abfd)[0].e_shnum) + switch (elf_elfsections(abfd)[index]->sh_type) + { + case SHT_V810_SCOMMON: + index = SHN_V810_SCOMMON; + break; + + case SHT_V810_ZCOMMON: + index = SHN_V810_ZCOMMON; + break; + + default: + break; + } + + switch (index) + { + case SHN_V810_SCOMMON: + *secp = bfd_make_section_old_way (abfd, ".scommon"); + (*secp)->flags |= SEC_IS_COMMON; + *valp = sym->st_size; + break; + + case SHN_V810_ZCOMMON: + *secp = bfd_make_section_old_way (abfd, ".zcommon"); + (*secp)->flags |= SEC_IS_COMMON; + *valp = sym->st_size; + break; + } + + return true; +} + +/*ARGSIGNORED*/ +static boolean +v810_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec) + bfd * abfd ATTRIBUTE_UNUSED; + struct bfd_link_info * info ATTRIBUTE_UNUSED; + const char * name ATTRIBUTE_UNUSED; + Elf_Internal_Sym * sym; + asection * input_sec; +{ + /* If we see a common symbol, which implies a relocatable link, then + if a symbol was in a special common section in an input file, mark + it as a special common in the output file. */ + + if (sym->st_shndx == SHN_COMMON) + { + if (strcmp (input_sec->name, ".scommon") == 0) + sym->st_shndx = SHN_V810_SCOMMON; + else if (strcmp (input_sec->name, ".zcommon") == 0) + sym->st_shndx = SHN_V810_ZCOMMON; + } + + return true; +} + +static boolean +v810_elf_section_from_shdr (abfd, hdr, name) + bfd * abfd; + Elf_Internal_Shdr * hdr; + char * name; +{ + /* There ought to be a place to keep ELF backend specific flags, but + at the moment there isn't one. We just keep track of the + sections by their name, instead. */ + + if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) + return false; + + switch (hdr->sh_type) + { + case SHT_V810_SCOMMON: + case SHT_V810_ZCOMMON: + if (! bfd_set_section_flags (abfd, hdr->bfd_section, + (bfd_get_section_flags (abfd, + hdr->bfd_section) + | SEC_IS_COMMON))) + return false; + } + + return true; +} + +/* Set the correct type for a V810 ELF section. We do this by the + section name, which is a hack, but ought to work. */ +static boolean +v810_elf_fake_sections (abfd, hdr, sec) + bfd * abfd ATTRIBUTE_UNUSED; + Elf32_Internal_Shdr * hdr; + asection * sec; +{ + register const char * name; + + name = bfd_get_section_name (abfd, sec); + + if (strcmp (name, ".scommon") == 0) + { + hdr->sh_type = SHT_V810_SCOMMON; + } + else if (strcmp (name, ".zcommon") == 0) + hdr->sh_type = SHT_V810_ZCOMMON; + + return true; +} + + + +#define TARGET_LITTLE_SYM bfd_elf32_v810_vec +#define TARGET_LITTLE_NAME "elf32-v810" +#define ELF_ARCH bfd_arch_v810 +#define ELF_MACHINE_CODE EM_V810 +#define ELF_MAXPAGESIZE 0x1000 + +#define elf_info_to_howto v810_elf_info_to_howto_rela +#define elf_info_to_howto_rel v810_elf_info_to_howto_rel + +#define elf_backend_check_relocs v810_elf_check_relocs +#define elf_backend_relocate_section v810_elf_relocate_section +#define elf_backend_object_p v810_elf_object_p +#define elf_backend_final_write_processing v810_elf_final_write_processing +#define elf_backend_section_from_bfd_section v810_elf_section_from_bfd_section +#define elf_backend_symbol_processing v810_elf_symbol_processing +#define elf_backend_add_symbol_hook v810_elf_add_symbol_hook +#define elf_backend_link_output_symbol_hook v810_elf_link_output_symbol_hook +#define elf_backend_section_from_shdr v810_elf_section_from_shdr +#define elf_backend_fake_sections v810_elf_fake_sections +#define elf_backend_gc_mark_hook v810_elf_gc_mark_hook +#define elf_backend_gc_sweep_hook v810_elf_gc_sweep_hook + +#define elf_backend_can_gc_sections 1 + + +#define bfd_elf32_bfd_is_local_label_name v810_elf_is_local_label_name +#define bfd_elf32_bfd_reloc_type_lookup v810_elf_reloc_type_lookup +#define bfd_elf32_bfd_copy_private_bfd_data v810_elf_copy_private_bfd_data +#define bfd_elf32_bfd_merge_private_bfd_data v810_elf_merge_private_bfd_data +#define bfd_elf32_bfd_set_private_flags v810_elf_set_private_flags +#define bfd_elf32_bfd_print_private_bfd_data v810_elf_print_private_bfd_data + +#define elf_symbol_leading_char '_' + +#include "elf32-target.h" diff -urN binutils-2.10.org/bfd/elf.c binutils-2.10/bfd/elf.c --- binutils-2.10.org/bfd/elf.c 2000-05-28 22:18:32.000000000 -0700 +++ binutils-2.10/bfd/elf.c 2011-03-20 03:53:01.000000000 -0700 @@ -3281,6 +3281,9 @@ case bfd_arch_avr: i_ehdrp->e_machine = EM_AVR; break; + case bfd_arch_v810: + i_ehdrp->e_machine = EM_V810; + break; case bfd_arch_v850: switch (bfd_get_mach (abfd)) { diff -urN binutils-2.10.org/bfd/libbfd.h binutils-2.10/bfd/libbfd.h --- binutils-2.10.org/bfd/libbfd.h 2000-04-28 18:45:48.000000000 -0700 +++ binutils-2.10/bfd/libbfd.h 2011-03-20 03:53:01.000000000 -0700 @@ -853,6 +853,12 @@ "BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET", "BFD_RELOC_V850_CALLT_6_7_OFFSET", "BFD_RELOC_V850_CALLT_16_16_OFFSET", + "BFD_RELOC_V810_9_PCREL", + "BFD_RELOC_V810_26_PCREL", + "BFD_RELOC_V810_SDA_16_16_OFFSET", + "BFD_RELOC_V810_SDA_15_16_OFFSET", + "BFD_RELOC_V810_ZDA_16_16_OFFSET", + "BFD_RELOC_V810_ZDA_15_16_OFFSET", "BFD_RELOC_MN10300_32_PCREL", "BFD_RELOC_MN10300_16_PCREL", diff -urN binutils-2.10.org/bfd/Makefile.am binutils-2.10/bfd/Makefile.am --- binutils-2.10.org/bfd/Makefile.am 2000-04-11 16:58:39.000000000 -0700 +++ binutils-2.10/bfd/Makefile.am 2011-03-20 03:53:01.000000000 -0700 @@ -67,6 +67,7 @@ cpu-sparc.lo \ cpu-tic30.lo \ cpu-tic80.lo \ + cpu-v810.lo \ cpu-v850.lo \ cpu-vax.lo \ cpu-we32k.lo \ @@ -104,6 +105,7 @@ cpu-sparc.c \ cpu-tic30.c \ cpu-tic80.c \ + cpu-v810.c \ cpu-v850.c \ cpu-vax.c \ cpu-we32k.c \ @@ -179,6 +181,7 @@ elf32-ppc.lo \ elf32-sh.lo \ elf32-sparc.lo \ + elf32-v810.lo \ elf32-v850.lo \ elf32.lo \ elflink.lo \ @@ -309,6 +312,7 @@ elf32-ppc.c \ elf32-sh.c \ elf32-sparc.c \ + elf32-v810.c \ elf32-v850.c \ elf32.c \ elflink.c \ @@ -715,6 +719,7 @@ cpu-sparc.lo: cpu-sparc.c cpu-tic30.lo: cpu-tic30.c cpu-tic80.lo: cpu-tic80.c +cpu-v810.lo: cpu-v810.c cpu-v850.lo: cpu-v850.c cpu-vax.lo: cpu-vax.c cpu-we32k.lo: cpu-we32k.c @@ -915,6 +920,9 @@ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/elf/sparc.h $(INCDIR)/elf/reloc-macros.h \ elf32-target.h +elf32-v810.lo: elf32-v810.c $(INCDIR)/bfdlink.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/elf/v810.h $(INCDIR)/elf/reloc-macros.h elf32-target.h elf32-v850.lo: elf32-v850.c $(INCDIR)/bfdlink.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/elf/v850.h $(INCDIR)/elf/reloc-macros.h elf32-target.h diff -urN binutils-2.10.org/bfd/Makefile.in binutils-2.10/bfd/Makefile.in --- binutils-2.10.org/bfd/Makefile.in 2000-04-11 16:58:39.000000000 -0700 +++ binutils-2.10/bfd/Makefile.in 2011-03-20 03:53:01.000000000 -0700 @@ -182,6 +182,7 @@ cpu-sparc.lo \ cpu-tic30.lo \ cpu-tic80.lo \ + cpu-v810.lo \ cpu-v850.lo \ cpu-vax.lo \ cpu-we32k.lo \ @@ -220,6 +221,7 @@ cpu-sparc.c \ cpu-tic30.c \ cpu-tic80.c \ + cpu-v810.c \ cpu-v850.c \ cpu-vax.c \ cpu-we32k.c \ @@ -296,6 +298,7 @@ elf32-ppc.lo \ elf32-sh.lo \ elf32-sparc.lo \ + elf32-v810.lo \ elf32-v850.lo \ elf32.lo \ elflink.lo \ @@ -427,6 +430,7 @@ elf32-ppc.c \ elf32-sh.c \ elf32-sparc.c \ + elf32-v810.c \ elf32-v850.c \ elf32.c \ elflink.c \ @@ -1243,6 +1247,7 @@ cpu-sparc.lo: cpu-sparc.c cpu-tic30.lo: cpu-tic30.c cpu-tic80.lo: cpu-tic80.c +cpu-v810.lo: cpu-v810.c cpu-v850.lo: cpu-v850.c cpu-vax.lo: cpu-vax.c cpu-we32k.lo: cpu-we32k.c @@ -1443,6 +1448,9 @@ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/elf/sparc.h $(INCDIR)/elf/reloc-macros.h \ elf32-target.h +elf32-v810.lo: elf32-v810.c $(INCDIR)/bfdlink.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/elf/v810.h $(INCDIR)/elf/reloc-macros.h elf32-target.h elf32-v850.lo: elf32-v850.c $(INCDIR)/bfdlink.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/elf/v850.h $(INCDIR)/elf/reloc-macros.h elf32-target.h diff -urN binutils-2.10.org/bfd/reloc.c binutils-2.10/bfd/reloc.c --- binutils-2.10.org/bfd/reloc.c 2000-04-11 16:02:50.000000000 -0700 +++ binutils-2.10/bfd/reloc.c 2011-03-20 03:53:01.000000000 -0700 @@ -2520,6 +2520,35 @@ COMMENT ENUM + BFD_RELOC_V810_9_PCREL +ENUMDOC + This is a 9-bit reloc +ENUM + BFD_RELOC_V810_26_PCREL +ENUMDOC + This is a 26-bit reloc + +ENUM + BFD_RELOC_V810_SDA_16_16_OFFSET +ENUMDOC + This is a 16 bit offset from the short data area pointer. +ENUM + BFD_RELOC_V810_SDA_15_16_OFFSET +ENUMDOC + This is a 16 bit offset (of which only 15 bits are used) from the + short data area pointer. +ENUM + BFD_RELOC_V810_ZDA_16_16_OFFSET +ENUMDOC + This is a 16 bit offset from the zero data area pointer. +ENUM + BFD_RELOC_V810_ZDA_15_16_OFFSET +ENUMDOC + This is a 16 bit offset (of which only 15 bits are used) from the + zero data area pointer. +COMMENT + +ENUM BFD_RELOC_MN10300_32_PCREL ENUMDOC This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the diff -urN binutils-2.10.org/bfd/targets.c binutils-2.10/bfd/targets.c --- binutils-2.10.org/bfd/targets.c 2000-03-27 00:39:12.000000000 -0800 +++ binutils-2.10/bfd/targets.c 2011-03-20 03:53:01.000000000 -0700 @@ -538,6 +538,7 @@ extern const bfd_target bfd_elf32_sh_vec; extern const bfd_target bfd_elf32_shl_vec; extern const bfd_target bfd_elf32_sparc_vec; +extern const bfd_target bfd_elf32_v810_vec; extern const bfd_target bfd_elf32_v850_vec; extern const bfd_target bfd_elf32_fr30_vec; extern const bfd_target bfd_elf32_mcore_big_vec; @@ -726,6 +727,7 @@ &bfd_elf32_pjl_vec, &bfd_elf32_powerpc_vec, &bfd_elf32_powerpcle_vec, + &bfd_elf32_v810_vec, &bfd_elf32_v850_vec, &bfd_elf32_fr30_vec, &bfd_elf32_mcore_big_vec, diff -urN binutils-2.10.org/binutils/Makefile.am binutils-2.10/binutils/Makefile.am --- binutils-2.10.org/binutils/Makefile.am 2000-04-06 21:39:24.000000000 -0700 +++ binutils-2.10/binutils/Makefile.am 2011-03-20 03:53:01.000000000 -0700 @@ -474,6 +474,7 @@ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \ $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \ + $(INCDIR)/elf/v810.h \ $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \ $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \ $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \ diff -urN binutils-2.10.org/binutils/Makefile.in binutils-2.10/binutils/Makefile.in --- binutils-2.10.org/binutils/Makefile.in 2000-04-06 21:39:24.000000000 -0700 +++ binutils-2.10/binutils/Makefile.in 2011-03-20 03:53:01.000000000 -0700 @@ -1330,6 +1330,7 @@ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \ $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \ + $(INCDIR)/elf/v810.h \ $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \ $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \ $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \ diff -urN binutils-2.10.org/binutils/readelf.c binutils-2.10/binutils/readelf.c --- binutils-2.10.org/binutils/readelf.c 2000-05-23 01:39:06.000000000 -0700 +++ binutils-2.10/binutils/readelf.c 2011-03-20 03:53:01.000000000 -0700 @@ -50,6 +50,7 @@ #define RELOC_MACROS_GEN_FUNC #include "elf/i386.h" +#include "elf/v810.h" #include "elf/v850.h" #include "elf/ppc.h" #include "elf/mips.h" @@ -553,6 +554,7 @@ case EM_SPARCV9: case EM_SPARC: case EM_PPC: + case EM_V810: case EM_CYGNUS_V850: case EM_CYGNUS_D30V: case EM_CYGNUS_MN10200: @@ -812,6 +814,10 @@ rtype = elf_sparc_reloc_type (type); break; + case EM_V810: + rtype = v810_reloc_type (type); + break; + case EM_CYGNUS_V850: rtype = v850_reloc_type (type); break; @@ -1215,6 +1221,7 @@ case EM_CYGNUS_MN10300: return "mn10300"; case EM_CYGNUS_MN10200: return "mn10200"; case EM_CYGNUS_FR30: return "Fujitsu FR30"; + case EM_V810: return "NEC v810"; case EM_PJ: return "picoJava"; case EM_MMA: return "Fujitsu Multimedia Accelerator"; case EM_PCP: return "Siemens PCP"; @@ -1272,6 +1279,21 @@ strcat (buf, ", relocatable-lib"); break; + case EM_V810: + switch (e_flags & EF_V810_ARCH) + { + case E_V830_ARCH: + strcat (buf, ", v830"); + break; + case E_V810_ARCH: + strcat (buf, ", v810"); + break; + default: + strcat (buf, ", unknown v810 architecture variant"); + break; + } + break; + case EM_CYGNUS_V850: switch (e_flags & EF_V850_ARCH) { diff -urN binutils-2.10.org/config.sub binutils-2.10/config.sub --- binutils-2.10.org/config.sub 2000-02-24 13:20:57.000000000 -0800 +++ binutils-2.10/config.sub 2011-03-20 03:53:01.000000000 -0700 @@ -182,7 +182,7 @@ | mips64orion | mips64orionel | mipstx39 | mipstx39el \ | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ | mips64vr5000 | miprs64vr5000el | mcore \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v810 | v850 | c4x \ | thumb | d10v | fr30 | avr) basic_machine=$basic_machine-unknown ;; @@ -197,7 +197,7 @@ ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration2 \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -219,7 +219,7 @@ | mipstx39-* | mipstx39el-* | mcore-* \ | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* ) + | thumb-* | v810-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* ) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. diff -urN binutils-2.10.org/configure.in binutils-2.10/configure.in --- binutils-2.10.org/configure.in 2000-06-10 05:40:21.000000000 -0700 +++ binutils-2.10/configure.in 2011-03-20 03:53:01.000000000 -0700 @@ -856,7 +856,7 @@ fi ;; v810-*-*) - noconfigdirs="$noconfigdirs bfd binutils gas gcc gdb ld target-libio target-libg++ target-libstdc++ opcodes target-libgloss" + noconfigdirs="$noconfigdirs target-libgloss" ;; v850-*-*) noconfigdirs="$noconfigdirs target-libgloss" diff -urN binutils-2.10.org/gas/app.c binutils-2.10/gas/app.c --- binutils-2.10.org/gas/app.c 2000-04-01 22:27:50.000000000 -0800 +++ binutils-2.10/gas/app.c 2011-03-20 03:53:01.000000000 -0700 @@ -68,7 +68,7 @@ #define LEX_IS_COLON 9 #define LEX_IS_NEWLINE 10 #define LEX_IS_ONECHAR_QUOTE 11 -#ifdef TC_V850 +#if (defined (TC_V850) || defined (TC_V810)) #define LEX_IS_DOUBLEDASH_1ST 12 #endif #ifdef TC_M32R @@ -183,7 +183,7 @@ } #endif -#ifdef TC_V850 +#if (defined (TC_V850) || defined (TC_V810)) lex['-'] = LEX_IS_DOUBLEDASH_1ST; #endif #ifdef DOUBLEBAR_PARALLEL @@ -366,7 +366,7 @@ 11: After seeing a symbol character in state 0 (eg a label definition) -1: output string in out_string and go to the state in old_state -2: flush text until a '*' '/' is seen, then go to state old_state -#ifdef TC_V850 +#if (defined (TC_V850) || defined (TC_V810)) 12: After seeing a dash, looking for a second dash as a start of comment. #endif #ifdef DOUBLEBAR_PARALLEL @@ -1024,7 +1024,7 @@ PUT (ch); break; -#ifdef TC_V850 +#if (defined (TC_V850) || defined (TC_V810)) case LEX_IS_DOUBLEDASH_1ST: ch2 = GET(); if (ch2 != '-') diff -urN binutils-2.10.org/gas/config/tc-v810.c binutils-2.10/gas/config/tc-v810.c --- binutils-2.10.org/gas/config/tc-v810.c 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/config/tc-v810.c 2011-03-20 03:56:52.000000000 -0700 @@ -0,0 +1,2090 @@ +/* tc-v810.c -- Assembler code for the NEC V810 + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "as.h" +#include "subsegs.h" +#include "opcode/v810.h" + +#define AREA_ZDA 0 +#define AREA_SDA 1 + +/* sign-extend a 16-bit number */ +#define SEXT16(x) ((((x) & 0xffff) ^ (~ 0x7fff)) + 0x8000) + +/* Temporarily holds the reloc in a cons expression. */ +static bfd_reloc_code_real_type hold_cons_reloc; + +/* Set to TRUE if we want to be pedantic about signed overflows. */ +static boolean warn_signed_overflows = FALSE; +static boolean warn_unsigned_overflows = FALSE; + +/* Indicates the target BFD machine number. */ +static int machine = -1; + +/* Indicates the target processor(s) for the assemble. */ +static unsigned int processor_mask = -1; + + +/* Structure to hold information about predefined registers. */ +struct reg_name +{ + const char * name; + int value; +}; + +/* Generic assembler global variables which must be defined by all targets. */ + +/* Characters which always start a comment. */ +const char comment_chars[] = "#"; + +/* Characters which start a comment at the beginning of a line. */ +const char line_comment_chars[] = ";#"; + +/* Characters which may be used to separate multiple commands on a + single line. */ +const char line_separator_chars[] = ";"; + +/* Characters which are used to indicate an exponent in a floating + point number. */ +const char EXP_CHARS[] = "eE"; + +/* Characters which mean that a number is a floating point constant, + as in 0d1.0. */ +const char FLT_CHARS[] = "dD"; + + +const relax_typeS md_relax_table[] = +{ + /* Conditional branches. */ + {0xff, -0x100, 2, 1}, + {0x1fffff, -0x200000, 6, 0}, + /* Unconditional branches. */ + {0xff, -0x100, 2, 3}, + {0x1fffff, -0x200000, 4, 0}, +}; + + +static segT sdata_section = NULL; +static segT zdata_section = NULL; +static segT sbss_section = NULL; +static segT zbss_section = NULL; +static segT rosdata_section = NULL; +static segT rozdata_section = NULL; +static segT scommon_section = NULL; +static segT zcommon_section = NULL; + +/* fixups */ +#define MAX_INSN_FIXUPS (5) +struct v810_fixup +{ + expressionS exp; + int opindex; + bfd_reloc_code_real_type reloc; +}; + +struct v810_fixup fixups [MAX_INSN_FIXUPS]; +static int fc; + + +void +v810_sdata (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (sdata_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_zdata (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (zdata_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_sbss (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (sbss_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_zbss (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (zbss_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_rosdata (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (rosdata_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_rozdata (int ignore) +{ + obj_elf_section_change_hook(); + + subseg_set (rozdata_section, (subsegT) get_absolute_expression ()); + + demand_empty_rest_of_line (); +} + +void +v810_bss (int ignore) +{ + register int temp = get_absolute_expression (); + + obj_elf_section_change_hook(); + + subseg_set (bss_section, (subsegT) temp); + + demand_empty_rest_of_line (); +} + +void +v810_offset (int ignore) +{ + int temp = get_absolute_expression (); + + temp -= frag_now_fix(); + + if (temp > 0) + (void) frag_more (temp); + + demand_empty_rest_of_line (); +} + +/* Copied from obj_elf_common() in gas/config/obj-elf.c */ +static void +v810_comm (area) + int area; +{ + char * name; + char c; + char * p; + int temp; + int size; + symbolS * symbolP; + int have_align; + + name = input_line_pointer; + c = get_symbol_end (); + + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + + SKIP_WHITESPACE (); + + if (*input_line_pointer != ',') + { + as_bad (_("Expected comma after symbol-name")); + ignore_rest_of_line (); + return; + } + + input_line_pointer ++; /* skip ',' */ + + if ((temp = get_absolute_expression ()) < 0) + { + /* xgettext:c-format */ + as_bad (_(".COMMon length (%d.) < 0! Ignored."), temp); + ignore_rest_of_line (); + return; + } + + size = temp; + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + + if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) + { + as_bad (_("Ignoring attempt to re-define symbol")); + ignore_rest_of_line (); + return; + } + + if (S_GET_VALUE (symbolP) != 0) + { + if (S_GET_VALUE (symbolP) != size) + { + /* xgettext:c-format */ + as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."), + S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); + } + } + + know (symbol_get_frag (symbolP) == & zero_address_frag); + + if (*input_line_pointer != ',') + have_align = 0; + else + { + have_align = 1; + input_line_pointer++; + SKIP_WHITESPACE (); + } + + if (! have_align || *input_line_pointer != '"') + { + if (! have_align) + temp = 0; + else + { + temp = get_absolute_expression (); + + if (temp < 0) + { + temp = 0; + as_warn (_("Common alignment negative; 0 assumed")); + } + } + + if (symbol_get_obj (symbolP)->local) + { + segT old_sec; + int old_subsec; + char * pfrag; + int align; + flagword applicable; + + old_sec = now_seg; + old_subsec = now_subseg; + + applicable = bfd_applicable_section_flags (stdoutput); + + applicable &= SEC_ALLOC; + + switch (area) + { + case AREA_SDA: + if (sbss_section == NULL) + { + sbss_section = subseg_new (".sbss", 0); + + bfd_set_section_flags (stdoutput, sbss_section, applicable); + + seg_info (sbss_section)->bss = 1; + } + break; + + case AREA_ZDA: + if (zbss_section == NULL) + { + zbss_section = subseg_new (".zbss", 0); + + bfd_set_section_flags (stdoutput, sbss_section, applicable); + + seg_info (zbss_section)->bss = 1; + } + break; + + } + + if (temp) + { + /* convert to a power of 2 alignment */ + for (align = 0; (temp & 1) == 0; temp >>= 1, ++align) + ; + + if (temp != 1) + { + as_bad (_("Common alignment not a power of 2")); + ignore_rest_of_line (); + return; + } + } + else + align = 0; + + switch (area) + { + case AREA_SDA: + record_alignment (sbss_section, align); + obj_elf_section_change_hook(); + subseg_set (sbss_section, 0); + break; + + case AREA_ZDA: + record_alignment (zbss_section, align); + obj_elf_section_change_hook(); + subseg_set (zbss_section, 0); + break; + + default: + abort(); + } + + if (align) + frag_align (align, 0, 0); + + switch (area) + { + case AREA_SDA: + if (S_GET_SEGMENT (symbolP) == sbss_section) + symbol_get_frag (symbolP)->fr_symbol = 0; + break; + + case AREA_ZDA: + if (S_GET_SEGMENT (symbolP) == zbss_section) + symbol_get_frag (symbolP)->fr_symbol = 0; + break; + + default: + abort (); + } + + symbol_set_frag (symbolP, frag_now); + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, + (offsetT) size, (char *) 0); + *pfrag = 0; + S_SET_SIZE (symbolP, size); + + switch (area) + { + case AREA_SDA: + S_SET_SEGMENT (symbolP, sbss_section); + break; + + case AREA_ZDA: + S_SET_SEGMENT (symbolP, zbss_section); + break; + + default: + abort(); + } + + S_CLEAR_EXTERNAL (symbolP); + obj_elf_section_change_hook(); + subseg_set (old_sec, old_subsec); + } + else + { + allocate_common: + S_SET_VALUE (symbolP, (valueT) size); + S_SET_ALIGN (symbolP, temp); + S_SET_EXTERNAL (symbolP); + + switch (area) + { + case AREA_SDA: + if (scommon_section == NULL) + { + flagword applicable; + + applicable = bfd_applicable_section_flags (stdoutput); + + scommon_section = subseg_new (".scommon", 0); + + bfd_set_section_flags (stdoutput, scommon_section, applicable + & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA + | SEC_HAS_CONTENTS) | SEC_IS_COMMON); + } + S_SET_SEGMENT (symbolP, scommon_section); + break; + + case AREA_ZDA: + if (zcommon_section == NULL) + { + flagword applicable; + + applicable = bfd_applicable_section_flags (stdoutput); + + zcommon_section = subseg_new (".zcommon", 0); + + bfd_set_section_flags (stdoutput, zcommon_section, applicable + & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA + | SEC_HAS_CONTENTS) | SEC_IS_COMMON); + } + S_SET_SEGMENT (symbolP, zcommon_section); + break; + + default: + abort(); + } + } + } + else + { + input_line_pointer++; + /* @@ Some use the dot, some don't. Can we get some consistency?? */ + if (*input_line_pointer == '.') + input_line_pointer++; + /* @@ Some say data, some say bss. */ + if (strncmp (input_line_pointer, "bss\"", 4) + && strncmp (input_line_pointer, "data\"", 5)) + { + while (*--input_line_pointer != '"') + ; + input_line_pointer--; + goto bad_common_segment; + } + while (*input_line_pointer++ != '"') + ; + goto allocate_common; + } + + symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; + + demand_empty_rest_of_line (); + return; + + { + bad_common_segment: + p = input_line_pointer; + while (*p && *p != '\n') + p++; + c = *p; + *p = '\0'; + as_bad (_("bad .common segment %s"), input_line_pointer + 1); + *p = c; + input_line_pointer = p; + ignore_rest_of_line (); + return; + } +} + +void +set_machine (int number) +{ + machine = number; + bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); + + switch (machine) + { + case 0: processor_mask = PROCESSOR_V810; break; + case bfd_mach_v830: processor_mask = PROCESSOR_V830; break; + } +} + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + {"sdata", v810_sdata, 0}, + {"zdata", v810_zdata, 0}, + {"sbss", v810_sbss, 0}, + {"zbss", v810_zbss, 0}, + {"rosdata", v810_rosdata, 0}, + {"rozdata", v810_rozdata, 0}, + {"bss", v810_bss, 0}, + {"offset", v810_offset, 0}, + {"word", cons, 4}, + {"zcomm", v810_comm, AREA_ZDA}, + {"scomm", v810_comm, AREA_SDA}, + {"v810", set_machine, 0}, + {"v830", set_machine, bfd_mach_v830}, + { NULL, NULL, 0} +}; + +/* Opcode hash table. */ +static struct hash_control *v810_hash; + +/* This table is sorted. Suitable for searching by a binary search. */ +static const struct reg_name pre_defined_registers[] = +{ + { "gp", 4 }, /* gp - global ptr */ + { "hp", 2 }, /* hp - handler stack ptr */ + { "lp", 31 }, /* lp - link ptr */ + { "r0", 0 }, + { "r1", 1 }, + { "r10", 10 }, + { "r11", 11 }, + { "r12", 12 }, + { "r13", 13 }, + { "r14", 14 }, + { "r15", 15 }, + { "r16", 16 }, + { "r17", 17 }, + { "r18", 18 }, + { "r19", 19 }, + { "r2", 2 }, + { "r20", 20 }, + { "r21", 21 }, + { "r22", 22 }, + { "r23", 23 }, + { "r24", 24 }, + { "r25", 25 }, + { "r26", 26 }, + { "r27", 27 }, + { "r28", 28 }, + { "r29", 29 }, + { "r3", 3 }, + { "r30", 30 }, + { "r31", 31 }, + { "r4", 4 }, + { "r5", 5 }, + { "r6", 6 }, + { "r7", 7 }, + { "r8", 8 }, + { "r9", 9 }, + { "sp", 3 }, /* sp - stack ptr */ + { "tp", 5 }, /* tp - text ptr */ + { "zero", 0 }, +}; +#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct reg_name)) + + +static const struct reg_name system_registers[] = +{ + { "adtre", 25 }, + { "chcw", 24 }, + { "ecr", 4 }, + { "eipc", 0 }, + { "eipsw", 1 }, + { "fepc", 2 }, + { "fepsw", 3 }, + { "pir", 6 }, + { "psw", 5 }, + { "sr0", 0 }, + { "sr1", 1 }, + { "sr10", 10 }, + { "sr11", 11 }, + { "sr12", 12 }, + { "sr13", 13 }, + { "sr14", 14 }, + { "sr15", 15 }, + { "sr16", 16 }, + { "sr17", 17 }, + { "sr18", 18 }, + { "sr19", 19 }, + { "sr2", 2 }, + { "sr20", 20 }, + { "sr21", 21 }, + { "sr22", 22 }, + { "sr23", 23 }, + { "sr24", 24 }, + { "sr25", 25 }, + { "sr26", 26 }, + { "sr27", 27 }, + { "sr28", 28 }, + { "sr29", 29 }, + { "sr3", 3 }, + { "sr30", 30 }, + { "sr31", 31 }, + { "sr4", 4 }, + { "sr5", 5 }, + { "sr6", 6 }, + { "sr7", 7 }, + { "sr8", 8 }, + { "sr9", 9 }, + { "tkcw", 7 }, +}; +#define SYSREG_NAME_CNT (sizeof (system_registers) / sizeof (struct reg_name)) + +static const struct reg_name system_list_registers[] = +{ + {"PS", 5 }, + {"SR", 0 + 1} +}; +#define SYSREGLIST_NAME_CNT (sizeof (system_list_registers) / sizeof (struct reg_name)) + +static const struct reg_name cc_names[] = +{ + { "c", 0x1 }, + { "e", 0x2 }, + { "ge", 0xe }, + { "gt", 0xf }, + { "h", 0xb }, + { "l", 0x1 }, + { "le", 0x7 }, + { "lt", 0x6 }, + { "n", 0x4 }, + { "nc", 0x9 }, + { "ne", 0xa }, + { "nh", 0x3 }, + { "nl", 0x9 }, + { "ns", 0xc }, + { "nv", 0x8 }, + { "nz", 0xa }, + { "p", 0xc }, + { "s", 0x4 }, + { "sa", 0xd }, + { "t", 0x5 }, + { "v", 0x0 }, + { "z", 0x2 }, +}; +#define CC_NAME_CNT (sizeof (cc_names) / sizeof (struct reg_name)) + +/* reg_name_search does a binary search of the given register table + to see if "name" is a valid regiter name. Returns the register + number from the array on success, or -1 on failure. */ + +static int +reg_name_search (regs, regcount, name, accept_numbers) + const struct reg_name * regs; + int regcount; + const char * name; + boolean accept_numbers; +{ + int middle, low, high; + int cmp; + symbolS * symbolP; + + /* If the register name is a symbol, then evaluate it. */ + if ((symbolP = symbol_find (name)) != NULL) + { + /* If the symbol is an alias for another name then use that. + If the symbol is an alias for a number, then return the number. */ + if (symbol_equated_p (symbolP)) + { + name = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol); + } + else if (accept_numbers) + { + int reg = S_GET_VALUE (symbolP); + + if (reg >= 0 && reg <= 31) + return reg; + } + + /* Otherwise drop through and try parsing name normally. */ + } + + low = 0; + high = regcount - 1; + + do + { + middle = (low + high) / 2; + cmp = strcasecmp (name, regs[middle].name); + if (cmp < 0) + high = middle - 1; + else if (cmp > 0) + low = middle + 1; + else + return regs[middle].value; + } + while (low <= high); + return -1; +} + + +/* Summary of register_name(). + * + * in: Input_line_pointer points to 1st char of operand. + * + * out: A expressionS. + * The operand may have been a register: in this case, X_op == O_register, + * X_add_number is set to the register number, and truth is returned. + * Input_line_pointer->(next non-blank) char after operand, or is in + * its original state. + */ +static boolean +register_name (expressionP) + expressionS * expressionP; +{ + int reg_number; + char * name; + char * start; + char c; + + /* Find the spelling of the operand */ + start = name = input_line_pointer; + + c = get_symbol_end (); + + reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, + name, FALSE); + + * input_line_pointer = c; /* put back the delimiting char */ + + /* look to see if it's in the register table */ + if (reg_number >= 0) + { + expressionP->X_op = O_register; + expressionP->X_add_number = reg_number; + + /* make the rest nice */ + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + + return true; + } + else + { + /* reset the line as if we had not done anything */ + input_line_pointer = start; + + return false; + } +} + +/* Summary of system_register_name(). + * + * in: Input_line_pointer points to 1st char of operand. + * expressionP points to an expression structure to be filled in. + * accept_numbers is true iff numerical register names may be used. + * accept_list_names is true iff the special names PS and SR may be + * accepted. + * + * out: A expressionS structure in expressionP. + * The operand may have been a register: in this case, X_op == O_register, + * X_add_number is set to the register number, and truth is returned. + * Input_line_pointer->(next non-blank) char after operand, or is in + * its original state. + */ +static boolean +system_register_name (expressionP, accept_numbers, accept_list_names) + expressionS * expressionP; + boolean accept_numbers; + boolean accept_list_names; +{ + int reg_number; + char * name; + char * start; + char c; + + /* Find the spelling of the operand */ + start = name = input_line_pointer; + + c = get_symbol_end (); + reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name, + accept_numbers); + + * input_line_pointer = c; /* put back the delimiting char */ + + if (reg_number < 0 + && accept_numbers) + { + input_line_pointer = start; /* reset input_line pointer */ + + if (isdigit (* input_line_pointer)) + { + reg_number = strtol (input_line_pointer, & input_line_pointer, 10); + + /* Make sure that the register number is allowable. */ + if ( reg_number < 0 + || reg_number > 5 + && reg_number < 16 + || reg_number > 20 + ) + { + reg_number = -1; + } + } + else if (accept_list_names) + { + c = get_symbol_end (); + reg_number = reg_name_search (system_list_registers, + SYSREGLIST_NAME_CNT, name, FALSE); + + * input_line_pointer = c; /* put back the delimiting char */ + } + } + + /* look to see if it's in the register table */ + if (reg_number >= 0) + { + expressionP->X_op = O_register; + expressionP->X_add_number = reg_number; + + /* make the rest nice */ + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + + return true; + } + else + { + /* reset the line as if we had not done anything */ + input_line_pointer = start; + + return false; + } +} + +/* Summary of cc_name(). + * + * in: Input_line_pointer points to 1st char of operand. + * + * out: A expressionS. + * The operand may have been a register: in this case, X_op == O_register, + * X_add_number is set to the register number, and truth is returned. + * Input_line_pointer->(next non-blank) char after operand, or is in + * its original state. + */ +static boolean +cc_name (expressionP) + expressionS * expressionP; +{ + int reg_number; + char * name; + char * start; + char c; + + /* Find the spelling of the operand */ + start = name = input_line_pointer; + + c = get_symbol_end (); + reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE); + + * input_line_pointer = c; /* put back the delimiting char */ + + /* look to see if it's in the register table */ + if (reg_number >= 0) + { + expressionP->X_op = O_constant; + expressionP->X_add_number = reg_number; + + /* make the rest nice */ + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + + return true; + } + else + { + /* reset the line as if we had not done anything */ + input_line_pointer = start; + + return false; + } +} + +static void +skip_white_space (void) +{ + while ( * input_line_pointer == ' ' + || * input_line_pointer == '\t') + ++ input_line_pointer; +} + + +CONST char * md_shortopts = "m:"; + +struct option md_longopts[] = +{ + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof md_longopts; + + +void +md_show_usage (stream) + FILE * stream; +{ + fprintf (stream, _(" V810 options:\n")); + fprintf (stream, _(" -mwarn-signed-overflow Warn if signed immediate values overflow\n")); + fprintf (stream, _(" -mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n")); + fprintf (stream, _(" -mv810 The code is targeted at the v810\n")); + fprintf (stream, _(" -mv830 The code is targeted at the v830\n")); +} + +int +md_parse_option (c, arg) + int c; + char * arg; +{ + if (c != 'm') + { + /* xgettext:c-format */ + fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg); + return 0; + } + + if (strcmp (arg, "warn-signed-overflow") == 0) + { + warn_signed_overflows = TRUE; + } + else if (strcmp (arg, "warn-unsigned-overflow") == 0) + { + warn_unsigned_overflows = TRUE; + } + else if (strcmp (arg, "v810") == 0) + { + machine = 0; + processor_mask = PROCESSOR_V810; + } + else if (strcmp (arg, "v830") == 0) + { + machine = bfd_mach_v830; + processor_mask = PROCESSOR_V830; + } + else + { + /* xgettext:c-format */ + fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg); + return 0; + } + + return 1; +} + +symbolS * +md_undefined_symbol (name) + char * name; +{ + return 0; +} + +char * +md_atof (type, litp, sizep) + int type; + char * litp; + int * sizep; +{ + int prec; + LITTLENUM_TYPE words[4]; + char * t; + int i; + + switch (type) + { + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + break; + + 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 * 2; + + for (i = prec - 1; i >= 0; i--) + { + md_number_to_chars (litp, (valueT) words[i], 2); + litp += 2; + } + + return NULL; +} + + +/* Very gross. */ +void +md_convert_frag (abfd, sec, fragP) + bfd * abfd; + asection * sec; + fragS * fragP; +{ + subseg_change (sec, 0); + + /* In range conditional or unconditional branch. */ + if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2) + { + fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode); + fragP->fr_var = 0; + fragP->fr_fix += 2; + } + /* Out of range conditional branch. Emit a branch around a jump. */ + else if (fragP->fr_subtype == 1) + { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + + /* Reverse the condition of the first branch. */ + buffer[1] ^= 0x10; + /* Mask off all the displacement bits. */ + buffer[0] &= 0x00; + buffer[1] &= 0xfe; + /* Now set the displacement bits so that we branch + around the unconditional branch. */ + buffer[0] |= 0x06; + + /* Now create the unconditional branch + fixup to the final + target. */ + md_number_to_chars (buffer + 2, 0x0000a800, 4); + fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_UNUSED + + (int) fragP->fr_opcode + 1); + fragP->fr_var = 0; + fragP->fr_fix += 6; + } + /* Out of range unconditional branch. Emit a jump. */ + else if (fragP->fr_subtype == 3) + { + md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x0000a800, 4); + fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_UNUSED + + (int) fragP->fr_opcode + 1); + fragP->fr_var = 0; + fragP->fr_fix += 4; + } + else + abort (); +} + +valueT +md_section_align (seg, addr) + asection * seg; + valueT addr; +{ + int align = bfd_get_section_alignment (stdoutput, seg); + return ((addr + (1 << align) - 1) & (-1 << align)); +} + +void +md_begin () +{ + char * prev_name = ""; + register const struct v810_opcode * op; + flagword applicable; + + if (strncmp (TARGET_CPU, "v830", 4) == 0) + { + if (machine == -1) + machine = bfd_mach_v830; + + if (processor_mask == -1) + processor_mask = PROCESSOR_V830; + } + else + if (strncmp (TARGET_CPU, "v810", 4) == 0) + { + if (machine == -1) + machine = 0; + + if (processor_mask == -1) + processor_mask = PROCESSOR_V810; + } + else + /* xgettext:c-format */ + as_bad (_("Unable to determine default target processor from string: %s"), + TARGET_CPU); + + v810_hash = hash_new(); + + /* Insert unique names into hash table. The V810 instruction set + has many identical opcode names that have different opcodes based + on the operands. This hash table then provides a quick index to + the first opcode with a particular name in the opcode table. */ + + op = v810_opcodes; + while (op->name) + { + if (strcmp (prev_name, op->name)) + { + prev_name = (char *) op->name; + hash_insert (v810_hash, op->name, (char *) op); + } + op++; + } + + bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); + + applicable = bfd_applicable_section_flags (stdoutput); + + /* Restore text section as the current default. */ + subseg_set (text_section, 0); +} + + +static bfd_reloc_code_real_type +handle_sdaoff (const struct v810_operand * operand) +{ + if (operand == NULL) return BFD_RELOC_V810_SDA_16_16_OFFSET; + if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V810_SDA_15_16_OFFSET; + + if ( operand->bits != 16 + || operand->shift != 16) + { + as_bad (_("sdaoff() relocation used on an instruction which does not support it")); + return BFD_RELOC_64; /* Used to indicate an error condition. */ + } + + return BFD_RELOC_V810_SDA_16_16_OFFSET; +} + +static bfd_reloc_code_real_type +handle_zdaoff (const struct v810_operand * operand) +{ + if (operand == NULL) return BFD_RELOC_V810_ZDA_16_16_OFFSET; + if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V810_ZDA_15_16_OFFSET; + + if ( operand->bits != 16 + || operand->shift != 16) + { + as_bad (_("zdaoff() relocation used on an instruction which does not support it")); + return BFD_RELOC_64; /* Used to indicate an error condition. */ + } + + return BFD_RELOC_V810_ZDA_16_16_OFFSET; +} + +/* Warning: The code in this function relies upon the definitions + in the v810_operands[] array (defined in opcodes/v810-opc.c) + matching the hard coded values contained herein. */ + +static bfd_reloc_code_real_type +v810_reloc_prefix (const struct v810_operand * operand) +{ + boolean paren_skipped = false; + + + /* Skip leading opening parenthesis. */ + if (* input_line_pointer == '(') + { + ++ input_line_pointer; + paren_skipped = true; + } + +#define CHECK_(name, reloc) \ + if (strncmp (input_line_pointer, name "(", strlen (name) + 1) == 0) \ + { \ + input_line_pointer += strlen (name); \ + return reloc; \ + } + + CHECK_ ("hi0", BFD_RELOC_HI16); + CHECK_ ("hi", BFD_RELOC_HI16_S); + CHECK_ ("lo", BFD_RELOC_LO16); + CHECK_ ("sdaoff", handle_sdaoff (operand)); + CHECK_ ("zdaoff", handle_zdaoff (operand)); + CHECK_ ("hilo", BFD_RELOC_32); + + /* Restore skipped parenthesis. */ + if (paren_skipped) + -- input_line_pointer; + + return BFD_RELOC_UNUSED; +} + +/* Insert an operand value into an instruction. */ + +static unsigned long +v810_insert_operand (insn, operand, val, file, line, str) + unsigned long insn; + const struct v810_operand * operand; + offsetT val; + char * file; + unsigned int line; + char * str; +{ + if (operand->insert) + { + const char * message = NULL; + + insn = operand->insert (insn, val, & message); + if (message != NULL) + { + if ((operand->flags & V810_OPERAND_SIGNED) + && ! warn_signed_overflows + && strstr (message, "out of range") != NULL) + { + /* skip warning... */ + } + else if ((operand->flags & V810_OPERAND_SIGNED) == 0 + && ! warn_unsigned_overflows + && strstr (message, "out of range") != NULL) + { + /* skip warning... */ + } + else if (str) + { + if (file == (char *) NULL) + as_warn ("%s: %s", str, message); + else + as_warn_where (file, line, "%s: %s", str, message); + } + else + { + if (file == (char *) NULL) + as_warn (message); + else + as_warn_where (file, line, message); + } + } + } + else + { + if (operand->bits != 32) + { + long min, max; + offsetT test; + + if ((operand->flags & V810_OPERAND_SIGNED) != 0) + { + if (! warn_signed_overflows) + max = (1 << operand->bits) - 1; + else + max = (1 << (operand->bits - 1)) - 1; + + min = - (1 << (operand->bits - 1)); + } + else + { + max = (1 << operand->bits) - 1; + + if (! warn_unsigned_overflows) + min = - (1 << (operand->bits - 1)); + else + min = 0; + } + + if (val < (offsetT) min || val > (offsetT) max) + { + /* xgettext:c-format */ + const char * err = _("operand out of range (%s not between %ld and %ld)"); + char buf[100]; + + /* Restore min and mix to expected values for decimal ranges. */ + if ((operand->flags & V810_OPERAND_SIGNED) + && ! warn_signed_overflows) + max = (1 << (operand->bits - 1)) - 1; + + if (! (operand->flags & V810_OPERAND_SIGNED) + && ! warn_unsigned_overflows) + min = 0; + + if (str) + { + sprintf (buf, "%s: ", str); + + sprint_value (buf + strlen (buf), val); + } + else + sprint_value (buf, val); + + if (file == (char *) NULL) + as_warn (err, buf, min, max); + else + as_warn_where (file, line, err, buf, min, max); + } + } + + insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); + } + + return insn; +} + + +static char copy_of_instruction [128]; + +void +md_assemble (str) + char * str; +{ + char * s; + char * start_of_operands; + struct v810_opcode * opcode; + struct v810_opcode * next_opcode; + const unsigned char * opindex_ptr; + int next_opindex; + int relaxable; + unsigned long insn; + unsigned long insn_size; + char * f; + int i; + int match; + boolean extra_data_after_insn = false; + unsigned extra_data_len; + unsigned long extra_data; + char * saved_input_line_pointer; + + + strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1); + + /* Get the opcode. */ + for (s = str; *s != '\0' && ! isspace (*s); s++) + continue; + + if (*s != '\0') + *s++ = '\0'; + + /* find the first opcode with the proper name */ + opcode = (struct v810_opcode *) hash_find (v810_hash, str); + if (opcode == NULL) + { + /* xgettext:c-format */ + as_bad (_("Unrecognized opcode: `%s'"), str); + ignore_rest_of_line (); + return; + } + + str = s; + while (isspace (* str)) + ++ str; + + start_of_operands = str; + + saved_input_line_pointer = input_line_pointer; + + for (;;) + { + const char * errmsg = NULL; + + match = 0; + + if ((opcode->processors & processor_mask) == 0) + { + errmsg = _("Target processor does not support this instruction."); + goto error; + } + + relaxable = 0; + fc = 0; + next_opindex = 0; + insn = opcode->opcode; + extra_data_after_insn = false; + + input_line_pointer = str = start_of_operands; + + for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr ++) + { + const struct v810_operand * operand; + char * hold; + expressionS ex; + bfd_reloc_code_real_type reloc; + + if (next_opindex == 0) + { + operand = & v810_operands[ * opindex_ptr ]; + } + else + { + operand = & v810_operands[ next_opindex ]; + next_opindex = 0; + } + + errmsg = NULL; + + while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') + ++ str; + + if (operand->flags & V810_OPERAND_RELAX) + relaxable = 1; + + /* Gather the operand. */ + hold = input_line_pointer; + input_line_pointer = str; + + /* lo(), hi(), hi0(), etc... */ + if ((reloc = v810_reloc_prefix (operand)) != BFD_RELOC_UNUSED) + { + /* This is a fake reloc, used to indicate an error condition. */ + if (reloc == BFD_RELOC_64) + { + match = 1; + goto error; + } + + expression (& ex); + + if (ex.X_op == O_constant) + { + switch (reloc) + { + case BFD_RELOC_V810_ZDA_16_16_OFFSET: + /* To cope with "not1 7, zdaoff(0xfffff006)[r0]" + and the like. */ + /* Fall through. */ + + case BFD_RELOC_LO16: + { + /* Truncate, then sign extend the value. */ + ex.X_add_number = SEXT16 (ex.X_add_number); + break; + } + + case BFD_RELOC_HI16: + { + /* Truncate, then sign extend the value. */ + ex.X_add_number = SEXT16 (ex.X_add_number >> 16); + break; + } + + case BFD_RELOC_HI16_S: + { + /* Truncate, then sign extend the value. */ + int temp = (ex.X_add_number >> 16) & 0xffff; + + temp += (ex.X_add_number >> 15) & 1; + + ex.X_add_number = SEXT16 (temp); + break; + } + + case BFD_RELOC_32: + if ((operand->flags & 0) == 0) + { + errmsg = _("immediate operand is too large"); + goto error; + } + + extra_data_after_insn = true; + extra_data_len = 4; + extra_data = ex.X_add_number; + ex.X_add_number = 0; + break; + + default: + fprintf (stderr, "reloc: %d\n", reloc); + as_bad (_("AAARG -> unhandled constant reloc")); + break; + } + + if (fc > MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[ fc ].exp = ex; + fixups[ fc ].opindex = * opindex_ptr; + fixups[ fc ].reloc = reloc; + fc++; + } + else + { + if (reloc == BFD_RELOC_32) + { + if ((operand->flags & 0) == 0) + { + errmsg = _("immediate operand is too large"); + goto error; + } + + extra_data_after_insn = true; + extra_data_len = 4; + extra_data = ex.X_add_number; + } + + if (fc > MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[ fc ].exp = ex; + fixups[ fc ].opindex = * opindex_ptr; + fixups[ fc ].reloc = reloc; + fc++; + } + } + else + { + errmsg = NULL; + + if ((operand->flags & V810_OPERAND_REG) != 0) + { + if (!register_name (& ex)) + { + errmsg = _("invalid register name"); + } + else if ((operand->flags & 0) + && ex.X_add_number == 0) + { + errmsg = _("register r0 cannot be used here"); + + /* Force an error message to be generated by + skipping over any following potential matches + for this opcode. */ + opcode += 3; + } + } + else if ((operand->flags & V810_OPERAND_SRG) != 0) + { + if (!system_register_name (& ex, true, false)) + { + errmsg = _("invalid system register name"); + } + } + else if ((operand->flags & 0) != 0) + { + char * start = input_line_pointer; + char c = get_symbol_end (); + + if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0) + { + /* Put things back the way we found them. */ + *input_line_pointer = c; + input_line_pointer = start; + errmsg = _("expected EP register"); + goto error; + } + + *input_line_pointer = c; + str = input_line_pointer; + input_line_pointer = hold; + + while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') + ++ str; + continue; + } + else if ((operand->flags & V810_OPERAND_CC) != 0) + { + if (!cc_name (& ex)) + { + errmsg = _("invalid condition code name"); + } + } + else if (register_name (& ex) + && (operand->flags & V810_OPERAND_REG) == 0) + { + char c; + int exists = 0; + + /* It is possible that an alias has been defined that + matches a register name. For example the code may + include a ".set ZERO, 0" directive, which matches + the register name "zero". Attempt to reparse the + field as an expression, and only complain if we + cannot generate a constant. */ + + input_line_pointer = str; + + c = get_symbol_end (); + + if (symbol_find (str) != NULL) + exists = 1; + + * input_line_pointer = c; + input_line_pointer = str; + + expression (& ex); + + if (ex.X_op != O_constant) + { + /* If this register is actually occuring too early on + the parsing of the instruction, (because another + field is missing) then report this. */ + if (opindex_ptr[1] != 0 + && (v810_operands [opindex_ptr [1]].flags & V810_OPERAND_REG)) + errmsg = _("syntax error: value is missing before the register name"); + else + errmsg = _("syntax error: register not expected"); + + /* If we created a symbol in the process of this test then + delete it now, so that it will not be output with the real + symbols... */ + if (exists == 0 + && ex.X_op == O_symbol) + symbol_remove (ex.X_add_symbol, + & symbol_rootP, & symbol_lastP); + } + } + else if (system_register_name (& ex, false, false) + && (operand->flags & V810_OPERAND_SRG) == 0) + { + errmsg = _("syntax error: system register not expected"); + } + else if (cc_name (&ex) + && (operand->flags & V810_OPERAND_CC) == 0) + { + errmsg = _("syntax error: condition code not expected"); + } + else + { + expression (& ex); + + if (ex.X_op == O_constant && (operand->flags & V810_OPERAND_DISP) != 0) + { + ex.X_add_symbol = &abs_symbol; + ex.X_op = O_symbol; + ex.X_op_symbol = NULL; + } + + /* Special case: + If we are assembling a MOV instruction (or a CALLT.... :-) + and the immediate value does not fit into the bits + available then create a fake error so that the next MOV + instruction will be selected. This one has a 32 bit + immediate field. */ + + if (((insn & 0xfc00) == 0x4000) + && ex.X_op == O_constant + && (ex.X_add_number < (- (1 << (operand->bits - 1))) + || ex.X_add_number > ((1 << operand->bits) - 1))) + errmsg = _("immediate operand is too large"); + } + + if (errmsg) + goto error; + +/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n", + insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */ + + switch (ex.X_op) + { + case O_illegal: + errmsg = _("illegal operand"); + goto error; + case O_absent: + errmsg = _("missing operand"); + goto error; + case O_register: + if ((operand->flags & (V810_OPERAND_REG | V810_OPERAND_SRG)) == 0) + { + errmsg = _("invalid operand"); + goto error; + } + insn = v810_insert_operand (insn, operand, ex.X_add_number, + (char *) NULL, 0, + copy_of_instruction); + break; + + case O_constant: + insn = v810_insert_operand (insn, operand, ex.X_add_number, + (char *) NULL, 0, + copy_of_instruction); + break; + + default: + /* We need to generate a fixup for this expression. */ + if (fc >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[ fc ].exp = ex; + fixups[ fc ].opindex = * opindex_ptr; + fixups[ fc ].reloc = BFD_RELOC_UNUSED; + ++fc; + break; + } + } + + str = input_line_pointer; + input_line_pointer = hold; + + while (*str == ' ' || *str == ',' || *str == '[' || *str == ']' + || *str == ')') + ++str; + } + match = 1; + + error: + if (match == 0) + { + next_opcode = opcode + 1; + if (next_opcode->name != NULL + && strcmp (next_opcode->name, opcode->name) == 0) + { + opcode = next_opcode; + + /* Skip versions that are not supported by the target + processor. */ + if ((opcode->processors & processor_mask) == 0) + goto error; + + continue; + } + + as_bad ("%s: %s", copy_of_instruction, errmsg); + + if (* input_line_pointer == ']') + ++ input_line_pointer; + + ignore_rest_of_line (); + input_line_pointer = saved_input_line_pointer; + return; + } + break; + } + + while (isspace (*str)) + ++str; + + if (*str != '\0') + /* xgettext:c-format */ + as_bad (_("junk at end of line: `%s'"), str); + + input_line_pointer = str; + + /* Write out the instruction. */ + + if (relaxable && fc > 0) + { + insn_size = 2; + fc = 0; + + if (!strcmp (opcode->name, "br")) + { + f = frag_var (rs_machine_dependent, 4, 2, 2, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 2); + } + else + { + f = frag_var (rs_machine_dependent, 6, 4, 0, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 4); + } + } + else + { + /* Four byte insns have an opcode with the two high bits on. */ + if ((insn & 0xfc00) >= 0xa000) + insn_size = 4; + else + insn_size = 2; + + f = frag_more (insn_size); + + md_number_to_chars (f, insn, insn_size); + + if (extra_data_after_insn) + { + f = frag_more (extra_data_len); + + md_number_to_chars (f, extra_data, extra_data_len); + + extra_data_after_insn = false; + } + } + + /* Create any fixups. At this point we do not use a + bfd_reloc_code_real_type, but instead just use the + BFD_RELOC_UNUSED plus the operand index. This lets us easily + handle fixups for any operand type, although that is admittedly + not a very exciting feature. We pick a BFD reloc type in + md_apply_fix. */ + for (i = 0; i < fc; i++) + { + const struct v810_operand * operand; + bfd_reloc_code_real_type reloc; + + operand = & v810_operands[ fixups[i].opindex ]; + + reloc = fixups[i].reloc; + + if (reloc != BFD_RELOC_UNUSED) + { + reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput, + reloc); + int size; + int address; + fixS * fixP; + + if (!reloc_howto) + abort(); + + size = bfd_get_reloc_size (reloc_howto); + + /* XXX This will abort on an R_V810_8 reloc - + is this reloc actually used ? */ + if (size != 2 && size != 4) + abort (); + + address = (f - frag_now->fr_literal) + insn_size - size; + + if (reloc == BFD_RELOC_32) + { + address += 2; + } + + fixP = fix_new_exp (frag_now, address, size, + & fixups[i].exp, + reloc_howto->pc_relative, + reloc); + + switch (reloc) + { + case BFD_RELOC_LO16: + case BFD_RELOC_HI16: + case BFD_RELOC_HI16_S: + fixP->fx_no_overflow = 1; + break; + } + } + else + { + fix_new_exp ( + frag_now, + f - frag_now->fr_literal, 4, + & fixups[i].exp, + 1 /* FIXME: V810_OPERAND_RELATIVE ??? */, + (bfd_reloc_code_real_type) (fixups[i].opindex + + (int) BFD_RELOC_UNUSED) + ); + } + } + + input_line_pointer = saved_input_line_pointer; +} + + +/* If while processing a fixup, a reloc really needs to be created */ +/* then it is done here. */ + +arelent * +tc_gen_reloc (seg, fixp) + asection * seg; + fixS * fixp; +{ + arelent * reloc; + + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr= symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + /* xgettext:c-format */ + _("reloc %d not supported by object file format"), + (int) fixp->fx_r_type); + + xfree (reloc); + + return NULL; + } + + if ( fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT) + reloc->addend = fixp->fx_offset; + else + reloc->addend = fixp->fx_addnumber; + + return reloc; +} + +/* Assume everything will fit in two bytes, then expand as necessary. */ +int +md_estimate_size_before_relax (fragp, seg) + fragS * fragp; + asection * seg; +{ + if (fragp->fr_subtype == 0) + fragp->fr_var = 4; + else if (fragp->fr_subtype == 2) + fragp->fr_var = 2; + else + abort (); + return 2; +} + +long +v810_pcrel_from_section (fixp, section) + fixS * fixp; + segT section; +{ + /* If the symbol is undefined, or in a section other than our own, + or it is weak (in which case it may well be in another section, + then let the linker figure it out. */ + if (fixp->fx_addsy != (symbolS *) NULL + && (! S_IS_DEFINED (fixp->fx_addsy) + || S_IS_WEAK (fixp->fx_addsy) + || (S_GET_SEGMENT (fixp->fx_addsy) != section))) + return 0; + + return fixp->fx_frag->fr_address + fixp->fx_where; +} + +int +md_apply_fix3 (fixp, valuep, seg) + fixS * fixp; + valueT * valuep; + segT seg; +{ + valueT value; + char * where; + + if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + { + fixp->fx_done = 0; + return 1; + } + + if (fixp->fx_addsy == (symbolS *) NULL) + { + value = * valuep; + fixp->fx_done = 1; + } + else if (fixp->fx_pcrel) + value = * valuep; + else + { + value = fixp->fx_offset; + if (fixp->fx_subsy != (symbolS *) NULL) + { + if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section) + value -= S_GET_VALUE (fixp->fx_subsy); + else + { + /* We don't actually support subtracting a symbol. */ + as_bad_where (fixp->fx_file, fixp->fx_line, + _("expression too complex")); + } + } + } + + if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) + { + int opindex; + const struct v810_operand * operand; + unsigned long insn; + + opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; + operand = & v810_operands[ opindex ]; + + /* Fetch the instruction, insert the fully resolved operand + value, and stuff the instruction back again. + + Note the instruction has been stored in little endian + format! */ + where = fixp->fx_frag->fr_literal + fixp->fx_where; + + insn = bfd_getl32 ((unsigned char *) where); + insn = v810_insert_operand (insn, operand, (offsetT) value, + fixp->fx_file, fixp->fx_line, NULL); + bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); + + if (fixp->fx_done) + { + /* Nothing else to do here. */ + return 1; + } + + /* Determine a BFD reloc value based on the operand information. + We are only prepared to turn a few of the operands into relocs. */ + + if (operand->bits == 26) + fixp->fx_r_type = BFD_RELOC_V810_26_PCREL; + else if (operand->bits == 9) + fixp->fx_r_type = BFD_RELOC_V810_9_PCREL; + else + { + /* fprintf (stderr, "bits: %d, insn: %x\n", operand->bits, insn); */ + + as_bad_where (fixp->fx_file, fixp->fx_line, + _("unresolved expression that must be resolved")); + fixp->fx_done = 1; + return 1; + } + } + else if (fixp->fx_done) + { + /* We still have to insert the value into memory! */ + where = fixp->fx_frag->fr_literal + fixp->fx_where; + + if (fixp->fx_size == 1) + * where = value & 0xff; + else if (fixp->fx_size == 2) + bfd_putl16 (value & 0xffff, (unsigned char *) where); + else if (fixp->fx_size == 4) + bfd_putl32 (value, (unsigned char *) where); + } + + fixp->fx_addnumber = value; + return 1; +} + + +/* Parse a cons expression. We have to handle hi(), lo(), etc + on the v810. */ +void +parse_cons_expression_v810 (exp) + expressionS * exp; +{ + /* See if there's a reloc prefix like hi() we have to handle. */ + hold_cons_reloc = v810_reloc_prefix (NULL); + + /* Do normal expression parsing. */ + expression (exp); +} + +/* Create a fixup for a cons expression. If parse_cons_expression_v810 + found a reloc prefix, then we use that reloc, else we choose an + appropriate one based on the size of the expression. */ +void +cons_fix_new_v810 (frag, where, size, exp) + fragS * frag; + int where; + int size; + expressionS *exp; +{ + if (hold_cons_reloc == BFD_RELOC_UNUSED) + { + if (size == 4) + hold_cons_reloc = BFD_RELOC_32; + if (size == 2) + hold_cons_reloc = BFD_RELOC_16; + if (size == 1) + hold_cons_reloc = BFD_RELOC_8; + } + + if (exp != NULL) + fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc); + else + fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc); +} + +boolean +v810_fix_adjustable (fixP) + fixS * fixP; +{ + if (fixP->fx_addsy == NULL) + return 1; + + /* Prevent all adjustments to global symbols. */ + if (S_IS_EXTERN (fixP->fx_addsy)) + return 0; + + if (S_IS_WEAK (fixP->fx_addsy)) + return 0; + + /* Don't adjust function names */ + if (S_IS_FUNCTION (fixP->fx_addsy)) + return 0; + + /* We need the symbol name for the VTABLE entries */ + if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + return 0; + + return 1; +} + +int +v810_force_relocation (fixP) + struct fix * fixP; +{ + if (fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)) + return 1; + + if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + return 1; + + return 0; +} diff -urN binutils-2.10.org/gas/config/tc-v810.h binutils-2.10/gas/config/tc-v810.h --- binutils-2.10.org/gas/config/tc-v810.h 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/config/tc-v810.h 2011-03-20 03:56:06.000000000 -0700 @@ -0,0 +1,80 @@ +/* tc-v810.h -- Header file for tc-v810.c. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#define TC_V810 + +#include + +#define TARGET_BYTES_BIG_ENDIAN 0 + +#ifndef BFD_ASSEMBLER + #error V810 support requires BFD_ASSEMBLER +#endif + +/* The target BFD architecture. */ +#define TARGET_ARCH bfd_arch_v810 + +/* The target BFD format. */ +#define TARGET_FORMAT "elf32-v810" + +#define MD_APPLY_FIX3 +#define md_operand(x) + +#define obj_fix_adjustable(fixP) v810_fix_adjustable(fixP) +#define TC_FORCE_RELOCATION(fixp) v810_force_relocation(fixp) +extern int v810_force_relocation PARAMS ((struct fix *)); + +/* Permit temporary numeric labels. */ +#define LOCAL_LABELS_FB 1 + +#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ + +/* We don't need to handle .word strangely. */ +#define WORKING_DOT_WORD + +#define md_number_to_chars number_to_chars_littleendian + +/* We need to handle lo(), hi(), etc etc in .hword, .word, etc + directives, so we have to parse "cons" expressions ourselves. */ +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_cons_expression_v810 (EXP) +#define TC_CONS_FIX_NEW cons_fix_new_v810 +/*extern const struct relax_type md_relax_table[]; +#define TC_GENERIC_RELAX_TABLE md_relax_table +*/ + +/* This section must be in the small data area (pointed to by GP). */ +#define SHF_V810_GPREL 0x10000000 +/* This section must be in the tiny data area (pointed to by EP). */ +#define SHF_V810_EPREL 0x20000000 +/* This section must be in the zero data area (pointed to by R0). */ +#define SHF_V810_R0REL 0x40000000 + +#define ELF_TC_SPECIAL_SECTIONS \ + { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V810_GPREL }, \ + { ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V810_GPREL }, \ + { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V810_GPREL }, \ + { ".scommon", SHT_V810_SCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V810_GPREL }, \ + { ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V810_R0REL }, \ + { ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V810_R0REL }, \ + { ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V810_R0REL }, \ + { ".zcommon", SHT_V810_ZCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V810_R0REL }, + +#define MD_PCREL_FROM_SECTION(fixP,section) v810_pcrel_from_section (fixP, section) +extern long v810_pcrel_from_section (); diff -urN binutils-2.10.org/gas/configure binutils-2.10/gas/configure --- binutils-2.10.org/gas/configure 2000-05-31 04:28:41.000000000 -0700 +++ binutils-2.10/gas/configure 2011-03-20 03:53:01.000000000 -0700 @@ -1640,6 +1640,7 @@ sparc64*) cpu_type=sparc arch=v9-64 ;; sparc86x*) cpu_type=sparc arch=sparc86x ;; sparc*) cpu_type=sparc arch=sparclite ;; # ??? See tc-sparc.c. + v810*) cpu_type=v810 ;; v850*) cpu_type=v850 ;; *) cpu_type=${cpu} ;; esac @@ -1887,6 +1888,9 @@ tic30-*-*coff*) fmt=coff bfd_gas=yes ;; tic80-*-*) fmt=coff ;; + v810-*-*) fmt=elf bfd_gas=yes ;; + v830-*-*) fmt=elf bfd_gas=yes ;; + v850-*-*) fmt=elf bfd_gas=yes ;; v850e-*-*) fmt=elf bfd_gas=yes ;; v850ea-*-*) fmt=elf bfd_gas=yes ;; diff -urN binutils-2.10.org/gas/configure.in binutils-2.10/gas/configure.in --- binutils-2.10.org/gas/configure.in 2000-05-31 04:28:42.000000000 -0700 +++ binutils-2.10/gas/configure.in 2011-03-20 03:53:01.000000000 -0700 @@ -118,6 +118,7 @@ sparc64*) cpu_type=sparc arch=v9-64 ;; sparc86x*) cpu_type=sparc arch=sparc86x ;; sparc*) cpu_type=sparc arch=sparclite ;; # ??? See tc-sparc.c. + v810*) cpu_type=v810 ;; v850*) cpu_type=v850 ;; *) cpu_type=${cpu} ;; esac @@ -361,6 +362,9 @@ tic30-*-*coff*) fmt=coff bfd_gas=yes ;; tic80-*-*) fmt=coff ;; + v810-*-*) fmt=elf bfd_gas=yes ;; + v830-*-*) fmt=elf bfd_gas=yes ;; + v850-*-*) fmt=elf bfd_gas=yes ;; v850e-*-*) fmt=elf bfd_gas=yes ;; v850ea-*-*) fmt=elf bfd_gas=yes ;; diff -urN binutils-2.10.org/gas/Makefile.am binutils-2.10/gas/Makefile.am --- binutils-2.10.org/gas/Makefile.am 2000-04-19 03:04:53.000000000 -0700 +++ binutils-2.10/gas/Makefile.am 2011-03-20 03:53:01.000000000 -0700 @@ -66,6 +66,7 @@ tic80 \ vax \ w65 \ + v810 \ v850 \ z8k @@ -236,6 +237,7 @@ config/tc-tic80.c \ config/tc-vax.c \ config/tc-w65.c \ + config/tc-v810.c \ config/tc-v850.c \ config/tc-z8k.c @@ -272,6 +274,7 @@ config/tc-tic80.h \ config/tc-vax.h \ config/tc-w65.h \ + config/tc-v810.h \ config/tc-v850.h \ config/tc-z8k.h @@ -1283,6 +1286,14 @@ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h \ emul.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h +DEPTC_v810_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ + $(srcdir)/config/tc-v810.h $(INCDIR)/coff/internal.h \ + $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/opcode/v810.h +DEPTC_v810_elf = $(INCDIR)/bin-bugs.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-v810.h \ + emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/v810.h DEPTC_v850_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-v850.h $(INCDIR)/coff/internal.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h subsegs.h \ @@ -1616,6 +1627,14 @@ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h \ emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h +DEPOBJ_v810_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ + $(srcdir)/config/tc-v810.h $(INCDIR)/coff/internal.h \ + $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h $(INCDIR)/obstack.h \ + subsegs.h +DEPOBJ_v810_elf = $(INCDIR)/bin-bugs.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-v810.h \ + emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h DEPOBJ_v850_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-v850.h $(INCDIR)/coff/internal.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h $(INCDIR)/obstack.h \ @@ -1844,6 +1863,11 @@ DEP_w65_elf = $(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-w65.h +DEP_v810_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v810.h \ + $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h +DEP_v810_elf = $(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-v810.h DEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h DEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ diff -urN binutils-2.10.org/gas/Makefile.in binutils-2.10/gas/Makefile.in --- binutils-2.10.org/gas/Makefile.in 2000-04-19 03:04:53.000000000 -0700 +++ binutils-2.10/gas/Makefile.in 2011-03-20 03:53:01.000000000 -0700 @@ -170,6 +170,7 @@ tic80 \ vax \ w65 \ + v810 \ v850 \ z8k @@ -346,6 +347,7 @@ config/tc-tic80.c \ config/tc-vax.c \ config/tc-w65.c \ + config/tc-v810.c \ config/tc-v850.c \ config/tc-z8k.c @@ -383,6 +385,7 @@ config/tc-tic80.h \ config/tc-vax.h \ config/tc-w65.h \ + config/tc-v810.h \ config/tc-v850.h \ config/tc-z8k.h @@ -1024,6 +1027,16 @@ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h \ emul.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h +DEPTC_v810_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ + $(srcdir)/config/tc-v810.h $(INCDIR)/coff/internal.h \ + $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/opcode/v810.h + +DEPTC_v810_elf = $(INCDIR)/bin-bugs.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-v810.h \ + emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/v810.h + DEPTC_v850_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-v850.h $(INCDIR)/coff/internal.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h subsegs.h \ @@ -1444,6 +1457,16 @@ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h \ emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h +DEPOBJ_v810_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ + $(srcdir)/config/tc-v810.h $(INCDIR)/coff/internal.h \ + $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h $(INCDIR)/obstack.h \ + subsegs.h + +DEPOBJ_v810_elf = $(INCDIR)/bin-bugs.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-v810.h \ + emul.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h + DEPOBJ_v850_coff = $(INCDIR)/bin-bugs.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-v850.h $(INCDIR)/coff/internal.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h emul.h $(INCDIR)/obstack.h \ @@ -1757,6 +1780,13 @@ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h +DEP_v810_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v810.h \ + $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h + +DEP_v810_elf = $(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-v810.h + DEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h diff -urN binutils-2.10.org/gas/testsuite/gas/v810/arith.s binutils-2.10/gas/testsuite/gas/v810/arith.s --- binutils-2.10.org/gas/testsuite/gas/v810/arith.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/arith.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,24 @@ + + .text + .global arith_opcodes +arith_opcodes: + add r5,r6 + add 5,r6 + addi 7,r5,r6 + divh r5,r6 + mulh r5,r6 + mulh 5,r6 + mulhi 7,r5,r6 + sar r5,r6 + sar 31,r6 + satadd r5,r6 + satadd 5,r6 + satsub r5,r6 + satsubi 7,r5,r6 + satsubr r5,r6 + shl r5,r6 + shl 31,r6 + shr r5,r6 + shr 31,r6 + sub r5,r6 + subr r5,r6 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/basic.exp binutils-2.10/gas/testsuite/gas/v810/basic.exp --- binutils-2.10.org/gas/testsuite/gas/v810/basic.exp 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/basic.exp 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,438 @@ +# Copyright (C) 1996 Free Software Foundation, Inc. + +# 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. */ + +# Please email any bugs, comments, and/or additions to this file to: +# DejaGnu@cygnus.com + +# Written by Cygnus Support. + +proc do_arith {} { + set testname "arith.s: Arithmetic operations" + set x 0 + + gas_start "arith.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + # -re "^ +\[0-9\]+ 0000 489A0000\[^\n\]*\n" { set x [expr $x+1] } + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 C531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 4532\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 05360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 4530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a E530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c E532\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e E5360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 E537A000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 BF32\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 C530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a 2532\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c A530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e 65360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0022 8530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0024 E537C000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0028 DF32\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 002a E5378000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 002e 9F32\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0030 A531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0032 8531\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==20] then { pass $testname } else { fail $testname } +} + +proc do_bit {} { + set testname "bit.s: bit operations" + set x 0 + + gas_start "bit.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 C6AF1000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 C66F1000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 C62F1000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c C6EF1000\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==4] then { pass $testname } else { fail $testname } +} + +proc do_branch {} { + set testname "branch.s: branch operations" + set x 0 + + gas_start "branch.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 8F05\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 FEFD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 E6FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 D7FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 CBFD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a B9FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c A1FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e 93FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 82FD\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 FAF5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 E0F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 D8F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 C4F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a BCF5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c A1F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e 99F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 82F5\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0022 FAED\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0024 E5ED\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0026 DDED\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==20] then { pass $testname } else { fail $testname } +} + +proc do_compare {} { + set testname "compare.s: compare operations" + set x 0 + + gas_start "compare.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 E531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 6532\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 E02F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 E82F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c E12F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 E12F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0014 E92F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0018 E92F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001c E22F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 EA2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0024 E32F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0028 EB2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 002c E42F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0030 E42F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0034 EC2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0038 EC2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 003c E52F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0040 ED2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0044 E62F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0048 EE2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 004c E72F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0050 EF2F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0054 6531\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==23] then { pass $testname } else { fail $testname } +} + +proc do_jumps {} { + set testname "jumps.s: jumps operations" + set x 0 + + gas_start "jumps.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 802F0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 6500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 BF07FAFF\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==3] then { pass $testname } else { fail $testname } +} + +proc do_logical {} { + set testname "logical.s: logical operations" + set x 0 + + gas_start "logical.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 4531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 C5360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0006 2530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 0531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000a 85360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e 2531\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 A5360700\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==7] then { pass $testname } else { fail $testname } +} + +proc do_mem {} { + set testname "mem.s: memory operations" + set x 0 + + gas_start "mem.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 05370500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 25370400\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 25370500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c 4033\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e 4034\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0010 4035\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 462F0500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 662F0400\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a 662F0500\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e C033\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0020 C034\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0022 4135\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==12] then { pass $testname } else { fail $testname } +} + +proc do_misc {} { + set testname "misc.s: misc operations" + set x 0 + + gas_start "misc.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 E0076001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 E0876001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 E0072001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000c 0000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 000e E0074001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0012 E0070001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0016 FF070001\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001a E72F2000\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 001e E53F4000\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==9] then { pass $testname } else { fail $testname } +} + +proc do_move {} { + set testname "move.s: move operations" + set x 0 + + gas_start "move.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 0530\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0002 0532\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 25360700\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 45360700\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==4] then { pass $testname } else { fail $testname } +} + +proc do_hilo {} { + set testname "hilo.s: hilo tests" + set x 0 + + gas_start "hilo.s" "-al" + + # Instead of having a variable for each match string just increment the + # total number of matches seen. That's simpler when testing large numbers + # of instructions (as these tests to). + while 1 { + expect { + -re "^ +\[0-9\]+ 0000 200EEFBE\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0004 410EAEDE\[^\n\]*\n" { set x [expr $x+1] } + -re "^ +\[0-9\]+ 0008 410EADDE\[^\n\]*\n" { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + gas_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==3] then { pass $testname } else { fail $testname } +} + + +proc do_simple_reloc_tests {} { + set testname "reloc.s: Test for proper relocations (part 2)" + set x 0 + + if [gas_test_old "reloc.s" "" "Test for proper relocation (part 1)"] then { + objdump_start_no_subdir "a.out" "-r" + + while 1 { + expect { + -re "^00000002\[^\n\]*R_V850_LO16\[^\n\]*\n" + { set x [expr $x+1] } + -re "^00000006\[^\n\]*R_V850_HI16_S\[^\n\]*\n" + { set x [expr $x+1] } + -re "^0000000a\[^\n\]*R_V850_HI16\[^\n\]*\n" + { set x [expr $x+1] } + -re "^0000000e\[^\n\]*R_V850_ZDA_16_16_OFFSET\[^\n\]*\n" + { set x [expr $x+1] } + -re "^00000012\[^\n\]*R_V850_TDA_16_16_OFFSET\[^\n\]*\n" + { set x [expr $x+1] } + -re "^00000016\[^\n\]*R_V850_SDA_16_16_OFFSET\[^\n\]*\n" + { set x [expr $x+1] } + -re "\[^\n\]*\n" { } + timeout { perror "timeout\n"; break } + eof { break } + } + } + } + + # This was intended to do any cleanup necessary. It kinda looks like it + # isn't needed, but just in case, please keep it in for now. + objdump_finish + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==6] then { pass $testname } else { fail $testname } +} + +if [istarget v850*-*-*] then { + # Test the basic instruction parser. + do_arith + do_bit + do_branch + do_compare + do_jumps + do_logical + do_mem + do_misc + do_move + + # Make sure we handle lo() hi() and hi0() correctly. + do_hilo + + # Check for proper relocs on lo, hi, hi0, zdaoff, tdaoff and sdaoff + # expressions + do_simple_reloc_tests + + gas_test "hilo2.s" "" "" "hi/lo regression test" + gas_test "fepsw.s" "" "" "eqsw regression test" + + gas_test_error "range.s" "-mwarn-signed-overflow" "Check for range error on byte load/store" +} diff -urN binutils-2.10.org/gas/testsuite/gas/v810/bit.s binutils-2.10/gas/testsuite/gas/v810/bit.s --- binutils-2.10.org/gas/testsuite/gas/v810/bit.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/bit.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,8 @@ + + .text + .global bit +bit: + clr1 5,16[r6] + not1 5,16[r6] + set1 5,16[r6] + tst1 5,16[r6] diff -urN binutils-2.10.org/gas/testsuite/gas/v810/branch.s binutils-2.10/gas/testsuite/gas/v810/branch.s --- binutils-2.10.org/gas/testsuite/gas/v810/branch.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/branch.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,24 @@ + + .text + .global bcc +bcc: + bgt bcc + bge bcc + blt bcc + ble bcc + bh bcc + bnl bcc + bl bcc + bnh bcc + be bcc + bne bcc + bv bcc + bnv bcc + bn bcc + bp bcc + bc bcc + bnc bcc + bz bcc + bnz bcc + br bcc + bsa bcc diff -urN binutils-2.10.org/gas/testsuite/gas/v810/compare.s binutils-2.10/gas/testsuite/gas/v810/compare.s --- binutils-2.10.org/gas/testsuite/gas/v810/compare.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/compare.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,28 @@ + + .text + .global compare +compare: + cmp r5,r6 + cmp 5,r6 + setf v,r5 + setf nv,r5 + setf c,r5 + setf l,r5 + setf nc,r5 + setf nl,r5 + setf z,r5 + setf nz,r5 + setf nh,r5 + setf h,r5 + setf s,r5 + setf n,r5 + setf ns,r5 + setf p,r5 + setf t,r5 + setf sa,r5 + setf lt,r5 + setf ge,r5 + setf le,r5 + setf gt,r5 + tst r5,r6 + diff -urN binutils-2.10.org/gas/testsuite/gas/v810/fepsw.s binutils-2.10/gas/testsuite/gas/v810/fepsw.s --- binutils-2.10.org/gas/testsuite/gas/v810/fepsw.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/fepsw.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,2 @@ + .text + ldsr r17,fepsw diff -urN binutils-2.10.org/gas/testsuite/gas/v810/hilo2.s binutils-2.10/gas/testsuite/gas/v810/hilo2.s --- binutils-2.10.org/gas/testsuite/gas/v810/hilo2.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/hilo2.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,4 @@ + .text + .org 0x10000 + movea hi(blah),r0,r1 +blah: diff -urN binutils-2.10.org/gas/testsuite/gas/v810/hilo.s binutils-2.10/gas/testsuite/gas/v810/hilo.s --- binutils-2.10.org/gas/testsuite/gas/v810/hilo.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/hilo.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,5 @@ + + .text + movea lo(0xdeadbeef),r0,r1 + movhi hi(0xdeadbeef),r1,r1 + movhi hi0(0xdeadbeef),r1,r1 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/jumps.s binutils-2.10/gas/testsuite/gas/v810/jumps.s --- binutils-2.10.org/gas/testsuite/gas/v810/jumps.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/jumps.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,8 @@ + + .text + .global jumps +jumps: + jarl jumps,r5 + jmp [r5] + jr jumps + diff -urN binutils-2.10.org/gas/testsuite/gas/v810/logical.s binutils-2.10/gas/testsuite/gas/v810/logical.s --- binutils-2.10.org/gas/testsuite/gas/v810/logical.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/logical.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,11 @@ + + .text + .global logicals +logicals: + and r5,r6 + andi 7,r5,r6 + not r5,r6 + or r5,r6 + ori 7,r5,r6 + xor r5,r6 + xori 7,r5,r6 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/mem.s binutils-2.10/gas/testsuite/gas/v810/mem.s --- binutils-2.10.org/gas/testsuite/gas/v810/mem.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/mem.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,16 @@ + + .text + .global memory +memory: + ld.b 5[r5],r6 + ld.h 4[r5],r6 + ld.w 4[r5],r6 + sld.b 64[ep],r6 + sld.h 128[ep],r6 + sld.w 128[ep],r6 + st.b r5,5[r6] + st.h r5,4[r6] + st.w r5,4[r6] + sst.b r6,64[ep] + sst.h r6,128[ep] + sst.w r6,128[ep] diff -urN binutils-2.10.org/gas/testsuite/gas/v810/misc.s binutils-2.10/gas/testsuite/gas/v810/misc.s --- binutils-2.10.org/gas/testsuite/gas/v810/misc.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/misc.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,13 @@ + + .text + .global misc +misc: + di + ei + halt + nop + reti + trap 0 + trap 31 + ldsr r7,psw + stsr psw,r7 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/move.s binutils-2.10/gas/testsuite/gas/v810/move.s --- binutils-2.10.org/gas/testsuite/gas/v810/move.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/move.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,8 @@ + + .text + .global move +move: + mov r5,r6 + mov 5,r6 + movea 7,r5,r6 + movhi 7,r5,r6 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/range.s binutils-2.10/gas/testsuite/gas/v810/range.s --- binutils-2.10.org/gas/testsuite/gas/v810/range.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/range.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,2 @@ + .text + ld.b 0xff62[r0],r0 diff -urN binutils-2.10.org/gas/testsuite/gas/v810/reloc.s binutils-2.10/gas/testsuite/gas/v810/reloc.s --- binutils-2.10.org/gas/testsuite/gas/v810/reloc.s 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/gas/testsuite/gas/v810/reloc.s 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,7 @@ + .text + movea lo(foo),r0,r1 + movhi hi(foo),r1,r1 + movhi hi0(foo),r1,r1 + movea zdaoff(_foo),r0,r1 + movhi tdaoff(_foo),ep,r1 + movhi sdaoff(_foo),gp,r1 diff -urN binutils-2.10.org/gas/write.c binutils-2.10/gas/write.c --- binutils-2.10.org/gas/write.c 1999-09-11 20:44:41.000000000 -0700 +++ binutils-2.10/gas/write.c 2011-03-20 03:53:01.000000000 -0700 @@ -2680,6 +2680,7 @@ else { seg_reloc_count++; +#if !(defined (TC_V810) && defined (OBJ_ELF)) #if !(defined (TC_V850) && defined (OBJ_ELF)) #if !(defined (TC_M68K) && defined (OBJ_ELF)) #if !(defined (TC_ARM) && defined (OBJ_ELF)) @@ -2689,6 +2690,7 @@ #endif #endif #endif +#endif #endif #endif } diff -urN binutils-2.10.org/include/dis-asm.h binutils-2.10/include/dis-asm.h --- binutils-2.10.org/include/dis-asm.h 2000-03-27 00:39:13.000000000 -0800 +++ binutils-2.10/include/dis-asm.h 2011-03-20 03:53:01.000000000 -0700 @@ -189,6 +189,7 @@ extern int print_insn_w65 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_d10v PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_d30v PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_v810 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_v850 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_vax PARAMS ((bfd_vma, disassemble_info*)); diff -urN binutils-2.10.org/include/elf/common.h binutils-2.10/include/elf/common.h --- binutils-2.10.org/include/elf/common.h 2000-05-23 01:39:07.000000000 -0700 +++ binutils-2.10/include/elf/common.h 2011-03-20 03:53:01.000000000 -0700 @@ -190,6 +190,9 @@ /* V850 backend magic number. Written in the absense of an ABI. */ #define EM_CYGNUS_V850 0x9080 +/* V810 backend magic number - no EABI available. */ +#define EM_V810 0x9081 + /* mn10200 and mn10300 backend magic numbers. Written in the absense of an ABI. */ #define EM_CYGNUS_MN10200 0xdead diff -urN binutils-2.10.org/include/elf/v810.h binutils-2.10/include/elf/v810.h --- binutils-2.10.org/include/elf/v810.h 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/include/elf/v810.h 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,89 @@ +/* V810 ELF support for BFD. + Copyright (C) 1997 Free Software Foundation, Inc. + Created by Michael Meissner, Cygnus Support + +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. */ + +/* This file holds definitions specific to the MIPS ELF ABI. Note + that most of this is not actually implemented by BFD. */ + +#ifndef _ELF_V810_H +#define _ELF_V810_H + +/* Processor specific flags for the ELF header e_flags field. */ + +/* Four bit V810 architecture field. */ +#define EF_V810_ARCH 0xf0000000 + +/* v810 code. */ +#define E_V810_ARCH 0x00000000 + +/* v830 code. */ +#define E_V830_ARCH 0x10000000 + + + +/* Flags for the st_other field */ +#define V810_OTHER_SDA 0x01 /* symbol had SDA relocations */ +#define V810_OTHER_ZDA 0x02 /* symbol had ZDA relocations */ +#define V810_OTHER_ERROR 0x80 /* symbol had an error reported */ + +/* V810 relocations */ +#include "elf/reloc-macros.h" + +START_RELOC_NUMBERS (v810_reloc_type) + RELOC_NUMBER (R_V810_NONE, 0) + RELOC_NUMBER (R_V810_9_PCREL, 1) + RELOC_NUMBER (R_V810_26_PCREL, 2) + RELOC_NUMBER (R_V810_HI16_S, 3) + RELOC_NUMBER (R_V810_HI16, 4) + RELOC_NUMBER (R_V810_LO16, 5) + RELOC_NUMBER (R_V810_32, 6) + RELOC_NUMBER (R_V810_16, 7) + RELOC_NUMBER (R_V810_8, 8) + RELOC_NUMBER( R_V810_SDA_16_16_OFFSET, 9) /* For ld.b, st.b, set1, clr1, not1, tst1, movea, movhi */ + RELOC_NUMBER( R_V810_SDA_15_16_OFFSET, 10) /* For ld.w, ld.h, ld.hu, st.w, st.h */ + RELOC_NUMBER( R_V810_ZDA_16_16_OFFSET, 11) /* For ld.b, st.b, set1, clr1, not1, tst1, movea, movhi */ + RELOC_NUMBER( R_V810_ZDA_15_16_OFFSET, 12) /* For ld.w, ld.h, ld.hu, st.w, st.h */ + RELOC_NUMBER (R_V810_GNU_VTINHERIT, 13) + RELOC_NUMBER (R_V810_GNU_VTENTRY, 14) + + EMPTY_RELOC (R_V810_max) +END_RELOC_NUMBERS + + +/* Processor specific section indices. These sections do not actually + exist. Symbols with a st_shndx field corresponding to one of these + values have a special meaning. */ + +/* Small data area common symbol. */ +#define SHN_V810_SCOMMON 0xff00 + +/* Zero data area common symbol. */ +#define SHN_V810_ZCOMMON 0xff02 + + +/* Processor specific section types. */ + +/* Section contains the .scommon data. */ +#define SHT_V810_SCOMMON 0x70000000 + +/* Section contains the .scommon data. */ +#define SHT_V810_ZCOMMON 0x70000002 + + +#endif /* _ELF_V810_H */ diff -urN binutils-2.10.org/include/opcode/v810.h binutils-2.10/include/opcode/v810.h --- binutils-2.10.org/include/opcode/v810.h 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/include/opcode/v810.h 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,149 @@ +/* v810.h -- Header file for NEC V810 opcode table + Copyright 1996 Free Software Foundation, Inc. + Written by J.T. Conklin, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +1, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef V810_H +#define V810_H + +/* The opcode table is an array of struct v810_opcode. */ + +struct v810_opcode +{ + /* The opcode name. */ + const char *name; + + /* The opcode itself. Those bits which will be filled in with + operands are zeroes. */ + unsigned long opcode; + + /* The opcode mask. This is used by the disassembler. This is a + mask containing ones indicating those bits which must match the + opcode field, and zeroes indicating those bits which need not + match (and are presumably filled in by operands). */ + unsigned long mask; + + /* An array of operand codes. Each code is an index into the + operand table. They appear in the order which the operands must + appear in assembly code, and are terminated by a zero. */ + unsigned char operands[8]; + + /* Which (if any) operand is a memory operand. */ + unsigned int memop; + + /* Target processor(s). A bit field of processors which support + this instruction. Note a bit field is used as some instructions + are available on multiple, different processor types, whereas + other instructions are only available on one specific type. */ + unsigned int processors; +}; + +/* Values for the processors field in the v810_opcode structure. */ +#define PROCESSOR_V810 (1 << 0) /* Just the V810. */ +#define PROCESSOR_ALL -1 /* Any processor. */ +#define PROCESSOR_V830 (1 << 1) /* Just the V830. */ +#define PROCESSOR_NOT_V810 (~ PROCESSOR_V810) /* Any processor except the V810. */ + +/* The table itself is sorted by major opcode number, and is otherwise + in the order in which the disassembler should consider + instructions. */ +extern const struct v810_opcode v810_opcodes[]; +extern const int v810_num_opcodes; + + +/* The operands table is an array of struct v810_operand. */ + +struct v810_operand +{ + /* The number of bits in the operand. */ + /* If this value is -1 then the operand's bits are in a discontinous distribution in the instruction. */ + int bits; + + /* (bits >= 0): How far the operand is left shifted in the instruction. */ + /* (bits == -1): Bit mask of the bits in the operand. */ + int shift; + + /* Insertion function. This is used by the assembler. To insert an + operand value into an instruction, check this field. + + If it is NULL, execute + i |= (op & ((1 << o->bits) - 1)) << o->shift; + (i is the instruction which we are filling in, o is a pointer to + this structure, and op is the opcode value; this assumes twos + complement arithmetic). + + If this field is not NULL, then simply call it with the + instruction and the operand value. It will return the new value + of the instruction. If the ERRMSG argument is not NULL, then if + the operand value is illegal, *ERRMSG will be set to a warning + string (the operand will be inserted in any case). If the + operand value is legal, *ERRMSG will be unchanged (most operands + can accept any value). */ + unsigned long (* insert) PARAMS ((unsigned long instruction, long op, + const char ** errmsg)); + + /* Extraction function. This is used by the disassembler. To + extract this operand type from an instruction, check this field. + + If it is NULL, compute + op = o->bits == -1 ? ((i) & o->shift) : ((i) >> o->shift) & ((1 << o->bits) - 1); + if (o->flags & V810_OPERAND_SIGNED) + op = (op << (32 - o->bits)) >> (32 - o->bits); + (i is the instruction, o is a pointer to this structure, and op + is the result; this assumes twos complement arithmetic). + + If this field is not NULL, then simply call it with the + instruction value. It will return the value of the operand. If + the INVALID argument is not NULL, *INVALID will be set to + non-zero if this operand type can not actually be extracted from + this operand (i.e., the instruction does not match). If the + operand is valid, *INVALID will not be changed. */ + unsigned long (* extract) PARAMS ((unsigned long instruction, int * invalid)); + + /* One bit syntax flags. */ + int flags; +}; + +/* Elements in the table are retrieved by indexing with values from + the operands field of the v810_opcodes table. */ + +extern const struct v810_operand v810_operands[]; + +/* Values defined for the flags field of a struct v810_operand. */ + +/* This operand names a general purpose register */ +#define V810_OPERAND_REG 0x01 + +/* This operand names a system register */ +#define V810_OPERAND_SRG 0x02 + +/* This operand names a condition code used in the setf instruction */ +#define V810_OPERAND_CC 0x04 + +/* This operand takes signed values */ +#define V810_OPERAND_SIGNED 0x08 + +/* This operand is a PC displacement */ +#define V810_OPERAND_DISP 0x20 + +/* This is a relaxable operand. Only used for D9->D22 branch relaxing + right now. We may need others in the future (or maybe handle them like + promoted operands on the mn10300?) */ +#define V810_OPERAND_RELAX 0x40 + +#endif /* V810_H */ diff -urN binutils-2.10.org/ld/configure.tgt binutils-2.10/ld/configure.tgt --- binutils-2.10.org/ld/configure.tgt 2000-05-28 04:32:34.000000000 -0700 +++ binutils-2.10/ld/configure.tgt 2011-03-20 03:53:01.000000000 -0700 @@ -288,6 +288,8 @@ v850-*-*) targ_emul=v850 ;; v850e-*-*) targ_emul=v850 ;; v850ea-*-*) targ_emul=v850 ;; +v810-*-*) targ_emul=v810 ;; +v830-*-*) targ_emul=v810 ;; w65-*-*) targ_emul=w65 ;; fr30-*-*) targ_emul=elf32fr30 ;; mcore-*-pe) targ_emul=mcorepe ; diff -urN binutils-2.10.org/ld/emulparams/v810.sh binutils-2.10/ld/emulparams/v810.sh --- binutils-2.10.org/ld/emulparams/v810.sh 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/ld/emulparams/v810.sh 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,12 @@ +MACHINE= +SCRIPT_NAME=v810 +OUTPUT_FORMAT="elf32-v810" +TEXT_START_ADDR=0x8000 +ZDATA_START_ADDR=0x160 +ROZDATA_START_ADDR="ALIGN (4)" +SDATA_START_ADDR="ALIGN (4)" +ROSDATA_START_ADDR="ALIGN (4)" +ARCH=v810 +MAXPAGESIZE=256 +ENTRY=_start +EMBEDDED=yes diff -urN binutils-2.10.org/ld/Makefile.am binutils-2.10/ld/Makefile.am --- binutils-2.10.org/ld/Makefile.am 2000-04-04 22:36:43.000000000 -0700 +++ binutils-2.10/ld/Makefile.am 2011-03-20 03:53:01.000000000 -0700 @@ -678,6 +678,9 @@ ev850.c: $(srcdir)/emulparams/v850.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/v850.sc ${GEN_DEPENDS} ${GENSCRIPTS} v850 "$(tdir_v850)" +ev810.c: $(srcdir)/emulparams/v810.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/v810.sc ${GEN_DEPENDS} + ${GENSCRIPTS} v810 "$(tdir_v810)" ew65.c: $(srcdir)/emulparams/w65.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/w65.sc ${GEN_DEPENDS} ${GENSCRIPTS} w65 "$(tdir_w65)" diff -urN binutils-2.10.org/ld/Makefile.in binutils-2.10/ld/Makefile.in --- binutils-2.10.org/ld/Makefile.in 2000-04-04 22:36:43.000000000 -0700 +++ binutils-2.10/ld/Makefile.in 2011-03-20 03:53:01.000000000 -0700 @@ -1377,6 +1377,9 @@ ev850.c: $(srcdir)/emulparams/v850.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/v850.sc ${GEN_DEPENDS} ${GENSCRIPTS} v850 "$(tdir_v850)" +ev810.c: $(srcdir)/emulparams/v810.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/v810.sc ${GEN_DEPENDS} + ${GENSCRIPTS} v810 "$(tdir_v810)" ew65.c: $(srcdir)/emulparams/w65.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/w65.sc ${GEN_DEPENDS} ${GENSCRIPTS} w65 "$(tdir_w65)" diff -urN binutils-2.10.org/ld/scripttempl/v810.sc binutils-2.10/ld/scripttempl/v810.sc --- binutils-2.10.org/ld/scripttempl/v810.sc 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/ld/scripttempl/v810.sc 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,191 @@ +cat << EOF +OUTPUT_FORMAT("elf32-v810", "elf32-v810", + "elf32-v810") +OUTPUT_ARCH(v810) +ENTRY(_start) +SEARCH_DIR(.); +/*/critters/slug/grossman/install/sun4/v810-elf/lib*/ +SECTIONS +{ + /* This saves a little space in the ELF file, since the zda starts + at a higher location that the ELF headers take up. */ + + .zdata ${ZDATA_START_ADDR} : { + *(.zdata) + *(.zbss) + *(reszdata) + *(.zcommon) + } + + /* This is the read only part of the zero data area. + Having it as a seperate section prevents its + attributes from being inherited by the zdata + section. Specifically it prevents the zdata + section from being marked READONLY. */ + + .rozdata ${ROZDATA_START_ADDR} : { + *(.rozdata) + *(romzdata) + *(romzbss) + } + + /* Read-only sections, merged into text segment: */ + . = ${TEXT_START_ADDR}; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { KEEP (*(.init)) } =0 + .plt : { *(.plt) } + + .text : { + *(.text) + ${RELOCATING+*(.text.*)} + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0 + + ${RELOCATING+_etext = .;} + ${RELOCATING+PROVIDE (etext = .);} + + /* This is special code area at the end of the normal text section. + It contains a small lookup table at the start followed by the + code pointed to by entries in the lookup table. */ + + .fini : { KEEP (*(.fini)) } =0 + .rodata : { *(.rodata) ${RELOCATING+*(.rodata.*)} *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + + .data : { + *(.data) + ${RELOCATING+*(.data.*)} + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .ctors : { + ${RELOCATING+___ctors = .;} + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend(.ctors)) + ${RELOCATING+___ctors_end = .;} + } + + .dtors : { + ${RELOCATING+___dtors = .;} + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + ${RELOCATING+___dtors_end = .;} + } + + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + + /* 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 ${SDATA_START_ADDR} : { + ${RELOCATING+PROVIDE (__gp = . + 0x8000);} + *(.sdata) + } + + /* See comment about .rozdata. */ + .rosdata ${ROSDATA_START_ADDR} : { + *(.rosdata) + } + + /* We place the .sbss data section AFTER the .rosdata section, so that + it can directly preceed the .bss section. This allows runtime startup + code to initialise all the zero-data sections by simply taking the + value of '_edata' and zeroing until it reaches '_end' */ + .sbss : { + ${RELOCATING+__sbss_start = .;} + *(.sbss) + *(.scommon) + } + + ${RELOCATING+_edata = DEFINED (__sbss_start) ? __sbss_start : . ;} + ${RELOCATING+PROVIDE (edata = _edata);} + + .bss : + { + ${RELOCATING+__bss_start = DEFINED (__sbss_start) ? __sbss_start : . ;} + ${RELOCATING+__real_bss_start = . ;} + *(.dynbss) + *(.bss) + *(COMMON) + } + + ${RELOCATING+_end = . ;} + ${RELOCATING+PROVIDE (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) } + .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) } + + /* User stack */ + .stack 0x200000 : { + ${RELOCATING+__stack = .;} + *(.stack) + } + /* These must appear regardless of . */ +} +EOF diff -urN binutils-2.10.org/opcodes/configure binutils-2.10/opcodes/configure --- binutils-2.10.org/opcodes/configure 2000-04-02 13:46:57.000000000 -0700 +++ binutils-2.10/opcodes/configure 2011-03-20 03:53:01.000000000 -0700 @@ -3951,6 +3951,8 @@ bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850e_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; + bfd_v810_arch) ta="$ta v810-opc.lo v810-dis.lo" ;; + bfd_v830_arch) ta="$ta v810-opc.lo v810-dis.lo" ;; bfd_vax_arch) ta="$ta vax-dis.lo" ;; bfd_w65_arch) ta="$ta w65-dis.lo" ;; bfd_we32k_arch) ;; diff -urN binutils-2.10.org/opcodes/configure.in binutils-2.10/opcodes/configure.in --- binutils-2.10.org/opcodes/configure.in 2000-03-27 00:39:14.000000000 -0800 +++ binutils-2.10/opcodes/configure.in 2011-03-20 03:53:01.000000000 -0700 @@ -163,6 +163,8 @@ bfd_tahoe_arch) ;; bfd_tic30_arch) ta="$ta tic30-dis.lo" ;; bfd_tic80_arch) ta="$ta tic80-dis.lo tic80-opc.lo" ;; + bfd_v810_arch) ta="$ta v810-opc.lo v810-dis.lo" ;; + bfd_v830_arch) ta="$ta v810-opc.lo v810-dis.lo" ;; bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850e_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; diff -urN binutils-2.10.org/opcodes/disassemble.c binutils-2.10/opcodes/disassemble.c --- binutils-2.10.org/opcodes/disassemble.c 2000-05-06 07:49:26.000000000 -0700 +++ binutils-2.10/opcodes/disassemble.c 2011-03-20 03:53:01.000000000 -0700 @@ -50,6 +50,7 @@ #define ARCH_tic30 #define ARCH_tic80 #define ARCH_v850 +#define ARCH_v810 #define ARCH_vax #define ARCH_w65 #define ARCH_z8k @@ -236,6 +237,11 @@ disassemble = print_insn_tic80; break; #endif +#ifdef ARCH_v810 + case bfd_arch_v810: + disassemble = print_insn_v810; + break; +#endif #ifdef ARCH_v850 case bfd_arch_v850: disassemble = print_insn_v850; diff -urN binutils-2.10.org/opcodes/Makefile.am binutils-2.10/opcodes/Makefile.am --- binutils-2.10.org/opcodes/Makefile.am 2000-04-04 22:36:43.000000000 -0700 +++ binutils-2.10/opcodes/Makefile.am 2011-03-20 03:53:01.000000000 -0700 @@ -83,6 +83,8 @@ tic30-dis.c \ tic80-dis.c \ tic80-opc.c \ + v810-dis.c \ + v810-opc.c \ v850-dis.c \ v850-opc.c \ vax-dis.c \ @@ -145,6 +147,8 @@ tic30-dis.lo \ tic80-dis.lo \ tic80-opc.lo \ + v810-dis.lo \ + v810-opc.lo \ v850-dis.lo \ v850-opc.lo \ vax-dis.lo \ @@ -366,6 +370,10 @@ tic80-dis.lo: tic80-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/tic80.h \ $(INCDIR)/dis-asm.h $(BFD_H) tic80-opc.lo: tic80-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/tic80.h +v810-dis.lo: v810-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v810.h \ + $(INCDIR)/dis-asm.h $(BFD_H) opintl.h +v810-opc.lo: v810-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v810.h \ + opintl.h v850-dis.lo: v850-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v850.h \ $(INCDIR)/dis-asm.h $(BFD_H) opintl.h v850-opc.lo: v850-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v850.h \ diff -urN binutils-2.10.org/opcodes/Makefile.in binutils-2.10/opcodes/Makefile.in --- binutils-2.10.org/opcodes/Makefile.in 2000-04-04 22:36:43.000000000 -0700 +++ binutils-2.10/opcodes/Makefile.in 2011-03-20 03:53:01.000000000 -0700 @@ -187,6 +187,8 @@ tic30-dis.c \ tic80-dis.c \ tic80-opc.c \ + v810-dis.c \ + v810-opc.c \ v850-dis.c \ v850-opc.c \ vax-dis.c \ @@ -250,6 +252,8 @@ tic30-dis.lo \ tic80-dis.lo \ tic80-opc.lo \ + v810-dis.lo \ + v810-opc.lo \ v850-dis.lo \ v850-opc.lo \ vax-dis.lo \ @@ -863,6 +867,10 @@ tic80-dis.lo: tic80-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/tic80.h \ $(INCDIR)/dis-asm.h $(BFD_H) tic80-opc.lo: tic80-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/tic80.h +v810-dis.lo: v810-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v810.h \ + $(INCDIR)/dis-asm.h $(BFD_H) opintl.h +v810-opc.lo: v810-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v810.h \ + opintl.h v850-dis.lo: v850-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v850.h \ $(INCDIR)/dis-asm.h $(BFD_H) opintl.h v850-opc.lo: v850-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/v850.h \ diff -urN binutils-2.10.org/opcodes/v810-dis.c binutils-2.10/opcodes/v810-dis.c --- binutils-2.10.org/opcodes/v810-dis.c 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/opcodes/v810-dis.c 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,238 @@ +/* Disassemble V810 instructions. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include + +#include "sysdep.h" +#include "opcode/v810.h" +#include "dis-asm.h" +#include "opintl.h" + +static const char *const v810_reg_names[] = +{ "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "lp" }; + +static const char *const v810_sreg_names[] = +{ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "pir", "tkcw", + "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", + "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23", + "chcw", "adtre", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" }; + +static const char *const v810_cc_names[] = +{ "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", + "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" }; + +static int +disassemble (memaddr, info, insn) + bfd_vma memaddr; + struct disassemble_info *info; + unsigned long insn; +{ + struct v810_opcode * op = (struct v810_opcode *)v810_opcodes; + const struct v810_operand * operand; + int match = 0; + int short_op = ((insn & 0xfc00) < 0xa000); + int bytes_read; + int target_processor; + + bytes_read = short_op ? 2 : 4; + + /* If this is a two byte insn, then mask off the high bits. */ + if (short_op) + insn &= 0xffff; + + switch (info->mach) + { + case 0: + default: + target_processor = PROCESSOR_V810; + break; + + case bfd_mach_v830: + target_processor = PROCESSOR_V830; + break; + } + + /* Find the opcode. */ + while (op->name) + { + if ((op->mask & insn) == op->opcode + && (op->processors & target_processor)) + { + const unsigned char * opindex_ptr; + unsigned int opnum; + unsigned int memop; + + match = 1; + (*info->fprintf_func) (info->stream, "%s\t", op->name); +/*fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );*/ + + memop = op->memop; + /* Now print the operands. + + MEMOP is the operand number at which a memory + address specification starts, or zero if this + instruction has no memory addresses. + + A memory address is always two arguments. + + This information allows us to determine when to + insert commas into the output stream as well as + when to insert disp[reg] expressions onto the + output stream. */ + + for (opindex_ptr = op->operands, opnum = 1; + *opindex_ptr != 0; + opindex_ptr++, opnum++) + { + long value; + int flag; + int status; + bfd_byte buffer[ 4 ]; + + operand = &v810_operands[*opindex_ptr]; + + if (operand->extract) + value = (operand->extract) (insn, 0); + else + { + if (operand->bits == -1) + value = (insn & operand->shift); + else + value = (insn >> operand->shift) & ((1 << operand->bits) - 1); + + if (operand->flags & V810_OPERAND_SIGNED) + value = ((long)(value << (32 - operand->bits)) + >> (32 - operand->bits)); + } + + /* The first operand is always output without any + special handling. + + For the following arguments: + + If memop && opnum == memop + 1, then we need '[' since + we're about to output the register used in a memory + reference. + + If memop && opnum == memop + 2, then we need ']' since + we just finished the register in a memory reference. We + also need a ',' before this operand. + + Else we just need a comma. + + We may need to output a trailing ']' if the last operand + in an instruction is the register for a memory address. + + The exception (and there's always an exception) is the + "jmp" insn which needs square brackets around it's only + register argument. */ + + if (memop && opnum == memop + 1) info->fprintf_func (info->stream, "["); + else if (memop && opnum == memop + 2) info->fprintf_func (info->stream, "],"); + else if (memop == 1 && opnum == 1 + && (operand->flags & V810_OPERAND_REG)) + info->fprintf_func (info->stream, "["); + else if (opnum > 1) info->fprintf_func (info->stream, ", "); + + /* extract the flags, ignorng ones which do not effect disassembly output. */ + flag = operand->flags; + flag &= ~ V810_OPERAND_SIGNED; + flag &= ~ V810_OPERAND_RELAX; + flag &= - flag; + + switch (flag) + { + case V810_OPERAND_REG: info->fprintf_func (info->stream, "%s", v810_reg_names[value]); break; + case V810_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v810_sreg_names[value]); break; + case V810_OPERAND_CC: info->fprintf_func (info->stream, "%s", v810_cc_names[value]); break; + default: info->fprintf_func (info->stream, "%d", value); break; + case V810_OPERAND_DISP: + { + bfd_vma addr = value + memaddr; + info->print_address_func (addr, info); + } + break; + } + + /* Handle jmp correctly. */ + if (memop == 1 && opnum == 1 + && ((operand->flags & V810_OPERAND_REG) != 0)) + (*info->fprintf_func) (info->stream, "]"); + } + + /* Close any square bracket we left open. */ + if (memop && opnum == memop + 2) + (*info->fprintf_func) (info->stream, "]"); + + /* All done. */ + break; + } + op++; + } + + if (!match) + { + if (short_op) + info->fprintf_func (info->stream, ".short\t0x%04x", insn); + else + info->fprintf_func (info->stream, ".long\t0x%08x", insn); + } + + return bytes_read; +} + +int +print_insn_v810 (memaddr, info) + bfd_vma memaddr; + struct disassemble_info * info; +{ + int status; + bfd_byte buffer[ 4 ]; + unsigned long insn = 0; + + /* First figure out how big the opcode is. */ + + status = info->read_memory_func (memaddr, buffer, 2, info); + if (status == 0) + { + insn = bfd_getl16 (buffer); + +/* if ( (insn & 0xfc00) >= 0xa000 + && (insn & 0xfc00) != 0xa000)*/ + if ((insn & 0xfc00) >= 0xa000) + { + /* If this is a 4 byte insn, read 4 bytes of stuff. */ + status = info->read_memory_func (memaddr, buffer, 4, info); + + if (status == 0) + insn = bfd_getl32 (buffer); + } + } + + if (status != 0) + { + info->memory_error_func (status, memaddr, info); + return -1; + } + + /* Make sure we tell our caller how many bytes we consumed. */ + return disassemble (memaddr, info, insn); +} diff -urN binutils-2.10.org/opcodes/v810-opc.c binutils-2.10/opcodes/v810-opc.c --- binutils-2.10.org/opcodes/v810-opc.c 1969-12-31 16:00:00.000000000 -0800 +++ binutils-2.10/opcodes/v810-opc.c 2011-03-20 03:53:01.000000000 -0700 @@ -0,0 +1,367 @@ +/* Assemble V810 instructions. + Copyright (C) 1996 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "opcode/v810.h" +#include +#include "opintl.h" + + +/* one-word opcodes */ +#define one(x) ((unsigned int) (x)) + +/* two-word opcodes */ +#define two(x,y) ((unsigned int) (x) | ((unsigned int) (y) << 16)) + + +/* The functions used to insert and extract complicated operands. */ + +/* Note: There is a conspiracy between these functions and + v810_insert_operand() in gas/config/tc-v810.c. Error messages + containing the string 'out of range' will be ignored unless a + specific command line option is given to GAS. */ + +static const char * not_valid = N_ ("displacement value is not in range and is not aligned"); +static const char * out_of_range = N_ ("displacement value is out of range"); +static const char * not_aligned = N_ ("displacement value is not aligned"); + +static const char * immediate_out_of_range = N_ ("immediate value is out of range"); + +static unsigned long +insert_d9 (insn, value, errmsg) + unsigned long insn; + long value; + const char ** errmsg; +{ + if (value > 0xff || value < -0x100) + { + if ((value % 2) != 0) + * errmsg = _("branch value not in range and to odd offset"); + else + * errmsg = _("branch value out of range"); + } + else if ((value % 2) != 0) + * errmsg = _("branch to odd offset"); + + return (insn | (value & 0x1fe)); +} + +static unsigned long +extract_d9 (insn, invalid) + unsigned long insn; + int * invalid; +{ + unsigned long ret = (insn & 0x1fe); + + if ((insn & 0x100) != 0) + ret |= ~0xFF; + + return ret; +} + +static unsigned long +insert_d26 (insn, value, errmsg) + unsigned long insn; + long value; + const char ** errmsg; +{ + if (value > 0x1ffffff || value < -0x2000000) + { + if ((value % 2) != 0) + * errmsg = _("branch value not in range and to an odd offset"); + else + * errmsg = _("branch value out of range"); + } + else if ((value % 2) != 0) + * errmsg = _("branch to odd offset"); + + return (insn | ((value & 0xfffe) << 16) | ((value & 0x3ff0000) >> 16)); +} + +static unsigned long +extract_d26 (insn, invalid) + unsigned long insn; + int * invalid; +{ + signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3ff) << 16); + + return (unsigned long) ((ret << 6) >> 6); +} + +static unsigned long +insert_i5 (insn, value, errmsg) + unsigned long insn; + signed long value; + const char ** errmsg; +{ + if (value > 0xf || value < -0x10) + * errmsg = _(immediate_out_of_range); + + return insn | (value & 0x1f); +} + +static unsigned long +extract_i5 (insn, invalid) + unsigned long insn; + int * invalid; +{ + signed long ret = insn & 0x001f; + if(ret & 0x10) ret |= ~0x0f; + return ret; +} + +static unsigned long +insert_i5u (insn, value, errmsg) + unsigned long insn; + unsigned long value; + const char ** errmsg; +{ + if (value > 0x1f) + * errmsg = _(immediate_out_of_range); + + return insn | (value & 0x1f); +} + +static unsigned long +extract_i5u (insn, invalid) + unsigned long insn; + int * invalid; +{ + return insn & 0x001f; +} + + + +/* Warning: code in gas/config/tc-v810.c examines the contents of this array. + If you change any of the values here, be sure to look for side effects in + that code. */ +const struct v810_operand v810_operands[] = +{ +#define UNUSED 0 + { 0, 0, NULL, NULL, 0 }, + +#define R1 (UNUSED + 1) + { 5, 0, NULL, NULL, V810_OPERAND_REG }, + +#define R2 (R1 + 1) + { 5, 5, NULL, NULL, V810_OPERAND_REG }, + +#define R3 (R2 + 1) + { 5, 16, NULL, NULL, V810_OPERAND_REG }, + +#define I5 (R3 + 1) + { 5, 0, insert_i5, extract_i5, V810_OPERAND_SIGNED }, + +#define I5U (I5 + 1) + { 5, 0, insert_i5u, extract_i5u, 0 }, + +#define I16 (I5U + 1) + { 16, 16, NULL, NULL, V810_OPERAND_SIGNED }, + +#define I16U (I16 + 1) + { 16, 16, NULL, NULL, 0 }, + +#define D16 (I16U + 1) + { 16, 16, NULL, NULL, V810_OPERAND_SIGNED }, + +#define D9 (D16 + 1) + { 9, 0, insert_d9, extract_d9, V810_OPERAND_RELAX | V810_OPERAND_SIGNED | V810_OPERAND_DISP }, + +#define D26 (D9 + 1) + { 26, 0, insert_d26, extract_d26, V810_OPERAND_SIGNED | V810_OPERAND_DISP }, + +#define SR (D26 + 1) + { 5, 0, NULL, NULL, V810_OPERAND_SRG }, + +#define CCCC (SR + 1) + { 4, 0, NULL, NULL, V810_OPERAND_CC }, +}; + + +/* The opcode table. + + The format of the opcode table is: + + NAME OPCODE MASK { OPERANDS } MEMOP PROCESSOR + + NAME is the name of the instruction. + OPCODE is the instruction opcode. + MASK is the opcode mask; this is used to tell the disassembler + which bits in the actual opcode must match OPCODE. + OPERANDS is the list of operands. + MEMOP specifies which operand (if any) is a memory operand. + PROCESSORS specifies which CPU(s) support the opcode. + + The disassembler reads the table in order and prints the first + instruction which matches, so this table is sorted to put more + specific instructions before more general instructions. It is also + sorted by major opcode. + + The table is also sorted by name. This is used by the assembler. + When parsing an instruction the assembler finds the first occurance + of the name of the instruciton in this table and then attempts to + match the instruction's arguments with description of the operands + associated with the entry it has just found in this table. If the + match fails the assembler looks at the next entry in this table. + If that entry has the same name as the previous entry, then it + tries to match the instruction against that entry and so on. This + is how the assembler copes with multiple, different formats of the + same instruction. */ + + +const struct v810_opcode v810_opcodes[] = +{ +{ "abc", one (0x8201), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abe", one (0x8401), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abge", one (0x9c01), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abgt", one (0x9e01), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abh", one (0x9601), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abl", one (0x8201), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "able", one (0x8e01), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "ablt", one (0x8c01), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abn", one (0x8801), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abnc", one (0x9201), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abne", one (0x9401), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abnh", one (0x8601), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abnl", one (0x9201), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abnv", one (0x9001), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abnz", one (0x9401), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abp", one (0x9801), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abr", one (0x8a01), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abv", one (0x8001), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "abz", one (0x8401), one (0xfe01), {D9}, 0, PROCESSOR_V830 }, +{ "add", one (0x0400), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "add", one (0x4400), one (0xfc00), {I5, R2}, 0, PROCESSOR_ALL }, +{ "addf.s", two (0xf800, 0x1000), two (0xfc00, 0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "addi", two (0xa400, 0x0000), two (0xfc00, 0x0000), {I16, R1, R2}, 0, PROCESSOR_ALL }, +{ "and", one (0x3400), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "andi", two (0xb400, 0x0000), two (0xfc00, 0x0000), {I16U, R1, R2}, 0, PROCESSOR_ALL }, + +{ "bc", one (0x8200), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bdld", two (0xf800, 0x8400), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_V830 }, +{ "bdst", two (0xf800, 0x8c00), two (0xfc00, 0xfc000), {R2, R1}, 0, PROCESSOR_V830 }, +{ "be", one (0x8400), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bge", one (0x9c00), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bgt", one (0x9e00), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bh", one (0x9600), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bild", two (0xf800, 0x8000), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_V830 }, +{ "bist", two (0xf800, 0x8800), two (0xfc00, 0xfc000), {R2, R1}, 0, PROCESSOR_V830 }, +{ "bl", one (0x8200), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "ble", one (0x8e00), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "blt", one (0x8c00), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bn", one (0x8800), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bnc", one (0x9200), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bne", one (0x9400), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bnh", one (0x8600), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bnl", one (0x9200), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bnv", one (0x9000), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bnz", one (0x9400), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bp", one (0x9800), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "br", one (0x8a00), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "breakpoint", one(0x601F), one (0xffff), {UNUSED}, 0, PROCESSOR_ALL }, +{ "brkret", one (0x6401), one (0xfc01), {UNUSED}, 0, PROCESSOR_ALL }, +{ "bv", one (0x8000), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, +{ "bz", one (0x8400), one (0xfe01), {D9}, 0, PROCESSOR_ALL }, + +{ "caxi", two (0xe800, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 0, PROCESSOR_ALL }, +{ "cmp", one (0x0c00), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "cmp", one (0x4c00), one (0xfc00), {I5, R2}, 0, PROCESSOR_ALL }, +{ "cmpf.s", two (0xf800, 0x0000), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, +{ "cvt.ws", two (0xf800, 0x0800), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, +{ "cvt.sw", two (0xf800, 0x0c00), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "di", one (0x7800), one (0xfc00), {UNUSED}, 0, PROCESSOR_ALL }, +{ "div", one (0x2400), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "divf.s", two (0xf800, 0x1c00), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, +{ "divu", one (0x2c00), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "ei", one (0x5800), one (0xfc00), {UNUSED}, 0, PROCESSOR_ALL }, + +{ "halt", one (0x6800), one (0xfc01), {UNUSED}, 0, PROCESSOR_ALL }, + +{ "in.b", two (0xe000, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, +{ "in.h", two (0xe400, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, +{ "in.w", two (0xec00, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, + +{ "jal", two (0xac00, 0x0000), two (0xfc00, 0x0000), {D26}, 0, PROCESSOR_ALL }, +{ "jmp", one (0x1800), one (0xfc00), {R1}, 1, PROCESSOR_ALL }, +{ "jr", two (0xa800, 0x0000), two (0xfc00, 0x0000), {D26}, 0, PROCESSOR_ALL }, + +{ "ld.b", two (0xc000, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, +{ "ld.h", two (0xc400, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, +{ "ld.w", two (0xcc00, 0x0000), two (0xfc00, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, +{ "ldsr", one (0x7000), one (0xfc00), {R2, SR}, 0, PROCESSOR_ALL }, + +{ "mac3", two (0xf800, 0x7400), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "maci", two (0xd800, 0x0000), two (0xfc00, 0x0000), {I16, R1, R2}, 0, PROCESSOR_V830 }, +{ "mact3", two (0xf800, 0x7000), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "max3", two (0xf800, 0x4c00), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "min3", two (0xf800, 0x4800), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "mov", one (0x0000), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "mov", one (0x4000), one (0xfc00), {I5, R2}, 0, PROCESSOR_ALL }, +{ "movea", two (0xa000, 0x0000), two (0xfc00, 0x0000), {I16, R1, R2}, 0, PROCESSOR_ALL }, +{ "movhi", two (0xbc00, 0x0000), two (0xfc00, 0x0000), {I16, R1, R2}, 0, PROCESSOR_ALL }, +{ "mul", one (0x2000), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "mul3", two (0xf800, 0x7c00), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "mulf.s", two (0xf800, 0x1800), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, +{ "muli", two (0xc800, 0x0000), two (0xfc00, 0x0000), {I16, R1, R2}, 0, PROCESSOR_V830 }, +{ "mult3", two (0xf800, 0x7800), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "mulu", one (0x2800), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "nop", one (0x9a00), one (0xfe01), {UNUSED}, 0, PROCESSOR_ALL }, +{ "not", one (0x3c00), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "or", one (0x3000), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "ori", two (0xb000, 0x0000), two (0xfc00, 0x0000), {I16U, R1, R2}, 0, PROCESSOR_ALL }, +{ "out.b", two (0xf000, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, +{ "out.h", two (0xf400, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, +{ "out.w", two (0xfc00, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, + +{ "reti", one (0x6400), one (0xfc01), {UNUSED}, 0, PROCESSOR_ALL }, + +{ "sar", one (0x1c00), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "sar", one (0x5c00), one (0xfc00), {I5U, R2}, 0, PROCESSOR_ALL }, +{ "satadd3",two (0xf800, 0x4000), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "satsub3",two (0xf800, 0x4400), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "setf", one (0x4800), one (0xfc00), {CCCC, R2}, 0, PROCESSOR_ALL }, +{ "shl", one (0x1000), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "shl", one (0x5000), one (0xfc00), {I5U, R2}, 0, PROCESSOR_ALL }, +{ "shld3", two (0xf800, 0x6000), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "shr", one (0x1400), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "shr", one (0x5400), one (0xfc00), {I5U, R2}, 0, PROCESSOR_ALL }, +{ "shrd3", two (0xf800, 0x6400), two (0xfc00, 0xfc000), {R1, R2, R3}, 0, PROCESSOR_V830 }, +{ "st.b", two (0xd000, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, +{ "st.h", two (0xd400, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, +{ "st.w", two (0xdc00, 0x0000), two (0xfc00, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, +{ "stby", one (0x6801), one (0xfc01), {UNUSED}, 0, PROCESSOR_ALL }, +{ "stsr", one (0x7400), one (0xfc00), {SR, R2}, 0, PROCESSOR_ALL }, +{ "sub", one (0x0800), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "subf.s", two (0xf800, 0x1400), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "trap", one (0x6000), one (0xfc00), {I5U}, 0, PROCESSOR_ALL }, +{ "trnc.sw",two (0xf800, 0x2c00), two (0xfc00, 0xfc000), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "xor", one (0x3800), one (0xfc00), {R1, R2}, 0, PROCESSOR_ALL }, +{ "xori", two (0xb800, 0x0000), two (0xfc00, 0x0000), {I16U, R1, R2}, 0, PROCESSOR_ALL }, + +{ 0, 0, 0, {0}, 0, 0 }, + +} ; + +const int v810_num_opcodes = + sizeof (v810_opcodes) / sizeof (v810_opcodes[0]); +