diff options
author | Nick Clifton <nickc@redhat.com> | 2002-12-30 19:25:13 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2002-12-30 19:25:13 +0000 |
commit | 8f401f174f9f4e4f8bda400324cef236bd3577ce (patch) | |
tree | 1cc54909c684ded9ee313d7bb5613047fe3f4240 | |
parent | 8ef2162bdaca6e53b27d384bf9e6e4e4d6376d19 (diff) | |
download | gdb-8f401f174f9f4e4f8bda400324cef236bd3577ce.tar.gz |
Add support for msp430.
-rw-r--r-- | bfd/ChangeLog | 15 | ||||
-rw-r--r-- | bfd/Makefile.am | 9 | ||||
-rw-r--r-- | bfd/Makefile.in | 9 | ||||
-rw-r--r-- | bfd/archures.c | 16 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 21 | ||||
-rw-r--r-- | bfd/config.bfd | 4 | ||||
-rwxr-xr-x | bfd/configure | 29 | ||||
-rw-r--r-- | bfd/configure.in | 1 | ||||
-rw-r--r-- | bfd/cpu-msp430.c | 107 | ||||
-rw-r--r-- | bfd/elf32-msp430.c | 720 | ||||
-rw-r--r-- | bfd/libbfd.h | 5 | ||||
-rw-r--r-- | bfd/reloc.c | 13 | ||||
-rw-r--r-- | bfd/targets.c | 2 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/dis-asm.h | 1 | ||||
-rw-r--r-- | include/elf/ChangeLog | 5 | ||||
-rw-r--r-- | include/elf/common.h | 7 | ||||
-rw-r--r-- | include/elf/msp430.h | 55 | ||||
-rw-r--r-- | include/opcode/ChangeLog | 4 | ||||
-rw-r--r-- | include/opcode/msp430.h | 111 | ||||
-rw-r--r-- | opcodes/ChangeLog | 7 | ||||
-rw-r--r-- | opcodes/Makefile.in | 8 | ||||
-rwxr-xr-x | opcodes/configure | 3 | ||||
-rw-r--r-- | opcodes/configure.in | 1 | ||||
-rw-r--r-- | opcodes/disassemble.c | 6 | ||||
-rw-r--r-- | opcodes/msp430-dis.c | 805 |
26 files changed, 1949 insertions, 19 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1d0a15c2d73..b2a283a9f2b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2002-12-30 Dmitry Diky <diwil@mail.ru> + + * Makefile.am: Add msp430 target. + * configure.in: Likewise. + * Makefile.in: Regenerate. + * configure: Regenerate. + * archures.c: Add msp430 architecture vector. + * config.bfd: Likewise. + * reloc.c: Add msp430 relocs. + * targets.c: Add msp320 target. + * cpu-msp430.c: New file: msp430 cpu detection. + * elf32-msp430.c: New file: msp430 reloc processing. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + 2002-12-28 Jakub Jelinek <jakub@redhat.com> * elf.c (elf_sort_sections): Don't reorder .tbss. diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 73739fdc57d..70de9e52f99 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -80,6 +80,7 @@ ALL_MACHINES = \ cpu-mcore.lo \ cpu-mips.lo \ cpu-mmix.lo \ + cpu-msp430.c \ cpu-or32.lo \ cpu-ns32k.lo \ cpu-openrisc.lo \ @@ -132,6 +133,7 @@ ALL_MACHINES_CFILES = \ cpu-mcore.c \ cpu-mips.c \ cpu-mmix.c \ + cpu-msp430.c \ cpu-or32.c \ cpu-ns32k.c \ cpu-openrisc.c \ @@ -231,6 +233,7 @@ BFD32_BACKENDS = \ elf32-mcore.lo \ elfxx-mips.lo \ elf32-mips.lo \ + elf32-msp430.c \ elf32-openrisc.lo \ elf32-or32.lo \ elf32-pj.lo \ @@ -388,6 +391,7 @@ BFD32_BACKENDS_CFILES = \ elf32-mcore.c \ elfxx-mips.c \ elf32-mips.c \ + elf32-msp430.c \ elf32-openrisc.c \ elf32-or32.c \ elf32-pj.c \ @@ -927,6 +931,7 @@ cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h +cpu-msp430.lo: cpu-msp430.c $(INCDIR)/filenames.h cpu-or32.lo: cpu-or32.c $(INCDIR)/filenames.h cpu-ns32k.lo: cpu-ns32k.c $(INCDIR)/filenames.h ns32k.h cpu-openrisc.lo: cpu-openrisc.c $(INCDIR)/filenames.h @@ -1212,6 +1217,10 @@ elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h \ $(INCDIR)/coff/external.h ecoffswap.h elf32-target.h +elf32-msp430.lo: elf32-msp430.c $(INCDIR)/filenames.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/reloc-macros.h \ + elf32-target.h elf32-openrisc.lo: elf32-openrisc.c $(INCDIR)/filenames.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/openrisc.h \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 2bd807c04eb..efcbd818644 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -205,6 +205,7 @@ ALL_MACHINES = \ cpu-mcore.lo \ cpu-mips.lo \ cpu-mmix.lo \ + cpu-msp430.c \ cpu-or32.lo \ cpu-ns32k.lo \ cpu-openrisc.lo \ @@ -258,6 +259,7 @@ ALL_MACHINES_CFILES = \ cpu-mcore.c \ cpu-mips.c \ cpu-mmix.c \ + cpu-msp430.c \ cpu-or32.c \ cpu-ns32k.c \ cpu-openrisc.c \ @@ -358,6 +360,7 @@ BFD32_BACKENDS = \ elf32-mcore.lo \ elfxx-mips.lo \ elf32-mips.lo \ + elf32-msp430.c \ elf32-openrisc.lo \ elf32-or32.lo \ elf32-pj.lo \ @@ -516,6 +519,7 @@ BFD32_BACKENDS_CFILES = \ elf32-mcore.c \ elfxx-mips.c \ elf32-mips.c \ + elf32-msp430.c \ elf32-openrisc.c \ elf32-or32.c \ elf32-pj.c \ @@ -1460,6 +1464,7 @@ cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h cpu-mcore.lo: cpu-mcore.c $(INCDIR)/filenames.h cpu-mips.lo: cpu-mips.c $(INCDIR)/filenames.h cpu-mmix.lo: cpu-mmix.c $(INCDIR)/filenames.h +cpu-msp430.lo: cpu-msp430.c $(INCDIR)/filenames.h cpu-or32.lo: cpu-or32.c $(INCDIR)/filenames.h cpu-ns32k.lo: cpu-ns32k.c $(INCDIR)/filenames.h ns32k.h cpu-openrisc.lo: cpu-openrisc.c $(INCDIR)/filenames.h @@ -1745,6 +1750,10 @@ elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h \ $(INCDIR)/coff/external.h ecoffswap.h elf32-target.h +elf32-msp430.lo: elf32-msp430.c $(INCDIR)/filenames.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/elf/msp430.h $(INCDIR)/elf/reloc-macros.h \ + elf32-target.h elf32-openrisc.lo: elf32-openrisc.c $(INCDIR)/filenames.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/openrisc.h \ diff --git a/bfd/archures.c b/bfd/archures.c index b73766f775f..2ad7267b353 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -286,6 +286,20 @@ DESCRIPTION . bfd_arch_mmix, {* Donald Knuth's educational processor. *} . bfd_arch_xstormy16, .#define bfd_mach_xstormy16 1 +. bfd_arch_msp430, {* Texas Instruments MSP430 architecture. *} +.#define bfd_mach_msp110 110 +.#define bfd_mach_msp11 11 +.#define bfd_mach_msp12 12 +.#define bfd_mach_msp13 13 +.#define bfd_mach_msp14 14 +.#define bfd_mach_msp41 41 +.#define bfd_mach_msp31 31 +.#define bfd_mach_msp32 32 +.#define bfd_mach_msp33 33 +.#define bfd_mach_msp43 43 +.#define bfd_mach_msp44 44 +.#define bfd_mach_msp15 15 +.#define bfd_mach_msp16 16 . bfd_arch_last . }; */ @@ -355,6 +369,7 @@ extern const bfd_arch_info_type bfd_mips_arch; extern const bfd_arch_info_type bfd_mmix_arch; extern const bfd_arch_info_type bfd_mn10200_arch; extern const bfd_arch_info_type bfd_mn10300_arch; +extern const bfd_arch_info_type bfd_msp430_arch; extern const bfd_arch_info_type bfd_ns32k_arch; extern const bfd_arch_info_type bfd_openrisc_arch; extern const bfd_arch_info_type bfd_or32_arch; @@ -412,6 +427,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_mmix_arch, &bfd_mn10200_arch, &bfd_mn10300_arch, + &bfd_msp430_arch, &bfd_ns32k_arch, &bfd_openrisc_arch, &bfd_or32_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 362cc8f04f4..c72767982ee 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1713,6 +1713,20 @@ enum bfd_architecture bfd_arch_mmix, /* Donald Knuth's educational processor. */ bfd_arch_xstormy16, #define bfd_mach_xstormy16 1 + bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ +#define bfd_mach_msp110 110 +#define bfd_mach_msp11 11 +#define bfd_mach_msp12 12 +#define bfd_mach_msp13 13 +#define bfd_mach_msp14 14 +#define bfd_mach_msp41 41 +#define bfd_mach_msp31 31 +#define bfd_mach_msp32 32 +#define bfd_mach_msp33 33 +#define bfd_mach_msp43 43 +#define bfd_mach_msp44 44 +#define bfd_mach_msp15 15 +#define bfd_mach_msp16 16 bfd_arch_last }; @@ -3246,6 +3260,13 @@ to follow the 16K memory bank of 68HC12 (seen as mapped in the window). */ BFD_RELOC_VAX_GLOB_DAT, BFD_RELOC_VAX_JMP_SLOT, BFD_RELOC_VAX_RELATIVE, + +/* msp430 specific relocation codes */ + BFD_RELOC_MSP430_10_PCREL, + BFD_RELOC_MSP430_16_PCREL, + BFD_RELOC_MSP430_16, + BFD_RELOC_MSP430_16_PCREL_BYTE, + BFD_RELOC_MSP430_16_BYTE, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; reloc_howto_type * diff --git a/bfd/config.bfd b/bfd/config.bfd index 9270d7e9e85..4379b6f547b 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -807,6 +807,10 @@ case "${targ}" in targ_defvec=bfd_elf32_mn10300_vec ;; + msp430-*-*) + targ_defvec=bfd_elf32_msp430_vec + ;; + ns32k-pc532-mach* | ns32k-pc532-ux*) targ_defvec=pc532machaout_vec targ_underscore=yes diff --git a/bfd/configure b/bfd/configure index 74fe037d5e0..6d68944b2e0 100755 --- a/bfd/configure +++ b/bfd/configure @@ -6108,6 +6108,7 @@ do bfd_elf32_mcore_little_vec) tb="$tb elf32-mcore.lo elf32.lo $elf" ;; bfd_elf32_mn10200_vec) tb="$tb elf-m10200.lo elf32.lo $elf" ;; bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;; + bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; @@ -6358,10 +6359,10 @@ case ${host64}-${target64}-${want64} in if test -n "$GCC" ; then bad_64bit_gcc=no; echo $ac_n "checking for gcc version with buggy 64-bit support""... $ac_c" 1>&6 -echo "configure:6362: checking for gcc version with buggy 64-bit support" >&5 +echo "configure:6363: checking for gcc version with buggy 64-bit support" >&5 # Add more tests for gcc versions with non-working 64-bit support here. cat > conftest.$ac_ext <<EOF -#line 6365 "configure" +#line 6366 "configure" #include "confdefs.h" :__GNUC__:__GNUC_MINOR__:__i386__: EOF @@ -6407,17 +6408,17 @@ for ac_hdr in stdlib.h unistd.h sys/stat.h sys/types.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:6411: checking for $ac_hdr" >&5 +echo "configure:6412: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6416 "configure" +#line 6417 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6421: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6422: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6446,12 +6447,12 @@ done for ac_func in getpagesize do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6450: checking for $ac_func" >&5 +echo "configure:6451: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6455 "configure" +#line 6456 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -6474,7 +6475,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:6478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -6499,7 +6500,7 @@ fi done echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:6503: checking for working mmap" >&5 +echo "configure:6504: checking for working mmap" >&5 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6507,7 +6508,7 @@ else ac_cv_func_mmap_fixed_mapped=no else cat > conftest.$ac_ext <<EOF -#line 6511 "configure" +#line 6512 "configure" #include "confdefs.h" /* Thanks to Mike Haertel and Jim Avera for this test. @@ -6660,7 +6661,7 @@ main() } EOF -if { (eval echo configure:6664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6665: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_mmap_fixed_mapped=yes else @@ -6685,12 +6686,12 @@ fi for ac_func in madvise mprotect do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6689: checking for $ac_func" >&5 +echo "configure:6690: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6694 "configure" +#line 6695 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -6713,7 +6714,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:6717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else diff --git a/bfd/configure.in b/bfd/configure.in index aa34e7da4b1..e641e7361a7 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -604,6 +604,7 @@ do bfd_elf32_mcore_little_vec) tb="$tb elf32-mcore.lo elf32.lo $elf" ;; bfd_elf32_mn10200_vec) tb="$tb elf-m10200.lo elf32.lo $elf" ;; bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;; + bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; diff --git a/bfd/cpu-msp430.c b/bfd/cpu-msp430.c new file mode 100644 index 00000000000..c7d283b63bb --- /dev/null +++ b/bfd/cpu-msp430.c @@ -0,0 +1,107 @@ +/* BFD library support routines for the MSP architecture. + Copyright (C) 2002 Free Software Foundation, Inc. + Contributed by Dmitry Diky <diwil@mail.ru> + + 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" + +static const bfd_arch_info_type *compatible + PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *)); + +#define N(addr_bits, machine, print, default, next) \ +{ \ + 16, /* 16 bits in a word. */ \ + addr_bits, /* Bits in an address. */ \ + 8, /* 8 bits in a byte. */ \ + bfd_arch_msp430, \ + machine, /* Machine number. */ \ + "msp430", /* Architecture name. */ \ + print, /* Printable name. */ \ + 1, /* Section align power. */ \ + default, /* The default machine. */ \ + compatible, \ + bfd_default_scan, \ + next \ +} + +static const bfd_arch_info_type arch_info_struct[] = +{ + /* msp430x11x. */ + N (16, bfd_mach_msp11, "msp:11", FALSE, & arch_info_struct[1]), + + /* msp430x12x. */ + N (16, bfd_mach_msp12, "msp:12", FALSE, & arch_info_struct[2]), + + /* msp430x13x. */ + N (16, bfd_mach_msp13, "msp:13", FALSE, & arch_info_struct[3]), + + /* msp430x14x. */ + N (16, bfd_mach_msp14, "msp:14", FALSE, & arch_info_struct[4]), + + /* msp430x31x. */ + N (16, bfd_mach_msp31, "msp:31", FALSE, & arch_info_struct[5]), + + /* msp430x32x. */ + N (16, bfd_mach_msp32, "msp:32", FALSE, & arch_info_struct[6]), + + /* msp430x33x. */ + N (16, bfd_mach_msp33, "msp:33", FALSE, & arch_info_struct[7]), + + /* msp430x41x. */ + N (16, bfd_mach_msp41, "msp:41", FALSE, & arch_info_struct[8]), + + /* msp430x43x. */ + N (16, bfd_mach_msp43, "msp:43", FALSE, & arch_info_struct[9]), + + /* msp430x44x. */ + N (16, bfd_mach_msp43, "msp:44", FALSE, & arch_info_struct[10]), + + /* msp430x15x. */ + N (16, bfd_mach_msp15, "msp:15", FALSE, & arch_info_struct[11]), + + /* msp430x16x. */ + N (16, bfd_mach_msp16, "msp:16", FALSE, & arch_info_struct[12]), + + /* msp430x11x1. */ + N (16, bfd_mach_msp110, "msp:110", FALSE, NULL) + +}; + +const bfd_arch_info_type bfd_msp430_arch = + N (16, bfd_mach_msp14, "msp:14", TRUE, & arch_info_struct[0]); + +/* This routine is provided two arch_infos and works out which MSP + machine which would be compatible with both and returns a pointer + to its info structure. */ + +static const bfd_arch_info_type * +compatible (a,b) + const bfd_arch_info_type * a; + const bfd_arch_info_type * b; +{ + /* If a & b are for different architectures we can do nothing. */ + if (a->arch != b->arch) + return NULL; + + if (a->mach <= b->mach) + return b; + + return a; +} diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c new file mode 100644 index 00000000000..694a30f1198 --- /dev/null +++ b/bfd/elf32-msp430.c @@ -0,0 +1,720 @@ +/* MSP430-specific support for 32-bit ELF + Copyright (C) 2002 Free Software Foundation, Inc. + Contributed by Dmitry Diky <diwil@mail.ru> + + 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 "libiberty.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/msp430.h" + +static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup + PARAMS ((bfd *, bfd_reloc_code_real_type)); + +static void msp430_info_to_howto_rela + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); + +static asection *elf32_msp430_gc_mark_hook + PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *)); + +static bfd_boolean elf32_msp430_gc_sweep_hook + PARAMS ((bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *)); + +static bfd_boolean elf32_msp430_check_relocs + PARAMS ((bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *)); + +static bfd_reloc_status_type msp430_final_link_relocate + PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, bfd_vma)); + +static bfd_boolean elf32_msp430_relocate_section + PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); + +static void bfd_elf_msp430_final_write_processing + PARAMS ((bfd *, bfd_boolean)); + +static bfd_boolean elf32_msp430_object_p + PARAMS ((bfd *)); + +static void elf32_msp430_post_process_headers + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Use RELA instead of REL. */ +#undef USE_REL + +static reloc_howto_type elf_msp430_howto_table[] = +{ + HOWTO (R_MSP430_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_MSP430_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MSP430_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MSP430_32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 13 bit PC relative relocation. */ + HOWTO (R_MSP430_10_PCREL, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MSP430_13_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A 16 bit absolute relocation. */ + HOWTO (R_MSP430_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_MSP430_16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit absolute relocation for command address. */ + HOWTO (R_MSP430_16_PCREL, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MSP430_16_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A 16 bit absolute relocation, byte operations. */ + HOWTO (R_MSP430_16_BYTE, /* 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_MSP430_16_BYTE", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit absolute relocation for command address. */ + HOWTO (R_MSP430_16_PCREL_BYTE,/* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MSP430_16_PCREL_BYTE", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE) /* pcrel_offset */ +}; + +/* Map BFD reloc types to MSP430 ELF reloc types. */ + +struct msp430_reloc_map +{ + bfd_reloc_code_real_type bfd_reloc_val; + unsigned int elf_reloc_val; +}; + +static const struct msp430_reloc_map msp430_reloc_map[] = + { + {BFD_RELOC_NONE, R_MSP430_NONE}, + {BFD_RELOC_32, R_MSP430_32}, + {BFD_RELOC_MSP430_10_PCREL, R_MSP430_10_PCREL}, + {BFD_RELOC_16, R_MSP430_16_BYTE}, + {BFD_RELOC_MSP430_16_PCREL, R_MSP430_16_PCREL}, + {BFD_RELOC_MSP430_16, R_MSP430_16}, + {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE}, + {BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE} + }; + +static reloc_howto_type * +bfd_elf32_bfd_reloc_type_lookup (abfd, code) + bfd *abfd ATTRIBUTE_UNUSED; + bfd_reloc_code_real_type code; +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (msp430_reloc_map); i++) + if (msp430_reloc_map[i].bfd_reloc_val == code) + return &elf_msp430_howto_table[msp430_reloc_map[i].elf_reloc_val]; + + return NULL; +} + +/* Set the howto pointer for an MSP430 ELF reloc. */ + +static void +msp430_info_to_howto_rela (abfd, cache_ptr, dst) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *cache_ptr; + Elf_Internal_Rela *dst; +{ + unsigned int r_type; + + r_type = ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (r_type < (unsigned int) R_MSP430_max); + cache_ptr->howto = &elf_msp430_howto_table[r_type]; +} + +static asection * +elf32_msp430_gc_mark_hook (sec, info, rel, h, sym) + asection *sec; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + Elf_Internal_Rela *rel; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; +{ + if (h != NULL) + { + switch (ELF32_R_TYPE (rel->r_info)) + { + default: + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + + default: + break; + } + } + } + else + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + + return NULL; +} + +static bfd_boolean +elf32_msp430_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; +{ + /* We don't use got and plt entries for msp430. */ + return TRUE; +} + +/* Look through the relocs for a section during the first phase. + Since we don't do .gots or .plts, we just need to consider the + virtual table relocs for gc. */ + +static bfd_boolean +elf32_msp430_check_relocs (abfd, info, sec, relocs) + bfd *abfd; + struct bfd_link_info *info; + asection *sec; + const Elf_Internal_Rela *relocs; +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + + if (info->relocateable) + return TRUE; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + sym_hashes_end = + sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); + if (!elf_bad_symtab (abfd)) + sym_hashes_end -= symtab_hdr->sh_info; + + rel_end = relocs + sec->reloc_count; + for (rel = relocs; rel < rel_end; rel++) + { + struct elf_link_hash_entry *h; + unsigned long r_symndx; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + else + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + } + + return TRUE; +} + +/* Perform a single relocation. By default we use the standard BFD + routines, but a few relocs, we have to do them ourselves. */ + +static bfd_reloc_status_type +msp430_final_link_relocate (howto, input_bfd, input_section, + contents, rel, relocation) + reloc_howto_type *howto; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + Elf_Internal_Rela *rel; + bfd_vma relocation; +{ + bfd_reloc_status_type r = bfd_reloc_ok; + bfd_vma x; + bfd_signed_vma srel; + + switch (howto->type) + { + case R_MSP430_10_PCREL: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; + srel -= rel->r_offset; + srel -= 2; /* Branch instructions add 2 to the PC... */ + srel -= (input_section->output_section->vma + + input_section->output_offset); + + if (srel & 1) + return bfd_reloc_outofrange; + + /* MSP430 addresses commands as words. */ + srel >>= 1; + + /* Check for an overflow. */ + if (srel < -512 || srel > 511) + return bfd_reloc_overflow; + + x = bfd_get_16 (input_bfd, contents); + x = (x & 0xfc00) | (srel & 0x3ff); + bfd_put_16 (input_bfd, x, contents); + break; + + case R_MSP430_16_PCREL: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; + srel -= rel->r_offset; + /* Only branch instructions add 2 to the PC... */ + srel -= (input_section->output_section->vma + + input_section->output_offset); + + if (srel & 1) + return bfd_reloc_outofrange; + + bfd_put_16 (input_bfd, srel & 0xffff, contents); + break; + + case R_MSP430_16_PCREL_BYTE: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; + srel -= rel->r_offset; + /* Only branch instructions add 2 to the PC... */ + srel -= (input_section->output_section->vma + + input_section->output_offset); + + bfd_put_16 (input_bfd, srel & 0xffff, contents); + break; + + case R_MSP430_16_BYTE: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; + bfd_put_16 (input_bfd, srel & 0xffff, contents); + break; + + case R_MSP430_16: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; + + if (srel & 1) + return bfd_reloc_notsupported; + + bfd_put_16 (input_bfd, srel & 0xffff, contents); + break; + + default: + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, rel->r_addend); + } + + return r; +} + +/* Relocate an MSP430 ELF section. */ + +static bfd_boolean +elf32_msp430_relocate_section (output_bfd, info, input_bfd, input_section, + contents, relocs, local_syms, local_sections) + bfd *output_bfd ATTRIBUTE_UNUSED; + struct bfd_link_info *info; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + Elf_Internal_Rela *relocs; + Elf_Internal_Sym *local_syms; + asection **local_sections; +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (input_bfd); + relend = relocs + input_section->reloc_count; + + for (rel = relocs; rel < relend; rel++) + { + reloc_howto_type *howto; + unsigned long r_symndx; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h; + bfd_vma relocation; + bfd_reloc_status_type r; + const char *name = NULL; + int r_type; + + /* This is a final link. */ + + r_type = ELF32_R_TYPE (rel->r_info); + r_symndx = ELF32_R_SYM (rel->r_info); + howto = elf_msp430_howto_table + ELF32_R_TYPE (rel->r_info); + h = NULL; + sym = NULL; + sec = NULL; + + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); + + name = bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name); + name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; + } + else + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + name = h->root.root.string; + + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + sec = h->root.u.def.section; + relocation = (h->root.u.def.value + + sec->output_section->vma + sec->output_offset); + } + else if (h->root.type == bfd_link_hash_undefweak) + { + relocation = 0; + } + else + { + if (!((*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, + input_section, rel->r_offset, TRUE))) + return FALSE; + relocation = 0; + } + } + + r = msp430_final_link_relocate (howto, input_bfd, input_section, + contents, rel, relocation); + + if (r != bfd_reloc_ok) + { + const char *msg = (const char *) NULL; + + switch (r) + { + case bfd_reloc_overflow: + r = info->callbacks->reloc_overflow + (info, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset); + break; + + case bfd_reloc_undefined: + r = info->callbacks->undefined_symbol + (info, name, input_bfd, input_section, rel->r_offset, TRUE); + break; + + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + break; + + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation error"); + break; + + case bfd_reloc_dangerous: + msg = _("internal error: dangerous relocation"); + break; + + default: + msg = _("internal error: unknown error"); + break; + } + + if (msg) + r = info->callbacks->warning + (info, msg, name, input_bfd, input_section, rel->r_offset); + + if (!r) + return FALSE; + } + + } + + return TRUE; +} + +/* The final processing done just before writing out a MSP430 ELF object + file. This gets the MSP430 architecture right based on the machine + number. */ + +static void +bfd_elf_msp430_final_write_processing (abfd, linker) + bfd *abfd; + bfd_boolean linker ATTRIBUTE_UNUSED; +{ + unsigned long val; + + switch (bfd_get_mach (abfd)) + { + default: + case bfd_mach_msp12: + val = E_MSP430_MACH_MSP430x12; + break; + + case bfd_mach_msp110: + val = E_MSP430_MACH_MSP430x11x1; + break; + + case bfd_mach_msp11: + val = E_MSP430_MACH_MSP430x11; + break; + + case bfd_mach_msp13: + val = E_MSP430_MACH_MSP430x13; + break; + + case bfd_mach_msp14: + val = E_MSP430_MACH_MSP430x14; + break; + + case bfd_mach_msp41: + val = E_MSP430_MACH_MSP430x41; + break; + + case bfd_mach_msp43: + val = E_MSP430_MACH_MSP430x43; + break; + + case bfd_mach_msp44: + val = E_MSP430_MACH_MSP430x44; + break; + + case bfd_mach_msp31: + val = E_MSP430_MACH_MSP430x31; + break; + + case bfd_mach_msp32: + val = E_MSP430_MACH_MSP430x32; + break; + + case bfd_mach_msp33: + val = E_MSP430_MACH_MSP430x33; + break; + + case bfd_mach_msp15: + val = E_MSP430_MACH_MSP430x15; + break; + + case bfd_mach_msp16: + val = E_MSP430_MACH_MSP430x16; + break; + } + + elf_elfheader (abfd)->e_machine = EM_MSP430; + elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH; + elf_elfheader (abfd)->e_flags |= val; +} + +/* Set the right machine number. */ + +static bfd_boolean +elf32_msp430_object_p (abfd) + bfd *abfd; +{ + int e_set = bfd_mach_msp14; + + if (elf_elfheader (abfd)->e_machine == EM_MSP430 + || elf_elfheader (abfd)->e_machine == EM_MSP430_OLD) + { + int e_mach = elf_elfheader (abfd)->e_flags & EF_MSP430_MACH; + + switch (e_mach) + { + default: + case E_MSP430_MACH_MSP430x12: + e_set = bfd_mach_msp12; + break; + + case E_MSP430_MACH_MSP430x11: + e_set = bfd_mach_msp11; + break; + + case E_MSP430_MACH_MSP430x11x1: + e_set = bfd_mach_msp110; + break; + + case E_MSP430_MACH_MSP430x13: + e_set = bfd_mach_msp13; + break; + + case E_MSP430_MACH_MSP430x14: + e_set = bfd_mach_msp14; + break; + + case E_MSP430_MACH_MSP430x41: + e_set = bfd_mach_msp41; + break; + + case E_MSP430_MACH_MSP430x31: + e_set = bfd_mach_msp31; + break; + + case E_MSP430_MACH_MSP430x32: + e_set = bfd_mach_msp32; + break; + + case E_MSP430_MACH_MSP430x33: + e_set = bfd_mach_msp33; + break; + + case E_MSP430_MACH_MSP430x43: + e_set = bfd_mach_msp43; + break; + + case E_MSP430_MACH_MSP430x44: + e_set = bfd_mach_msp44; + break; + + case E_MSP430_MACH_MSP430x15: + e_set = bfd_mach_msp15; + break; + + case E_MSP430_MACH_MSP430x16: + e_set = bfd_mach_msp16; + break; + } + } + + return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set); +} + +static void +elf32_msp430_post_process_headers (abfd, link_info) + bfd *abfd; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; +{ + Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */ + + i_ehdrp = elf_elfheader (abfd); + +#ifndef ELFOSABI_STANDALONE +#define ELFOSABI_STANDALONE 255 +#endif + + i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE; +} + + +#define ELF_ARCH bfd_arch_msp430 +#define ELF_MACHINE_CODE EM_MSP430 +#define ELF_MACHINE_ALT1 EM_MSP430_OLD +#define ELF_MAXPAGESIZE 1 + +#define TARGET_LITTLE_SYM bfd_elf32_msp430_vec +#define TARGET_LITTLE_NAME "elf32-msp430" + +#define elf_info_to_howto msp430_info_to_howto_rela +#define elf_info_to_howto_rel NULL +#define elf_backend_relocate_section elf32_msp430_relocate_section +#define elf_backend_gc_mark_hook elf32_msp430_gc_mark_hook +#define elf_backend_gc_sweep_hook elf32_msp430_gc_sweep_hook +#define elf_backend_check_relocs elf32_msp430_check_relocs +#define elf_backend_can_gc_sections 1 +#define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing +#define elf_backend_object_p elf32_msp430_object_p +#define elf_backend_post_process_headers elf32_msp430_post_process_headers + +#include "elf32-target.h" diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 8f3cf58b61d..3a3a8a03c50 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1373,6 +1373,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_VAX_GLOB_DAT", "BFD_RELOC_VAX_JMP_SLOT", "BFD_RELOC_VAX_RELATIVE", + "BFD_RELOC_MSP430_10_PCREL", + "BFD_RELOC_MSP430_16_PCREL", + "BFD_RELOC_MSP430_16", + "BFD_RELOC_MSP430_16_PCREL_BYTE", + "BFD_RELOC_MSP430_16_BYTE", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif diff --git a/bfd/reloc.c b/bfd/reloc.c index 23224f3b3ab..ebf59aae9f5 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3613,6 +3613,19 @@ ENUMX BFD_RELOC_VAX_RELATIVE ENUMDOC Relocations used by VAX ELF. + +ENUM + BFD_RELOC_MSP430_10_PCREL +ENUMX + BFD_RELOC_MSP430_16_PCREL +ENUMX + BFD_RELOC_MSP430_16 +ENUMX + BFD_RELOC_MSP430_16_PCREL_BYTE +ENUMX + BFD_RELOC_MSP430_16_BYTE +ENUMDOC + msp430 specific relocation codes ENDSENUM BFD_RELOC_UNUSED diff --git a/bfd/targets.c b/bfd/targets.c index 998327de1d0..bebd6a0a1b9 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -547,6 +547,7 @@ extern const bfd_target bfd_elf32_mcore_big_vec; extern const bfd_target bfd_elf32_mcore_little_vec; extern const bfd_target bfd_elf32_mn10200_vec; extern const bfd_target bfd_elf32_mn10300_vec; +extern const bfd_target bfd_elf32_msp430_vec; extern const bfd_target bfd_elf32_nbigmips_vec; extern const bfd_target bfd_elf32_nlittlemips_vec; extern const bfd_target bfd_elf32_ntradbigmips_vec; @@ -833,6 +834,7 @@ static const bfd_target * const _bfd_target_vector[] = { &bfd_elf32_mcore_little_vec, &bfd_elf32_mn10200_vec, &bfd_elf32_mn10300_vec, + &bfd_elf32_msp430_vec, #ifdef BFD64 &bfd_elf32_nbigmips_vec, &bfd_elf32_nlittlemips_vec, diff --git a/include/ChangeLog b/include/ChangeLog index 60b54242736..5cde93615fb 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2002-12-24 Dmitry Diky <diwil@mail.ru> + + * dis-asm.h: Add msp430 disassembler prototype. + 2002-12-27 Chris Demetriou <cgd@broadcom.com> * dis-asm.h (print_mips_disassembler_options): Prototype. diff --git a/include/dis-asm.h b/include/dis-asm.h index 04a7f5dab38..2e1b1961655 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -217,6 +217,7 @@ extern int print_insn_mcore PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_mmix PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_mn10200 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_mn10300 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_msp430 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_ns32k PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_openrisc PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_big_or32 PARAMS ((bfd_vma, disassemble_info*)); diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index de95f20c5a8..87e8a3bac1f 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,8 @@ +2002-12-24 Dmitry Diky <diwil@mail.ru> + + * common.h: Define msp430 machine numbers. + * msp430.h: New file. Define msp430 relocs. + 2002-12-20 DJ Delorie <dj@redhat.com> * xstormy16.h: Add XSTORMY16_12. diff --git a/include/elf/common.h b/include/elf/common.h index 0cef267e952..629c6146ff9 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -251,6 +251,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Ubicom IP2xxx; no ABI */ #define EM_IP2K_OLD 0x8217 +/* MSP430 magic number + Written in the absense everything. */ +#define EM_MSP430_OLD 0x1059 + +/* TI msp430 micro controller. */ +#define EM_MSP430 0x430 + /* See the above comment before you add a new EM_* value here. */ /* Values for e_version. */ diff --git a/include/elf/msp430.h b/include/elf/msp430.h new file mode 100644 index 00000000000..cb3f241dea1 --- /dev/null +++ b/include/elf/msp430.h @@ -0,0 +1,55 @@ +/* MSP430 ELF support for BFD. + Copyright (C) 2002 Free Software Foundation, Inc. + Contributed by Dmitry Diky <diwil@mail.ru> + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _ELF_MSP430_H +#define _ELF_MSP430_H + +#include "elf/reloc-macros.h" + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_MSP430_MACH 0xff + +#define E_MSP430_MACH_MSP430x11x1 110 +#define E_MSP430_MACH_MSP430x11 11 +#define E_MSP430_MACH_MSP430x12 12 +#define E_MSP430_MACH_MSP430x13 13 +#define E_MSP430_MACH_MSP430x14 14 +#define E_MSP430_MACH_MSP430x31 31 +#define E_MSP430_MACH_MSP430x32 32 +#define E_MSP430_MACH_MSP430x33 33 +#define E_MSP430_MACH_MSP430x41 41 +#define E_MSP430_MACH_MSP430x43 43 +#define E_MSP430_MACH_MSP430x44 44 +#define E_MSP430_MACH_MSP430x15 15 +#define E_MSP430_MACH_MSP430x16 16 + +/* Relocations. */ +START_RELOC_NUMBERS (elf_msp430_reloc_type) + RELOC_NUMBER (R_MSP430_NONE, 0) + RELOC_NUMBER (R_MSP430_32, 1) + RELOC_NUMBER (R_MSP430_10_PCREL, 2) + RELOC_NUMBER (R_MSP430_16, 3) + RELOC_NUMBER (R_MSP430_16_PCREL, 4) + RELOC_NUMBER (R_MSP430_16_BYTE, 5) + RELOC_NUMBER (R_MSP430_16_PCREL_BYTE, 6) + +END_RELOC_NUMBERS (R_MSP430_max) + +#endif /* _ELF_MSP430_H */ diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index a0d7b5ba2ed..10fbb98f040 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,7 @@ +2002-12-24 Dmitry Diky <diwil@mail.ru> + + * msp430.h: New file. Defines msp430 opcodes. + 2002-12-30 D.Venkatasubramanian <dvenkat@noida.hcltech.com> * h8300.h: Added some more pseudo opcodes for system call diff --git a/include/opcode/msp430.h b/include/opcode/msp430.h new file mode 100644 index 00000000000..19702254eef --- /dev/null +++ b/include/opcode/msp430.h @@ -0,0 +1,111 @@ +/* Opcode table for the TI MSP430 microcontrollers + + Copyright 2002 Free Software Foundation, Inc. + Contributed by Dmitry Diky <diwil@mail.ru> + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef __MSP430_H_ +#define __MSP430_H_ + +struct msp430_operand_s +{ + int ol; /* Operand length words. */ + int am; /* Addr mode. */ + int reg; /* Register. */ + int mode; /* Pperand mode. */ +#define OP_REG 0 +#define OP_EXP 1 +#ifndef DASM_SECTION + expressionS exp; +#endif +}; + +#define BYTE_OPERATION (1 << 6) /* Byte operation flag for all instructions. */ + +struct msp430_opcode_s +{ + char *name; + int fmt; + int insn_opnumb; + int bin_opcode; + int bin_mask; +}; + +#define MSP_INSN(name, size, numb, bin, mask) { #name, size, numb, bin, mask } + +static struct msp430_opcode_s msp430_opcodes[] = +{ + MSP_INSN (and, 1, 2, 0xf000, 0xf000), + MSP_INSN (inv, 0, 1, 0xe330, 0xfff0), + MSP_INSN (xor, 1, 2, 0xe000, 0xf000), + MSP_INSN (setz, 0, 0, 0xd322, 0xffff), + MSP_INSN (setc, 0, 0, 0xd312, 0xffff), + MSP_INSN (eint, 0, 0, 0xd232, 0xffff), + MSP_INSN (setn, 0, 0, 0xd222, 0xffff), + MSP_INSN (bis, 1, 2, 0xd000, 0xf000), + MSP_INSN (clrz, 0, 0, 0xc322, 0xffff), + MSP_INSN (clrc, 0, 0, 0xc312, 0xffff), + MSP_INSN (dint, 0, 0, 0xc232, 0xffff), + MSP_INSN (clrn, 0, 0, 0xc222, 0xffff), + MSP_INSN (bic, 1, 2, 0xc000, 0xf000), + MSP_INSN (bit, 1, 2, 0xb000, 0xf000), + MSP_INSN (dadc, 0, 1, 0xa300, 0xff30), + MSP_INSN (dadd, 1, 2, 0xa000, 0xf000), + MSP_INSN (tst, 0, 1, 0x9300, 0xff30), + MSP_INSN (cmp, 1, 2, 0x9000, 0xf000), + MSP_INSN (decd, 0, 1, 0x8320, 0xff30), + MSP_INSN (dec, 0, 1, 0x8310, 0xff30), + MSP_INSN (sub, 1, 2, 0x8000, 0xf000), + MSP_INSN (sbc, 0, 1, 0x7300, 0xff30), + MSP_INSN (subc, 1, 2, 0x7000, 0xf000), + MSP_INSN (adc, 0, 1, 0x6300, 0xff30), + MSP_INSN (rlc, 0, 2, 0x6000, 0xf000), + MSP_INSN (addc, 1, 2, 0x6000, 0xf000), + MSP_INSN (incd, 0, 1, 0x5320, 0xff30), + MSP_INSN (inc, 0, 1, 0x5310, 0xff30), + MSP_INSN (rla, 0, 2, 0x5000, 0xf000), + MSP_INSN (add, 1, 2, 0x5000, 0xf000), + MSP_INSN (nop, 0, 0, 0x4303, 0xffff), + MSP_INSN (clr, 0, 1, 0x4300, 0xff30), + MSP_INSN (ret, 0, 0, 0x4130, 0xff30), + MSP_INSN (pop, 0, 1, 0x4130, 0xff30), + MSP_INSN (br, 0, 3, 0x4000, 0xf000), + MSP_INSN (mov, 1, 2, 0x4000, 0xf000), + MSP_INSN (jmp, 3, 1, 0x3c00, 0xfc00), + MSP_INSN (jl, 3, 1, 0x3800, 0xfc00), + MSP_INSN (jge, 3, 1, 0x3400, 0xfc00), + MSP_INSN (jn, 3, 1, 0x3000, 0xfc00), + MSP_INSN (jc, 3, 1, 0x2c00, 0xfc00), + MSP_INSN (jhs, 3, 1, 0x2c00, 0xfc00), + MSP_INSN (jnc, 3, 1, 0x2800, 0xfc00), + MSP_INSN (jlo, 3, 1, 0x2800, 0xfc00), + MSP_INSN (jz, 3, 1, 0x2400, 0xfc00), + MSP_INSN (jeq, 3, 1, 0x2400, 0xfc00), + MSP_INSN (jnz, 3, 1, 0x2000, 0xfc00), + MSP_INSN (jne, 3, 1, 0x2000, 0xfc00), + MSP_INSN (reti, 2, 0, 0x1300, 0xffc0), + MSP_INSN (call, 2, 1, 0x1280, 0xffc0), + MSP_INSN (push, 2, 1, 0x1200, 0xff80), + MSP_INSN (sxt, 2, 1, 0x1180, 0xffc0), + MSP_INSN (rra, 2, 1, 0x1100, 0xff80), + MSP_INSN (swpb, 2, 1, 0x1080, 0xffc0), + MSP_INSN (rrc, 2, 1, 0x1000, 0xff80), + + /* End of instruction set. */ + { NULL, 0, 0, 0, 0 } +}; + +#endif diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c5dff567378..7ff7f953639 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2002-12-30 Dmitry Diky <diwil@mail.ru> + + * configure.in: Add msp430 target. + * configure: Regenerate. + * disassemble.c: Add entry for msp430 disassembly. + * msp430-dis.c: New file: msp430 disassembler. + 2002-12-27 Chris Demetriou <cgd@broadcom.com> * disassemble.c (disassembler_usage): Add invocation of diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index da66cf594e8..08ea4b222db 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -451,7 +451,7 @@ acinclude.m4 aclocal.m4 config.in configure configure.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best SOURCES = libopcodes.a.c $(libopcodes_la_SOURCES) OBJECTS = libopcodes.a.$(OBJEXT) $(libopcodes_la_OBJECTS) @@ -600,7 +600,7 @@ maintainer-clean-recursive: dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ - test "$$subdir" = "." && dot_seen=yes; \ + test "$$subdir" != "." || dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ diff --git a/opcodes/configure b/opcodes/configure index 6825a0b020b..8eed735ed5a 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -2338,7 +2338,7 @@ if test "${enable_install_libbfd+set}" = set; then enableval="$enable_install_libbfd" install_libbfd_p=$enableval else - if test "${host}" = "${target}" -o "$enable_shared" = "yes"; then + if test "${host}" = "${target}" || test "$enable_shared" = "yes"; then install_libbfd_p=yes else install_libbfd_p=no @@ -4625,6 +4625,7 @@ if test x${all_targets} = xfalse ; then bfd_mmix_arch) ta="$ta mmix-dis.lo mmix-opc.lo" ;; bfd_mn10200_arch) ta="$ta m10200-dis.lo m10200-opc.lo" ;; bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;; + bfd_msp430_arch) ta="$ta msp430-dis.lo" ;; bfd_ns32k_arch) ta="$ta ns32k-dis.lo" ;; bfd_openrisc_arch) ta="$ta openrisc-asm.lo openrisc-desc.lo openrisc-dis.lo openrisc-ibld.lo openrisc-opc.lo" using_cgen=yes ;; bfd_or32_arch) ta="$ta or32-dis.lo or32-opc.lo" using_cgen=yes ;; diff --git a/opcodes/configure.in b/opcodes/configure.in index 0e5eb6f5fb4..bc8d6f8e942 100644 --- a/opcodes/configure.in +++ b/opcodes/configure.in @@ -200,6 +200,7 @@ if test x${all_targets} = xfalse ; then bfd_mmix_arch) ta="$ta mmix-dis.lo mmix-opc.lo" ;; bfd_mn10200_arch) ta="$ta m10200-dis.lo m10200-opc.lo" ;; bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;; + bfd_msp430_arch) ta="$ta msp430-dis.lo" ;; bfd_ns32k_arch) ta="$ta ns32k-dis.lo" ;; bfd_openrisc_arch) ta="$ta openrisc-asm.lo openrisc-desc.lo openrisc-dis.lo openrisc-ibld.lo openrisc-opc.lo" using_cgen=yes ;; bfd_or32_arch) ta="$ta or32-dis.lo or32-opc.lo" using_cgen=yes ;; diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index bfee746a0c1..1c2c21c1788 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -49,6 +49,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ARCH_mmix #define ARCH_mn10200 #define ARCH_mn10300 +#define ARCH_msp430 #define ARCH_ns32k #define ARCH_openrisc #define ARCH_or32 @@ -214,6 +215,11 @@ disassembler (abfd) disassemble = print_insn_m88k; break; #endif +#ifdef ARCH_msp430 + case bfd_arch_msp430: + disassemble = print_insn_msp430; + break; +#endif #ifdef ARCH_ns32k case bfd_arch_ns32k: disassemble = print_insn_ns32k; diff --git a/opcodes/msp430-dis.c b/opcodes/msp430-dis.c new file mode 100644 index 00000000000..767ffa472c1 --- /dev/null +++ b/opcodes/msp430-dis.c @@ -0,0 +1,805 @@ +/* Disassemble MSP430 instructions. + Copyright (C) 2002 Free Software Foundation, Inc. + + Contributed by Dmitry Diky <diwil@mail.ru> + + 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 <stdio.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> + +#include "dis-asm.h" +#include "opintl.h" +#include "libiberty.h" + +#define DASM_SECTION +#include "opcode/msp430.h" +#undef DASM_SECTION + + +static unsigned short msp430dis_opcode + PARAMS ((bfd_vma, disassemble_info *)); +int print_insn_msp430 + PARAMS ((bfd_vma, disassemble_info *)); +int msp430_nooperands + PARAMS ((struct msp430_opcode_s *, bfd_vma, unsigned short, char *, int *)); +int msp430_singleoperand + PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, + char *, char *, int *)); +int msp430_doubleoperand + PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, + char *, char *, char *, char *, int *)); +int msp430_branchinstr + PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, + char *, char *, int *)); + +#define PS(x) (0xffff & (x)) + +static unsigned short +msp430dis_opcode (addr, info) + bfd_vma addr; + disassemble_info *info; +{ + bfd_byte buffer[2]; + int status; + + status = info->read_memory_func (addr, buffer, 2, info); + if (status != 0) + { + info->memory_error_func (status, addr, info); + return -1; + } + return bfd_getl16 (buffer); +} + +int +print_insn_msp430 (addr, info) + bfd_vma addr; + disassemble_info *info; +{ + void *stream = info->stream; + fprintf_ftype prin = info->fprintf_func; + struct msp430_opcode_s *opcode; + char op1[32], op2[32], comm1[64], comm2[64]; + int cmd_len = 0; + unsigned short insn; + int cycles = 0; + char *bc = ""; + char dinfo[32]; /* Debug purposes. */ + + insn = msp430dis_opcode (addr, info); + sprintf (dinfo, "0x%04x", insn); + + if (((int) addr & 0xffff) > 0xffdf) + { + (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn); + return 2; + } + + *comm1 = 0; + *comm2 = 0; + + for (opcode = msp430_opcodes; opcode->name; opcode++) + { + if ((insn & opcode->bin_mask) == opcode->bin_opcode + && opcode->bin_opcode != 0x9300) + { + *op1 = 0; + *op2 = 0; + *comm1 = 0; + *comm2 = 0; + + /* r0 as destination. Ad should be zero. */ + if (opcode->insn_opnumb == 3 && (insn & 0x000f) == 0 + && (0x0080 & insn) == 0) + { + cmd_len = + msp430_branchinstr (info, opcode, addr, insn, op1, comm1, + &cycles); + if (cmd_len) + break; + } + + switch (opcode->insn_opnumb) + { + case 0: + cmd_len = msp430_nooperands (opcode, addr, insn, comm1, &cycles); + break; + case 2: + cmd_len = + msp430_doubleoperand (info, opcode, addr, insn, op1, op2, + comm1, comm2, &cycles); + if (insn & BYTE_OPERATION) + bc = ".b"; + break; + case 1: + cmd_len = + msp430_singleoperand (info, opcode, addr, insn, op1, comm1, + &cycles); + if (insn & BYTE_OPERATION && opcode->fmt != 3) + bc = ".b"; + break; + default: + break; + } + } + + if (cmd_len) + break; + } + + dinfo[5] = 0; + + if (cmd_len < 1) + { + /* Unknown opcode, or invalid combination of operands. */ + (*prin) (stream, ".word 0x%04x; ????", PS (insn)); + return 2; + } + + (*prin) (stream, "%s%s", opcode->name, bc); + + if (*op1) + (*prin) (stream, "\t%s", op1); + if (*op2) + (*prin) (stream, ","); + + if (strlen (op1) < 7) + (*prin) (stream, "\t"); + if (!strlen (op1)) + (*prin) (stream, "\t"); + + if (*op2) + (*prin) (stream, "%s", op2); + if (strlen (op2) < 8) + (*prin) (stream, "\t"); + + if (*comm1 || *comm2) + (*prin) (stream, ";"); + else if (cycles) + { + if (*op2) + (*prin) (stream, ";"); + else + { + if (strlen (op1) < 7) + (*prin) (stream, ";"); + else + (*prin) (stream, "\t;"); + } + } + if (*comm1) + (*prin) (stream, "%s", comm1); + if (*comm1 && *comm2) + (*prin) (stream, ","); + if (*comm2) + (*prin) (stream, " %s", comm2); + return cmd_len; +} + +int +msp430_nooperands (opcode, addr, insn, comm, cycles) + struct msp430_opcode_s *opcode; + bfd_vma addr ATTRIBUTE_UNUSED; + unsigned short insn ATTRIBUTE_UNUSED; + char *comm; + int *cycles; +{ + /* Pop with constant. */ + if (insn == 0x43b2) + return 0; + if (insn == opcode->bin_opcode) + return 2; + + if (opcode->fmt == 0) + { + if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2) + return 0; + + strcpy (comm, "emulated..."); + *cycles = 1; + } + else + { + strcpy (comm, "return from interupt"); + *cycles = 5; + } + + return 2; +} + + +int +msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles) + disassemble_info *info; + struct msp430_opcode_s *opcode; + bfd_vma addr; + unsigned short insn; + char *op; + char *comm; + int *cycles; +{ + int regs = 0, regd = 0; + int ad = 0, as = 0; + int where = 0; + int cmd_len = 2; + short dst = 0; + + regd = insn & 0x0f; + regs = (insn & 0x0f00) >> 8; + as = (insn & 0x0030) >> 4; + ad = (insn & 0x0080) >> 7; + + switch (opcode->fmt) + { + case 0: /* Emulated work with dst register. */ + if (regs != 2 && regs != 3 && regs != 1) + return 0; + + /* Check if not clr insn. */ + if (opcode->bin_opcode == 0x4300 && (ad || as)) + return 0; + + /* Check if really inc, incd insns. */ + if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3) + return 0; + + if (ad == 0) + { + *cycles = 1; + + /* Register. */ + if (regd == 0) + { + *cycles += 1; + sprintf (op, "r0"); + } + else if (regd == 1) + sprintf (op, "r1"); + + else if (regd == 2) + sprintf (op, "r2"); + + else + sprintf (op, "r%d", regd); + } + else /* ad == 1 msp430dis_opcode. */ + { + if (regd == 0) + { + /* PC relative. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + *cycles = 4; + sprintf (op, "0x%04x", dst); + sprintf (comm, "PC rel. abs addr 0x%04x", + PS ((short) (addr + 2) + dst)); + } + else if (regd == 2) + { + /* Absolute. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + *cycles = 4; + sprintf (op, "&0x%04x", PS (dst)); + } + else + { + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + *cycles = 4; + sprintf (op, "%d(r%d)", dst, regd); + } + } + break; + + case 2: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */ + + if (as == 0) + { + if (regd == 3) + { + /* Constsnts. */ + sprintf (op, "#0"); + sprintf (comm, "r3 As==00"); + } + else + { + /* Register. */ + sprintf (op, "r%d", regd); + } + *cycles = 1; + } + else if (as == 2) + { + *cycles = 1; + if (regd == 2) + { + sprintf (op, "#4"); + sprintf (comm, "r2 As==10"); + } + else if (regd == 3) + { + sprintf (op, "#2"); + sprintf (comm, "r3 As==10"); + } + else + { + *cycles = 3; + /* Indexed register mode @Rn. */ + sprintf (op, "@r%d", regd); + } + } + else if (as == 3) + { + *cycles = 1; + if (regd == 2) + { + sprintf (op, "#8"); + sprintf (comm, "r2 As==11"); + } + else if (regd == 3) + { + sprintf (op, "#-1"); + sprintf (comm, "r3 As==11"); + } + else if (regd == 0) + { + *cycles = 3; + /* absolute. @pc+ */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op, "#%d", dst); + sprintf (comm, "#0x%04x", PS (dst)); + } + else + { + *cycles = 3; + sprintf (op, "@r%d+", regd); + } + } + else if (as == 1) + { + *cycles = 4; + if (regd == 0) + { + /* PC relative. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op, "0x%04x", PS (dst)); + sprintf (comm, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + } + else if (regd == 2) + { + /* Absolute. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op, "&0x%04x", PS (dst)); + } + else if (regd == 3) + { + *cycles = 1; + sprintf (op, "#1"); + sprintf (comm, "r3 As==01"); + } + else + { + /* Indexd. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op, "%d(r%d)", dst, regd); + } + } + break; + + case 3: /* Jumps. */ + where = insn & 0x03ff; + if (where & 0x200) + where |= ~0x03ff; + if (where > 512 || where < -511) + return 0; + + where *= 2; + sprintf (op, "$%+-8d", where + 2); + sprintf (comm, "abs 0x%x", PS ((short) (addr) + 2 + where)); + *cycles = 2; + return 2; + break; + default: + cmd_len = 0; + } + + return cmd_len; +} + +int +msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) + disassemble_info *info; + struct msp430_opcode_s *opcode; + bfd_vma addr; + unsigned short insn; + char *op1, *op2; + char *comm1, *comm2; + int *cycles; +{ + int regs = 0, regd = 0; + int ad = 0, as = 0; + int cmd_len = 2; + short dst = 0; + + regd = insn & 0x0f; + regs = (insn & 0x0f00) >> 8; + as = (insn & 0x0030) >> 4; + ad = (insn & 0x0080) >> 7; + + if (opcode->fmt == 0) + { + /* Special case: rla and rlc are the only 2 emulated instructions that + fall into two operand instructions. */ + /* With dst, there are only: + Rm Register, + x(Rm) Indexed, + 0xXXXX Relative, + &0xXXXX Absolute + emulated_ins dst + basic_ins dst, dst. */ + + if (regd != regs || as != ad) + return 0; /* May be 'data' section. */ + + if (ad == 0) + { + /* Register mode. */ + if (regd == 3) + { + strcpy (comm1, "Illegal as emulation instr"); + return -1; + } + + sprintf (op1, "r%d", regd); + *cycles = 1; + } + else /* ad == 1 */ + { + if (regd == 0) + { + /* PC relative, Symbolic. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 4; + *cycles = 6; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + + } + else if (regd == 2) + { + /* Absolute. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 4; + *cycles = 6; + sprintf (op1, "&0x%04x", PS (dst)); + } + else + { + /* Indexed. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 4; + *cycles = 6; + sprintf (op1, "%d(r%d)", dst, regd); + } + } + + *op2 = 0; + *comm2 = 0; + return cmd_len; + } + + /* Two operands exactly. */ + if (ad == 0 && regd == 3) + { + /* R2/R3 are illegal as dest: may be data section. */ + strcpy (comm1, "Illegal as 2-op instr"); + return -1; + } + + /* Source. */ + if (as == 0) + { + *cycles = 1; + if (regs == 3) + { + /* Constsnts. */ + sprintf (op1, "#0"); + sprintf (comm1, "r3 As==00"); + } + else + { + /* Register. */ + sprintf (op1, "r%d", regs); + } + } + else if (as == 2) + { + *cycles = 1; + + if (regs == 2) + { + sprintf (op1, "#4"); + sprintf (comm1, "r2 As==10"); + } + else if (regs == 3) + { + sprintf (op1, "#2"); + sprintf (comm1, "r3 As==10"); + } + else + { + *cycles = 2; + + /* Indexed register mode @Rn. */ + sprintf (op1, "@r%d", regs); + } + if (!regs) + *cycles = 3; + } + else if (as == 3) + { + if (regs == 2) + { + sprintf (op1, "#8"); + sprintf (comm1, "r2 As==11"); + *cycles = 1; + } + else if (regs == 3) + { + sprintf (op1, "#-1"); + sprintf (comm1, "r3 As==11"); + *cycles = 1; + } + else if (regs == 0) + { + *cycles = 3; + /* Absolute. @pc+ */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "#%d", dst); + sprintf (comm1, "#0x%04x", PS (dst)); + } + else + { + *cycles = 2; + sprintf (op1, "@r%d+", regs); + } + } + else if (as == 1) + { + if (regs == 0) + { + *cycles = 4; + /* PC relative. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + } + else if (regs == 2) + { + *cycles = 2; + /* Absolute. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "&0x%04x", PS (dst)); + sprintf (comm1, "0x%04x", PS (dst)); + } + else if (regs == 3) + { + *cycles = 1; + sprintf (op1, "#1"); + sprintf (comm1, "r3 As==01"); + } + else + { + *cycles = 3; + /* Indexed. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "%d(r%d)", dst, regs); + } + } + + /* Destination. Special care needed on addr + XXXX. */ + + if (ad == 0) + { + /* Register. */ + if (regd == 0) + { + *cycles += 1; + sprintf (op2, "r0"); + } + else if (regd == 1) + sprintf (op2, "r1"); + + else if (regd == 2) + sprintf (op2, "r2"); + + else + sprintf (op2, "r%d", regd); + } + else /* ad == 1. */ + { + * cycles += 3; + + if (regd == 0) + { + /* PC relative. */ + *cycles += 1; + dst = msp430dis_opcode (addr + cmd_len, info); + sprintf (op2, "0x%04x", PS (dst)); + sprintf (comm2, "PC rel. 0x%04x", + PS ((short) addr + cmd_len + dst)); + cmd_len += 2; + } + else if (regd == 2) + { + /* Absolute. */ + dst = msp430dis_opcode (addr + cmd_len, info); + cmd_len += 2; + sprintf (op2, "&0x%04x", PS (dst)); + } + else + { + dst = msp430dis_opcode (addr + cmd_len, info); + cmd_len += 2; + sprintf (op2, "%d(r%d)", dst, regd); + } + } + + return cmd_len; +} + + +int +msp430_branchinstr (info, opcode, addr, insn, op1, comm1, cycles) + disassemble_info *info; + struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED; + bfd_vma addr ATTRIBUTE_UNUSED; + unsigned short insn; + char *op1; + char *comm1; + int *cycles; +{ + int regs = 0, regd = 0; + int ad = 0, as = 0; + int cmd_len = 2; + short dst = 0; + + regd = insn & 0x0f; + regs = (insn & 0x0f00) >> 8; + as = (insn & 0x0030) >> 4; + ad = (insn & 0x0080) >> 7; + + if (regd != 0) /* Destination register is not a PC. */ + return 0; + + /* dst is a source register. */ + if (as == 0) + { + /* Constants. */ + if (regs == 3) + { + *cycles = 1; + sprintf (op1, "#0"); + sprintf (comm1, "r3 As==00"); + } + else + { + /* Register. */ + *cycles = 1; + sprintf (op1, "r%d", regs); + } + } + else if (as == 2) + { + if (regs == 2) + { + *cycles = 2; + sprintf (op1, "#4"); + sprintf (comm1, "r2 As==10"); + } + else if (regs == 3) + { + *cycles = 1; + sprintf (op1, "#2"); + sprintf (comm1, "r3 As==10"); + } + else + { + /* Indexed register mode @Rn. */ + *cycles = 2; + sprintf (op1, "@r%d", regs); + } + } + else if (as == 3) + { + if (regs == 2) + { + *cycles = 1; + sprintf (op1, "#8"); + sprintf (comm1, "r2 As==11"); + } + else if (regs == 3) + { + *cycles = 1; + sprintf (op1, "#-1"); + sprintf (comm1, "r3 As==11"); + } + else if (regs == 0) + { + /* Absolute. @pc+ */ + *cycles = 3; + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "#0x%04x", PS (dst)); + } + else + { + *cycles = 2; + sprintf (op1, "@r%d+", regs); + } + } + else if (as == 1) + { + * cycles = 3; + + if (regs == 0) + { + /* PC relative. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + (*cycles)++; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + } + else if (regs == 2) + { + /* Absolute. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "&0x%04x", PS (dst)); + } + else if (regs == 3) + { + (*cycles)--; + sprintf (op1, "#1"); + sprintf (comm1, "r3 As==01"); + } + else + { + /* Indexd. */ + dst = msp430dis_opcode (addr + 2, info); + cmd_len += 2; + sprintf (op1, "%d(r%d)", dst, regs); + } + } + + return cmd_len; +} |