diff -Nru binutils-msp430-2.21~msp20110716/ChangeLog binutils-msp430-2.22~msp20110716p5/ChangeLog --- binutils-msp430-2.21~msp20110716/ChangeLog 1970-01-01 00:00:00.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/ChangeLog 2012-01-14 15:51:42.000000000 +0000 @@ -0,0 +1,326 @@ +commit d27b40618334cf4ae485d7be18f6826539ba11a2 +Author: Peter A. Bigot +Date: Tue Aug 30 08:48:49 2011 -0500 + + SF 3400750 infomemnobits missing from LTS 20110716 + + Improperly removed in MCU cleanup under 5877af82. + +commit 8d46e87b5fc8a2190b92bcc4e91ae0f9b121bc50 +Author: Peter A. Bigot +Date: Tue Aug 30 08:38:09 2011 -0500 + + SF 3400711 consts placed in RAM instead of ROM with -fdata-sections + + .rodata section not previously supported in msp430 binutils. + +commit 55832bf9e80b04a1e59eacff69a5205c8b558384 +Author: Peter A. Bigot +Date: Thu Aug 4 06:24:47 2011 -0500 + + SF 3143071 error in addend of relocation entry in output + + Update the addend of section-based relocations when doing relocatable links. + +commit f90d28c55f24735372d6c2d47043ff4384103551 +Author: Peter A. Bigot +Date: Thu Aug 4 06:24:01 2011 -0500 + + SF 3386145 gc-sections broken in LTS 20110716 + +commit 74b7db4b4eb69e42b930b0283747bf9b4b864aaf +Author: Peter A. Bigot +Date: Wed Jul 27 11:06:56 2011 -0500 + + SF 3379341: non-empty ARCH environment variable results unusable ld + +commit bf4dc9a7b52373f48bccecbb7b0f77bd5ed08ff0 +Author: Alan Modra +Date: Thu Feb 10 23:44:12 2011 +0000 + + Revert 2010-11-02 H.J. Lu. + + Hand-apply relevant part of upstream commit 3a3848ee225722 + +commit 4863b8069b412d89b84d277bdba3daea9c55b58c +Author: Peter A. Bigot +Date: Sun Jun 12 11:09:24 2011 -0500 + + SF 3315471 remove _init_section__ function + + There is no such thing as a noinit region in the ROM. + +commit f3f850212509bd6a19bed10e1d5783cc5f95777a +Author: Peter A. Bigot +Date: Sat May 7 11:43:29 2011 -0500 + + SF 3293911 gas 2.21 segfault when building gcc 4.4.5 + +commit 83014a1a607b8934e0177498da30bc062128bc7c +Author: Peter A. Bigot +Date: Thu Apr 21 10:02:40 2011 -0500 + + Avoid complaints in relocatable links + + Such links don't work anyway (see SF 3143071), but the complaint is + gratuitous. + +commit 7403104de33312296cfec03b0886f2c11d24b711 +Author: Peter A. Bigot +Date: Mon Apr 18 16:42:26 2011 -0500 + + SF 3289064 uniarch binutils missing far section support + + Add legacy .fartext section into REGION_FAR_ROM. + +commit 06250ac7c2a4eea45ec832e58cc1b46959fc8939 +Author: Peter A. Bigot +Date: Wed Apr 13 19:06:23 2011 -0500 + + SF 3286248 broken #hlo calculation for small constants + + If sizeof(long)==4, shifting a long value right by 32-bits is a no-op. + Constants that don't need to be stored in O_big ops still need correct + results for #hlo. + +commit fe611a8aba8d01fa5ee1a3e6cc1cb6a2a287179d +Author: Peter A. Bigot +Date: Sun Apr 10 21:39:34 2011 -0500 + + SF 3237855: clean up -mmcu documentation + + The as --target-help is automatically printed when gcc --target-help is + invoked; highlight that what's described is relevant only to as. + +commit 405e961a1ecc309571ec72f2d9c7fa99c03a6041 +Author: Peter A. Bigot +Date: Sat Apr 2 09:11:34 2011 -0500 + + SF 3266079: binutils link does not preserve cpu architecture + + Customize emulator script to walk input components and set the elf flags + based on what went into the output. + +commit 9c37f0321e82f70c987c3d46b0c11d56e50dbeda +Author: Peter A. Bigot +Date: Sat Apr 2 09:09:52 2011 -0500 + + Clone genelf.em prior to msp430-specific mods + +commit 4c47737d70c76e4402def2e6e4d1719b3532098a +Author: Peter A. Bigot +Date: Tue Mar 22 09:55:52 2011 -0500 + + Store architecture, not CPU, in elf flags field + + Not clear how to express cpu/mpy/near/far, especially since e_flags applies + to the whole file, not individual symbols. + +commit b1ccb84aaa1688e8ba41c6aa2405833894c9bc2b +Author: Peter A. Bigot +Date: Mon Mar 14 12:55:23 2011 -0500 + + Clean up section management. + + Put fini sections immediately after init sections, so things fall through + properly. Remove redundant non-KEEP patterns. Remove KEEP where it might + make sense to do section garbage collection. Ensure ctors section and + __data_start are aligned. + +commit aac204826d7126df896c383e27c2f0372c724c21 +Author: Peter A. Bigot +Date: Sat Mar 12 11:19:17 2011 -0600 + + SF 3207853: bad constant extraction on 64-bit systems + + This is part of the problem: on 64-bit systems, O_constant can represent + 64-bit values in its offsetT field even when int is 32 bits. Don't assume + it's a 32-bit value. + + make check-gas RUNTESTFLAGS=msp430.exp + +commit 3ae4c6c099057f4e78a8a03bddc5a5def7bbd876 +Author: Peter A. Bigot +Date: Sat Mar 12 09:55:14 2011 -0600 + + SF 3207853: validate llo/lhi/hlo/hhi + +commit 7970684869ea7af3b4854757d0078aa8634b9487 +Author: Peter A. Bigot +Date: Sat Mar 12 09:28:50 2011 -0600 + + Update to match current output (whitespace variations only) + +commit 989579c43fdd68bf707cef075b0b6ca7b52b76d4 +Author: Peter A. Bigot +Date: Wed Mar 2 18:24:57 2011 -0600 + + SF 3197755: long long type not working + + This occurs because an assembly language shift operation corrupts a token + string while processing it, resulting in the wrong opcode values being + written. Make a local copy of token before mutating it. + +commit b0fcba5243b9127c6b3fa4209429b4bdb485879e +Author: Peter A. Bigot +Date: Sun Feb 20 14:44:58 2011 -0600 + + Eliminate warning that breaks gcc test infrastructure + +commit 5a5c7b9cfa1ca229f661e5080f1af7584753c900 +Author: Peter A. Bigot +Date: Thu Feb 10 17:01:58 2011 -0600 + + SF 3177314: undefined reference with too many template parameters + + This patch eliminates bounds on the length of symbols and instruction + operands, and some rather inefficient string processing operations. Storage + of the appropriate length for a specific symbol is dynamically allocated, + and freed when no longer necessary. + +commit 7e953d0a89911a7df6c210f27fa09dd94a77aecf +Author: Peter A. Bigot +Date: Mon Feb 7 10:49:43 2011 -0600 + + Parse cpu/mpy directives in assembly code + +commit 3fd56bb7addcead0e84e84fe890b93d60bc4fa5f +Author: Peter A. Bigot +Date: Mon Feb 7 09:03:21 2011 -0600 + + Remove hard-coded MCU-specific information from msp430 port. + + * bfd/cpu-msp430.c: Reduce to one architecture with two machines (430x not + currently used). + + * bfd/elf32-msp430.c: Remove all but the two new machines. + + * gas/config/tc-msp430.c: List all known errata in preparation for eventual + proper support of these. Remove MCU definitions in favor of separated + cpu, mpy, errata values. + + * include/elf/msp430.h: Bit masks for MSP430-related features. + + * include/opcode.msp430.h: CPU and MPY variant enumerations. + + * ld/{configure.tgt,Makefile.{am,in}}: Remove specific emulations. + + * ld/emulparams/msp430all.sh: Delete + + * ld/emulparams/msp430uni.sh: New + + * ld/scripttempl/elf32msp430.sc: Read memory and peripheral values from + external files for non-relocatables. Remove bootloader section. Remove + infomemnobits section. Use generic stack offset. + + * ld/scripttempl/elf32msp430_3.sc: Delete + + * opcodes/msp430-dis.c: Use new flags to identify CPU type. + +commit d326a72083d7ab86a09d5ff81ded9996095b189a +Author: Peter A. Bigot +Date: Sat Feb 5 21:37:53 2011 -0600 + + Correct vector start for ISA_24 chips + +commit 8bedb57e2552feda187cd2b587997c9b05c2a88c +Author: Peter A. Bigot +Date: Sat Feb 5 13:36:03 2011 -0600 + + Regenerate + +commit 5938e0d1f48a0b1322e977f6266e60f71da63392 +Author: Peter A. Bigot +Date: Sat Feb 5 13:35:39 2011 -0600 + + Add MCUs supported by msp430all.sh + +commit fae9f6fe91485874bf9286240a96ee5974b1227f +Author: Peter A. Bigot +Date: Sat Feb 5 13:31:09 2011 -0600 + + Regenerate + +commit 47fd0f00b9630264515e942c34f1dfb59f9075ea +Author: Peter A. Bigot +Date: Sat Feb 5 13:29:08 2011 -0600 + + Update to match MCUs in msp430all.sh + +commit 16e97e674ad621d7d09c6a9a80ac636de3b731bf +Author: Peter A. Bigot +Date: Wed Jan 26 11:53:58 2011 -0600 + + SF 3154622: Correct support for MSP430F2132 + +commit b11dceafe75dcced6630979b4607189a7360e6c3 +Author: Peter A. Bigot +Date: Wed Jan 26 11:12:49 2011 -0600 + + SF 3146404: Support for msp430f550x chips + +commit 3e6a58cc177bdc97a02499064489a3272ab13623 +Author: Radu Rendec +Date: Fri Jan 21 16:01:15 2011 +0200 + + Add support for msp430f471x3 + +commit 638070a1eb05342cf4e020820ffab27f2bf14271 +Author: Peter A. Bigot +Date: Mon Jan 3 15:30:29 2011 -0600 + + Regenerate + +commit e845ac171fb33c4a3c7c5adee4f016fb94fa14c4 +Author: Peter A. Bigot +Date: Sun Nov 14 10:07:12 2010 -0600 + + SF 3109143: Support value-line MSP430G22x1 devices + + Note that the value-line devices are not compatible with the mainline + devices with the same generation/series/family numbers: for example, the + MSP430F2001 has more memory than the MSP430G2001. Fortunately, the + MSP430G22x1 devices do not have companion MSP430F22x1 device series, so they + can be added without conflict (for now). + +commit 3909fd669f2c5db237a8855de4d6423c0e6c8a3e +Author: Peter A. Bigot +Date: Sat Nov 6 14:31:43 2010 -0500 + + SF 3096352: Illegal disassembly instruction (addx.a R14,R15) + + The disassembly of MSP430X double operands did not verify that a + non-register mode extension word applied before using operand equivalence as + a recognition cue for an emulated instruction. It now rejects the emulation + when distinct register operands are used. + +commit e291e093ac872b44e7f9782ef581ff0e36dec473 +Author: Peter A. Bigot +Date: Sun Aug 29 13:11:44 2010 -0500 + + SF 3055519: add support for 55xx chips + + msp430x5510 msp430x5513 msp430x5514 msp430x5515 msp430x5517 msp430x5519 + msp430x5521 msp430x5522 msp430x5524 msp430x5525 msp430x5526 msp430x5527 + msp430x5528 msp430x5529 msp430x6638 + +commit a0f3a608ceaf58d7ad062cf2ff9c1b16b8ca2fcb +Author: Peter A. Bigot +Date: Thu May 27 12:22:04 2010 -0500 + + Replace undefined cc430x5123 with missing cc430x5133 + +commit aeec5cce244f9a3b4e7aa1bf3e47c50dab084fa3 +Author: Peter A. Bigot +Date: Thu May 27 11:32:07 2010 -0500 + + Fix info/bsl locations on newer chips + +commit 70aa46c2977f4257091042666f78c4dc58a0d2cc +Author: Peter A. Bigot +Date: Sun Jan 2 10:53:49 2011 -0600 + + Apply binutils-2.20.patch from revision aac9a66b of mspgcc4 repository. + + This commit excludes the genates to /bfd/doc/archures.texi which does not + exist in development revisions. diff -Nru binutils-msp430-2.21~msp20110716/debian/changelog binutils-msp430-2.22~msp20110716p5/debian/changelog --- binutils-msp430-2.21~msp20110716/debian/changelog 2012-01-20 11:36:30.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/debian/changelog 2012-01-20 11:36:30.000000000 +0000 @@ -1,3 +1,14 @@ +binutils-msp430 (2.22~msp20110716p5-1) unstable; urgency=low + + * Upstream patch-point + + SF 3379341: non-empty ARCH environment variable results unusable ld + + SF 3386145: gc-sections broken in LTS 20110716 + + SF 3143071: error in addend of relocation entry in output + + SF 3400711: consts placed in RAM instead of ROM with -fdata-sections + + SF 3400750: infomemnobits missing from LTS 20110716 + + -- Luca Bruno Sat, 14 Jan 2012 16:54:13 +0100 + binutils-msp430 (2.21~msp20110716-1) unstable; urgency=low * New upstream release diff -Nru binutils-msp430-2.21~msp20110716/debian/control binutils-msp430-2.22~msp20110716p5/debian/control --- binutils-msp430-2.21~msp20110716/debian/control 2012-01-20 11:36:30.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/debian/control 2012-01-20 11:36:30.000000000 +0000 @@ -6,9 +6,9 @@ Build-Depends: autoconf (>= 2.13), bison, flex, gettext, texinfo, binutils (>= 2.9.5.0.12), gcc (>= 2.95.2), debhelper (>= 7), tar (>= 1.13.18), bzip2, - findutils(>=4.2.31), binutils-source (>= 2.21.53~), + findutils(>= 4.2.31), binutils-source (>= 2.22), msp430mcu -Built-Using: binutils (= 2.21.53.20110805-1) +Built-Using: binutils (= 2.22-4) Package: binutils-msp430 Architecture: any diff -Nru binutils-msp430-2.21~msp20110716/debian/patchlist binutils-msp430-2.22~msp20110716p5/debian/patchlist --- binutils-msp430-2.21~msp20110716/debian/patchlist 2012-01-20 11:36:30.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/debian/patchlist 2012-01-20 11:36:30.000000000 +0000 @@ -1 +1 @@ -../lts-20110716.patch +../lts-20110716p5.patch diff -Nru binutils-msp430-2.21~msp20110716/debian/rules binutils-msp430-2.22~msp20110716p5/debian/rules --- binutils-msp430-2.21~msp20110716/debian/rules 2012-01-20 11:36:30.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/debian/rules 2012-01-20 11:36:30.000000000 +0000 @@ -78,7 +78,7 @@ dh_testroot dh_installdocs -n dh_installman - dh_installchangelogs + dh_installchangelogs ChangeLog dh_lintian dh_link dh_strip diff -Nru binutils-msp430-2.21~msp20110716/lts-20110716p5.patch binutils-msp430-2.22~msp20110716p5/lts-20110716p5.patch --- binutils-msp430-2.21~msp20110716/lts-20110716p5.patch 1970-01-01 00:00:00.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/lts-20110716p5.patch 2012-01-14 16:26:39.000000000 +0000 @@ -0,0 +1,7332 @@ +diff --git a/bfd/archures.c b/bfd/archures.c +index 44850e7..91f557f 100644 +--- a/bfd/archures.c ++++ b/bfd/archures.c +@@ -413,21 +413,8 @@ DESCRIPTION + . bfd_arch_xstormy16, + .#define bfd_mach_xstormy16 1 + . bfd_arch_msp430, {* Texas Instruments MSP430 architecture. *} +-.#define bfd_mach_msp11 11 +-.#define bfd_mach_msp110 110 +-.#define bfd_mach_msp12 12 +-.#define bfd_mach_msp13 13 +-.#define bfd_mach_msp14 14 +-.#define bfd_mach_msp15 15 +-.#define bfd_mach_msp16 16 +-.#define bfd_mach_msp21 21 +-.#define bfd_mach_msp31 31 +-.#define bfd_mach_msp32 32 +-.#define bfd_mach_msp33 33 +-.#define bfd_mach_msp41 41 +-.#define bfd_mach_msp42 42 +-.#define bfd_mach_msp43 43 +-.#define bfd_mach_msp44 44 ++.#define bfd_mach_msp430 430 ++.#define bfd_mach_msp430x 431 + . bfd_arch_xc16x, {* Infineon's XC16X Series. *} + .#define bfd_mach_xc16x 1 + .#define bfd_mach_xc16xl 2 +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 22fcdf6..3bd5738 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -2120,21 +2120,8 @@ enum bfd_architecture + bfd_arch_xstormy16, + #define bfd_mach_xstormy16 1 + bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ +-#define bfd_mach_msp11 11 +-#define bfd_mach_msp110 110 +-#define bfd_mach_msp12 12 +-#define bfd_mach_msp13 13 +-#define bfd_mach_msp14 14 +-#define bfd_mach_msp15 15 +-#define bfd_mach_msp16 16 +-#define bfd_mach_msp21 21 +-#define bfd_mach_msp31 31 +-#define bfd_mach_msp32 32 +-#define bfd_mach_msp33 33 +-#define bfd_mach_msp41 41 +-#define bfd_mach_msp42 42 +-#define bfd_mach_msp43 43 +-#define bfd_mach_msp44 44 ++#define bfd_mach_msp430 430 ++#define bfd_mach_msp430x 431 + bfd_arch_xc16x, /* Infineon's XC16X Series. */ + #define bfd_mach_xc16x 1 + #define bfd_mach_xc16xl 2 +@@ -4649,6 +4636,25 @@ This is the 5 bits of a value. */ + BFD_RELOC_MSP430_16_BYTE, + BFD_RELOC_MSP430_2X_PCREL, + BFD_RELOC_MSP430_RL_PCREL, ++ BFD_RELOC_MSP430X_SRC_BYTE, ++ BFD_RELOC_MSP430X_SRC, ++ BFD_RELOC_MSP430X_DST_BYTE, ++ BFD_RELOC_MSP430X_DST, ++ BFD_RELOC_MSP430X_DST_2ND_BYTE, ++ BFD_RELOC_MSP430X_DST_2ND, ++ BFD_RELOC_MSP430X_PCREL_SRC_BYTE, ++ BFD_RELOC_MSP430X_PCREL_SRC, ++ BFD_RELOC_MSP430X_PCREL_DST_BYTE, ++ BFD_RELOC_MSP430X_PCREL_DST, ++ BFD_RELOC_MSP430X_PCREL_DST_2ND, ++ BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE, ++ BFD_RELOC_MSP430X_S_BYTE, ++ BFD_RELOC_MSP430X_S, ++ BFD_RELOC_MSP430X_D_BYTE, ++ BFD_RELOC_MSP430X_D, ++ BFD_RELOC_MSP430X_PCREL_D, ++ BFD_RELOC_MSP430X_INDXD, ++ BFD_RELOC_MSP430X_PCREL_INDXD, + + /* IQ2000 Relocations. */ + BFD_RELOC_IQ2000_OFFSET_16, +diff --git a/bfd/cpu-msp430.c b/bfd/cpu-msp430.c +index 63c301a..9e9fcdd 100644 +--- a/bfd/cpu-msp430.c ++++ b/bfd/cpu-msp430.c +@@ -23,86 +23,14 @@ + #include "bfd.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]), +- +- /* msp430x11x1. */ +- N (16, bfd_mach_msp110, "msp:110", FALSE, & arch_info_struct[2]), +- +- /* msp430x12x. */ +- N (16, bfd_mach_msp12, "msp:12", FALSE, & arch_info_struct[3]), +- +- /* msp430x13x. */ +- N (16, bfd_mach_msp13, "msp:13", FALSE, & arch_info_struct[4]), +- +- /* msp430x14x. */ +- N (16, bfd_mach_msp14, "msp:14", FALSE, & arch_info_struct[5]), +- +- /* msp430x15x. */ +- N (16, bfd_mach_msp15, "msp:15", FALSE, & arch_info_struct[6]), +- +- /* msp430x16x. */ +- N (16, bfd_mach_msp16, "msp:16", FALSE, & arch_info_struct[7]), +- +- /* msp430x21x. */ +- N (16, bfd_mach_msp21, "msp:21", FALSE, & arch_info_struct[8]), +- +- /* msp430x31x. */ +- N (16, bfd_mach_msp31, "msp:31", FALSE, & arch_info_struct[9]), +- +- /* msp430x32x. */ +- N (16, bfd_mach_msp32, "msp:32", FALSE, & arch_info_struct[10]), +- +- /* msp430x33x. */ +- N (16, bfd_mach_msp33, "msp:33", FALSE, & arch_info_struct[11]), +- +- /* msp430x41x. */ +- N (16, bfd_mach_msp41, "msp:41", FALSE, & arch_info_struct[12]), +- +- /* msp430x42x. */ +- N (16, bfd_mach_msp42, "msp:42", FALSE, & arch_info_struct[13]), +- +- /* msp430x43x. */ +- N (16, bfd_mach_msp43, "msp:43", FALSE, & arch_info_struct[14]), +- +- /* msp430x44x. */ +- N (16, bfd_mach_msp43, "msp:44", 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. */ +- ++ 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; ++compatible (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 & b are for different architectures we can do nothing */ + if (a->arch != b->arch) + return NULL; + +@@ -111,3 +39,35 @@ compatible (a,b) + + return a; + } ++ ++/* Architecture for MSP430X and MSP430XV2 */ ++static const bfd_arch_info_type bfd_msp430x_arch = { ++ 16, /* 16 bits in a word */ ++ 20, /* 20 bits in an address */ ++ 8, /* 8 bits in a byte */ ++ bfd_arch_msp430, ++ bfd_mach_msp430x, /* Machine number */ ++ "msp430", /* Architecture name. */ ++ "msp430:430X", /* Printable name */ ++ 1, /* Section align power */ ++ FALSE, /* The default machine */ ++ compatible, ++ bfd_default_scan, ++ 0 ++}; ++ ++/* Architecture for MSP430 */ ++const bfd_arch_info_type bfd_msp430_arch = { ++ 16, /* 16 bits in a word */ ++ 16, /* 16 bits in an address */ ++ 8, /* 8 bits in a byte */ ++ bfd_arch_msp430, ++ bfd_mach_msp430, /* Machine number */ ++ "msp430", /* Architecture name */ ++ "msp430:430", /* Printable name */ ++ 1, /* Section align power */ ++ TRUE, /* The default machine */ ++ compatible, ++ bfd_default_scan, ++ &bfd_msp430x_arch ++}; +diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c +index 9a5fb2a..8a217fa 100644 +--- a/bfd/elf32-msp430.c ++++ b/bfd/elf32-msp430.c +@@ -90,7 +90,7 @@ static reloc_howto_type elf_msp430_howto_table[] = + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + +- /* A 16 bit absolute relocation for command address. */ ++ /* A 16 bit PC relative relocation for command address. */ + HOWTO (R_MSP430_16_PCREL, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ +@@ -120,7 +120,7 @@ static reloc_howto_type elf_msp430_howto_table[] = + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + +- /* A 16 bit absolute relocation for command address. */ ++ /* A 16 bit PC relative relocation, byte operations. */ + HOWTO (R_MSP430_16_PCREL_BYTE,/* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ +@@ -163,7 +163,292 @@ static reloc_howto_type elf_msp430_howto_table[] = + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ +- TRUE) /* pcrel_offset */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute src operand relocation, byte operations */ ++ HOWTO (R_MSP430X_SRC_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_SRC_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute src operand relocation */ ++ HOWTO (R_MSP430X_SRC, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_SRC", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute dst operand relocation, src is register mode, byte operations */ ++ HOWTO (R_MSP430X_DST_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_DST_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute dst operand relocation, src is register mode */ ++ HOWTO (R_MSP430X_DST, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_DST", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute dst operand relocation, byte operations */ ++ HOWTO (R_MSP430X_DST_2ND_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_DST_2ND_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x absolute dst operand relocation */ ++ HOWTO (R_MSP430X_DST_2ND, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_DST_2ND", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative src operand relocation, byte operations */ ++ HOWTO (R_MSP430X_PCREL_SRC_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_SRC_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative src operand relocation */ ++ HOWTO (R_MSP430X_PCREL_SRC, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_SRC", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative dst operand relocation, src is register mode, byte operations */ ++ HOWTO (R_MSP430X_PCREL_DST_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_DST_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative dst operand relocation, src is register mode */ ++ HOWTO (R_MSP430X_PCREL_DST, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_DST", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative dst operand relocation, byte operations */ ++ HOWTO (R_MSP430X_PCREL_DST_2ND_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_DST_2ND_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x PC relative dst operand relocation */ ++ HOWTO (R_MSP430X_PCREL_DST_2ND, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_DST_2ND", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x address instructions immediate src operand relocation */ ++ HOWTO (R_MSP430X_S_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_S_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x address instructions absolute src operand relocation */ ++ HOWTO (R_MSP430X_S, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_S", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xfffff, /* src_mask */ ++ 0, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x address instructions immediate dst operand relocation */ ++ HOWTO (R_MSP430X_D_BYTE, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_D_BYTE", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x address instructions absolute dst operand relocation */ ++ HOWTO (R_MSP430X_D, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_D", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ ++ ++ /* A 20 bit msp430x address instructions absolute dst operand relocation */ ++ HOWTO (R_MSP430X_PCREL_D, /* type */ ++ 0, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 20, /* bitsize */ ++ TRUE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont,/* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_MSP430X_PCREL_D", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xfffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 16 bit msp430x relocation *** for msp430x calla 16-bit PC-relative index ***/ ++ HOWTO (R_MSP430X_PCREL_INDXD, /* type */ ++ 0, /* 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_MSP430X_PCREL_INDXD", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xffff, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ TRUE), /* pcrel_offset */ ++ ++ /* A 16 bit msp430x relocation *** for msp430x bra/calla 16-bit index ***/ ++ HOWTO (R_MSP430X_INDXD, /* 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_MSP430X_INDXD", /* name */ ++ FALSE, /* partial_inplace */ ++ 0xffff, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* Map BFD reloc types to MSP430 ELF reloc types. */ +@@ -185,7 +470,29 @@ static const struct msp430_reloc_map msp430_reloc_map[] = + {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE}, + {BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE}, + {BFD_RELOC_MSP430_2X_PCREL, R_MSP430_2X_PCREL}, +- {BFD_RELOC_MSP430_RL_PCREL, R_MSP430_RL_PCREL} ++ {BFD_RELOC_MSP430_RL_PCREL, R_MSP430_RL_PCREL}, ++ ++ {BFD_RELOC_MSP430X_SRC_BYTE, R_MSP430X_SRC_BYTE}, ++ {BFD_RELOC_MSP430X_SRC, R_MSP430X_SRC}, ++ {BFD_RELOC_MSP430X_DST_BYTE, R_MSP430X_DST_BYTE}, ++ {BFD_RELOC_MSP430X_DST, R_MSP430X_DST}, ++ {BFD_RELOC_MSP430X_DST_2ND_BYTE, R_MSP430X_DST_2ND_BYTE}, ++ {BFD_RELOC_MSP430X_DST_2ND, R_MSP430X_DST_2ND}, ++ ++ {BFD_RELOC_MSP430X_PCREL_SRC_BYTE, R_MSP430X_PCREL_SRC_BYTE}, ++ {BFD_RELOC_MSP430X_PCREL_SRC, R_MSP430X_PCREL_SRC}, ++ {BFD_RELOC_MSP430X_PCREL_DST_BYTE, R_MSP430X_PCREL_DST_BYTE}, ++ {BFD_RELOC_MSP430X_PCREL_DST, R_MSP430X_PCREL_DST}, ++ {BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE, R_MSP430X_PCREL_DST_2ND_BYTE}, ++ {BFD_RELOC_MSP430X_PCREL_DST_2ND, R_MSP430X_PCREL_DST_2ND}, ++ ++ {BFD_RELOC_MSP430X_S_BYTE, R_MSP430X_S_BYTE}, ++ {BFD_RELOC_MSP430X_S, R_MSP430X_S}, ++ {BFD_RELOC_MSP430X_D_BYTE, R_MSP430X_D_BYTE}, ++ {BFD_RELOC_MSP430X_D, R_MSP430X_D}, ++ {BFD_RELOC_MSP430X_PCREL_D, R_MSP430X_PCREL_D}, ++ {BFD_RELOC_MSP430X_INDXD, R_MSP430X_INDXD}, ++ {BFD_RELOC_MSP430X_PCREL_INDXD, R_MSP430X_PCREL_INDXD}, + }; + + static reloc_howto_type * +@@ -207,10 +514,7 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + { + unsigned int i; + +- for (i = 0; +- i < (sizeof (elf_msp430_howto_table) +- / sizeof (elf_msp430_howto_table[0])); +- i++) ++ for (i = 0; i < ARRAY_SIZE (elf_msp430_howto_table); i++) + if (elf_msp430_howto_table[i].name != NULL + && strcasecmp (elf_msp430_howto_table[i].name, r_name) == 0) + return &elf_msp430_howto_table[i]; +@@ -282,18 +586,44 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, + { + bfd_reloc_status_type r = bfd_reloc_ok; + bfd_vma x; +- bfd_signed_vma srel; ++ bfd_signed_vma srel = 0; + +- switch (howto->type) ++ if (howto->type > R_MSP430_32 && howto->type < R_MSP430_max) + { +- case R_MSP430_10_PCREL: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation; + srel += rel->r_addend; +- srel -= rel->r_offset; ++ ++ if(howto->pc_relative) ++ { ++ srel -= rel->r_offset; ++ srel -= (input_section->output_section->vma + ++ input_section->output_offset); ++ } ++ ++ switch (howto->type) ++ { ++ case R_MSP430X_PCREL_D: // PC relative dst operand of calla ++ case R_MSP430X_PCREL_INDXD: // 16-bit idx in mova/bra instruction PC relative (symbolic) mode operand ++ srel -= 2; // operand located 2 bytes after opcode ++ break; ++ case R_MSP430X_PCREL_SRC: // PC-relative 20-bit address operand ++ case R_MSP430X_PCREL_SRC_BYTE: ++ case R_MSP430X_PCREL_DST: ++ case R_MSP430X_PCREL_DST_BYTE: ++ srel -= 4; // operand located 4 bytes after opcode ++ break; ++ case R_MSP430X_PCREL_DST_2ND: ++ case R_MSP430X_PCREL_DST_2ND_BYTE: ++ srel -= 6; // operand located 6 bytes after opcode ++ break; ++ } ++ } ++ ++ switch (howto->type) ++ { ++ case R_MSP430_10_PCREL: + 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; +@@ -311,13 +641,7 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, + break; + + case R_MSP430_2X_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; +@@ -341,13 +665,7 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, + + case R_MSP430_16_PCREL: + case R_MSP430_RL_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; +@@ -356,35 +674,138 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, + 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; + ++ case R_MSP430X_SRC: // address operand ++ case R_MSP430X_PCREL_SRC: // PC-relative address operand ++ ++ // 20 bit reloc for msp430x ++ // src in Non-register mode extended instructions, ++ // imm/abs in bra instruction ++ ++ // src(19:16) located at positions 10:7 of extension word ++ // src(15:0) located just after opcode ++ ++ if (srel & 1) // odd address ++ return bfd_reloc_notsupported; ++ /* and fall trough, no break here!!! */ ++ case R_MSP430X_SRC_BYTE: // byte instructions or immediate operand ++ case R_MSP430X_PCREL_SRC_BYTE: ++ x = bfd_get_16 (input_bfd, contents); ++ /* 4 most-significant bits */ ++ x = (x & 0xf87f) | ((srel >> 9) & 0x0780); ++ bfd_put_16 (input_bfd, x, contents); ++ /* 16 least-significant bits */ ++ bfd_put_16 (input_bfd, srel & 0xffff, contents + 4); ++ break; ++ ++ case R_MSP430X_DST: // address operand ++ case R_MSP430X_PCREL_DST: ++ ++ // 20 bit reloc for msp430x ++ // dst in Non-register mode extended instructions, ++ // imm/abs/20-bit idx in calla instruction ++ ++ // dst(19:16) located at positions 3:0 of extension word ++ // dst(15:0) located just after opcode ++ ++ if (srel & 1) // odd address ++ return bfd_reloc_notsupported; ++ /* and fall trough, no break here!!! */ ++ case R_MSP430X_DST_BYTE: // byte instructions or immediate operand ++ case R_MSP430X_PCREL_DST_BYTE: ++ x = bfd_get_16 (input_bfd, contents); ++ /* 4 most-significant bits */ ++ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); ++ bfd_put_16 (input_bfd, x, contents); ++ /* 16 least-significant bits */ ++ bfd_put_16 (input_bfd, srel & 0xffff, contents + 4); ++ break; ++ ++ case R_MSP430X_DST_2ND: // address operand ++ case R_MSP430X_PCREL_DST_2ND: ++ ++ // 20 bit reloc for msp430x ++ // dst in Non-register mode extended instructions, ++ ++ // dst(19:16) located at positions 3:0 of extension word ++ // dst(15:0) located after src(15:0) ++ ++ if (srel & 1) // odd address ++ return bfd_reloc_notsupported; ++ /* and fall trough, no break here!!! */ ++ case R_MSP430X_DST_2ND_BYTE: // byte instructions or immediate operand ++ case R_MSP430X_PCREL_DST_2ND_BYTE: ++ x = bfd_get_16 (input_bfd, contents); ++ /* 4 most-significant bits */ ++ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); ++ bfd_put_16 (input_bfd, x, contents); ++ /* 16 least-significant bits */ ++ bfd_put_16 (input_bfd, srel & 0xffff, contents + 6); ++ break; ++ ++ case R_MSP430X_S: // absolute src operand of address instructions ++ // 20 bit reloc for msp430x ++ ++ // src(19:16) located at positions 11:8 of opcode ++ // src(15:0) located just after opcode ++ ++ if (srel & 1) //odd address ++ return bfd_reloc_notsupported; ++ /* and fall trough, no break here!!! */ ++ case R_MSP430X_S_BYTE: // immediate src operand of address instructions ++ x = bfd_get_16 (input_bfd, contents); ++ /* 4 most-significant bits */ ++ x = (x & 0xf0ff) | ((srel >> 8) & 0x0f00); ++ bfd_put_16 (input_bfd, x, contents); ++ /* 16 least-significant bits */ ++ bfd_put_16 (input_bfd, srel & 0xffff, contents + 2); ++ break; ++ ++ case R_MSP430X_D: // absolute dst operand of address instructions ++ case R_MSP430X_PCREL_D: // PC relative dst operand of calla ++ // 20 bit reloc for msp430x, ++ ++ // dst(19:16) located at positions 3:0 of opcode ++ // dst(15:0) located just after opcode ++ ++ if (srel & 1) //odd address ++ return bfd_reloc_notsupported; ++ /* and fall trough, no break here!!! */ ++ case R_MSP430X_D_BYTE: //immediate dst operand of address instructions ++ ++ x = bfd_get_16 (input_bfd, contents); ++ /* 4 most-significant bits */ ++ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); ++ bfd_put_16 (input_bfd, x, contents); ++ /* 16 least-significant bits */ ++ bfd_put_16 (input_bfd, srel & 0xffff, contents + 2); ++ break; ++ ++ case R_MSP430X_PCREL_INDXD: // 16-bit idx in mova/bra instruction PC relative (symbolic) mode operand ++ ++ if (srel & 1) //odd address ++ return bfd_reloc_notsupported; ++ case R_MSP430X_INDXD: // 16-bit idx in calla/mova/bra instruction ++ ++ x = srel & 0xffff; ++ bfd_put_16 (input_bfd, x, contents + 2); //16 least-significant bits ++ break; ++ + default: + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, +@@ -459,7 +880,12 @@ elf32_msp430_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, + rel, relend, howto, contents); + + if (info->relocatable) +- continue; ++ { ++ BFD_ASSERT (! howto->partial_inplace); ++ if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) ++ rel->r_addend += sec->output_offset; ++ continue; ++ } + + r = msp430_final_link_relocate (howto, input_bfd, input_section, + contents, rel, relocation); +@@ -517,150 +943,54 @@ elf32_msp430_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, + number. */ + + static void +-bfd_elf_msp430_final_write_processing (bfd * abfd, +- bfd_boolean linker ATTRIBUTE_UNUSED) ++msp430_elf_backend_final_write_processing (bfd * abfd, ++ bfd_boolean linker ATTRIBUTE_UNUSED) + { +- unsigned long val; ++ Elf_Internal_Ehdr * i_ehdrp; ++ unsigned long flags; + ++ i_ehdrp = elf_elfheader (abfd); ++ i_ehdrp->e_machine = EM_MSP430; ++ flags = 0; + switch (bfd_get_mach (abfd)) + { + default: +- case bfd_mach_msp110: +- val = E_MSP430_MACH_MSP430x11x1; +- break; +- +- case bfd_mach_msp11: +- val = E_MSP430_MACH_MSP430x11; +- break; +- +- case bfd_mach_msp12: +- val = E_MSP430_MACH_MSP430x12; +- break; +- +- case bfd_mach_msp13: +- val = E_MSP430_MACH_MSP430x13; +- break; +- +- case bfd_mach_msp14: +- val = E_MSP430_MACH_MSP430x14; +- break; +- +- case bfd_mach_msp15: +- val = E_MSP430_MACH_MSP430x15; +- break; +- +- case bfd_mach_msp16: +- val = E_MSP430_MACH_MSP430x16; +- 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_msp41: +- val = E_MSP430_MACH_MSP430x41; +- break; +- +- case bfd_mach_msp42: +- val = E_MSP430_MACH_MSP430x42; +- break; +- +- case bfd_mach_msp43: +- val = E_MSP430_MACH_MSP430x43; ++ case bfd_mach_msp430: ++ flags = EF_MSP430_ARCH_430; + break; +- +- case bfd_mach_msp44: +- val = E_MSP430_MACH_MSP430x44; ++ case bfd_mach_msp430x: ++ flags = EF_MSP430_ARCH_430X; + break; + } +- +- elf_elfheader (abfd)->e_machine = EM_MSP430; +- elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH; +- elf_elfheader (abfd)->e_flags |= val; ++ i_ehdrp->e_flags = EF_MSP430_UNIARCH | flags; + } + + /* Set the right machine number. */ + + static bfd_boolean +-elf32_msp430_object_p (bfd * abfd) ++msp430_elf_backend_object_p (bfd * abfd ATTRIBUTE_UNUSED) + { +- 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_MSP430x11: +- e_set = bfd_mach_msp11; +- break; +- +- case E_MSP430_MACH_MSP430x11x1: +- e_set = bfd_mach_msp110; +- break; +- +- case E_MSP430_MACH_MSP430x12: +- e_set = bfd_mach_msp12; +- 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_MSP430x15: +- e_set = bfd_mach_msp15; +- break; +- +- case E_MSP430_MACH_MSP430x16: +- e_set = bfd_mach_msp16; +- 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_MSP430x41: +- e_set = bfd_mach_msp41; +- break; +- +- case E_MSP430_MACH_MSP430x42: +- e_set = bfd_mach_msp42; +- break; +- +- case E_MSP430_MACH_MSP430x43: +- e_set = bfd_mach_msp43; +- break; +- +- case E_MSP430_MACH_MSP430x44: +- e_set = bfd_mach_msp44; +- break; +- } +- } +- +- return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set); ++ Elf_Internal_Ehdr * i_ehdrp; ++ int bfd_mach; ++ ++ i_ehdrp = elf_elfheader (abfd); ++ if (EM_MSP430 != i_ehdrp->e_machine) ++ return FALSE; ++ if (EF_MSP430_UNIARCH & i_ehdrp->e_flags) { ++ switch (i_ehdrp->e_flags & EF_MSP430_ARCH) ++ { ++ default: ++ case EF_MSP430_ARCH_430: ++ bfd_mach = bfd_mach_msp430; ++ break; ++ case EF_MSP430_ARCH_430X: ++ bfd_mach = bfd_mach_msp430x; ++ break; ++ } ++ } else { ++ bfd_mach = bfd_mach_msp430; ++ } ++ return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, bfd_mach); + } + + /* These functions handle relaxing for the msp430. +@@ -1167,13 +1497,12 @@ error_return: + #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_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 _bfd_elf_set_osabi + #define bfd_elf32_bfd_relax_section msp430_elf_relax_section ++#define elf_backend_final_write_processing msp430_elf_backend_final_write_processing ++#define elf_backend_object_p msp430_elf_backend_object_p + + #include "elf32-target.h" +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index 200a6fa..481c0c5 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2219,6 +2219,25 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_MSP430_16_BYTE", + "BFD_RELOC_MSP430_2X_PCREL", + "BFD_RELOC_MSP430_RL_PCREL", ++ "BFD_RELOC_MSP430X_SRC_BYTE", ++ "BFD_RELOC_MSP430X_SRC", ++ "BFD_RELOC_MSP430X_DST_BYTE", ++ "BFD_RELOC_MSP430X_DST", ++ "BFD_RELOC_MSP430X_DST_2ND_BYTE", ++ "BFD_RELOC_MSP430X_DST_2ND", ++ "BFD_RELOC_MSP430X_PCREL_SRC_BYTE", ++ "BFD_RELOC_MSP430X_PCREL_SRC", ++ "BFD_RELOC_MSP430X_PCREL_DST_BYTE", ++ "BFD_RELOC_MSP430X_PCREL_DST", ++ "BFD_RELOC_MSP430X_PCREL_DST_2ND", ++ "BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE", ++ "BFD_RELOC_MSP430X_S_BYTE", ++ "BFD_RELOC_MSP430X_S", ++ "BFD_RELOC_MSP430X_D_BYTE", ++ "BFD_RELOC_MSP430X_D", ++ "BFD_RELOC_MSP430X_PCREL_D", ++ "BFD_RELOC_MSP430X_INDXD", ++ "BFD_RELOC_MSP430X_PCREL_INDXD", + "BFD_RELOC_IQ2000_OFFSET_16", + "BFD_RELOC_IQ2000_OFFSET_21", + "BFD_RELOC_IQ2000_UHI16", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 6ac7148..94127d5 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -5314,6 +5314,44 @@ ENUMX + BFD_RELOC_MSP430_2X_PCREL + ENUMX + BFD_RELOC_MSP430_RL_PCREL ++ENUMX ++ BFD_RELOC_MSP430X_SRC_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_SRC ++ENUMX ++ BFD_RELOC_MSP430X_DST_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_DST ++ENUMX ++ BFD_RELOC_MSP430X_DST_2ND_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_DST_2ND ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_SRC_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_SRC ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_DST_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_DST ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_DST_2ND ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_S_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_S ++ENUMX ++ BFD_RELOC_MSP430X_D_BYTE ++ENUMX ++ BFD_RELOC_MSP430X_D ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_D ++ENUMX ++ BFD_RELOC_MSP430X_INDXD ++ENUMX ++ BFD_RELOC_MSP430X_PCREL_INDXD + ENUMDOC + msp430 specific relocation codes + +diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c +index 98d90c6..15eefb1 100644 +--- a/gas/config/tc-msp430.c ++++ b/gas/config/tc-msp430.c +@@ -23,7 +23,6 @@ + + #include + +-#define PUSH_1X_WORKAROUND + #include "as.h" + #include "subsegs.h" + #include "opcode/msp430.h" +@@ -69,6 +68,7 @@ + + int msp430_enable_relax; + int msp430_enable_polys; ++int msp430x_repeats; // It's not a right way to use global variable, but I don't know other way how to do it + + /* GCC uses the some condition codes which we'll + implement as new polymorph instructions. +@@ -99,12 +99,13 @@ int msp430_enable_polys; + Also, we add 'jump' instruction: + jump UNCOND -> jmp br lab + +- They will have fmt == 4, and insn_opnumb == number of instruction. */ ++ They will have opcode_format() == FMT_EMULATED_POLYMORPH_JUMP, ++ and opcode_variant() == number of instruction. */ + + struct rcodes_s + { + char * name; +- int index; /* Corresponding insn_opnumb. */ ++ int index; /* Corresponding opcode_variant(). */ + int sop; /* Opcode if jump length is short. */ + long lpos; /* Label position. */ + long lop0; /* Opcode 1 _word_ (16 bits). */ +@@ -143,7 +144,7 @@ static struct rcodes_s msp430_rcodes[] = + struct hcodes_s + { + char * name; +- int index; /* Corresponding insn_opnumb. */ ++ int index; /* Corresponding opcode_variant(). */ + int tlab; /* Number of labels in short mode. */ + int op0; /* Opcode for first word of short jump. */ + int op1; /* Opcode for second word of short jump. */ +@@ -228,116 +229,373 @@ relax_typeS md_relax_table[] = + }; + + +-#define MAX_OP_LEN 256 +- +-struct mcu_type_s ++/** List known silicon errata with a description of the problem (where ++ * this can be found). Errata descriptions are available in PDF files ++ * that can be found on the device-specific web page at TI. Errata ++ * numbers are consistent across the product line. ++ * ++ * Note that not all documented errata are currently recognized by the ++ * assembler. In fact, most are completely ignored. Future work... ++ * ++ * Legacy errata descriptions are from previous versions of ++ * binutils. */ ++typedef enum msp430_errata_e + { +- char * name; +- int isa; +- int mach; +-}; +- +-#define MSP430_ISA_11 11 +-#define MSP430_ISA_110 110 +-#define MSP430_ISA_12 12 +-#define MSP430_ISA_13 13 +-#define MSP430_ISA_14 14 +-#define MSP430_ISA_15 15 +-#define MSP430_ISA_16 16 +-#define MSP430_ISA_21 21 +-#define MSP430_ISA_31 31 +-#define MSP430_ISA_32 32 +-#define MSP430_ISA_33 33 +-#define MSP430_ISA_41 41 +-#define MSP430_ISA_42 42 +-#define MSP430_ISA_43 43 +-#define MSP430_ISA_44 44 +- +-#define CHECK_RELOC_MSP430 ((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16) +-#define CHECK_RELOC_MSP430_PCREL ((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL) +- +-static struct mcu_type_s mcu_types[] = +-{ +- {"msp1", MSP430_ISA_11, bfd_mach_msp11}, +- {"msp2", MSP430_ISA_14, bfd_mach_msp14}, +- {"msp430x110", MSP430_ISA_11, bfd_mach_msp11}, +- {"msp430x112", MSP430_ISA_11, bfd_mach_msp11}, +- {"msp430x1101", MSP430_ISA_110, bfd_mach_msp110}, +- {"msp430x1111", MSP430_ISA_110, bfd_mach_msp110}, +- {"msp430x1121", MSP430_ISA_110, bfd_mach_msp110}, +- {"msp430x1122", MSP430_ISA_11, bfd_mach_msp110}, +- {"msp430x1132", MSP430_ISA_11, bfd_mach_msp110}, +- +- {"msp430x122", MSP430_ISA_12, bfd_mach_msp12}, +- {"msp430x123", MSP430_ISA_12, bfd_mach_msp12}, +- {"msp430x1222", MSP430_ISA_12, bfd_mach_msp12}, +- {"msp430x1232", MSP430_ISA_12, bfd_mach_msp12}, +- +- {"msp430x133", MSP430_ISA_13, bfd_mach_msp13}, +- {"msp430x135", MSP430_ISA_13, bfd_mach_msp13}, +- {"msp430x1331", MSP430_ISA_13, bfd_mach_msp13}, +- {"msp430x1351", MSP430_ISA_13, bfd_mach_msp13}, +- {"msp430x147", MSP430_ISA_14, bfd_mach_msp14}, +- {"msp430x148", MSP430_ISA_14, bfd_mach_msp14}, +- {"msp430x149", MSP430_ISA_14, bfd_mach_msp14}, +- +- {"msp430x155", MSP430_ISA_15, bfd_mach_msp15}, +- {"msp430x156", MSP430_ISA_15, bfd_mach_msp15}, +- {"msp430x157", MSP430_ISA_15, bfd_mach_msp15}, +- {"msp430x167", MSP430_ISA_16, bfd_mach_msp16}, +- {"msp430x168", MSP430_ISA_16, bfd_mach_msp16}, +- {"msp430x169", MSP430_ISA_16, bfd_mach_msp16}, +- {"msp430x1610", MSP430_ISA_16, bfd_mach_msp16}, +- {"msp430x1611", MSP430_ISA_16, bfd_mach_msp16}, +- {"msp430x1612", MSP430_ISA_16, bfd_mach_msp16}, +- +- {"msp430x2101", MSP430_ISA_21, bfd_mach_msp21}, +- {"msp430x2111", MSP430_ISA_21, bfd_mach_msp21}, +- {"msp430x2121", MSP430_ISA_21, bfd_mach_msp21}, +- {"msp430x2131", MSP430_ISA_21, bfd_mach_msp21}, ++ /* CPU4: PUSH #4, PUSH #8 ++ * ++ * The single operand instruction PUSH cannot use the internal ++ * constants (CG) 4 and 8. The other internal constants (0, 1, 2, ++ * –1) can be used. The number of clock cycles is different: ++ * ++ * - PUSH #CG uses address mode 00, requiring 3 cycles, 1-word instruction ++ * - PUSH #4/#8 uses address mode 11, requiring 5 cycles, 2-word instruction ++ * ++ * Workaround: ++ * - Assembler generate code not referencing constant generator ++ */ ++ ERRATUM_CPU4 = 4, ++ ++ // CALL and PUSH with @SP+, @SP, and X(SP) uses the SP to calculate the address, then decrements it ++ ERRATUM_CPU7 = 7, ++ ++ /* CPU8: Using odd values in the SP register ++ * ++ * The SP can be written with odd values. In the original CPU, an ++ * odd SP value could be combined with an odd offset (for example, ++ * mov. #value, 5(SP)). In the new CPU, the SP can be written with ++ * an odd value, but the first time the SP is used, the LSB is ++ * forced to 0. ++ * ++ * Workaround: ++ * - Do not use odd values with the SP. ++ */ ++ ERRATUM_CPU8 = 8, /* UNHANDLED */ ++ ++ /* CPU11: Invalid status register after program counter access ++ * ++ * When addressing the program counter (PC) in register mode when ++ * the PC is the destination, the Status Register (SR) may be ++ * erroneous. The instructions BIS, BIC, and MOV do not affect SR ++ * contents. Only CPU flags are affected. This bug does not apply to ++ * LPMx control bits. ++ * ++ * Workaround: None ++ */ ++ ERRATUM_CPU11 = 11, /* UNHANDLED */ ++ ++ /* CPU12: CMP or BIT with PC destination ++ * ++ * Any instruction immediately following a CMP(.B) or BIT(.B) ++ * instruction when the PC is the destination address using register ++ * mode is ignored or erroneously executed. When the following ++ * instruction is longer than one word, the second word is fetched ++ * by the CPU and decoded as the instruction, leading to ++ * unpredictable behavior. Affected source-addressing modes are ++ * indexed and indirect addressing modes. ++ * ++ * Example: ++ * cmp &200,PC ++ * add #4,R8 ++ * The add command is not executed. ++ * ++ * Workaround: ++ * - Insert a NOP instruction after the BIT or CMP instruction. The ++ * NOP is ignored, and program execution continues as expected. ++ */ ++ ERRATUM_CPU12 = 12, /* UNHANDLED */ ++ ++ /* CPU13: Arithmetic operations and the SR ++ * ++ * Performing arithmetic operations with the Status Register (SR) as ++ * the destination address does not update the SR as intended. The ++ * result in SR can be invalid, leading to erroneous low-power mode ++ * entry. Arithmetic operations are defined as all instructions that ++ * modify the SR flag bits (RRA, SUB, XOR, and ADD, for example). ++ * ++ * Workaround: None ++ */ ++ ERRATUM_CPU13 = 13, /* UNHANDLED */ ++ ++ /* CPU15: Modifying the Program Counter (PC) behaves differently ++ * than in previous devices ++ * ++ * When using instructions with immediate or indirect addressing ++ * mode to modify the PC, a different value compared to previous ++ * devices must be added to get to the same destination. ++ * ++ * NOTE: The MOV instruction is not affected ++ * ++ * Example: Previous device (MSP430F4619) ++ * label_1 ADD.W #Branch1-label_1-4h,PC ++ * MSP430F5438: ++ * label_1 ADD.W #Branch1-label_1-2h,PC ++ * ++ * Workaround: ++ * - Additional NOP after the PC-modifying instruction; or ++ * - Change the offset value in software ++ */ ++ ERRATUM_CPU15 = 15, /* UNHANDLED */ ++ ++ /* CPU16 Indexed addressing with instructions calla, mova, and bra ++ * ++ * With indexed addressing mode and instructions calla, mova, and bra, it is not possible ++ * to reach memory above 64k if the register content is < 64k. ++ * Example: Assume R5 = FFFEh. The instruction calla 0004h(R5) results in a 20-bit call ++ * of address 0002h instead of 10002h. ++ * ++ * Workaround: ++ * - Use different addressing mode to reach memory above 64k. ++ * - First use adda [index],[Rx] to calculate address in upper memory and then use ++ * calla [Rx]. ++ */ ++ ERRATUM_CPU16 = 16, /* UNHANDLED */ ++ ++ /* CPU18: LPM instruction can corrupt PC/SR registers ++ * ++ * The PC and SR registers have the potential to be corrupted when: ++ * - An instruction using register, absolute, indexed, indirect, ++ * indirect auto-increment, or symbolic mode is used to set the ++ * LPM bits (for example, BIS &xyh, SR). ++ * and ++ * - This instruction is followed by a CALL or CALLA instruction. ++ * ++ * Upon servicing an interrupt service routine, the program counter ++ * (PC) is pushed twice onto the stack instead of the correct ++ * operation where the PC, then the SR registers are pushed onto the ++ * stack. This corrupts the SR and possibly the PC on RETI from the ++ * ISR. ++ * ++ * Workaround: ++ * - Insert a NOP or __no_operation() intrinsic function between the ++ * instruction to enter low-power mode and the CALL or CALLA ++ * instruction. ++ */ ++ ERRATUM_CPU18 = 18, /* UNHANDLED */ ++ ++ /* CPU19: CPUOFF can change register values ++ * ++ * If a CPUOFF command is followed by an instruction with an ++ * indirect addressed operand (for example, mov @R8, R9, and RET), ++ * an unintentional register-read operation can occur during the ++ * wakeup of the CPU. If the unintentional read occurs to a ++ * read-sensitive register (for example, UCB0RXBUF or TAIV), which ++ * changes its value or the value of other registers (IFGs), the bug ++ * leads to lost interrupts or wrong register read values. ++ * ++ * Workaround: ++ * - Insert a NOP instruction after each CPUOFF instruction. ++ */ ++ ERRATUM_CPU19 = 19, /* UNHANDLED */ ++ ++ /* CPU20: An unexpected Vacant Memory Access Flag (VMAIFG) can be ++ * triggered due to the CPU autoincrement of the MAB + 2 ++ * outside the range of a valid memory block. ++ * ++ * The VMAIFG is triggered if a PC-modifying instruction (for ++ * example, ret, push, call, pop, jmp, br) is fetched from the last ++ * address of a section of memory (for example, flash or RAM) that ++ * is not contiguous to a higher valid section on the memory map. ++ * ++ * Workaround: ++ * - If code is affected, edit the linker command file to make the ++ * last four bytes of affected memory sections unavailable. ++ */ ++ ERRATUM_CPU20 = 20, /* UNHANDLED */ ++ ++ /* NO DESCRIPTION */ ++ ERRATUM_CPU21 = 21, /* UNHANDLED */ ++ ++ /* NO DESCRIPTION */ ++ ERRATUM_CPU22 = 22, /* UNHANDLED */ ++ ++ /* NO DESCRIPTION */ ++ ERRATUM_CPU23 = 23, /* UNHANDLED */ ++ ++ /* CPU26: CALL SP does not behave as expected ++ * ++ * When the intention is to execute code from the stack, a CALL SP ++ * instruction skips the first piece of data (instruction) on the ++ * stack. The second piece of data at SP + 2 is used as the first ++ * executable instruction. ++ * ++ * Workaround: ++ * - Write the op code for a NOP as the first instruction on the ++ * stack. Begin the intended subroutine at address SP + 2. ++ */ ++ ERRATUM_CPU26 = 26, /* UNHANDLED */ ++ ++ /* CPU27: Program Counter (PC) is corrupted during the context save ++ * of a nested interrupt ++ * ++ * When a low-power mode is entered within an interrupt service ++ * routine that has enabled nested interrupts (by setting the GIE ++ * bit), and the instruction that sets the low-power mode is ++ * directly followed by a RETI instruction, an incorrect value of PC ++ * + 2 is pushed to the stack during the context save. Hence, the ++ * RETI instruction is not executed on return from the nested ++ * interrupt, and the PC becomes corrupted. ++ * ++ * Workaround: ++ * - Insert a NOP or __no_operation() intrinsic function between the ++ * instruction that sets the lower power mode and the RETI ++ * instruction. ++ */ ++ ERRATUM_CPU27 = 27, /* UNHANDLED */ ++ ++ /* CPU28: PC is corrupted when using certain extended addressing ++ * mode combinations ++ * ++ * An extended memory instruction that modifies the program counter ++ * executes incorrectly when preceded by an extended memory ++ * write-back instruction under the following conditions: ++ * ++ * - First instruction: ++ * 2-operand instruction, extended mode using (register,index), ++ * (register,absolute), or (register,symbolic) addressing modes ++ * - Second instruction: ++ * 2-operand instruction, extended mode using the (indirect,PC), ++ * (indirect auto-increment,PC), or (indexed [with ind 0], PC) ++ * addressing modes ++ * ++ * Example: ++ * BISX.A R6,&AABCD ++ * ANDX.A @R4+,PC ++ * ++ * Workaround: ++ * - Insert a NOP or a __no_operation() intrinsic function between ++ * the two instructions. ++ * or ++ * - Do not use an extended memory instruction to modify the PC. ++ */ ++ ERRATUM_CPU28 = 28, /* UNHANDLED */ ++ ++ /* CPU29: Using a certain instruction sequence to enter low-power ++ * mode(s) affects the instruction width of the first ++ * instruction in an NMI ISR ++ * ++ * If there is a pending NMI request when the CPU enters a low-power ++ * mode (LPMx) using an instruction of Indexed source addressing ++ * mode, and that instruction is followed by a 20-bit wide ++ * instruction of Register source and Destination addressing modes, ++ * the first instruction of the ISR is executed as a 20-bit wide ++ * instruction. ++ * ++ * Example: ++ * main: ++ * ... ++ * MOV.W [indexed],SR ; Enter LPMx ++ * MOVX.A [register],[register] ; 20-bit wide instruction ++ * ... ++ * ISR_start: ++ * MOV.B [indexed],[register] ; ERROR - Executed as a 20-bit instruction! ++ * ++ * Note: [ ] indicates addressing mode ++ * ++ * Workaround: ++ * - Insert a NOP or a __no_operation() intrinsic function following ++ * the instruction that enters the LPMx using indexed addressing ++ * mode. ++ * or ++ * - Use a NOP or a __no_operation() intrinsic function as first ++ * instruction in the ISR. ++ * or ++ * - Do not use the indexed mode to enter LPMx. ++ */ ++ ERRATUM_CPU29 = 29, /* UNHANDLED */ + +- {"msp430x311", MSP430_ISA_31, bfd_mach_msp31}, +- {"msp430x312", MSP430_ISA_31, bfd_mach_msp31}, +- {"msp430x313", MSP430_ISA_31, bfd_mach_msp31}, +- {"msp430x314", MSP430_ISA_31, bfd_mach_msp31}, +- {"msp430x315", MSP430_ISA_31, bfd_mach_msp31}, +- {"msp430x323", MSP430_ISA_32, bfd_mach_msp32}, +- {"msp430x325", MSP430_ISA_32, bfd_mach_msp32}, +- {"msp430x336", MSP430_ISA_33, bfd_mach_msp33}, +- {"msp430x337", MSP430_ISA_33, bfd_mach_msp33}, +- +- {"msp430x412", MSP430_ISA_41, bfd_mach_msp41}, +- {"msp430x413", MSP430_ISA_41, bfd_mach_msp41}, +- {"msp430x415", MSP430_ISA_41, bfd_mach_msp41}, +- {"msp430x417", MSP430_ISA_41, bfd_mach_msp41}, +- +- {"msp430xE423", MSP430_ISA_42, bfd_mach_msp42}, +- {"msp430xE425", MSP430_ISA_42, bfd_mach_msp42}, +- {"msp430xE427", MSP430_ISA_42, bfd_mach_msp42}, +- +- {"msp430xW423", MSP430_ISA_42, bfd_mach_msp42}, +- {"msp430xW425", MSP430_ISA_42, bfd_mach_msp42}, +- {"msp430xW427", MSP430_ISA_42, bfd_mach_msp42}, +- +- {"msp430xG437", MSP430_ISA_43, bfd_mach_msp43}, +- {"msp430xG438", MSP430_ISA_43, bfd_mach_msp43}, +- {"msp430xG439", MSP430_ISA_43, bfd_mach_msp43}, +- +- {"msp430x435", MSP430_ISA_43, bfd_mach_msp43}, +- {"msp430x436", MSP430_ISA_43, bfd_mach_msp43}, +- {"msp430x437", MSP430_ISA_43, bfd_mach_msp43}, +- {"msp430x447", MSP430_ISA_44, bfd_mach_msp44}, +- {"msp430x448", MSP430_ISA_44, bfd_mach_msp44}, +- {"msp430x449", MSP430_ISA_44, bfd_mach_msp44}, +- +- {NULL, 0, 0} ++ /* CPU30: ADDA, SUBA, CMPA [immediate],PC behave as if immediate ++ * value were offset by -2 ++ * ++ * The extended address instructions ADDA, SUBA, and CMPA in ++ * immediate addressing mode are represented by 4 bytes of opcode ++ * (see the MSP430F5xx Family User's Guide (SLAU208) for more ++ * details). In cases where the program counter (PC) is used as the ++ * destination register, only 2 bytes of the current instruction's ++ * 4-byte opcode are accounted for in the PC value. The resulting ++ * operation executes as if the immediate value were offset by a ++ * value of -2. ++ * ++ * Example: ++ * Ideal: ADDA #Immediate-4, PC ++ * ...is equivalent to... ++ * Actual: ADDA #Immediate-2, PC ++ * NOTE: The MOV instruction is not affected. ++ * ++ * Workaround: ++ * - Modify immediate value in software to account for the offset of 2. ++ * or ++ * - Use extended 20-bit instructions (addx.a, subx.a, cmpx.a) instead. ++ */ ++ ERRATUM_CPU30 = 30, /* UNHANDLED */ ++ ++ /* CPU40: PC is corrupted when executing jump/conditional jump ++ * instruction that is followed by instruction with PC as ++ * destination register or a data section ++ * ++ * If the value at the memory location immediately following a ++ * jump/conditional jump instruction is 0X40h or 0X50h (where X = ++ * don't care), which could either be an instruction opcode (for ++ * instructions like RRCM, RRAM, RLAM, RRUM) with PC as destination ++ * register or a data section (const data in flash memory or data ++ * variable in RAM), then the PC value gets auto-incremented by 2 ++ * after the jump instruction is executed; thus branching to a wrong ++ * address location in code and leading to wrong program execution. ++ * ++ * For example, a conditional jump instruction followed by data ++ * section (0140h). ++ * ++ * @0x8012 Loop DEC.W R6 ++ * @0x8014 DEC.W R7 ++ * @0x8016 JNZ Loop ++ * @0x8018 Value1 DW 0140h ++ * ++ * Workaround: ++ * - In assembly, insert a NOP between the jump/conditional jump ++ * instruction and program code with instruction that contains PC ++ * as destination register or the data section. ++ */ ++ ERRATUM_CPU40 = 40, /* UNHANDLED */ ++} msp430_errata_e; ++ ++/* sed -e '1,/enum msp430_errata/d' -e '/^\}/,$d' tc-msp430.c \ ++ | grep '^ *ERRATUM_*' \ ++ | cut -d= -f1 \ ++ | sed 's@ *$@,@' */ ++static const int recognized_errata[] = { ++ ERRATUM_CPU4, ++ ERRATUM_CPU7, ++ ERRATUM_CPU8, ++ ERRATUM_CPU11, ++ ERRATUM_CPU12, ++ ERRATUM_CPU13, ++ ERRATUM_CPU15, ++ ERRATUM_CPU16, ++ ERRATUM_CPU18, ++ ERRATUM_CPU19, ++ ERRATUM_CPU20, ++ ERRATUM_CPU21, ++ ERRATUM_CPU22, ++ ERRATUM_CPU23, ++ ERRATUM_CPU26, ++ ERRATUM_CPU27, ++ ERRATUM_CPU28, ++ ERRATUM_CPU29, ++ ERRATUM_CPU30, ++ ERRATUM_CPU40, + }; + ++#define CHECK_RELOC_MSP430 ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16) ++#define CHECK_RELOC_MSP430_PCREL ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430_16_PCREL_BYTE : BFD_RELOC_MSP430_16_PCREL) ++#define CHECK_RELOC_MSP430X_SRC ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_SRC_BYTE : BFD_RELOC_MSP430X_SRC) ++#define CHECK_RELOC_MSP430X_PCREL_SRC ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_SRC_BYTE : BFD_RELOC_MSP430X_PCREL_SRC) ++#define CHECK_RELOC_MSP430X_DST ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_DST_BYTE : BFD_RELOC_MSP430X_DST) ++#define CHECK_RELOC_MSP430X_PCREL_DST ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_DST_BYTE : BFD_RELOC_MSP430X_PCREL_DST) ++#define CHECK_RELOC_MSP430X_DST_2ND ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_DST_2ND_BYTE : BFD_RELOC_MSP430X_DST_2ND) ++#define CHECK_RELOC_MSP430X_PCREL_DST_2ND ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE : BFD_RELOC_MSP430X_PCREL_DST_2ND) + +-static struct mcu_type_s default_mcu = +- { "msp430x11", MSP430_ISA_11, bfd_mach_msp11 }; +- +-static struct mcu_type_s * msp430_mcu = & default_mcu; ++static int msp430_cpu = MSP430_CPU_MSP430; ++static int msp430_mpy = MSP430_MPY_NONE; ++static int *msp430_errata = 0; + + /* Profiling capability: + It is a performance hit to use gcc's profiling approach for this tiny target. +@@ -446,32 +704,14 @@ pow2value (int y) + static char * + parse_exp (char * s, expressionS * op) + { ++ char * in_save = input_line_pointer; + input_line_pointer = s; + expression (op); ++ s = input_line_pointer; ++ input_line_pointer = in_save; + if (op->X_op == O_absent) + as_bad (_("missing operand")); +- return input_line_pointer; +-} +- +- +-/* Delete spaces from s: X ( r 1 2) => X(r12). */ +- +-static void +-del_spaces (char * s) +-{ +- while (*s) +- { +- if (ISSPACE (*s)) +- { +- char *m = s + 1; +- +- while (ISSPACE (*m) && *m) +- m++; +- memmove (s, m, strlen (m) + 1); +- } +- else +- s++; +- } ++ return s; + } + + static inline char * +@@ -482,42 +722,46 @@ skip_space (char * s) + return s; + } + +-/* Extract one word from FROM and copy it to TO. Delimiters are ",;\n" */ +- ++/* Extract one word from the input. Delimiters are ",;\n" */ + static char * +-extract_operand (char * from, char * to, int limit) ++get_operand (void) + { +- int size = 0; +- +- /* Drop leading whitespace. */ +- from = skip_space (from); ++ char* sp = input_line_pointer; ++ char* end_ilp; ++ char* dest; ++ char* dp; ++ int operand_length = 0; + +- while (size < limit && *from) ++ while (*sp && ',' != *sp && ';' != *sp && '\n' != *sp) + { +- *(to + size) = *from; +- if (*from == ',' || *from == ';' || *from == '\n') +- break; +- from++; +- size++; ++ if (! ISSPACE(*sp)) ++ ++operand_length; ++ ++sp; + } +- +- *(to + size) = 0; +- del_spaces (to); +- +- from++; +- +- return from; ++ end_ilp = sp; ++ if (',' == *end_ilp) ++ ++end_ilp; ++ ++ dp = dest = xmalloc(operand_length + 1); ++ sp = input_line_pointer; ++ while (0 < operand_length) { ++ if (! ISSPACE(*sp)) { ++ *dp++ = *sp; ++ --operand_length; ++ } ++ ++sp; ++ } ++ *dp = 0; ++ input_line_pointer = end_ilp; ++ return dest; + } + + static void + msp430_profiler (int dummy ATTRIBUTE_UNUSED) + { +- char buffer[1024]; +- char f[32]; +- char * str = buffer; +- char * flags = f; ++ char * flag_token = 0; ++ char * flags; + int p_flags = 0; +- char * halt; + int ops = 0; + int left; + char * s; +@@ -549,8 +793,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) + return; + } + +- input_line_pointer = extract_operand (input_line_pointer, flags, 32); +- ++ flags = flag_token = get_operand (); + while (*flags) + { + switch (*flags) +@@ -608,6 +851,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) + } + flags++; + } ++ xfree (flag_token); + + if (p_flags + && ( ! pow2value (p_flags & ( MSP430_PROFILER_FLAG_ENTRY +@@ -658,11 +902,11 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) + while (ops--) + { + /* Now get profiling info. */ +- halt = extract_operand (input_line_pointer, str, 1024); ++ char *halt = get_operand (); + /* Process like ".word xxx" directive. */ +- parse_exp (str, & exp); ++ parse_exp (halt, & exp); + emit_expr (& exp, 2); +- input_line_pointer = halt; ++ xfree(halt); + } + + /* Fill the rest with zeros. */ +@@ -675,79 +919,178 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) + subseg_set (seg, subseg); + } + +-static char * +-extract_word (char * from, char * to, int limit) ++struct tag_value_pair_t + { +- char *op_end; +- int size = 0; ++ const char *tag; ++ unsigned long value; ++}; + +- /* Drop leading whitespace. */ +- from = skip_space (from); +- *to = 0; ++static const struct tag_value_pair_t cpu_tag_value_map[] = { ++ {"430", MSP430_CPU_MSP430}, ++ {"430x", MSP430_CPU_MSP430X}, ++ {"430xv2", MSP430_CPU_MSP430XV2}, ++ {0, 0} ++}; ++ ++static const struct tag_value_pair_t mpy_tag_value_map[] = { ++ {"none", MSP430_MPY_NONE}, ++ {"16", MSP430_MPY_16}, ++ {"16se", MSP430_MPY_16SE}, ++ {"32", MSP430_MPY_32}, ++ {"32dw", MSP430_MPY_32DW}, ++ {0, 0} ++}; + +- /* Find the op code end. */ +- for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);) ++static const struct tag_value_pair_t * ++find_pair_by_tag (const char *tag, const struct tag_value_pair_t *map) ++{ ++ while (map->tag) + { +- to[size++] = *op_end++; +- if (size + 1 >= limit) +- break; ++ if (0 == strcmp (tag, map->tag)) ++ return map; ++ ++map; + } ++ return 0; ++} + +- to[size] = 0; +- return op_end; ++#if 0 ++static const struct tag_value_pair_t * ++find_pair_by_value (unsigned long value, const struct tag_value_pair_t *map) ++{ ++ while (map->tag) ++ { ++ if (map->value == value) ++ return map; ++ ++map; ++ } ++ return 0; + } ++#endif + +-#define OPTION_MMCU 'm' +-#define OPTION_RELAX 'Q' +-#define OPTION_POLYMORPHS 'P' ++enum { ++ OPTION_MMCU = 'm', ++ OPTION_RELAX = 'Q', ++ OPTION_POLYMORPHS = 'P', ++ OPTION_CPU = OPTION_MD_BASE + 0, ++ OPTION_MPY, ++ OPTION_ERRATA, ++}; ++ ++static int ++erratum_applies (int erratum) ++{ ++ if (! msp430_errata) ++ if (ERRATUM_CPU4 == erratum) ++ return msp430_cpu < MSP430_CPU_MSP430X; ++ return 0; ++} ++ ++static int ++cpu_from_text (const char* text) ++{ ++ const struct tag_value_pair_t* mp = find_pair_by_tag(text, cpu_tag_value_map); ++ if (! mp) ++ as_fatal (_("unrecognized cpu type %s"), text); ++ return mp->value; ++} ++ ++static int ++mpy_from_text (const char* text) ++{ ++ const struct tag_value_pair_t* mp = find_pair_by_tag(text, mpy_tag_value_map); ++ if (! mp) ++ as_fatal (_("unrecognized hardware multiplier type %s"), text); ++ return mp->value; ++} + + static void +-msp430_set_arch (int dummy ATTRIBUTE_UNUSED) ++set_arch_mach (int cpu, ++ int mpy ATTRIBUTE_UNUSED) + { +- char *str = (char *) alloca (32); /* 32 for good measure. */ ++ unsigned long mach = bfd_mach_msp430; ++ if (MSP430_CPU_MSP430X <= cpu) ++ mach = bfd_mach_msp430x; ++ bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach); ++} + +- input_line_pointer = extract_word (input_line_pointer, str, 32); ++/* Like get_symbol_end, but accepts sequences that start with ++ * digits and doesn't strip out name ends */ ++static char ++get_token_end (void) ++{ ++ char c; + +- md_parse_option (OPTION_MMCU, str); +- bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); ++ while (is_part_of_name (c = *input_line_pointer++)) ++ ; ++ *--input_line_pointer = 0; ++ return (c); + } + + static void +-show_mcu_list (FILE * stream) ++msp430_set_mcu (int dummy ATTRIBUTE_UNUSED) + { +- int i; ++ SKIP_WHITESPACE(); ++ if (!is_end_of_line[(unsigned char) *input_line_pointer]) ++ { ++ char* tag_start = input_line_pointer; ++ int ch = get_token_end (); ++ md_parse_option (OPTION_MMCU, tag_start); ++ *input_line_pointer = ch; ++ demand_empty_rest_of_line (); ++ } ++ else ++ as_bad (_("missing value for arch")); ++} ++ ++static void ++msp430_set (int option) ++{ ++ char* tag = 0; ++ ++ SKIP_WHITESPACE (); ++ if (!is_end_of_line[(unsigned char) *input_line_pointer]) ++ { ++ char *tag_start = input_line_pointer; ++ char e = get_token_end (); ++ int tag_len = input_line_pointer + 1 - tag_start; ++ tag = (char *) xmalloc(tag_len); ++ memcpy (tag, tag_start, tag_len); ++ *input_line_pointer = e; ++ demand_empty_rest_of_line (); ++ } ++ ++ switch (option) ++ { ++ case OPTION_CPU: ++ if (! tag) ++ as_bad (_("missing value for cpu")); ++ msp430_cpu = cpu_from_text(tag); ++ break; ++ case OPTION_MPY: ++ if (! tag) ++ as_bad (_("missing value for mpy")); ++ msp430_mpy = mpy_from_text(tag); ++ break; ++ default: ++ abort(); ++ } + +- fprintf (stream, _("Known MCU names:\n")); ++ set_arch_mach (msp430_cpu, msp430_mpy); + +- for (i = 0; mcu_types[i].name; i++) +- fprintf (stream, _("\t %s\n"), mcu_types[i].name); ++} + +- fprintf (stream, "\n"); ++static void ++msp430_set_errata (int dummy ATTRIBUTE_UNUSED) ++{ + } + + int + md_parse_option (int c, char * arg) + { +- int i; +- + switch (c) + { + case OPTION_MMCU: +- for (i = 0; mcu_types[i].name; ++i) +- if (strcmp (mcu_types[i].name, arg) == 0) +- break; +- +- if (!mcu_types[i].name) +- { +- show_mcu_list (stderr); +- as_fatal (_("unknown MCU: %s\n"), arg); +- } +- +- if (msp430_mcu == &default_mcu || msp430_mcu->mach == mcu_types[i].mach) +- msp430_mcu = &mcu_types[i]; +- else +- as_fatal (_("redefinition of mcu type %s' to %s'"), +- msp430_mcu->name, mcu_types[i].name); ++ //as_tsktsk(_("mcu option ignored")); + return 1; + break; + +@@ -760,16 +1103,35 @@ md_parse_option (int c, char * arg) + msp430_enable_polys = 1; + return 1; + break; ++ ++ case OPTION_CPU: ++ msp430_cpu = cpu_from_text(arg); ++ return 1; ++ break; ++ ++ case OPTION_MPY: ++ msp430_mpy = mpy_from_text(arg); ++ return 1; ++ break; ++ ++ case OPTION_ERRATA: ++ break; + } + + return 0; + } + ++static void ++msp430_repeat_insn (int dummy ATTRIBUTE_UNUSED); + + const pseudo_typeS md_pseudo_table[] = + { +- {"arch", msp430_set_arch, 0}, ++ {"arch", msp430_set_mcu, 0}, + {"profiler", msp430_profiler, 0}, ++ {"rpt", msp430_repeat_insn, 0}, ++ {"cpu", msp430_set, OPTION_CPU}, ++ {"mpy", msp430_set, OPTION_MPY}, ++ {"errata", msp430_set_errata, 0}, + {NULL, NULL, 0} + }; + +@@ -780,6 +1142,9 @@ struct option md_longopts[] = + {"mmcu", required_argument, NULL, OPTION_MMCU}, + {"mP", no_argument, NULL, OPTION_POLYMORPHS}, + {"mQ", no_argument, NULL, OPTION_RELAX}, ++ {"mcpu", required_argument, NULL, OPTION_CPU }, ++ {"mmpy", required_argument, NULL, OPTION_MPY }, ++ {"merrata", required_argument, NULL, OPTION_ERRATA }, + {NULL, no_argument, NULL, 0} + }; + +@@ -789,33 +1154,13 @@ void + md_show_usage (FILE * stream) + { + fprintf (stream, +- _("MSP430 options:\n" +- " -mmcu=[msp430-name] select microcontroller type\n" +- " msp430x110 msp430x112\n" +- " msp430x1101 msp430x1111\n" +- " msp430x1121 msp430x1122 msp430x1132\n" +- " msp430x122 msp430x123\n" +- " msp430x1222 msp430x1232\n" +- " msp430x133 msp430x135\n" +- " msp430x1331 msp430x1351\n" +- " msp430x147 msp430x148 msp430x149\n" +- " msp430x155 msp430x156 msp430x157\n" +- " msp430x167 msp430x168 msp430x169\n" +- " msp430x1610 msp430x1611 msp430x1612\n" +- " msp430x311 msp430x312 msp430x313 msp430x314 msp430x315\n" +- " msp430x323 msp430x325\n" +- " msp430x336 msp430x337\n" +- " msp430x412 msp430x413 msp430x415 msp430x417\n" +- " msp430xE423 msp430xE425 msp430E427\n" +- " msp430xW423 msp430xW425 msp430W427\n" +- " msp430xG437 msp430xG438 msp430G439\n" +- " msp430x435 msp430x436 msp430x437\n" +- " msp430x447 msp430x448 msp430x449\n")); +- fprintf (stream, +- _(" -mQ - enable relaxation at assembly time. DANGEROUS!\n" ++ _("MSP430 as-specific options:\n" ++ " -mmcu=[msp430-name] select microcontroller type (ignored)\n" ++ " -mcpu={430,430x,430xv2} select cpu model\n" ++ " -mmpy={none,16,16se,32,32dw} select hardware multiplier type\n" ++ " -merrata=[cpuX,...] list relevant errata\n" ++ " -mQ - enable relaxation at assembly time. DANGEROUS!\n" + " -mP - enable polymorph instructions\n")); +- +- show_mcu_list (stream); + } + + symbolS * +@@ -824,23 +1169,6 @@ md_undefined_symbol (char * name ATTRIBUTE_UNUSED) + return 0; + } + +-static char * +-extract_cmd (char * from, char * to, int limit) +-{ +- int size = 0; +- +- while (*from && ! ISSPACE (*from) && *from != '.' && limit > size) +- { +- *(to + size) = *from; +- from++; +- size++; +- } +- +- *(to + size) = 0; +- +- return from; +-} +- + char * + md_atof (int type, char * litP, int * sizeP) + { +@@ -850,13 +1178,13 @@ md_atof (int type, char * litP, int * sizeP) + void + md_begin (void) + { +- struct msp430_opcode_s * opcode; ++ struct msp430_opcode_s const * opcode; + msp430_hash = hash_new (); + + for (opcode = msp430_opcodes; opcode->name; opcode++) + hash_insert (msp430_hash, opcode->name, (char *) opcode); + +- bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); ++ set_arch_mach (msp430_cpu, msp430_mpy); + } + + static int +@@ -880,13 +1208,74 @@ check_reg (char * t) + return 0; + } + ++static void ++msp430_substitute_CG(struct msp430_operand_s * op, int workaround) ++{ ++ /* Substitute register mode with a constant generator if applicable. */ ++ if( op->mode != OP_EXP || ( op->exp.X_op != O_constant && op->exp.X_op != O_big )) ++ return; ++ if( op->am != 3 || op->reg != 0 ) // not #N ++ return; ++ int x = (short) op->exp.X_add_number; /* Extend sign. */ ++ ++ if (x == 0) ++ { ++ op->reg = 3; ++ op->am = 0; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++ else if (x == 1) ++ { ++ op->reg = 3; ++ op->am = 1; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++ else if (x == 2) ++ { ++ op->reg = 3; ++ op->am = 2; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++ else if (x == -1) ++ { ++ op->reg = 3; ++ op->am = 3; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++ else if (x == 4 && !workaround) ++ { ++ op->reg = 2; ++ op->am = 2; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++ else if (x == 8 && ! workaround) ++ { ++ op->reg = 2; ++ op->am = 3; ++ op->ol = 0; ++ op->mode = OP_REG; ++ } ++} + + static int + msp430_srcoperand (struct msp430_operand_s * op, +- char * l, int bin, int * imm_op) ++ const char * operand_string, int * imm_op, int imm_min, int imm_max) + { +- char *__tl = l; ++ char *l = ""; ++ char *__tl; + ++ if (operand_string) ++ { ++ l = alloca(strlen(operand_string) + 1); ++ strcpy(l, operand_string); ++ } ++ __tl = l; ++ + /* Check if an immediate #VALUE. The hash sign should be only at the beginning! */ + if (*l == '#') + { +@@ -943,100 +1332,27 @@ msp430_srcoperand (struct msp430_operand_s * op, + parse_exp (__tl, &(op->exp)); + if (op->exp.X_op == O_constant) + { +- int x = op->exp.X_add_number; ++ offsetT x = op->exp.X_add_number; ++ int is_negative = 0 > x; + +- if (vshift == 0) +- { +- x = x & 0xffff; +- op->exp.X_add_number = x; +- } +- else if (vshift == 1) ++ if (0 <= vshift) + { +- x = (x >> 16) & 0xffff; +- op->exp.X_add_number = x; +- } +- else if (vshift > 1) +- { +- if (x < 0) +- op->exp.X_add_number = -1; ++ unsigned int shift_bits = vshift * 16; ++ if (shift_bits < (8 * sizeof (x))) ++ x >>= shift_bits; ++ else ++ x = 0; ++ if (0 == x) ++ op->exp.X_add_number = is_negative ? -1 : 0; + else +- op->exp.X_add_number = 0; /* Nothing left. */ ++ op->exp.X_add_number = x & 0xFFFF; + x = op->exp.X_add_number; + } +- +- if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768) ++ if (x >= imm_max || x < imm_min) + { +- as_bad (_("value %d out of range. Use #lo() or #hi()"), x); ++ as_bad (_("value %ld out of %d...%d (0x%X...0x%X) range."), (long int)x, imm_min, imm_max - 1, imm_min, imm_max - 1); + return 1; + } +- +- /* Now check constants. */ +- /* Substitute register mode with a constant generator if applicable. */ +- +- x = (short) x; /* Extend sign. */ +- +- if (x == 0) +- { +- op->reg = 3; +- op->am = 0; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 1) +- { +- op->reg = 3; +- op->am = 1; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 2) +- { +- op->reg = 3; +- op->am = 2; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == -1) +- { +- op->reg = 3; +- op->am = 3; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 4) +- { +-#ifdef PUSH_1X_WORKAROUND +- if (bin == 0x1200) +- { +- /* Remove warning as confusing. +- as_warn (_("Hardware push bug workaround")); */ +- } +- else +-#endif +- { +- op->reg = 2; +- op->am = 2; +- op->ol = 0; +- op->mode = OP_REG; +- } +- } +- else if (x == 8) +- { +-#ifdef PUSH_1X_WORKAROUND +- if (bin == 0x1200) +- { +- /* Remove warning as confusing. +- as_warn (_("Hardware push bug workaround")); */ +- } +- else +-#endif +- { +- op->reg = 2; +- op->am = 3; +- op->ol = 0; +- op->mode = OP_REG; +- } +- } + } + else if (op->exp.X_op == O_symbol) + { +@@ -1044,12 +1360,10 @@ msp430_srcoperand (struct msp430_operand_s * op, + } + else if (op->exp.X_op == O_big) + { +- short x; + if (vshift != -1) + { + op->exp.X_op = O_constant; + op->exp.X_add_number = 0xffff & generic_bignum[vshift]; +- x = op->exp.X_add_number; + } + else + { +@@ -1058,49 +1372,6 @@ msp430_srcoperand (struct msp430_operand_s * op, + l); + return 1; + } +- +- if (x == 0) +- { +- op->reg = 3; +- op->am = 0; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 1) +- { +- op->reg = 3; +- op->am = 1; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 2) +- { +- op->reg = 3; +- op->am = 2; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == -1) +- { +- op->reg = 3; +- op->am = 3; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 4) +- { +- op->reg = 2; +- op->am = 2; +- op->ol = 0; +- op->mode = OP_REG; +- } +- else if (x == 8) +- { +- op->reg = 2; +- op->am = 3; +- op->ol = 0; +- op->mode = OP_REG; +- } + } + /* Redundant (yet) check. */ + else if (op->exp.X_op == O_register) +@@ -1127,7 +1398,7 @@ msp430_srcoperand (struct msp430_operand_s * op, + { + int x = op->exp.X_add_number; + +- if (x > 65535 || x < -32768) ++ if (x >= imm_max || x < imm_min) + { + as_bad (_("value out of range: %d"), x); + return 1; +@@ -1262,7 +1533,7 @@ msp430_srcoperand (struct msp430_operand_s * op, + { + int x = op->exp.X_add_number; + +- if (x > 65535 || x < -32768) ++ if (x > imm_max || x < imm_min) + { + as_bad (_("value out of range: %d"), x); + return 1; +@@ -1338,10 +1609,10 @@ msp430_srcoperand (struct msp430_operand_s * op, + + + static int +-msp430_dstoperand (struct msp430_operand_s * op, char * l, int bin) ++msp430_dstoperand (struct msp430_operand_s * op, const char * l, int imm_min, int imm_max) + { + int dummy; +- int ret = msp430_srcoperand (op, l, bin, & dummy); ++ int ret = msp430_srcoperand (op, l, & dummy, imm_min, imm_max); + + if (ret) + return ret; +@@ -1373,39 +1644,139 @@ msp430_dstoperand (struct msp430_operand_s * op, char * l, int bin) + return 0; + } + ++static void ++msp430_repeat_insn (int dummy ATTRIBUTE_UNUSED) ++{ ++ char *operand = 0; ++ struct msp430_operand_s op; ++ int imm_op = 0; ++ char *line = input_line_pointer; ++ ++ if (msp430_cpu < MSP430_CPU_MSP430X) ++ { ++ as_bad (_("Repeatable instructions require 430X-based mcu")); ++ goto done; ++ } ++ ++ if (msp430x_repeats) ++ as_warn (_("two consecutive .rpt pseudo-ops. Previous .rpt discarded")); ++ ++ if (!*line || *line == '\n') ++ { ++ as_bad (_("rpt pseudo-op requires 1 operand")); ++ goto done; ++ } ++ ++ memset (&op, 0, sizeof (op)); ++ operand = get_operand (); ++ ++ if (msp430_srcoperand(&op, operand, &imm_op, 1, 15) != 0) ++ goto done; ++ ++ if ( !(op.mode == OP_REG && op.am == 0) // Rn ++ && !(op.mode == OP_EXP && op.am == 3) // #N ++ ) ++ { ++ as_bad (_("rpt pseudo-op requires immediate or register operand")); ++ goto done; ++ } ++ ++ if (op.am == 0) // rpt Rn ++ msp430x_repeats = (((1 << 7) | op.reg) << 1) | 1; // last bit as .rpt flag ++ else // rpt #N ++ msp430x_repeats = ((op.exp.X_add_number - 1) << 1) | 1; // last bit as .rpt flag ++ ++ done: ++ if (operand) ++ xfree(operand); ++} + + /* Parse instruction operands. + Return binary opcode. */ + + static unsigned int +-msp430_operands (struct msp430_opcode_s * opcode, char * line) ++msp430_operands (struct msp430_opcode_s const * opcode, char * line) + { + int bin = opcode->bin_opcode; /* Opcode mask. */ + int __is = 0; +- char l1[MAX_OP_LEN], l2[MAX_OP_LEN]; +- char *frag; +- int where; ++ char *l1 = 0; ++ char *l2 = 0; ++ char *frag = 0; ++ int where = 0; + struct msp430_operand_s op1, op2; + int res = 0; + static short ZEROS = 0; +- int byte_op, imm_op; +- ++ int imm_op; ++ opwidth_t op_width = DEFAULT_OP; ++ + /* Opcode is the one from opcodes table + line contains something like + [.w] @r2+, 5(R1) + or +- .b @r2+, 5(R1). */ ++ .b @r2+, 5(R1) ++ or ++ .a @r2+, 5(R1) */ + + /* Check if byte or word operation. */ ++ + if (*line == '.' && TOLOWER (*(line + 1)) == 'b') + { +- bin |= BYTE_OPERATION; +- byte_op = 1; ++ op_width = BYTE_OP; ++ } ++ else if (*line == '.' && TOLOWER (*(line + 1)) == 'w') ++ { ++ op_width = WORD_OP; ++ } ++ else if (*line == '.' && TOLOWER (*(line + 1)) == 'a') ++ { ++ op_width = ADDR_OP; + } +- else +- byte_op = 0; + +- /* skip .[bwBW]. */ ++ if ((op_width == WORD_OP && !(opcode_modifier(opcode) & MOD_W)) ++ || (op_width == BYTE_OP && !(opcode_modifier(opcode) & MOD_B)) ++ || (op_width == ADDR_OP && !(opcode_modifier(opcode) & MOD_A)) ++ ) ++ { ++ static char* const modifier[] = { "", ".w", ".b", ".a" }; ++ as_bad (_("%s not allowed with %s instruction"), ++ modifier[op_width], opcode->name); ++ return 0; ++ } ++ ++ if ( opcode_format(opcode) == FMT_X_DOUBLE_OPERAND ++ || opcode_format(opcode) == FMT_X_SINGLE_OPERAND ++ || opcode_format(opcode) == FMT_X_EMULATED ++ ) ++ { ++ switch(op_width) ++ { ++ case DEFAULT_OP: ++ case WORD_OP: ++ bin |= NON_ADDR_OPERATION; ++ break; ++ case BYTE_OP: ++ bin |= NON_ADDR_OPERATION; ++ bin |= BYTE_OPERATION_X; ++ break; ++ case ADDR_OP: ++ bin |= BYTE_OPERATION_X; ++ break; ++ } ++ } ++ else ++ { ++ if(msp430x_repeats) ++ { ++ as_bad (_("%s instruction is not repeatable"), opcode->name); ++ return 0; ++ } ++ ++ if ( opcode_format(opcode) < FMT_X && op_width == BYTE_OP ) // 430 instructions ++ { ++ bin |= BYTE_OPERATION; ++ } ++ } ++ /* skip .[abwABW]. */ + while (! ISSPACE (*line) && *line) + line++; + +@@ -1416,29 +1787,29 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + return 0; + } + +- memset (l1, 0, sizeof (l1)); +- memset (l2, 0, sizeof (l2)); ++ input_line_pointer = line; ++ + memset (&op1, 0, sizeof (op1)); + memset (&op2, 0, sizeof (op2)); + + imm_op = 0; + +- switch (opcode->fmt) ++ switch (opcode_format(opcode)) + { +- case 0: /* Emulated. */ +- switch (opcode->insn_opnumb) ++ case FMT_EMULATED: /* Emulated. */ ++ switch (opcode_variant(opcode)) + { +- case 0: +- /* Set/clear bits instructions. */ ++ case V_NOOP: ++ /* Set/clear SR bits instructions, ret, nop */ + __is = 2; + frag = frag_more (__is); + bfd_putl16 ((bfd_vma) bin, frag); + dwarf2_emit_insn (__is); + break; +- case 1: ++ case V_NONE: + /* Something which works with destination operand. */ +- line = extract_operand (line, l1, sizeof (l1)); +- res = msp430_dstoperand (&op1, l1, opcode->bin_opcode); ++ l1 = get_operand (); ++ res = msp430_dstoperand (&op1, l1, -(1<<15), (1<<16) ); + if (res) + break; + +@@ -1463,14 +1834,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + +- case 2: ++ case V_SHIFT: + { + /* Shift instruction. */ +- line = extract_operand (line, l1, sizeof (l1)); +- strncpy (l2, l1, sizeof (l2)); +- l2[sizeof (l2) - 1] = '\0'; +- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); +- res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); ++ msp430_substitute_CG(&op1, 0); ++ res += msp430_dstoperand (&op2, l1, -(1<<15), (1<<16)); + + if (res) + break; /* An error occurred. All warnings were done before. */ +@@ -1498,7 +1868,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + + if (op2.mode == OP_EXP) + { +- imm_op = 0; ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &TONI and x(PC) = TONI ++ */ ++ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); ++ + bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); + + if (op2.reg) /* Not PC relative. */ +@@ -1510,16 +1885,20 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + } +- case 3: ++ case V_BR: + /* Branch instruction => mov dst, r0. */ +- line = extract_operand (line, l1, sizeof (l1)); +- +- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); ++ msp430_substitute_CG(&op1, 0); + if (res) + break; + +- byte_op = 0; +- imm_op = 0; ++ if (op1.mode == 1 && (op1.reg == 2 || op1.reg == 0)) ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &EDE and x(PC) = EDE ++ */ ++ imm_op = 0; + + bin |= ((op1.reg << 8) | (op1.am << 4)); + __is = 1 + op1.ol; +@@ -1544,11 +1923,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + +- case 1: /* Format 1, double operand. */ +- line = extract_operand (line, l1, sizeof (l1)); +- line = extract_operand (line, l2, sizeof (l2)); +- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); +- res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); ++ case FMT_DOUBLE_OPERAND: /* Format 1, double operand. */ ++ l1 = get_operand (); ++ l2 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); ++ msp430_substitute_CG(&op1, 0); ++ res += msp430_dstoperand (&op2, l2, -(1<<15), (1<<16)); + + if (res) + break; /* Error occurred. All warnings were done before. */ +@@ -1576,7 +1956,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + + if (op2.mode == OP_EXP) + { +- imm_op = 0; ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &TONI and x(PC) = TONI ++ */ ++ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); ++ + bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); + + if (op2.reg) /* Not PC relative. */ +@@ -1588,8 +1973,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + +- case 2: /* Single-operand mostly instr. */ +- if (opcode->insn_opnumb == 0) ++ case FMT_SINGLE_OPERAND: /* Single-operand mostly instr. */ ++ if (opcode_variant(opcode) == V_RETI) + { + /* reti instruction. */ + frag = frag_more (2); +@@ -1598,10 +1983,11 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + break; + } + +- line = extract_operand (line, l1, sizeof (l1)); +- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); + if (res) + break; /* Error in operand. */ ++ msp430_substitute_CG(&op1, erratum_applies(ERRATUM_CPU4) && (opcode->bin_opcode == 0x1200)); + + bin |= op1.reg | (op1.am << 4); + __is = 1 + op1.ol; +@@ -1623,8 +2009,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + +- case 3: /* Conditional jumps instructions. */ +- line = extract_operand (line, l1, sizeof (l1)); ++ case FMT_JUMP: /* Conditional jumps instructions. */ ++ l1 = get_operand (); + /* l1 is a label. */ + if (l1[0]) + { +@@ -1693,11 +2079,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + else if (*l1 == '$') + { + as_bad (_("instruction requires label sans '$'")); ++ break; + } + else + { + as_bad (_ + ("instruction requires label or value in range -511:512")); ++ break; + } + dwarf2_emit_insn (2 * __is); + break; +@@ -1709,14 +2097,14 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + } + break; + +- case 4: /* Extended jumps. */ ++ case FMT_EMULATED_POLYMORPH_JUMP: /* Extended jumps. */ + if (!msp430_enable_polys) + { + as_bad (_("polymorphs are not enabled. Use -mP option to enable.")); + break; + } + +- line = extract_operand (line, l1, sizeof (l1)); ++ l1 = get_operand (); + if (l1[0]) + { + char *m = l1; +@@ -1730,7 +2118,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + if (exp.X_op == O_symbol) + { + /* Relaxation required. */ +- struct rcodes_s rc = msp430_rcodes[opcode->insn_opnumb]; ++ struct rcodes_s rc = msp430_rcodes[opcode_variant(opcode)]; + + /* The parameter to dwarf2_emit_insn is actually the offset to the start + of the insn from the fix piece of instruction that was emitted. +@@ -1751,13 +2139,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + as_bad (_("instruction requires label")); + break; + +- case 5: /* Emulated extended branches. */ ++ case FMT_EMULATED_LONG_POLYMORPH_JUMP: /* Emulated extended branches. */ + if (!msp430_enable_polys) + { + as_bad (_("polymorphs are not enabled. Use -mP option to enable.")); + break; + } +- line = extract_operand (line, l1, sizeof (l1)); ++ l1 = get_operand (); + if (l1[0]) + { + char * m = l1; +@@ -1771,7 +2159,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + if (exp.X_op == O_symbol) + { + /* Relaxation required. */ +- struct hcodes_s hc = msp430_hcodes[opcode->insn_opnumb]; ++ struct hcodes_s hc = msp430_hcodes[opcode_variant(opcode)]; + + frag = frag_more (8); + dwarf2_emit_insn (0); +@@ -1790,42 +2178,716 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) + as_bad (_("instruction requires label")); + break; + ++ case FMT_X_DOUBLE_OPERAND: /* Extended Format 1 ( double operand). */ ++ l1 = get_operand (); ++ l2 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ msp430_substitute_CG(&op1, 0); ++ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); ++ ++ if (res) ++ break; /* Error occurred. All warnings were done before. */ ++ ++ if (msp430x_repeats) ++ { ++ if (op1.mode != OP_REG || op2.mode != OP_REG) ++ { ++ as_bad(_("Repeated instruction must have register mode operands")); ++ break; ++ } ++ bin |= msp430x_repeats >> 1; ++ msp430x_repeats = 0; ++ } ++ ++ bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)) << 16; ++ ++ __is = 2 + op1.ol + op2.ol; /* insn size in words, opcode is 2 words wide. */ ++ frag = frag_more (2 * __is); ++ where = frag - frag_now->fr_literal; ++ bfd_putl32 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2 * __is); ++ ++ if (op1.mode == OP_EXP) ++ { ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); ++ ++ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_SRC); ++ else ++ fix_new_exp (frag_now, where , 2, ++ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_SRC); ++ } ++ ++ if (op2.mode == OP_EXP) ++ { ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &TONI and x(PC) = TONI ++ */ ++ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4 + ((__is == 4) ? 2 : 0)); ++ ++ if (op1.mode == OP_EXP) ++ { ++ if (op2.reg) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST_2ND); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST_2ND); ++ } ++ else ++ { ++ if (op2.reg) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); ++ } ++ } ++ break; ++ ++ case FMT_X_SINGLE_OPERAND: /* Extended format 2 (single-operand). */ ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ msp430_substitute_CG(&op1, 0); ++ if (res) ++ break; /* Error in operand. */ ++ ++ if (opcode_variant(opcode) != V_PUSHX && op1.mode == OP_EXP && op1.am == 3) // #N ++ { ++ as_bad (_("bad operand [%s]"), l1); ++ break; ++ } ++ ++ if (msp430x_repeats) ++ { ++ if (op1.mode != OP_REG) ++ { ++ as_bad(_("Repeated instruction must have register mode operand")); ++ break; ++ } ++ bin |= msp430x_repeats >> 1; ++ msp430x_repeats = 0; ++ } ++ ++ if(opcode_variant(opcode) == V_SWPSXT && op_width == ADDR_OP) ++ { // sxtx.a | swpbx.a opcode ++ bin ^= BYTE_OPERATION_X; ++ } ++ ++ bin |= (op1.reg | (op1.am << 4)) << 16; ++ __is = 2 + op1.ol; /* insn size in words, opcode is 2 words wide. */ ++ frag = frag_more (2 * __is); ++ where = frag - frag_now->fr_literal; ++ bfd_putl32 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2 * __is); ++ ++ if (op1.mode == OP_EXP) ++ { ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); ++ ++ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_DST); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); ++ } ++ break; ++ ++ case FMT_X_EXCEPTION: ++ /* calla, pushm, popm, rrcm, rrum, rram, rlam */ ++ bin = opcode->bin_opcode; // remove WB/AL bits ++ l1 = get_operand (); ++ switch(opcode_variant(opcode)) ++ { ++ case V_CALLA: // calla ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ if (res) ++ break; /* Error in operand. */ ++ __is = 1 + op1.ol; ++ frag = frag_more(__is * 2); ++ ++ if (op1.mode == OP_REG) ++ { ++ bin |= op1.reg; ++ switch (op1.am) ++ { ++ case 0: // Rdst ++ bin |= 0x0040; ++ break; ++ case 2: // @Rdst ++ bin |= 0x0060; ++ break; ++ case 3: // @Rdst+ ++ bin |= 0x0070; ++ break; ++ } ++ bin |= op1.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_EXP) ++ { ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ where = frag - frag_now->fr_literal; ++ switch (op1.am) ++ { ++ case 1: ++ switch(op1.reg) ++ { ++ case 0: // x(PC) = EDE ++ bin |= 0x0090; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), TRUE, BFD_RELOC_MSP430X_PCREL_D); ++ break; ++ case 2: // &abs20 ++ bin |= 0x0080; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_D); ++ break; ++ default: //z16(Rdst) ++ bin |= 0x0050 | op1.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); ++ break; ++ } ++ break; ++ case 3: // calla #imm ++ bin |= 0x00b0; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_D); ++ break; ++ } ++ dwarf2_emit_insn (__is * 2); ++ } ++ break; ++ case V_ROTM: // rxxm ++ l2 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, 1, 5); ++ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); ++ if(res) ++ break; /* An error occurred. All warnings were done before. */ ++ ++ if(op_width != ADDR_OP) ++ bin |= (1 << 4); ++ ++ if(op1.mode != OP_EXP || op1.am != 3) // not #imm ++ { ++ as_bad (_("bad operand [%s]"), l1); ++ break; ++ } ++ ++ bin |= ((op1.exp.X_add_number - 1) & 0x0003) << 10; ++ ++ if(op2.mode != OP_REG) ++ { ++ as_bad (_("bad operand [%s]"), l2); ++ break; ++ } ++ bin |= op2.reg; ++ ++ frag = frag_more (2); ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2); ++ break; ++ case V_PUSHM: ++ case V_POPM: ++ l2 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, 1, 17); ++ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); ++ if(res) ++ break; /* An error occurred. All warnings were done before. */ ++ ++ ++ if(imm_op == 0) ++ { ++ as_bad (_("bad operand [%s]"), l1); ++ break; ++ } ++ ++ if(op_width != ADDR_OP) ++ { ++ bin |= (1 << 8); ++ } ++ bin |= ((op1.exp.X_add_number - 1) & 0x000F) << 4; ++ ++ if(op2.mode != OP_REG) ++ { ++ as_bad (_("bad operand [%s]"), l2); ++ break; ++ } ++ if(opcode_variant(opcode) == V_POPM) ++ { ++ /* popm */ ++ bin |= (op2.reg - op1.exp.X_add_number + 1) & 0x000F; ++ } ++ else ++ { ++ /* pushm */ ++ bin |= op2.reg; ++ } ++ ++ frag = frag_more (2); ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2); ++ break; ++ } ++ break; ++ case FMT_X_ADDRESS: ++ /* mova, adda, suba, cmpa */ ++ l1 = get_operand (); ++ l2 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); ++ if (res) ++ break; /* Error in operand. */ ++ ++ __is = 1 + op1.ol + op2.ol; ++ frag = frag_more(__is * 2); ++ where = frag - frag_now->fr_literal; ++ bin = opcode->bin_opcode; // remove WB/AL bits ++ if( opcode_variant(opcode) == V_MOVA) ++ { ++ if (op1.mode == OP_REG && op1.am == 0) ++ { // Rsrc ++ if(op2.mode == OP_REG && op2.am == 0) ++ { ++ // mova Rsrc, Rdst ++ bin |= 0x00c0 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if(op2.mode == OP_EXP && op2.am == 1 && op2.reg == 2) ++ { ++ // mova Rsrc, &abs20 ++ bin |= 0x0060 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, BFD_RELOC_MSP430X_D); ++ } ++ else if(op2.mode == OP_EXP && op2.am == 1 && op2.reg == 0) ++ { ++ bin |= 0x0070 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, BFD_RELOC_MSP430X_PCREL_D); ++ } ++ else if(op2.mode == OP_EXP && op2.am == 1) ++ { ++ // mova Rsrc, z16(Rdst) ++ bin |= 0x0070 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ if(op2.reg == 0) ++ // mova Rsrc, TONI == mova Rsrc, z16(PC) ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, BFD_RELOC_MSP430X_PCREL_INDXD); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, BFD_RELOC_MSP430X_INDXD); ++ } ++ else ++ as_bad (_("destination operand address mode not allowed with mova instruction")); ++ ++ } ++ else if (op2.mode == OP_REG && op2.am == 0) ++ { // Rdst ++ if(op1.mode == OP_REG && op1.am == 2) ++ { ++ // mova @Rsrc, Rdst ++ bin |= 0x0000 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_REG && op1.am == 3) ++ { ++ // mova @Rsrc+, Rdst ++ bin |= 0x0010 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_EXP && op1.am == 1 && op1.reg == 2) ++ { ++ if (op1.reg == 2) ++ { ++ // mova &abs20, Rdst ++ bin |= 0x0020 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); ++ } ++ else ++ { ++ // mova z16(Rsrc), Rdst ++ bin |= 0x0030 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ if (op1.reg == 0) ++ // mova TONI, Rdst ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_PCREL_INDXD); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); ++ } ++ } ++ else if (op1.mode == OP_EXP && op1.am == 3) ++ { ++ // mova #imm20, Rdst ++ bin |= 0x0080 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ if (op2.reg == 0) ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S_BYTE); ++ } ++ else ++ as_bad (_("source operand address mode not allowed with mova instruction")); ++ } ++ break; ++ } ++ else ++ /* adda, suba, cmpa */ ++ { ++ if(op2.mode == OP_REG && op2.am == 0) ++ { ++ if (op1.mode == OP_REG && op1.am == 0) ++ { // Rsrc, Rdst ++ bin |= 0x0040 | op1.reg << 8 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_EXP && op1.am == 3) ++ { ++ // #imm20, Rdst ++ bin |= 0x0080 | op2.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ if (op2.reg == 0) ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S_BYTE); ++ } ++ else ++ as_bad (_("source operand address mode not allowed with %s instruction"), opcode->name); ++ } ++ else ++ as_bad (_("destination operand address mode not allowed with %s instruction"), opcode->name); ++ break; ++ } ++ break; ++ ++ case FMT_X_EMULATED: /* Extended emulated. */ ++ switch (opcode_variant(opcode)) ++ { ++ case V_NONE: ++ /* single operand instruction emulated with Extended type 1 (double operand) instructions. */ ++ l1 = get_operand (); ++ res = msp430_dstoperand (&op1, l1, -(1<<19), (1<<20) ); ++ if (res) ++ break; ++ ++ if (msp430x_repeats) ++ { ++ if ((bin >> 20) && 0x3 == 1) ++ { ++ as_bad (_("%s instruction is not repeatable"), opcode->name); ++ break; ++ } ++ if (op1.mode != OP_REG) ++ { ++ as_bad(_("Repeated instruction must have register mode operand")); ++ break; ++ } ++ bin |= msp430x_repeats >> 1; ++ msp430x_repeats = 0; ++ } ++ ++ bin |= (op1.reg | (op1.am << 7)) << 16; ++ __is = 2 + op1.ol; ++ frag = frag_more (2 * __is); ++ where = frag - frag_now->fr_literal; ++ bfd_putl32 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2 * __is); ++ ++ if (op1.mode == OP_EXP) ++ { ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &TONI and x(PC) = TONI ++ */ ++ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); ++ ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); ++ if (op1.reg || (op1.reg == 0 && op1.am == 3)) ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_DST); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); ++ } ++ break; ++ case V_X_SHIFT: ++ { ++ /* Shift instruction. */ ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ msp430_substitute_CG(&op1, 0); ++ res += msp430_dstoperand (&op2, l1, -(1<<19), (1<<20)); ++ ++ if (res) ++ break; /* An error occurred. All warnings were done before. */ ++ ++ if (msp430x_repeats) ++ { ++ if (op2.mode != OP_REG) ++ { ++ as_bad(_("Repeated instruction must have register mode operands")); ++ break; ++ } ++ bin |= msp430x_repeats >> 1; ++ msp430x_repeats = 0; ++ } ++ ++ bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)) << 16; ++ ++ __is = 2 + op1.ol + op2.ol; /* insn size in words. */ ++ frag = frag_more (2 * __is); ++ where = frag - frag_now->fr_literal; ++ bfd_putl32 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2 * __is); ++ ++ if (op1.mode == OP_EXP) ++ { ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); ++ ++ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_SRC); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_SRC); ++ } ++ ++ if (op2.mode == OP_EXP) ++ { ++ /* ++ x(Rn). x can be odd in non-byte operations ++ except x(R2) = x(0) = &TONI and x(PC) = TONI ++ */ ++ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); ++ ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 4 + ((__is == 4) ? 2 : 0)); ++ if (op1.mode == OP_EXP) ++ { ++ ++ if (op2.reg) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST_2ND); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST_2ND); ++ } ++ else ++ { ++ ++ if (op2.reg) /* Not PC relative. */ ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); ++ } ++ } ++ } ++ break; ++ case V_RETA: ++ /* reta */ ++ if (msp430x_repeats) ++ { ++ as_bad (_("%s instruction is not repeatable"), opcode->name); ++ break; ++ } ++ bin = opcode->bin_opcode; // remove WB/AL bits ++ frag = frag_more (2); ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2); ++ break; ++ case V_EMU_ADDR: // incda, decda, tsta ++ if (msp430x_repeats) ++ { ++ as_bad (_("%s instruction is not repeatable"), opcode->name); ++ break; ++ } ++ bin = opcode->bin_opcode; // remove WB/AL bits ++ l1 = get_operand (); ++ res = msp430_dstoperand (&op1, l1, -(1<<19), (1<<20) ); ++ if (res) ++ break; ++ ++ if(op1.mode == OP_REG && op1.am == 0) ++ { ++ frag = frag_more(2); ++ bin |= op1.reg; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (2); ++ } ++ else ++ as_bad (_("destination operand address mode not allowed with %s instruction"), opcode->name); ++ break; ++ case V_BRA: // bra, emulated with Address type instruction ++ if (msp430x_repeats) ++ { ++ as_bad (_("%s instruction is not repeatable"), opcode->name); ++ break; ++ } ++ ++ bin = opcode->bin_opcode; // remove WB/AL bits ++ l1 = get_operand (); ++ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); ++ if (res) ++ break; /* Error in operand. */ ++ ++ __is = 1 + op1.ol; ++ frag = frag_more(__is * 2); ++ where = frag - frag_now->fr_literal; ++ if (op1.mode == OP_REG && op1.am == 0) ++ { ++ // mova Rsrc, PC ++ bin |= 0x00C0 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if(op1.mode == OP_REG && op1.am == 2) ++ { ++ // mova @Rsrc, PC ++ bin |= 0x0000 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_REG && op1.am == 3) ++ { ++ // mova @Rsrc+, PC ++ bin |= 0x0010 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ } ++ else if (op1.mode == OP_EXP && op1.am == 1) ++ { ++ if (op1.reg == 2) ++ { ++ // mova &abs20, PC ++ bin |= 0x0020; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); ++ } ++ else ++ { ++ // mova z16(Rsrc), PC ++ bin |= 0x0030 | op1.reg << 8; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ if (op1.reg == 0) ++ // mova z16(PC), PC = mova TONI, PC ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), TRUE, BFD_RELOC_MSP430X_PCREL_INDXD); ++ else ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); ++ } ++ } ++ else if (op1.mode == OP_EXP && op1.am == 3) ++ { ++ // mova #imm20, Rdst ++ bin |= 0x0080; ++ bfd_putl16 ((bfd_vma) bin, frag); ++ dwarf2_emit_insn (__is * 2); ++ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); ++ fix_new_exp (frag_now, where, 2, ++ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); ++ } ++ else ++ as_bad (_("source operand address mode not allowed with bra instruction")); ++ } ++ break; ++ + default: + as_bad (_("Illegal instruction or not implemented opcode.")); + } + +- input_line_pointer = line; ++ if (l1) ++ xfree(l1); ++ if (l2) ++ xfree(l2); ++ + return 0; + } + + void + md_assemble (char * str) + { +- struct msp430_opcode_s * opcode; +- char cmd[32]; +- unsigned int i = 0; +- +- str = skip_space (str); /* Skip leading spaces. */ +- str = extract_cmd (str, cmd, sizeof (cmd)); +- +- while (cmd[i] && i < sizeof (cmd)) +- { +- char a = TOLOWER (cmd[i]); +- cmd[i] = a; +- i++; +- } +- +- if (!cmd[0]) ++ struct msp430_opcode_s const * opcode; ++ char* cmda; ++ char* cmd; ++ int i = 0; ++ int cmd_length; ++ ++ while (ISSPACE (*str)) ++ ++str; ++ cmd = str; ++ while (*str && (! ISSPACE (*str)) && '.' != *str) ++ ++str; ++ cmd_length = str - cmd; ++ if (0 == cmd_length) + { + as_bad (_("can't find opcode ")); + return; + } + +- opcode = (struct msp430_opcode_s *) hash_find (msp430_hash, cmd); ++ cmda = alloca(1+cmd_length); ++ do { ++ cmda[i] = TOLOWER(cmd[i]); ++ } while (++i < cmd_length); ++ cmda[i] = 0; ++ ++ opcode = (struct msp430_opcode_s const *) hash_find (msp430_hash, cmda); + + if (opcode == NULL) + { +- as_bad (_("unknown opcode `%s'"), cmd); ++ as_bad (_("unknown opcode `%s'"), cmda); ++ return; ++ } ++ ++ if (msp430_cpu < MSP430_CPU_MSP430X && opcode_format(opcode) >= FMT_X) ++ { ++ as_bad (_("Extended instruction (%s) requires 430X-based mcu"), opcode->name); + return; + } + +@@ -1963,6 +3025,26 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) + + switch (fixp->fx_r_type) + { ++ case BFD_RELOC_MSP430X_PCREL_D: ++ case BFD_RELOC_MSP430X_PCREL_INDXD: ++ value -= 2; // operand located 2 bytes after opcode ++ break; ++ case BFD_RELOC_MSP430X_PCREL_SRC: ++ case BFD_RELOC_MSP430X_PCREL_SRC_BYTE: ++ case BFD_RELOC_MSP430X_PCREL_DST: ++ case BFD_RELOC_MSP430X_PCREL_DST_BYTE: ++ value -= 4; // operand located 4 bytes after opcode ++ break; ++ case BFD_RELOC_MSP430X_PCREL_DST_2ND: ++ case BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE: ++ value -= 6; // operand located 6 bytes after opcode ++ break; ++ default: ++ break; ++ } ++ ++ switch (fixp->fx_r_type) ++ { + case BFD_RELOC_MSP430_10_PCREL: + if (value & 1) + as_bad_where (fixp->fx_file, fixp->fx_line, +@@ -1987,7 +3069,7 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) + _("odd address operand: %ld"), value); + + /* Nothing to be corrected here. */ +- if (value < -32768 || value > 65536) ++ if (value < -32768 || value > 65535) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("operand out of range: %ld"), value); + +@@ -1997,7 +3079,7 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) + + case BFD_RELOC_MSP430_16_PCREL_BYTE: + /* Nothing to be corrected here. */ +- if (value < -32768 || value > 65536) ++ if (value < -32768 || value > 65535) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("operand out of range: %ld"), value); + +@@ -2016,6 +3098,76 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) + bfd_putl16 ((bfd_vma) value, where); + break; + ++ case BFD_RELOC_MSP430X_SRC: ++ case BFD_RELOC_MSP430X_PCREL_SRC: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_SRC_BYTE: ++ case BFD_RELOC_MSP430X_PCREL_SRC_BYTE: ++ value &= 0xfffff; ++ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xf87f) | ((value >> 9) & 0x0780), where); ++ /* 16 least-significant bits */ ++ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 4); ++ break; ++ case BFD_RELOC_MSP430X_DST: ++ case BFD_RELOC_MSP430X_PCREL_DST: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_DST_BYTE: ++ case BFD_RELOC_MSP430X_PCREL_DST_BYTE: ++ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); ++ /* 16 least-significant bits */ ++ value &= 0xfffff; ++ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 4); ++ break; ++ case BFD_RELOC_MSP430X_DST_2ND: ++ case BFD_RELOC_MSP430X_PCREL_DST_2ND: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_DST_2ND_BYTE: ++ case BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE: ++ value &= 0xfffff; ++ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); ++ /* 16 least-significant bits */ ++ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 6); ++ break; ++ case BFD_RELOC_MSP430X_S: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_S_BYTE: ++ value &= 0xfffff; ++ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xf0ff) | ((value >> 8) & 0x0f00), where); ++ /* 16 least-significant bits */ ++ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 2); ++ break; ++ case BFD_RELOC_MSP430X_D: ++ case BFD_RELOC_MSP430X_PCREL_D: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_D_BYTE: ++ value &= 0xfffff; ++ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); ++ /* 16 least-significant bits */ ++ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 2); ++ break; ++ case BFD_RELOC_MSP430X_PCREL_INDXD: ++ if (value & 1) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("odd operand: %ld"), value); ++ case BFD_RELOC_MSP430X_INDXD: ++ if (value < -32768 || value > 65535) ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("operand out of range: %ld"), value); ++ ++ value &= 0xffff; /* Get rid of extended sign. */ ++ bfd_putl16 ((bfd_vma) value, where + 2); ++ break; ++ + default: + as_fatal (_("line %d: unknown relocation type: 0x%x"), + fixp->fx_line, fixp->fx_r_type); +diff --git a/gas/testsuite/gas/msp430/opcode.d b/gas/testsuite/gas/msp430/opcode.d +index 22df51c..297d3e1 100644 +--- a/gas/testsuite/gas/msp430/opcode.d ++++ b/gas/testsuite/gas/msp430/opcode.d +@@ -5,41 +5,49 @@ + + Disassembly of section .text: + 0+000 <[^>]*> 1b f3 and #1, r11 ;r3 As==01 +-0+002 <[^>]*> 3a e3 inv r10 ; ++0+002 <[^>]*> 3a e3 inv r10 + 0+004 <[^>]*> 3b e0 ff 00 xor #255, r11 ;#0x00ff + 0+008 <[^>]*> 3c d2 bis #8, r12 ;r2 As==11 + 0+00a <[^>]*> 3d b0 10 00 bit #16, r13 ;#0x0010 + 0+00e <[^>]*> 3e c0 a0 00 bic #160, r14 ;#0x00a0 +-0+012 <[^>]*> 0f 93 cmp #0, r15 ;r3 As==00 +-0+014 <[^>]*> 1a 83 dec r10 ; +-0+016 <[^>]*> 0b 73 sbc r11 ; +-0+018 <[^>]*> 1c 53 inc r12 ; ++0+012 <[^>]*> 0f 93 tst r15 ++0+014 <[^>]*> 1a 83 dec r10 ++0+016 <[^>]*> 0b 73 sbc r11 ++0+018 <[^>]*> 1c 53 inc r12 + 0+01a <[^>]*> 2d 63 addc #2, r13 ;r3 As==10 +-0+01c <[^>]*> 0e 12 push r14 ; +-0+01e <[^>]*> 3f 41 pop r15 ; +-0+020 <[^>]*> 8a 11 sxt r10 ; +-0+022 <[^>]*> 0b 11 rra r11 ; +-0+024 <[^>]*> 8c 10 swpb r12 ; +-0+026 <[^>]*> 0d 10 rrc r13 ; ++0+01c <[^>]*> 0e 12 push r14 ++0+01e <[^>]*> 3f 41 pop r15 ++0+020 <[^>]*> 8a 11 sxt r10 ++0+022 <[^>]*> 0b 11 rra r11 ++0+024 <[^>]*> 8c 10 swpb r12 ++0+026 <[^>]*> 0d 10 rrc r13 + 0+028 <[^>]*> 30 41 ret + 0+02a <[^>]*> 31 40 00 00 mov #0, r1 ;#0x0000 +-0+02e <[^>]*> b0 12 00 00 call #0 ;#0x0000 +-0+032 <[^>]*> 1e 42 00 00 mov &0x0000,r14 ;0x0000 +-0+036 <[^>]*> 0f 4e mov r14, r15 ; +-0+038 <[^>]*> 0f 5f rla r15 ; +-0+03a <[^>]*> 0f 7f subc r15, r15 ; +-0+03c <[^>]*> 3f e3 inv r15 ; +-0+03e <[^>]*> b0 12 00 00 call #0 ;#0x0000 +-0+042 <[^>]*> 82 4e 00 00 mov r14, &0x0000 ; +-0+046 <[^>]*> 82 4f 00 00 mov r15, &0x0000 ; +-0+04a <[^>]*> 1e 42 00 00 mov &0x0000,r14 ;0x0000 +-0+04e <[^>]*> 0f 4e mov r14, r15 ; +-0+050 <[^>]*> 0f 5f rla r15 ; +-0+052 <[^>]*> 0f 7f subc r15, r15 ; +-0+054 <[^>]*> 3f e3 inv r15 ; +-0+056 <[^>]*> b0 12 00 00 call #0 ;#0x0000 +-0+05a <[^>]*> 82 4e 00 00 mov r14, &0x0000 ; +-0+05e <[^>]*> 82 4f 00 00 mov r15, &0x0000 ; ++0+02e <[^>]*> b0 12 00 00 call #0x0000 ++0+032 <[^>]*> 1e 42 00 00 mov &0x0000,r14 ++0+036 <[^>]*> 0f 4e mov r14, r15 ++0+038 <[^>]*> 0f 5f rla r15 ++0+03a <[^>]*> 0f 7f subc r15, r15 ++0+03c <[^>]*> 3f e3 inv r15 ++0+03e <[^>]*> b0 12 00 00 call #0x0000 ++0+042 <[^>]*> 82 4e 00 00 mov r14, &0x0000 ++0+046 <[^>]*> 82 4f 00 00 mov r15, &0x0000 ++0+04a <[^>]*> 1e 42 00 00 mov &0x0000,r14 ++0+04e <[^>]*> 0f 4e mov r14, r15 ++0+050 <[^>]*> 0f 5f rla r15 ++0+052 <[^>]*> 0f 7f subc r15, r15 ++0+054 <[^>]*> 3f e3 inv r15 ++0+056 <[^>]*> b0 12 00 00 call #0x0000 ++0+05a <[^>]*> 82 4e 00 00 mov r14, &0x0000 ++0+05e <[^>]*> 82 4f 00 00 mov r15, &0x0000 + 0+062 <[^>]*> 3f 40 f0 00 mov #240, r15 ;#0x00f0 +-0+066 <[^>]*> 30 40 00 00 br #0x0000 ; +-0+06a <[^>]*> 92 52 00 02 72 01 add &0x0200,&0x0172 ;0x0200 ++0+066 <[^>]*> 30 40 00 00 br #0x0000 ++0+06a <[^>]*> 92 52 00 02 72 01 add &0x0200,&0x0172 ++0+070 3a 40 f0 de mov #-8464, r10 ;#0xdef0 ++0+074 3b 40 bc 9a mov #-25924,r11 ;#0x9abc ++0+078 3c 40 78 56 mov #22136, r12 ;#0x5678 ++0+07c 3d 40 34 12 mov #4660, r13 ;#0x1234 ++0+080 3a 40 7b 00 mov #123, r10 ;#0x007b ++0+084 0b 43 clr r11 ++0+086 0c 43 clr r12 ++0+088 0d 43 clr r13 +diff --git a/gas/testsuite/gas/msp430/opcode.s b/gas/testsuite/gas/msp430/opcode.s +index b85a463..8fa444f 100644 +--- a/gas/testsuite/gas/msp430/opcode.s ++++ b/gas/testsuite/gas/msp430/opcode.s +@@ -55,3 +55,19 @@ main: + ;; This next instruction triggered a bug which + ;; was fixed by a patch to msp430-dis.c on Jan 2, 2004 + add &0x200, &0x172 ++ ++.global extract ++ .type extract,@function ++extract: ++ mov #llo(0x123456789abcdef0), r10 ++ mov #lhi(0x123456789abcdef0), r11 ++ mov #hlo(0x123456789abcdef0), r12 ++ mov #hhi(0x123456789abcdef0), r13 ++ ++.global extract0 ++ .type extract,@function ++extract0: ++ mov #llo(123), r10 ++ mov #lhi(123), r11 ++ mov #hlo(123), r12 ++ mov #hhi(123), r13 +diff --git a/include/elf/msp430.h b/include/elf/msp430.h +index 44f5c51..1eeb56b 100644 +--- a/include/elf/msp430.h ++++ b/include/elf/msp430.h +@@ -23,24 +23,6 @@ + + #include "elf/reloc-macros.h" + +-/* Processor specific flags for the ELF header e_flags field. */ +-#define EF_MSP430_MACH 0xff +- +-#define E_MSP430_MACH_MSP430x11 11 +-#define E_MSP430_MACH_MSP430x11x1 110 +-#define E_MSP430_MACH_MSP430x12 12 +-#define E_MSP430_MACH_MSP430x13 13 +-#define E_MSP430_MACH_MSP430x14 14 +-#define E_MSP430_MACH_MSP430x15 15 +-#define E_MSP430_MACH_MSP430x16 16 +-#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_MSP430x42 42 +-#define E_MSP430_MACH_MSP430x43 43 +-#define E_MSP430_MACH_MSP430x44 44 +- + /* Relocations. */ + START_RELOC_NUMBERS (elf_msp430_reloc_type) + RELOC_NUMBER (R_MSP430_NONE, 0) +@@ -52,7 +34,71 @@ START_RELOC_NUMBERS (elf_msp430_reloc_type) + RELOC_NUMBER (R_MSP430_16_PCREL_BYTE, 6) + RELOC_NUMBER (R_MSP430_2X_PCREL, 7) + RELOC_NUMBER (R_MSP430_RL_PCREL, 8) ++ RELOC_NUMBER (R_MSP430X_SRC_BYTE, 9) ++ RELOC_NUMBER (R_MSP430X_SRC, 10) ++ RELOC_NUMBER (R_MSP430X_DST_BYTE, 11) ++ RELOC_NUMBER (R_MSP430X_DST, 12) ++ RELOC_NUMBER (R_MSP430X_DST_2ND_BYTE, 13) ++ RELOC_NUMBER (R_MSP430X_DST_2ND, 14) ++ RELOC_NUMBER (R_MSP430X_PCREL_SRC_BYTE, 15) ++ RELOC_NUMBER (R_MSP430X_PCREL_SRC, 16) ++ RELOC_NUMBER (R_MSP430X_PCREL_DST_BYTE, 17) ++ RELOC_NUMBER (R_MSP430X_PCREL_DST, 18) ++ RELOC_NUMBER (R_MSP430X_PCREL_DST_2ND, 19) ++ RELOC_NUMBER (R_MSP430X_PCREL_DST_2ND_BYTE, 20) ++ RELOC_NUMBER (R_MSP430X_S_BYTE, 21) ++ RELOC_NUMBER (R_MSP430X_S, 22) ++ RELOC_NUMBER (R_MSP430X_D_BYTE, 23) ++ RELOC_NUMBER (R_MSP430X_D, 24) ++ RELOC_NUMBER (R_MSP430X_PCREL_D, 25) ++ RELOC_NUMBER (R_MSP430X_INDXD, 26) ++ RELOC_NUMBER (R_MSP430X_PCREL_INDXD, 27) + + END_RELOC_NUMBERS (R_MSP430_max) + ++/* TODO: Define a set of flags that are appropriate for storage in the e_flags field. ++ * Potential members include: ++ * - Whether CPUX instructions are present ++ * - Whether hardware multiply register references are present (which kind) ++ * - The code addressing mode ++ * - The data addressing mode ++ */ ++ ++/* Pre-uniarch versions of binutils stored machine types in the ++ * e_flags field, with values up to 471 decimal. Now we store the ++ * machine type in the e_mach field, and use e_flags to identify the ++ * characteristics of the code. ++ * ++ * Use the following flag to indicate that this object file uses the ++ * uniarch flag layout. */ ++#define EF_MSP430_UNIARCH 0x10000000 ++ ++#define EF_MSP430_ARCH_430 0x00000000 ++#define EF_MSP430_ARCH_430X 0x00000001 ++#define EF_MSP430_ARCH 0x000000FF ++#if 0 ++/* These are symbol-associated, not archive-associated, attributes. ++ * Not sure what to do with them. */ ++#define EF_MSP430_CPU_430 0x00000000 ++#define EF_MSP430_CPU_430X 0x00000200 ++#define EF_MSP430_CPU_430XV2 0x00000300 ++#define EF_MSP430_CPU 0x00000300 ++#define EF_MSP430_MPY_NONE 0x00000000 ++#define EF_MSP430_MPY_16 0x00001000 ++#define EF_MSP430_MPY_16_SE (0x00008000 + EF_MSP430_MPY_16) ++#define EF_MSP430_MPY_32 0x00002000 ++#define EF_MSP430_MPY_32_DW (0x00008000 + EF_MSP430_MPY_32) ++#define EF_MSP430_MPY_CLASS 0x00003000 ++#define EF_MSP430_MPY 0x0000F000 ++#define EF_MSP430_CODE_NEAR 0x00010000 ++#define EF_MSP430_CODE_FAR 0x00020000 ++#define EF_MSP430_CODE_MIXED 0x00030000 ++#define EF_MSP430_CODE 0x00030000 ++#define EF_MSP430_DATA_NEAR 0x00040000 ++#define EF_MSP430_DATA_FAR 0x00080000 ++#define EF_MSP430_DATA_MIXED 0x000c0000 ++#define EF_MSP430_DATA 0x000c0000 ++#define EF_MSP430_A20 0x000F0000 ++#endif ++ + #endif /* _ELF_MSP430_H */ +diff --git a/include/opcode/msp430.h b/include/opcode/msp430.h +index d3bf130..c281a49 100644 +--- a/include/opcode/msp430.h ++++ b/include/opcode/msp430.h +@@ -26,7 +26,7 @@ struct msp430_operand_s + int ol; /* Operand length words. */ + int am; /* Addr mode. */ + int reg; /* Register. */ +- int mode; /* Pperand mode. */ ++ int mode; /* Operand mode. */ + #define OP_REG 0 + #define OP_EXP 1 + #ifndef DASM_SECTION +@@ -34,91 +34,252 @@ struct msp430_operand_s + #endif + }; + +-#define BYTE_OPERATION (1 << 6) /* Byte operation flag for all instructions. */ ++#define BYTE_OPERATION (1 << 6) /* Byte operation flag for 430 instructions. */ ++#define BYTE_OPERATION_X (1 << 22) /* Byte operation flag for 430x instructions. */ ++#define NON_ADDR_OPERATION (1 << 6) /* Address operation flag for 430x instructions. */ ++ ++typedef enum ++{ ++ DEFAULT_OP, // instruction has no modifier ++ WORD_OP, // .w ++ BYTE_OP, // .b ++ ADDR_OP // .a ++} ++opwidth_t; ++ ++/** Bit-markers for type of CPU present. */ ++typedef enum msp430_cpu_e ++{ ++ MSP430_CPU_MSP430 = 0x0000, ++ MSP430_CPU_MSP430X = 0x0002, ++ MSP430_CPU_MSP430XV2 = 0x0003, ++ MSP430_CPU = 0x0003, ++} msp430_cpu_e; ++ ++/** Bit-markers for type of hardware multiplier present. */ ++typedef enum msp430_mpy_e ++{ ++ MSP430_MPY_NONE = 0x0000, ++ MSP430_MPY_16 = 0x0010, ++ MSP430_MPY_16SE = 0x0011, ++ MSP430_MPY_32 = 0x0020, ++ MSP430_MPY_32DW = 0x0022, ++ MSP430_MPY = 0x0030 ++} msp430_mpy_e; ++ ++typedef enum ++{ ++ FMT_EMULATED = 0, ++ FMT_DOUBLE_OPERAND, ++ FMT_SINGLE_OPERAND, ++ FMT_JUMP, ++ FMT_EMULATED_POLYMORPH_JUMP, ++ FMT_EMULATED_LONG_POLYMORPH_JUMP, ++ FMT_X_DOUBLE_OPERAND, ++ FMT_X_SINGLE_OPERAND, ++ FMT_X_EXCEPTION, ++ FMT_X_EMULATED, ++ FMT_X_ADDRESS, ++ ++ FMT_X = FMT_X_DOUBLE_OPERAND, ++ FMT_MASK = 0x000f, ++ ++ /* allowed modifiers: .b, .w, .a */ ++ MOD_NONE = 0, ++ MOD_W = 1 << 4, ++ MOD_B = 1 << 5, ++ MOD_A = 1 << 6, ++ MOD_MASK = 0x0070, ++ ++ /* opcode variant */ ++ VAR_MASK = 0x0380, ++} ++format_t; ++ ++#define OP_V(x) (x << 7) + + struct msp430_opcode_s + { + char *name; +- int fmt; +- int insn_opnumb; +- int bin_opcode; +- int bin_mask; ++ format_t fmt; ++ unsigned int insn_opnumb; ++ unsigned int bin_opcode; ++ unsigned int bin_mask; + }; + +-#define MSP_INSN(name, size, numb, bin, mask) { #name, size, numb, bin, mask } ++#define opcode_format(opcode) (opcode->fmt & FMT_MASK) ++#define opcode_modifier(opcode) (opcode->fmt & MOD_MASK) ++#define opcode_variant(opcode) ((opcode->fmt & VAR_MASK) >> 7) ++ ++/* opcode variants: */ ++enum ++{ ++ V_NONE = 0, // ordinary instruction ++ ++ /* FMT_EMULATED: */ ++ V_NOOP, // no operands: set/clear bit instructions, reti ++ V_SHIFT, // shift instructions ++ V_BR, // br instruction ++ ++ /* FMT_SINGLE_OPERAND: */ ++ V_RETI = 1, // reti ++ V_CALL = 2, // hex operand in disassembly ++ ++ /* FMT_X_SINGLE_OPERAND: */ ++ // V_NONE - #N operand disallowed ++ V_SWPSXT = 1, // #N operand disallowed, special A/L, B/W bits case with .a modifier ++ V_PUSHX, // #N operand allowed + +-static struct msp430_opcode_s msp430_opcodes[] = ++ /* FMT_X_EXCEPTIONS: */ ++ V_CALLA = 0, // calla ++ V_ROTM, // two operands, rotations ++ V_POPM, // two operands, popm ++ V_PUSHM, // two operands, pushm ++ ++ /* FMT_X_EMULATED: */ ++ // V_NONE - substituted by 430x double operand instruction ++ V_X_SHIFT, // shifts ++ V_RETA, // reta, short instruction, no operands ++ V_EMU_ADDR, // substituted by address instruction other than mova ++ V_BRA, // bra, substituted by mova address instruction == format II exception instruction ++ // clra emulated by msp430 instruction ++ ++ /* FMT_X_ADDRESS: */ ++ V_MOVA = 1, // mova, more address modes allowed ++}; ++ ++#define MSP_INSN(name, format, opnumb, bin, mask) { #name, format, opnumb, bin, mask } ++ ++static struct msp430_opcode_s const 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), ++ MSP_INSN (and, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xf000, 0xfffff000), ++ MSP_INSN (inv, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0xe330, 0xfffffff0), ++ MSP_INSN (xor, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xe000, 0xfffff000), ++ MSP_INSN (setz, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd322, 0xffffffff), ++ MSP_INSN (setc, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd312, 0xffffffff), ++ MSP_INSN (eint, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd232, 0xffffffff), ++ MSP_INSN (setn, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd222, 0xffffffff), ++ MSP_INSN (bis, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xd000, 0xfffff000), ++ MSP_INSN (clrz, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc322, 0xffffffff), ++ MSP_INSN (clrc, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc312, 0xffffffff), ++ MSP_INSN (dint, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc232, 0xffffffff), ++ MSP_INSN (clrn, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc222, 0xffffffff), ++ MSP_INSN (bic, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xc000, 0xfffff000), ++ MSP_INSN (bit, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xb000, 0xfffff000), ++ MSP_INSN (dadc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0xa300, 0xffffff30), ++ MSP_INSN (dadd, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xa000, 0xfffff000), ++ MSP_INSN (tst, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x9300, 0xffffff30), ++ MSP_INSN (cmp, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x9000, 0xfffff000), ++ MSP_INSN (decd, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x8320, 0xffffff30), ++ MSP_INSN (dec, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x8310, 0xffffff30), ++ MSP_INSN (sub, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x8000, 0xfffff000), ++ MSP_INSN (sbc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x7300, 0xffffff30), ++ MSP_INSN (subc, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x7000, 0xfffff000), ++ MSP_INSN (adc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x6300, 0xffffff30), ++ MSP_INSN (rlc, FMT_EMULATED | MOD_W|MOD_B | OP_V(V_SHIFT), 2, 0x6000, 0xfffff000), ++ MSP_INSN (addc, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x6000, 0xfffff000), ++ MSP_INSN (incd, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x5320, 0xffffff30), ++ MSP_INSN (inc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x5310, 0xffffff30), ++ MSP_INSN (rla, FMT_EMULATED | MOD_W|MOD_B | OP_V(V_SHIFT), 2, 0x5000, 0xfffff000), ++ MSP_INSN (add, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x5000, 0xfffff000), ++ MSP_INSN (nop, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0x4303, 0xffffffff), ++ MSP_INSN (clr, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x4300, 0xffffff30), ++ MSP_INSN (clra, FMT_EMULATED | MOD_NONE | OP_V(0), 1, 0x4300, 0xffffff30), // MOV #0, Rdst ++ MSP_INSN (ret, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0x4130, 0xffffffff), ++ MSP_INSN (pop, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x4130, 0xffffff30), ++ MSP_INSN (br, FMT_EMULATED | MOD_NONE | OP_V(V_BR), 1, 0x4000, 0xfffff08f), ++ MSP_INSN (mov, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x4000, 0xfffff000), ++ ++ MSP_INSN (jmp, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3c00, 0xfffffc00), ++ MSP_INSN (jl, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3800, 0xfffffc00), ++ MSP_INSN (jge, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3400, 0xfffffc00), ++ MSP_INSN (jn, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3000, 0xfffffc00), ++ MSP_INSN (jc, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2c00, 0xfffffc00), ++ MSP_INSN (jhs, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2c00, 0xfffffc00), ++ MSP_INSN (jnc, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2800, 0xfffffc00), ++ MSP_INSN (jlo, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2800, 0xfffffc00), ++ MSP_INSN (jz, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2400, 0xfffffc00), ++ MSP_INSN (jeq, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2400, 0xfffffc00), ++ MSP_INSN (jnz, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2000, 0xfffffc00), ++ MSP_INSN (jne, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2000, 0xfffffc00), ++ ++ MSP_INSN (reti, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(V_RETI), 0, 0x1300, 0xffffffc0), ++ MSP_INSN (call, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(V_CALL), 1, 0x1280, 0xffffffc0), ++ MSP_INSN (push, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1200, 0xffffff80), ++ MSP_INSN (sxt, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(0), 1, 0x1180, 0xffffffc0), ++ MSP_INSN (rra, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1100, 0xffffff80), ++ MSP_INSN (swpb, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(0), 1, 0x1080, 0xffffffc0), ++ MSP_INSN (rrc, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1000, 0xffffff80), ++ ++ ++ /* emulated instructions placed just before instruction emulated by for disassembly search */ ++ MSP_INSN (popx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x41301800, 0xff30f800), // MOVX @SP+, dst ++ MSP_INSN (clrx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x43001800, 0xff30f800), // MOVX #0, dst ++ MSP_INSN (movx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x40001800, 0xf000f800), ++ MSP_INSN (incx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x53101800, 0xff30f800), // ADDX #1, dst ++ MSP_INSN (incdx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x53201800, 0xff30f800), // ADDX #2, dst ++ MSP_INSN (rlax, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(V_X_SHIFT), 1, 0x50001800, 0xf000f800), // ADDX dst, dst ++ MSP_INSN (addx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x50001800, 0xf000f800), ++ MSP_INSN (adcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x63001800, 0xff30f800), // ADDCX #0, dst ++ MSP_INSN (rlcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(V_X_SHIFT), 1, 0x60001800, 0xf000f800), // ADDCX dst, dst ++ MSP_INSN (addcx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x60001800, 0xf000f800), ++ MSP_INSN (sbcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x73001800, 0xff30f800), // SUBCX #0, dst ++ MSP_INSN (subcx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x70001800, 0xf000f800), ++ MSP_INSN (decx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x83101800, 0xff30f800), // SUBX #1, dst ++ MSP_INSN (decdx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x83201800, 0xff30f800), // SUBX #2, dst ++ MSP_INSN (subx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x80001800, 0xf000f800), ++ MSP_INSN (tstx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x93001800, 0xff30f800), // CMPX #0, dst ++ MSP_INSN (cmpx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x90001800, 0xf000f800), ++ MSP_INSN (dadcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0xa3001800, 0xff30f800), // DADDX #0, dst ++ MSP_INSN (daddx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xa0001800, 0xf000f800), ++ MSP_INSN (bitx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xb0001800, 0xf000f800), ++ MSP_INSN (bicx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xc0001800, 0xf000f800), ++ MSP_INSN (bisx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xd0001800, 0xf000f800), ++ MSP_INSN (invx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0xe3301800, 0xff30f800), // XORX #-1, dst ++ MSP_INSN (xorx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xe0001800, 0xf000f800), ++ MSP_INSN (andx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xf0001800, 0xf000f800), ++ ++ MSP_INSN (rrcx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x10001800, 0xff80f800), ++ MSP_INSN (swpbx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_A | OP_V(V_SWPSXT), 1, 0x10801800, 0xffc0f800), ++ MSP_INSN (rrax, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x11001800, 0xff80f800), ++ MSP_INSN (sxtx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_A | OP_V(V_SWPSXT), 1, 0x11801800, 0xffc0f800), ++ MSP_INSN (pushx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(V_PUSHX), 1, 0x12001800, 0xff80f800), ++ ++ MSP_INSN (calla, FMT_X_EXCEPTION | MOD_NONE | OP_V(V_CALLA), 1, 0x1300, 0xffffff00), ++ MSP_INSN (pushm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_PUSHM), 2, 0x1400, 0xfffffe00), ++ MSP_INSN (popm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_POPM), 2, 0x1600, 0xfffffe00), ++ MSP_INSN (rrcm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0040, 0xfffff3e0), ++ MSP_INSN (rram, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0140, 0xfffff3e0), ++ MSP_INSN (rlam, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0240, 0xfffff3e0), ++ MSP_INSN (rrum, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0340, 0xfffff3e0), ++ ++ /* Address. */ ++ MSP_INSN (incda, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03e0, 0xfffffff0), // ADDA #2, Rdst = ADDA R3, Rdst ++ MSP_INSN (adda, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x00a0, 0xfffff0b0), ++ MSP_INSN (tsta, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03d0, 0xfffffff0), // CMPA #0, Rdst = CMPA R3, Rdst ++ MSP_INSN (cmpa, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x0090, 0xfffff0b0), ++ MSP_INSN (decda, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03f0, 0xfffffff0), // SUBA #2, Rdst = SUBA R3, Rdst ++ MSP_INSN (suba, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x00b0, 0xfffff0b0), ++ MSP_INSN (reta, FMT_X_EMULATED | MOD_NONE | OP_V(V_RETA), 0, 0x0110, 0xffffffff), // MOVA @SP+, PC ++ MSP_INSN (bra, FMT_X_EMULATED | MOD_NONE | OP_V(V_BRA), 1, 0x0000, 0xfffff0cf), // MOVA dst, PC ++ MSP_INSN (bra, FMT_X_EMULATED | MOD_NONE | OP_V(V_BRA), 1, 0x0080, 0xfffff0bf), // MOVA #imm20, PC; MOVA Rsrc, Rdst ++ MSP_INSN (mova, FMT_X_ADDRESS | MOD_NONE | OP_V(V_MOVA), 1, 0x0000, 0xfffff000), ++ + /* Simple polymorphs. */ +- MSP_INSN (beq, 4, 0, 0, 0xffff), +- MSP_INSN (bne, 4, 1, 0, 0xffff), +- MSP_INSN (blt, 4, 2, 0, 0xffff), +- MSP_INSN (bltu, 4, 3, 0, 0xffff), +- MSP_INSN (bge, 4, 4, 0, 0xffff), +- MSP_INSN (bgeu, 4, 5, 0, 0xffff), +- MSP_INSN (bltn, 4, 6, 0, 0xffff), +- MSP_INSN (jump, 4, 7, 0, 0xffff), +- /* Long polymorphs. */ +- MSP_INSN (bgt, 5, 0, 0, 0xffff), +- MSP_INSN (bgtu, 5, 1, 0, 0xffff), +- MSP_INSN (bleu, 5, 2, 0, 0xffff), +- MSP_INSN (ble, 5, 3, 0, 0xffff), ++ MSP_INSN (beq, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(0), 1, 0, 0xffff), ++ MSP_INSN (bne, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(1), 1, 0, 0xffff), ++ MSP_INSN (blt, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(2), 1, 0, 0xffff), ++ MSP_INSN (bltu, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(3), 1, 0, 0xffff), ++ MSP_INSN (bge, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(4), 1, 0, 0xffff), ++ MSP_INSN (bgeu, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(5), 1, 0, 0xffff), ++ MSP_INSN (bltn, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(6), 1, 0, 0xffff), ++ MSP_INSN (jump, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(7), 1, 0, 0xffff), + ++ /* Long polymorphs. */ ++ MSP_INSN (bgt, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(0), 1, 0, 0xffff), ++ MSP_INSN (bgtu, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(1), 1, 0, 0xffff), ++ MSP_INSN (bleu, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(2), 1, 0, 0xffff), ++ MSP_INSN (ble, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(3), 1, 0, 0xffff), + /* End of instruction set. */ + { NULL, 0, 0, 0, 0 } + }; +diff --git a/ld/Makefile.am b/ld/Makefile.am +index 5ae86ba..2530b48 100644 +--- a/ld/Makefile.am ++++ b/ld/Makefile.am +@@ -335,65 +335,7 @@ ALL_EMULATION_SOURCES = \ + emipspe.c \ + emn10200.c \ + emn10300.c \ +- emsp430x110.c \ +- emsp430x1101.c \ +- emsp430x1111.c \ +- emsp430x112.c \ +- emsp430x1121.c \ +- emsp430x1122.c \ +- emsp430x1132.c \ +- emsp430x122.c \ +- emsp430x1222.c \ +- emsp430x123.c \ +- emsp430x1232.c \ +- emsp430x133.c \ +- emsp430x1331.c \ +- emsp430x135.c \ +- emsp430x1351.c \ +- emsp430x147.c \ +- emsp430x148.c \ +- emsp430x149.c \ +- emsp430x155.c \ +- emsp430x156.c \ +- emsp430x157.c \ +- emsp430x1610.c \ +- emsp430x1611.c \ +- emsp430x1612.c \ +- emsp430x167.c \ +- emsp430x168.c \ +- emsp430x169.c \ +- emsp430x2101.c \ +- emsp430x2111.c \ +- emsp430x2121.c \ +- emsp430x2131.c \ +- emsp430x311.c \ +- emsp430x312.c \ +- emsp430x313.c \ +- emsp430x314.c \ +- emsp430x315.c \ +- emsp430x323.c \ +- emsp430x325.c \ +- emsp430x336.c \ +- emsp430x337.c \ +- emsp430x412.c \ +- emsp430x413.c \ +- emsp430x415.c \ +- emsp430x417.c \ +- emsp430x435.c \ +- emsp430x436.c \ +- emsp430x437.c \ +- emsp430x447.c \ +- emsp430x448.c \ +- emsp430x449.c \ +- emsp430xE423.c \ +- emsp430xE425.c \ +- emsp430xE427.c \ +- emsp430xG437.c \ +- emsp430xG438.c \ +- emsp430xG439.c \ +- emsp430xW423.c \ +- emsp430xW425.c \ +- emsp430xW427.c \ ++ emsp430.c \ + enews.c \ + ens32knbsd.c \ + eor32.c \ +@@ -1436,242 +1378,10 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ + $(srcdir)/emulparams/mn10200.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} mn10300 "$(tdir_mn10300)" +-emsp430x110.c: $(srcdir)/emulparams/msp430all.sh \ ++emsp430.c: $(srcdir)/emulparams/msp430uni.sh \ + $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ + ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x110 "$(tdir_msp430x110)" msp430all +-emsp430x1101.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1101 "$(tdir_msp430x1101)" msp430all +-emsp430x1111.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1111 "$(tdir_msp430x1111)" msp430all +-emsp430x112.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x112 "$(tdir_msp430x112)" msp430all +-emsp430x1121.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1121 "$(tdir_msp430x1121)" msp430all +-emsp430x1122.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1122 "$(tdir_msp430x1122)" msp430all +-emsp430x1132.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1132 "$(tdir_msp430x1132)" msp430all +-emsp430x122.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x122 "$(tdir_msp430x122)" msp430all +-emsp430x1222.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1222 "$(tdir_msp430x1222)" msp430all +-emsp430x123.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x123 "$(tdir_msp430x123)" msp430all +-emsp430x1232.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1232 "$(tdir_msp430x1232)" msp430all +-emsp430x133.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x133 "$(tdir_msp430x133)" msp430all +-emsp430x1331.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1331 "$(tdir_msp430x1331)" msp430all +-emsp430x135.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x135 "$(tdir_msp430x135)" msp430all +-emsp430x1351.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1351 "$(tdir_msp430x1351)" msp430all +-emsp430x147.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x147 "$(tdir_msp430x147)" msp430all +-emsp430x148.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x148 "$(tdir_msp430x148)" msp430all +-emsp430x149.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x149 "$(tdir_msp430x149)" msp430all +-emsp430x155.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x155 "$(tdir_msp430x155)" msp430all +-emsp430x156.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x156 "$(tdir_msp430x156)" msp430all +-emsp430x157.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x157 "$(tdir_msp430x157)" msp430all +-emsp430x1610.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1610 "$(tdir_msp430x1610)" msp430all +-emsp430x1611.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1611 "$(tdir_msp430x1611)" msp430all +-emsp430x1612.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1612 "$(tdir_msp430x1612)" msp430all +-emsp430x167.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x167 "$(tdir_msp430x167)" msp430all +-emsp430x168.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x168 "$(tdir_msp430x168)" msp430all +-emsp430x169.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x169 "$(tdir_msp430x169)" msp430all +-emsp430x2101.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2101 "$(tdir_msp430x2101)" msp430all +-emsp430x2111.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2111 "$(tdir_msp430x2111)" msp430all +-emsp430x2121.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2121 "$(tdir_msp430x2121)" msp430all +-emsp430x2131.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2131 "$(tdir_msp430x2131)" msp430all +-emsp430x311.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x311 "$(tdir_msp430x311)" msp430all +-emsp430x312.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x312 "$(tdir_msp430x312)" msp430all +-emsp430x313.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x313 "$(tdir_msp430x313)" msp430all +-emsp430x314.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x314 "$(tdir_msp430x314)" msp430all +-emsp430x315.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x315 "$(tdir_msp430x315)" msp430all +-emsp430x323.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x323 "$(tdir_msp430x323)" msp430all +-emsp430x325.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x325 "$(tdir_msp430x325)" msp430all +-emsp430x336.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x336 "$(tdir_msp430x336)" msp430all +-emsp430x337.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x337 "$(tdir_msp430x337)" msp430all +-emsp430x412.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x412 "$(tdir_msp430x412)" msp430all +-emsp430x413.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x413 "$(tdir_msp430x413)" msp430all +-emsp430x415.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x415 "$(tdir_msp430x415)" msp430all +-emsp430x417.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x417 "$(tdir_msp430x417)" msp430all +-emsp430x435.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x435 "$(tdir_msp430x435)" msp430all +-emsp430x436.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x436 "$(tdir_msp430x436)" msp430all +-emsp430x437.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x437 "$(tdir_msp430x437)" msp430all +-emsp430x447.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x447 "$(tdir_msp430x447)" msp430all +-emsp430x448.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x448 "$(tdir_msp430x448)" msp430all +-emsp430x449.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x449 "$(tdir_msp430x449)" msp430all +-emsp430xE423.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE423 "$(tdir_msp430xE423)" msp430all +-emsp430xE425.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE425 "$(tdir_msp430xE425)" msp430all +-emsp430xE427.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE427 "$(tdir_msp430xE427)" msp430all +-emsp430xG437.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG437 "$(tdir_msp430xG437)" msp430all +-emsp430xG438.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG438 "$(tdir_msp430xG438)" msp430all +-emsp430xG439.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG439 "$(tdir_msp430xG439)" msp430all +-emsp430xW423.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW423 "$(tdir_msp430xW423)" msp430all +-emsp430xW425.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW425 "$(tdir_msp430xW425)" msp430all +-emsp430xW427.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW427 "$(tdir_msp430xW427)" msp430all ++ ${GENSCRIPTS} msp430 "$(tdir_msp430)" msp430uni + enews.c: $(srcdir)/emulparams/news.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} news "$(tdir_news)" +diff --git a/ld/Makefile.in b/ld/Makefile.in +index f062b92..ac63d29 100644 +--- a/ld/Makefile.in ++++ b/ld/Makefile.in +@@ -641,65 +641,7 @@ ALL_EMULATION_SOURCES = \ + emipspe.c \ + emn10200.c \ + emn10300.c \ +- emsp430x110.c \ +- emsp430x1101.c \ +- emsp430x1111.c \ +- emsp430x112.c \ +- emsp430x1121.c \ +- emsp430x1122.c \ +- emsp430x1132.c \ +- emsp430x122.c \ +- emsp430x1222.c \ +- emsp430x123.c \ +- emsp430x1232.c \ +- emsp430x133.c \ +- emsp430x1331.c \ +- emsp430x135.c \ +- emsp430x1351.c \ +- emsp430x147.c \ +- emsp430x148.c \ +- emsp430x149.c \ +- emsp430x155.c \ +- emsp430x156.c \ +- emsp430x157.c \ +- emsp430x1610.c \ +- emsp430x1611.c \ +- emsp430x1612.c \ +- emsp430x167.c \ +- emsp430x168.c \ +- emsp430x169.c \ +- emsp430x2101.c \ +- emsp430x2111.c \ +- emsp430x2121.c \ +- emsp430x2131.c \ +- emsp430x311.c \ +- emsp430x312.c \ +- emsp430x313.c \ +- emsp430x314.c \ +- emsp430x315.c \ +- emsp430x323.c \ +- emsp430x325.c \ +- emsp430x336.c \ +- emsp430x337.c \ +- emsp430x412.c \ +- emsp430x413.c \ +- emsp430x415.c \ +- emsp430x417.c \ +- emsp430x435.c \ +- emsp430x436.c \ +- emsp430x437.c \ +- emsp430x447.c \ +- emsp430x448.c \ +- emsp430x449.c \ +- emsp430xE423.c \ +- emsp430xE425.c \ +- emsp430xE427.c \ +- emsp430xG437.c \ +- emsp430xG438.c \ +- emsp430xG439.c \ +- emsp430xW423.c \ +- emsp430xW425.c \ +- emsp430xW427.c \ ++ emsp430.c \ + enews.c \ + ens32knbsd.c \ + eor32.c \ +@@ -1270,65 +1212,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10300.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x110.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1101.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1111.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x112.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1121.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1122.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1132.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x122.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1222.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x123.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1232.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x133.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1331.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x135.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1351.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x147.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x148.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x149.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x155.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x156.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x157.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1610.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1611.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1612.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x167.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x168.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x169.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2101.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2111.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2121.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2131.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x311.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x312.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x313.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x314.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x315.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x323.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x325.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x336.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x337.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x412.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x413.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x415.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x417.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x435.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x436.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x437.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x447.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x448.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x449.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE423.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE425.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE427.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG437.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG438.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG439.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW423.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW425.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW427.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enews.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ens32knbsd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eor32.Po@am__quote@ +@@ -2889,242 +2773,10 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ + $(srcdir)/emulparams/mn10200.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} mn10300 "$(tdir_mn10300)" +-emsp430x110.c: $(srcdir)/emulparams/msp430all.sh \ ++emsp430.c: $(srcdir)/emulparams/msp430uni.sh \ + $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ + ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x110 "$(tdir_msp430x110)" msp430all +-emsp430x1101.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1101 "$(tdir_msp430x1101)" msp430all +-emsp430x1111.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1111 "$(tdir_msp430x1111)" msp430all +-emsp430x112.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x112 "$(tdir_msp430x112)" msp430all +-emsp430x1121.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1121 "$(tdir_msp430x1121)" msp430all +-emsp430x1122.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1122 "$(tdir_msp430x1122)" msp430all +-emsp430x1132.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1132 "$(tdir_msp430x1132)" msp430all +-emsp430x122.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x122 "$(tdir_msp430x122)" msp430all +-emsp430x1222.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1222 "$(tdir_msp430x1222)" msp430all +-emsp430x123.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x123 "$(tdir_msp430x123)" msp430all +-emsp430x1232.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1232 "$(tdir_msp430x1232)" msp430all +-emsp430x133.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x133 "$(tdir_msp430x133)" msp430all +-emsp430x1331.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1331 "$(tdir_msp430x1331)" msp430all +-emsp430x135.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x135 "$(tdir_msp430x135)" msp430all +-emsp430x1351.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1351 "$(tdir_msp430x1351)" msp430all +-emsp430x147.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x147 "$(tdir_msp430x147)" msp430all +-emsp430x148.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x148 "$(tdir_msp430x148)" msp430all +-emsp430x149.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x149 "$(tdir_msp430x149)" msp430all +-emsp430x155.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x155 "$(tdir_msp430x155)" msp430all +-emsp430x156.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x156 "$(tdir_msp430x156)" msp430all +-emsp430x157.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x157 "$(tdir_msp430x157)" msp430all +-emsp430x1610.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1610 "$(tdir_msp430x1610)" msp430all +-emsp430x1611.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1611 "$(tdir_msp430x1611)" msp430all +-emsp430x1612.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x1612 "$(tdir_msp430x1612)" msp430all +-emsp430x167.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x167 "$(tdir_msp430x167)" msp430all +-emsp430x168.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x168 "$(tdir_msp430x168)" msp430all +-emsp430x169.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x169 "$(tdir_msp430x169)" msp430all +-emsp430x2101.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2101 "$(tdir_msp430x2101)" msp430all +-emsp430x2111.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2111 "$(tdir_msp430x2111)" msp430all +-emsp430x2121.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2121 "$(tdir_msp430x2121)" msp430all +-emsp430x2131.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x2131 "$(tdir_msp430x2131)" msp430all +-emsp430x311.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x311 "$(tdir_msp430x311)" msp430all +-emsp430x312.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x312 "$(tdir_msp430x312)" msp430all +-emsp430x313.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x313 "$(tdir_msp430x313)" msp430all +-emsp430x314.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x314 "$(tdir_msp430x314)" msp430all +-emsp430x315.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x315 "$(tdir_msp430x315)" msp430all +-emsp430x323.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x323 "$(tdir_msp430x323)" msp430all +-emsp430x325.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x325 "$(tdir_msp430x325)" msp430all +-emsp430x336.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x336 "$(tdir_msp430x336)" msp430all +-emsp430x337.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x337 "$(tdir_msp430x337)" msp430all +-emsp430x412.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x412 "$(tdir_msp430x412)" msp430all +-emsp430x413.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x413 "$(tdir_msp430x413)" msp430all +-emsp430x415.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x415 "$(tdir_msp430x415)" msp430all +-emsp430x417.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x417 "$(tdir_msp430x417)" msp430all +-emsp430x435.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x435 "$(tdir_msp430x435)" msp430all +-emsp430x436.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x436 "$(tdir_msp430x436)" msp430all +-emsp430x437.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x437 "$(tdir_msp430x437)" msp430all +-emsp430x447.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x447 "$(tdir_msp430x447)" msp430all +-emsp430x448.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x448 "$(tdir_msp430x448)" msp430all +-emsp430x449.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430x449 "$(tdir_msp430x449)" msp430all +-emsp430xE423.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE423 "$(tdir_msp430xE423)" msp430all +-emsp430xE425.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE425 "$(tdir_msp430xE425)" msp430all +-emsp430xE427.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xE427 "$(tdir_msp430xE427)" msp430all +-emsp430xG437.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG437 "$(tdir_msp430xG437)" msp430all +-emsp430xG438.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG438 "$(tdir_msp430xG438)" msp430all +-emsp430xG439.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xG439 "$(tdir_msp430xG439)" msp430all +-emsp430xW423.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW423 "$(tdir_msp430xW423)" msp430all +-emsp430xW425.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW425 "$(tdir_msp430xW425)" msp430all +-emsp430xW427.c: $(srcdir)/emulparams/msp430all.sh \ +- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ +- ${GEN_DEPENDS} +- ${GENSCRIPTS} msp430xW427 "$(tdir_msp430xW427)" msp430all ++ ${GENSCRIPTS} msp430 "$(tdir_msp430)" msp430uni + enews.c: $(srcdir)/emulparams/news.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} news "$(tdir_news)" +diff --git a/ld/configure.tgt b/ld/configure.tgt +index 23cf347..26a6db8 100644 +--- a/ld/configure.tgt ++++ b/ld/configure.tgt +@@ -436,8 +436,7 @@ mn10300-*-*) targ_emul=mn10300 + ;; + mt-*elf) targ_emul=elf32mt + ;; +-msp430-*-*) targ_emul=msp430x110 +- targ_extra_emuls="msp430x112 msp430x1101 msp430x1111 msp430x1121 msp430x1122 msp430x1132 msp430x122 msp430x123 msp430x1222 msp430x1232 msp430x133 msp430x135 msp430x1331 msp430x1351 msp430x147 msp430x148 msp430x149 msp430x155 msp430x156 msp430x157 msp430x167 msp430x168 msp430x169 msp430x1610 msp430x1611 msp430x1612 msp430x2101 msp430x2111 msp430x2121 msp430x2131 msp430x311 msp430x312 msp430x313 msp430x314 msp430x315 msp430x323 msp430x325 msp430x336 msp430x337 msp430x412 msp430x413 msp430x415 msp430x417 msp430xE423 msp430xE425 msp430xE427 msp430xW423 msp430xW425 msp430xW427 msp430xG437 msp430xG438 msp430xG439 msp430x435 msp430x436 msp430x437 msp430x447 msp430x448 msp430x449" ++msp430-*-*) targ_emul=msp430 + ;; + ns32k-pc532-mach* | ns32k-pc532-ux*) targ_emul=pc532macha ;; + ns32k-*-netbsd* | ns32k-pc532-lites*) targ_emul=ns32knbsd +diff --git a/ld/emulparams/msp430all.sh b/ld/emulparams/msp430all.sh +deleted file mode 100644 +index 57d21c2..0000000 +--- a/ld/emulparams/msp430all.sh ++++ /dev/null +@@ -1,553 +0,0 @@ +-#!/bin/sh +- +-# This called by genscripts_extra.sh +- +-MSP430_NAME=${EMULATION_NAME} +- +-SCRIPT_NAME=elf32msp430 +-TEMPLATE_NAME=generic +-EXTRA_EM_FILE=genelf +-OUTPUT_FORMAT="elf32-msp430" +-MACHINE= +-MAXPAGESIZE=1 +-EMBEDDED=yes +- +-if [ "${MSP430_NAME}" = "msp430x110" ] ; then +-ARCH=msp:11 +-ROM_START=0xfc00 +-ROM_SIZE=0x3e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1101" ] ; then +-ARCH=msp:110 +-ROM_START=0xfc00 +-ROM_SIZE=0x3e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1111" ] ; then +-ARCH=msp:110 +-ROM_START=0xf800 +-ROM_SIZE=0x07e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x112" ] ; then +-ARCH=msp:11 +-ROM_START=0xf000 +-ROM_SIZE=0xfe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1121" ] ; then +-ARCH=msp:110 +-ROM_START=0xf000 +-ROM_SIZE=0x0fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1122" ] ; then +-ARCH=msp:110 +-ROM_START=0xf000 +-ROM_SIZE=0x0fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1132" ] ; then +-ARCH=msp:110 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x122" ] ; then +-ARCH=msp:12 +-ROM_START=0xf000 +-ROM_SIZE=0xfe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1222" ] ; then +-ARCH=msp:12 +-ROM_START=0xf000 +-ROM_SIZE=0xfe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x123" ] ; then +-ARCH=msp:12 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1232" ] ; then +-ARCH=msp:12 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x133" ] ; then +-ARCH=msp:13 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1331" ] ; then +-ARCH=msp:13 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x135" ] ; then +-ARCH=msp:13 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1351" ] ; then +-ARCH=msp:13 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x147" ] ; then +-ARCH=msp:14 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1K +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x148" ] ; then +-ARCH=msp:14 +-ROM_START=0x4000 +-ROM_SIZE=0xbfe0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x149" ] ; then +-ARCH=msp:14 +-ROM_START=0x1100 +-ROM_SIZE=0xeee0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x155" ] ; then +-ARCH=msp:15 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x156" ] ; then +-ARCH=msp:15 +-ROM_START=0xa000 +-ROM_SIZE=0x5fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x157" ] ; then +-ARCH=msp:15 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1K +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x167" ] ; then +-ARCH=msp:16 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1K +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x168" ] ; then +-ARCH=msp:16 +-ROM_START=0x4000 +-ROM_SIZE=0xbfe0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x169" ] ; then +-ARCH=msp:16 +-ROM_START=0x1100 +-ROM_SIZE=0xeee0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1610" ] ; then +-ARCH=msp:16 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x1100 +-RAM_SIZE=0x1400 +-STACK=0x2500 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1611" ] ; then +-ARCH=msp:16 +-ROM_START=0x4000 +-ROM_SIZE=0xbfe0 +-RAM_START=0x1100 +-RAM_SIZE=0x2800 +-STACK=0x3900 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x1612" ] ; then +-ARCH=msp:16 +-ROM_START=0x2500 +-ROM_SIZE=0xdae0 +-RAM_START=0x1100 +-RAM_SIZE=0x1400 +-STACK=0x2500 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x2101" ] ; then +-ARCH=msp:21 +-ROM_START=0xFC00 +-ROM_SIZE=0x03e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x2111" ] ; then +-ARCH=msp:21 +-ROM_START=0xF800 +-ROM_SIZE=0x07e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x2121" ] ; then +-ARCH=msp:21 +-ROM_START=0xf000 +-ROM_SIZE=0x0fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x2131" ] ; then +-ARCH=msp:21 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x311" ] ; then +-ARCH=msp:31 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xf800 +-ROM_SIZE=0x07e0 +-RAM_START=0x0200 +-RAM_SIZE=128 +-STACK=0x280 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x312" ] ; then +-ARCH=msp:31 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xf000 +-ROM_SIZE=0x0fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x313" ] ; then +-ARCH=msp:31 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x314" ] ; then +-ARCH=msp:31 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xd000 +-ROM_SIZE=0x2fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x315" ] ; then +-ARCH=msp:31 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x323" ] ; then +-ARCH=msp:32 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x325" ] ; then +-ARCH=msp:32 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x336" ] ; then +-ARCH=msp:33 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0xa000 +-ROM_SIZE=0x5fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x337" ] ; then +-ARCH=msp:33 +-SCRIPT_NAME=elf32msp430_3 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x412" ] ; then +-ARCH=msp:41 +-ROM_START=0xf000 +-ROM_SIZE=0x0fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x413" ] ; then +-ARCH=msp:41 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x415" ] ; then +-ARCH=msp:41 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x417" ] ; then +-ARCH=msp:41 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x435" ] ; then +-ARCH=msp:43 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x436" ] ; then +-ARCH=msp:43 +-ROM_START=0xa000 +-ROM_SIZE=0x5fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x437" ] ; then +-ARCH=msp:43 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x447" ] ; then +-ARCH=msp:44 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x448" ] ; then +-ARCH=msp:44 +-ROM_START=0x4000 +-ROM_SIZE=0xbfe0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430x449" ] ; then +-ARCH=msp:44 +-ROM_START=0x1100 +-ROM_SIZE=0xeee0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xE423" ] ; then +-ARCH=msp:42 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xE425" ] ; then +-ARCH=msp:42 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xE427" ] ; then +-ARCH=msp:42 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xG437" ] ; then +-ARCH=msp:43 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=1024 +-STACK=0x600 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xG438" ] ; then +-ARCH=msp:43 +-ROM_START=0x4000 +-ROM_SIZE=0xbef0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xG439" ] ; then +-ARCH=msp:43 +-ROM_START=0x1100 +-ROM_SIZE=0xeee0 +-RAM_START=0x0200 +-RAM_SIZE=0x0800 +-STACK=0xa00 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xW423" ] ; then +-ARCH=msp:42 +-ROM_START=0xe000 +-ROM_SIZE=0x1fe0 +-RAM_START=0x0200 +-RAM_SIZE=256 +-STACK=0x300 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xW425" ] ; then +-ARCH=msp:42 +-ROM_START=0xc000 +-ROM_SIZE=0x3fe0 +-RAM_START=0x0200 +-RAM_SIZE=512 +-STACK=0x400 +-fi +- +-if [ "${MSP430_NAME}" = "msp430xW427" ] ; then +-ARCH=msp:42 +-ROM_START=0x8000 +-ROM_SIZE=0x7fe0 +-RAM_START=0x0200 +-RAM_SIZE=0x400 +-STACK=0x600 +-fi +diff --git a/ld/emulparams/msp430uni.sh b/ld/emulparams/msp430uni.sh +new file mode 100644 +index 0000000..949fe85 +--- /dev/null ++++ b/ld/emulparams/msp430uni.sh +@@ -0,0 +1,14 @@ ++#!/bin/sh ++ ++# This called by genscripts_extra.sh ++ ++MSP430_NAME=${EMULATION_NAME} ++ARCH=msp430 ++SCRIPT_NAME=elf32msp430 ++TEMPLATE_NAME=generic ++EXTRA_EM_FILE=msp430 ++OUTPUT_FORMAT="elf32-msp430" ++MACHINE= ++MAXPAGESIZE=1 ++EMBEDDED=yes ++ +diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em +new file mode 100644 +index 0000000..f4586f8 +--- /dev/null ++++ b/ld/emultempl/msp430.em +@@ -0,0 +1,107 @@ ++# This shell script emits a C file. -*- C -*- ++# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ++# ++# This file is part of the GNU Binutils. ++# ++# 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 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, ++# MA 02110-1301, USA. ++# ++ ++# Adapt genelf.em for MSP430 ++# This file is sourced from generic.em ++# ++fragment <link_next) ++ if ((syms = bfd_get_outsymbols (ibfd)) != NULL ++ && bfd_get_flavour (ibfd) == bfd_target_elf_flavour) ++ for (sec = ibfd->sections; sec != NULL; sec = sec->next) ++ if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP) ++ { ++ struct bfd_elf_section_data *sec_data = elf_section_data (sec); ++ elf_group_id (sec) = syms[sec_data->this_hdr.sh_info - 1]; ++ } ++} ++ ++static void ++gld${EMULATION_NAME}_before_allocation (void) ++{ ++ if (link_info.relocatable ++ && !_bfd_elf_size_group_sections (&link_info)) ++ einfo ("%X%P: can not size group sections: %E\n"); ++ before_allocation_default (); ++} ++ ++static void ++gld${EMULATION_NAME}_after_allocation (void) ++{ ++ gld${EMULATION_NAME}_map_segments (FALSE); ++} ++ ++static void ++gld${EMULATION_NAME}_finish (void) ++{ ++ bfd *obfd = link_info.output_bfd; ++ Elf_Internal_Ehdr *o_ehdrp = elf_elfheader (obfd); ++ unsigned long flags = 0; ++ bfd *ibfd; ++ ++ for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { ++ Elf_Internal_Ehdr * i_ehdrp = elf_elfheader (ibfd); ++ ++ if (EF_MSP430_UNIARCH & i_ehdrp->e_flags) ++ flags |= i_ehdrp->e_flags; ++ } ++ if (EF_MSP430_UNIARCH & flags) { ++ int bfd_mach; ++ switch (flags & EF_MSP430_ARCH) ++ { ++ default: ++ case EF_MSP430_ARCH_430: ++ bfd_mach = bfd_mach_msp430; ++ break; ++ case EF_MSP430_ARCH_430X: ++ bfd_mach = bfd_mach_msp430x; ++ break; ++ } ++ bfd_default_set_arch_mach (obfd, bfd_arch_msp430, bfd_mach); ++ o_ehdrp->e_flags = flags; ++ } ++ finish_default(); ++} ++EOF ++# Put these extra routines in ld_${EMULATION_NAME}_emulation ++# ++LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open ++LDEMUL_BEFORE_ALLOCATION=gld${EMULATION_NAME}_before_allocation ++LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation ++LDEMUL_FINISH=gld${EMULATION_NAME}_finish +diff --git a/ld/scripttempl/elf32msp430.sc b/ld/scripttempl/elf32msp430.sc +index cbffe48..05c87ee 100644 +--- a/ld/scripttempl/elf32msp430.sc ++++ b/ld/scripttempl/elf32msp430.sc +@@ -1,37 +1,11 @@ + #!/bin/sh + +-HEAP_SECTION_MSP430=" " +-HEAP_MEMORY_MSP430=" " +- +-if test ${GOT_HEAP_MSP-0} -ne 0 +-then +-HEAP_SECTION_MSP430=".heap ${RELOCATING-0} : +- { +- ${RELOCATING+ PROVIDE (__heap_data_start = .) ; } +- *(.heap*) +- ${RELOCATING+ PROVIDE (_heap_data_end = .) ; } +- ${RELOCATING+. = ALIGN(2);} +- ${RELOCATING+ PROVIDE (__heap_bottom = .) ; } +- ${RELOCATING+ PROVIDE (__heap_top = ${HEAP_START} + ${HEAP_LENGTH}) ; } +- } ${RELOCATING+ > heap}" +-HEAP_MEMORY_MSP430="heap(rwx) : ORIGIN = $HEAP_START, LENGTH = $HEAP_LENGTH" +-fi +- +- + cat < REGION_TEXT} + +- ${RELOCATING+. = ALIGN(2);} +- *(.fini9) /* */ +- *(.fini8) +- *(.fini7) +- *(.fini6) /* C++ destructors. */ +- *(.fini5) +- *(.fini4) +- *(.fini3) +- *(.fini2) +- *(.fini1) +- *(.fini0) /* Infinite loop after program termination. */ +- *(.fini) +- +- _etext = .; +- } ${RELOCATING+ > text} +- +- .data ${RELOCATING-0} : ${RELOCATING+AT (ADDR (.text) + SIZEOF (.text))} ++ .rodata ${RELOCATING-0} : ++ { ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) ++ ${RELOCATING+ . = ALIGN(2);} ++ } ${RELOCATING+ > REGION_TEXT} ++ ${RELOCATING+ _etext = .;} /* Past last read-only (loadable) segment */ ++ ++ .data ${RELOCATING-0} : + { ++ ${RELOCATING+ . = ALIGN(2);} + ${RELOCATING+ PROVIDE (__data_start = .) ; } +- ${RELOCATING+. = ALIGN(2);} + *(.data) +- ${RELOCATING+. = ALIGN(2);} ++ *(SORT_BY_ALIGNMENT(.data.*)) ++ ${RELOCATING+ . = ALIGN(2);} + *(.gnu.linkonce.d*) +- ${RELOCATING+. = ALIGN(2);} ++ ${RELOCATING+ . = ALIGN(2);} + ${RELOCATING+ _edata = . ; } +- } ${RELOCATING+ > data} ++ } ${RELOCATING+ > REGION_DATA AT > REGION_TEXT} ++ ${RELOCATING+ PROVIDE (__data_load_start = LOADADDR(.data) ); } ++ ${RELOCATING+ PROVIDE (__data_size = SIZEOF(.data) ); } + +- /* Bootloader. */ +- .bootloader ${RELOCATING-0} : +- { +- ${RELOCATING+ PROVIDE (__boot_start = .) ; } +- *(.bootloader) +- ${RELOCATING+. = ALIGN(2);} +- *(.bootloader.*) +- } ${RELOCATING+ > bootloader} +- +- /* Information memory. */ +- .infomem ${RELOCATING-0} : +- { +- *(.infomem) +- ${RELOCATING+. = ALIGN(2);} +- *(.infomem.*) +- } ${RELOCATING+ > infomem} +- +- /* Information memory (not loaded into MPU). */ +- .infomemnobits ${RELOCATING-0} : +- { +- *(.infomemnobits) +- ${RELOCATING+. = ALIGN(2);} +- *(.infomemnobits.*) +- } ${RELOCATING+ > infomemnobits} +- +- .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : ++ .bss ${RELOCATING-0} : + { + ${RELOCATING+ PROVIDE (__bss_start = .) ; } + *(.bss) ++ *(SORT_BY_ALIGNMENT(.bss.*)) + *(COMMON) + ${RELOCATING+ PROVIDE (__bss_end = .) ; } + ${RELOCATING+ _end = . ; } +- } ${RELOCATING+ > data} ++ } ${RELOCATING+ > REGION_DATA} ++ ${RELOCATING+ PROVIDE (__bss_size = SIZEOF(.bss) ); } + +- .noinit ${RELOCATING+ SIZEOF(.bss) + ADDR(.bss)} : ++ .noinit ${RELOCATING-0} : + { + ${RELOCATING+ PROVIDE (__noinit_start = .) ; } + *(.noinit) ++ *(.noinit.*) + *(COMMON) + ${RELOCATING+ PROVIDE (__noinit_end = .) ; } + ${RELOCATING+ _end = . ; } +- } ${RELOCATING+ > data} ++ } ${RELOCATING+ > REGION_DATA} ++ ++ /* Information memory. */ ++ .infomem ${RELOCATING-0} : ++ { ++ *(.infomem) ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.infomem.*) ++ } ${RELOCATING+ > infomem} ++ ++ .infomemnobits ${RELOCATING-0} : ++ { ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.infomemnobits) ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.infomemnobits.*) ++ } ${RELOCATING+ > infomem} + + .vectors ${RELOCATING-0}: + { + ${RELOCATING+ PROVIDE (__vectors_start = .) ; } +- *(.vectors*) ++ KEEP(*(.vectors*)) + ${RELOCATING+ _vectors_end = . ; } + } ${RELOCATING+ > vectors} + +- ${HEAP_SECTION_MSP430} ++ .fartext : ++ { ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.fartext) ++ ${RELOCATING+ . = ALIGN(2);} ++ *(.fartext.*) ++ ${RELOCATING+ _efartext = .;} ++ } ${RELOCATING+ > REGION_FAR_ROM} + + /* Stabs for profiling information*/ + .profiler 0 : { *(.profiler) } +@@ -239,11 +222,12 @@ SECTIONS + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + +- PROVIDE (__stack = ${STACK}) ; +- PROVIDE (__data_start_rom = _etext) ; +- PROVIDE (__data_end_rom = _etext + SIZEOF (.data)) ; +- PROVIDE (__noinit_start_rom = _etext + SIZEOF (.data)) ; +- PROVIDE (__noinit_end_rom = _etext + SIZEOF (.data) + SIZEOF (.noinit)) ; +- PROVIDE (__subdevice_has_heap = ${GOT_HEAP_MSP-0}) ; ++ /* DWARF 3 */ ++ .debug_pubtypes 0 : { *(.debug_pubtypes) } ++ .debug_ranges 0 : { *(.debug_ranges) } ++ ++ ${RELOCATING+ PROVIDE (__stack = ORIGIN(ram) + LENGTH(ram));} ++ ${RELOCATING+ PROVIDE (__data_start_rom = _etext);} ++ ${RELOCATING+ PROVIDE (__data_end_rom = _etext + SIZEOF (.data));} + } + EOF +diff --git a/ld/scripttempl/elf32msp430_3.sc b/ld/scripttempl/elf32msp430_3.sc +deleted file mode 100644 +index 15eb517..0000000 +--- a/ld/scripttempl/elf32msp430_3.sc ++++ /dev/null +@@ -1,192 +0,0 @@ +-cat < text} +- +- .data ${RELOCATING-0} : ${RELOCATING+AT (ADDR (.text) + SIZEOF (.text))} +- { +- ${RELOCATING+ PROVIDE (__data_start = .) ; } +- *(.data) +- *(.gnu.linkonce.d*) +- ${RELOCATING+. = ALIGN(2);} +- ${RELOCATING+ _edata = . ; } +- } ${RELOCATING+ > data} +- +- .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : +- { +- ${RELOCATING+ PROVIDE (__bss_start = .) ; } +- *(.bss) +- *(COMMON) +- ${RELOCATING+ PROVIDE (__bss_end = .) ; } +- ${RELOCATING+ _end = . ; } +- } ${RELOCATING+ > data} +- +- .noinit ${RELOCATING+ SIZEOF(.bss) + ADDR(.bss)} : +- { +- ${RELOCATING+ PROVIDE (__noinit_start = .) ; } +- *(.noinit) +- *(COMMON) +- ${RELOCATING+ PROVIDE (__noinit_end = .) ; } +- ${RELOCATING+ _end = . ; } +- } ${RELOCATING+ > data} +- +- .vectors ${RELOCATING-0}: +- { +- ${RELOCATING+ PROVIDE (__vectors_start = .) ; } +- *(.vectors*) +- ${RELOCATING+ _vectors_end = . ; } +- } ${RELOCATING+ > vectors} +- +- /* Stabs debugging sections. */ +- .stab 0 : { *(.stab) } +- .stabstr 0 : { *(.stabstr) } +- .stab.excl 0 : { *(.stab.excl) } +- .stab.exclstr 0 : { *(.stab.exclstr) } +- .stab.index 0 : { *(.stab.index) } +- .stab.indexstr 0 : { *(.stab.indexstr) } +- .comment 0 : { *(.comment) } +- +- /* DWARF debug sections. +- Symbols in the DWARF debugging sections are relative to the beginning +- of the section so we begin them at 0. */ +- +- /* DWARF 1 */ +- .debug 0 : { *(.debug) } +- .line 0 : { *(.line) } +- +- /* GNU DWARF 1 extensions */ +- .debug_srcinfo 0 : { *(.debug_srcinfo) } +- .debug_sfnames 0 : { *(.debug_sfnames) } +- +- /* DWARF 1.1 and DWARF 2 */ +- .debug_aranges 0 : { *(.debug_aranges) } +- .debug_pubnames 0 : { *(.debug_pubnames) } +- +- /* DWARF 2 */ +- .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } +- .debug_abbrev 0 : { *(.debug_abbrev) } +- .debug_line 0 : { *(.debug_line) } +- .debug_frame 0 : { *(.debug_frame) } +- .debug_str 0 : { *(.debug_str) } +- .debug_loc 0 : { *(.debug_loc) } +- .debug_macinfo 0 : { *(.debug_macinfo) } +- +- PROVIDE (__stack = ${STACK}) ; +- PROVIDE (__data_start_rom = _etext) ; +- PROVIDE (__data_end_rom = _etext + SIZEOF (.data)) ; +- PROVIDE (__noinit_start_rom = _etext + SIZEOF (.data)) ; +- PROVIDE (__noinit_end_rom = _etext + SIZEOF (.data) + SIZEOF (.noinit)) ; +-} +-EOF +diff --git a/opcodes/msp430-dis.c b/opcodes/msp430-dis.c +index 9d7edbe..a00c718 100644 +--- a/opcodes/msp430-dis.c ++++ b/opcodes/msp430-dis.c +@@ -52,12 +52,153 @@ msp430dis_opcode (bfd_vma addr, disassemble_info *info) + return bfd_getl16 (buffer); + } + ++static unsigned short ++msp430dis_operand (bfd_vma addr, disassemble_info *info, int reg, int am, int *cmd_len) ++{ ++ static int const op_length [][5] = ++ { ++ // am | reg 0 1 2 3 >3 ++ /* 0 */ { 0, 0, 0, 0, 0 }, // Rn ++ /* 1 */ { 2, 2, 2, 0, 2 }, // x(Rn) ++ /* 2 */ { 0, 0, 0, 0, 0 }, // @Rn ++ /* 3 */ { 2, 0, 0, 0, 0 }, // @Rn+ ++ }; ++ if (reg >= (int)(sizeof(op_length[0]) / sizeof(op_length[0][0]))) ++ reg = sizeof(op_length[0]) / sizeof(op_length[0][0])- 1; ++ ++ if (op_length[am][reg]) ++ { ++ bfd_byte buffer[2]; ++ int status = info->read_memory_func (addr, buffer, 2, info); ++ if (status != 0) ++ { ++ info->memory_error_func (status, addr, info); ++ return -1; ++ } ++ *cmd_len += 2; ++ return bfd_getl16 (buffer); ++ } ++ return 0; ++} ++ ++typedef enum ++{ ++ OP_20BIT, ++ OP_16BIT, ++ OP_20BIT_HEX, ++ OP_16BIT_HEX, ++ OP_DECIMAL, ++} operand_t; ++ ++static void ++msp430x_decode_operand(int reg, int am, int addr, int dst, operand_t size, char *op, char *comm) ++{ ++ if (op) // if operand not hidden in emulated instruction ++ switch (am) ++ { ++ case 0: // Rn ++ if (reg == 3) ++ { ++ sprintf (op, "#0"); // constant #0 ++ sprintf (comm, "r3 As==00"); ++ } ++ else ++ { ++ sprintf (op, "r%d", reg); ++ } ++ break; ++ case 1: // x(Rn) ++ if (reg == 0) // Symbolic, ADDR ++ { ++ if (size == OP_20BIT || size == OP_20BIT_HEX) ++ sprintf (op, "0x%05x", dst & 0xfffff); ++ else ++ sprintf (op, "0x%04x", dst & 0xffff); ++ sprintf (comm, "PC rel. 0x%05x", ((int)addr + dst) & 0xfffff); ++ } ++ else if (reg == 2) // Absolute, &ADDR ++ { ++ if (size == OP_20BIT || size == OP_20BIT_HEX) ++ sprintf (op, "&0x%05x", dst & 0xfffff); ++ else ++ sprintf (op, "&0x%04x", dst & 0xffff); ++ } ++ else if (reg == 3) // constant #1 ++ { ++ sprintf (op, "#1"); ++ sprintf (comm, "r3 As==01"); ++ } ++ else // Indexed, x(Rn) ++ { ++ sprintf (op, "%d(r%d)", dst, reg); ++ if (size == OP_20BIT || size == OP_20BIT_HEX) ++ sprintf (comm, "0x%05x(r%d)", dst & 0xfffff, reg); ++ else ++ sprintf (comm, "0x%04x(r%d)", dst & 0xffff, reg); ++ } ++ break; ++ case 2: // @Rn ++ if (reg == 2) // constant #4 ++ { ++ sprintf (op, "#4"); ++ sprintf (comm, "r2 As==10"); ++ } ++ else if(reg == 3) // constant #2 ++ { ++ sprintf (op, "#2"); ++ sprintf (comm, "r3 As==10"); ++ } ++ else ++ { ++ sprintf (op, "@r%d", reg); ++ } ++ break; ++ case 3: // @Rn+ ++ switch (reg) ++ { ++ case 0: // immediate, #N ++ switch (size) ++ { ++ case OP_16BIT: ++ sprintf (op, "#%d", dst); ++ sprintf (comm, "#0x%04x", dst & 0xffff); ++ break; ++ case OP_16BIT_HEX: ++ sprintf (op, "#0x%04x", dst & 0xffff); ++ break; ++ case OP_20BIT: ++ sprintf (op, "#%d", dst); ++ sprintf (comm, "#0x%05x", dst & 0xfffff); ++ break; ++ case OP_20BIT_HEX: ++ sprintf (op, "#0x%05x", dst & 0xfffff); ++ break; ++ default: // #n in rxxm ++ sprintf (op, "#%d", dst); ++ break; ++ } ++ break; ++ case 2: // constant #8 ++ sprintf (op, "#8"); ++ sprintf (comm, "r2 As==11"); ++ break; ++ case 3: // constant #-1 ++ sprintf (op, "#-1"); ++ sprintf (comm, "r3 As==11"); ++ break; ++ default: ++ sprintf (op, "@r%d+", reg); ++ break; ++ } ++ break; ++ } ++} ++ + static int +-msp430_nooperands (struct msp430_opcode_s *opcode, ++msp430_nooperands (struct msp430_opcode_s const *opcode, + bfd_vma addr ATTRIBUTE_UNUSED, + unsigned short insn ATTRIBUTE_UNUSED, +- char *comm, +- int *cycles) ++ char *comm) + { + /* Pop with constant. */ + if (insn == 0x43b2) +@@ -65,18 +206,16 @@ msp430_nooperands (struct msp430_opcode_s *opcode, + if (insn == opcode->bin_opcode) + return 2; + +- if (opcode->fmt == 0) ++ if (opcode_format(opcode) == FMT_EMULATED) + { + if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2) + return 0; + + strcpy (comm, "emulated..."); +- *cycles = 1; + } + else + { + strcpy (comm, "return from interupt"); +- *cycles = 5; + } + + return 2; +@@ -84,16 +223,14 @@ msp430_nooperands (struct msp430_opcode_s *opcode, + + static int + msp430_singleoperand (disassemble_info *info, +- struct msp430_opcode_s *opcode, ++ struct msp430_opcode_s const *opcode, + bfd_vma addr, + unsigned short insn, + char *op, +- char *comm, +- int *cycles) ++ char *comm) + { + int regs = 0, regd = 0; + int ad = 0, as = 0; +- int where = 0; + int cmd_len = 2; + short dst = 0; + +@@ -102,9 +239,9 @@ msp430_singleoperand (disassemble_info *info, + as = (insn & 0x0030) >> 4; + ad = (insn & 0x0080) >> 7; + +- switch (opcode->fmt) ++ switch (opcode_format(opcode)) + { +- case 0: /* Emulated work with dst register. */ ++ case FMT_EMULATED: /* Emulated work with dst register. */ + if (regs != 2 && regs != 3 && regs != 1) + return 0; + +@@ -116,167 +253,23 @@ msp430_singleoperand (disassemble_info *info, + 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); +- } +- } ++ dst = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); ++ msp430x_decode_operand (regd, ad, addr + cmd_len, dst, OP_16BIT, op, comm); + 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); +- } +- } ++ case FMT_SINGLE_OPERAND: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */ ++ dst = msp430dis_operand (addr + cmd_len, info, regd, as, &cmd_len); ++ if(opcode_variant(opcode) != V_CALL) ++ msp430x_decode_operand (regd, as, addr + cmd_len, dst, OP_16BIT, op, comm); ++ else ++ msp430x_decode_operand (regd, as, addr + cmd_len, dst, OP_16BIT_HEX, op, comm); + 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; ++ case FMT_JUMP: /* Jumps. */ ++ dst = (short)((insn & 0x03ff) << 6) >> 5; // sign extension, word addr to byte addr conversion ++ sprintf (op, "$%+-8d", dst + 2); ++ sprintf (comm, "abs 0x%x", PS ((short) (addr) + 2 + dst)); + return 2; +- break; + default: + cmd_len = 0; + } +@@ -286,26 +279,26 @@ msp430_singleoperand (disassemble_info *info, + + static int + msp430_doubleoperand (disassemble_info *info, +- struct msp430_opcode_s *opcode, ++ struct msp430_opcode_s const *opcode, + bfd_vma addr, + unsigned short insn, + char *op1, + char *op2, + char *comm1, +- char *comm2, +- int *cycles) ++ char *comm2) + { + int regs = 0, regd = 0; + int ad = 0, as = 0; + int cmd_len = 2; +- short dst = 0; ++ short ops; ++ short opd; + + regd = insn & 0x0f; + regs = (insn & 0x0f00) >> 8; + as = (insn & 0x0030) >> 4; + ad = (insn & 0x0080) >> 7; + +- if (opcode->fmt == 0) ++ if (opcode_format(opcode) == FMT_EMULATED) + { + /* Special case: rla and rlc are the only 2 emulated instructions that + fall into two operand instructions. */ +@@ -320,347 +313,354 @@ msp430_doubleoperand (disassemble_info *info, + 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 (ad == 0 && regd == 3) // #N + { +- 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); +- /* If the 'src' field is not the same as the dst +- then this is not an rla instruction. */ +- if (dst != msp430dis_opcode (addr + 4, info)) +- return 0; +- 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); +- } ++ strcpy (comm1, _("Illegal as emulation instr")); ++ return -1; + } ++ ops = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); ++ opd = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); ++ /* If the 'src' field is not the same as the dst ++ then this is not an rla instruction. */ ++ if (ops != opd) ++ return 0; ++ msp430x_decode_operand (regs, as, addr + cmd_len, ops, OP_16BIT, op1, comm1); + + *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; + } ++ ops = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); ++ msp430x_decode_operand (regs, as, addr + cmd_len, ops, OP_16BIT, op1, comm1); + +- /* 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; ++ opd = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); ++ msp430x_decode_operand (regd, ad, addr + cmd_len, opd, OP_16BIT, op2, comm2); ++ return cmd_len; ++} + +- 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; ++static int ++msp430_branchinstr (disassemble_info *info, ++ struct msp430_opcode_s const *opcode ATTRIBUTE_UNUSED, ++ bfd_vma addr ATTRIBUTE_UNUSED, ++ unsigned short insn, ++ char *op1, ++ char *comm1) ++{ ++ int regs = (insn & 0x0f00) >> 8; ++ int as = (insn & 0x0030) >> 4; ++ int cmd_len = 2; ++ short dst; + +- /* Indexed register mode @Rn. */ +- sprintf (op1, "@r%d", regs); +- } +- if (!regs) +- *cycles = 3; +- } +- else if (as == 3) ++ dst = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); ++ msp430x_decode_operand(regs, as, addr + cmd_len, dst, OP_16BIT_HEX, op1, comm1); ++ ++ return cmd_len; ++} ++ ++static opwidth_t ++msp430x_opwidth(unsigned int insn) ++{ ++ insn &= NON_ADDR_OPERATION | BYTE_OPERATION_X; ++ ++ if(insn == (NON_ADDR_OPERATION | BYTE_OPERATION_X)) ++ return BYTE_OP; ++ if(insn == NON_ADDR_OPERATION) ++ return WORD_OP; ++ if(insn == BYTE_OPERATION_X) ++ return ADDR_OP; ++ ++ return 0; // reserved ++} ++ ++static int ++msp430x_singleoperand (disassemble_info *info, ++ struct msp430_opcode_s const *opcode, ++ bfd_vma addr, ++ unsigned int insn, ++ char *op, ++ char *comm, ++ int *repeats) ++{ ++ int reg = (insn >> 16) & 0xf; ++ int am = (insn >> 20) & 0x3; ++ int cmd_len = 4; ++ int dst = 0; ++ ++ if ( opcode_variant(opcode) < V_PUSHX ) ++ if ((am == 3 && reg == 0) // #N operand ++ || (am == 0 && reg == 3) // R3 is illegal as dest: may be data section. ++ ) ++ { ++ strcpy (comm, _("Illegal as 1-op instr")); ++ return -1; ++ } ++ ++ // extract repeat count if any ++ if ( am == 0 ) // extension word for register mode + { +- 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); +- } ++ if (insn & 0x008f) // repetitions ++ { ++ if (insn & 0x0080) ++ *repeats = insn & 0xf; // positive number is Rn ++ else ++ *repeats = 0 - (insn & 0xf); // negative number is #N ++ } + } + +- /* Destination. Special care needed on addr + XXXX. */ ++ // extract operands ++ dst = msp430dis_operand(addr + cmd_len, info, reg, am, &cmd_len) | ((insn & 0x0000000f) << 16); ++ dst = (dst << 12) >> 12; // sign extension ++ msp430x_decode_operand(reg, am, addr + cmd_len, dst, OP_20BIT, op, comm); ++ ++ return cmd_len; ++} ++ ++static int ++msp430x_exception (disassemble_info *info, ++ struct msp430_opcode_s const *opcode, ++ bfd_vma addr, ++ unsigned int insn, ++ char *op1, ++ char *op2, ++ char *comm1, ++ char *comm2, ++ opwidth_t *op_width) ++{ ++ int reg = 0; ++ int cmd_len = 2; ++ int n = 0; ++ int dst = 0; ++ ++ reg = insn & 0xf; + +- if (ad == 0) ++ switch(opcode_variant(opcode)) + { +- /* Register. */ +- if (regd == 0) +- { +- *cycles += 1; +- sprintf (op2, "r0"); +- } +- else if (regd == 1) +- sprintf (op2, "r1"); ++ case V_CALLA: ++ switch((insn >> 4) & 0xf) ++ { ++ case 4: // Rdst ++ msp430x_decode_operand(reg, 0, 0, 0, 0, op1, comm1); ++ break; ++ case 5: // x(Rdst) ++ dst = (short)msp430dis_operand(addr + cmd_len, info, reg, 1, &cmd_len); ++ msp430x_decode_operand(reg, 1, addr + cmd_len, dst, OP_16BIT, op1, comm1); ++ break; ++ case 6: // @Rdst ++ msp430x_decode_operand(reg, 2, 0, 0, 0, op1, comm1); ++ break; ++ case 7: // @Rdst+ ++ msp430x_decode_operand(reg, 3, 0, 0, 0, op1, comm1); ++ break; ++ case 8: // &abs20 ++ dst = msp430dis_operand(addr + cmd_len, info, 2, 1, &cmd_len) | ((insn & 0x000f) << 16); ++ msp430x_decode_operand(2, 1, addr + cmd_len, dst, OP_20BIT_HEX, op1, comm1); ++ break; ++ case 9: // EDE ++ dst = msp430dis_operand(addr + cmd_len, info, 0, 1, &cmd_len) | ((insn & 0x000f) << 16); ++ msp430x_decode_operand(0, 1, addr + cmd_len, dst, OP_20BIT, op1, comm1); ++ break; ++ case 0xb: // #imm20 ++ dst = msp430dis_operand(addr + cmd_len, info, 0, 3, &cmd_len) | ((insn & 0x000f) << 16); ++ msp430x_decode_operand(0, 3, addr + cmd_len, dst, OP_20BIT_HEX, op1, comm1); ++ break; ++ } ++ break; ++ case V_PUSHM: ++ n = ((insn >> 4) & 0xf) + 1; ++ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N ++ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst ++ if ((insn & 0x0100) == 0) ++ *op_width = ADDR_OP; ++ break; ++ case V_POPM: ++ n = ((insn >> 4) & 0xf) + 1; ++ reg = (reg + n - 1) & 0xf; ++ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N ++ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst ++ if ((insn & 0x0100) == 0) ++ *op_width = ADDR_OP; ++ break; ++ case V_ROTM: ++ n = ((insn >> 10) & 0x3) + 1; ++ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N ++ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst ++ if ((insn & 0x0010) == 0) ++ *op_width = ADDR_OP; ++ break; ++ default: ++ break; ++ } ++ return cmd_len; ++} ++ ++static int ++msp430x_doubleoperand (disassemble_info *info, ++ struct msp430_opcode_s const *opcode, ++ bfd_vma addr, ++ unsigned int insn, ++ char *op1, ++ char *op2, ++ char *comm1, ++ char *comm2, ++ opwidth_t *op_width, ++ int *repeats) ++{ ++ int regs, regd; ++ int as, ad; ++ int ops, opd; ++ int cmd_len = 4; + +- else if (regd == 2) +- sprintf (op2, "r2"); ++ regd = (insn >> 16) & 0xf; ++ regs = (insn >> 24) & 0xf; ++ as = (insn >> 20) & 0x3; ++ ad = (insn >> 23) & 0x1; + +- else +- sprintf (op2, "r%d", regd); ++ if (ad == 0 && regd == 3) ++ { ++ // R3 is illegal as dest: may be data section. ++ if (comm1) ++ strcpy (comm1, _("Illegal as 2-op instr")); ++ else if (comm2) ++ strcpy (comm2, _("Illegal as 2-op instr")); ++ return -1; + } +- else /* ad == 1. */ ++ *op_width = msp430x_opwidth(insn); ++ ++ // extract repeat count if any ++ if ( as == 0 && ad == 0 ) // extension word for register mode + { +- * 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); +- } ++ if (insn & 0x008f) // repetitions ++ { ++ if (insn & 0x0080) ++ *repeats = insn & 0xf; // positive number is Rn ++ else ++ *repeats = 0 - (insn & 0xf); // negative number is #N ++ } + } ++ // extract operands ++ ops = msp430dis_operand(addr + cmd_len, info, regs, as, &cmd_len) | ((insn & 0x00000780) << 9); ++ ops = (ops << 12) >> 12; // sign extension ++ msp430x_decode_operand(regs, as, addr + cmd_len, ops, OP_20BIT, op1, comm1); ++ ++ opd = msp430dis_operand(addr + cmd_len, info, regd, ad, &cmd_len) | ((insn & 0x0000000f) << 16); ++ opd = (opd << 12) >> 12; // sign extension ++ if (opcode_variant(opcode) == V_X_SHIFT ++ && ((0 == (as | ad) && ops != opd) /* non-register extension different ops */ ++ || regs != regd)) /* register extension different regs */ ++ return 0; // different operand => not emulated shift ++ ++ msp430x_decode_operand(regd, ad, addr + cmd_len, opd, OP_20BIT, op2, comm2); + + return cmd_len; + } + + static int +-msp430_branchinstr (disassemble_info *info, +- struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED, +- bfd_vma addr ATTRIBUTE_UNUSED, ++msp430x_address (disassemble_info *info, ++ bfd_vma addr, + unsigned short insn, + char *op1, ++ char *op2, + char *comm1, +- int *cycles) ++ char *comm2) + { +- int regs = 0, regd = 0; +- int as = 0; + int cmd_len = 2; +- short dst = 0; +- +- regd = insn & 0x0f; +- regs = (insn & 0x0f00) >> 8; +- as = (insn & 0x0030) >> 4; +- +- if (regd != 0) /* Destination register is not a PC. */ +- return 0; +- +- /* dst is a source register. */ +- if (as == 0) ++ int dst = 0; ++ typedef struct + { +- /* Constants. */ +- if (regs == 3) +- { +- *cycles = 1; +- sprintf (op1, "#0"); +- sprintf (comm1, "r3 As==00"); +- } +- else +- { +- /* Register. */ +- *cycles = 1; +- sprintf (op1, "r%d", regs); +- } ++ int as, regs; ++ int ad, regd; ++ int length; + } +- else if (as == 2) ++ operands_t; ++ ++ static operands_t const operands_table[] = + { +- 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) ++ { 2, -1, 0, -1, 0 }, // 0 @Rsrc, Rdst ++ { 3, -1, 0, -1, 0 }, // 1 @Rsrc+, Rdst ++ { 1, 2, 0, -1, 2 }, // 2 &abs20, Rdst ++ { 1, -1, 0, -1, 2 }, // 3 x(Rsrc), Rdst ++ { 0, 0, 0, 0, 0 }, // 4 ++ { 0, 0, 0, 0, 0 }, // 5 ++ { 0, -1, 1, 2, 2 }, // 6 Rsrc, &abs20 ++ { 0, -1, 1, -1, 2 }, // 7 Rsrc, x(Rdst) ++ { 3, 0, 0, -1, 2 }, // 8 #imm20, Rdst ++ { 3, 0, 0, -1, 2 }, // 9 #imm20, Rdst ++ { 3, 0, 0, -1, 2 }, // a #imm20, Rdst ++ { 3, 0, 0, -1, 2 }, // b #imm20, Rdst ++ { 0, -1, 0, -1, 0 }, // c Rsrc, Rdst ++ { 0, -1, 0, -1, 0 }, // d Rsrc, Rdst ++ { 0, -1, 0, -1, 0 }, // e Rsrc, Rdst ++ { 0, -1, 0, -1, 0 }, // f Rsrc, Rdst ++ }; ++ ++ operands_t operands = operands_table[(insn >> 4) & 0xf]; ++ if(((insn >> 4) & 0xf) == 6) ++ dst = msp430dis_opcode (addr + cmd_len, info) | ((insn & 0x000f) << 16); ++ else if(((insn >> 4) & 0xb) == 3) ++ dst = (short)msp430dis_opcode (addr + cmd_len, info); ++ else if(operands.length != 0) ++ dst = msp430dis_opcode(addr + cmd_len, info) | ((insn & 0x0f00) << 8); ++ ++ if(operands.regs == -1) ++ operands.regs = (insn >> 8 ) & 0x000f; ++ if(operands.regd == -1) ++ operands.regd = (insn >> 0 ) & 0x000f; ++ ++ if (operands.regd == 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); +- } ++ // R3 is illegal as dest: may be data section. ++ if (comm1) ++ strcpy (comm1, _("Illegal as address instr")); ++ else if (comm2) ++ strcpy (comm2, _("Illegal as address instr")); ++ return -1; + } +- else if (as == 1) +- { +- * cycles = 3; ++ // extract operands ++ msp430x_decode_operand(operands.regs, operands.as, addr + cmd_len, dst, ++ ((insn >> 4) & 0xf) == 3 ? OP_16BIT_HEX : OP_20BIT_HEX, op1, comm1); ++ msp430x_decode_operand(operands.regd, operands.ad, addr + cmd_len, dst, ++ ((insn >> 4) & 0xf) == 7 ? OP_16BIT_HEX : OP_20BIT_HEX, op2, comm2); ++ return cmd_len + operands.length; ++} + +- 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); +- } +- } ++static int ++msp430x_emulated (disassemble_info *info, ++ struct msp430_opcode_s const *opcode, ++ bfd_vma addr, ++ unsigned int insn, ++ char *op1, ++ char *comm1, ++ opwidth_t *op_width, ++ int *repeats) ++{ + +- return cmd_len; ++ switch(opcode_variant(opcode)) ++ { ++ case V_NONE: ++ case V_X_SHIFT: ++ // emulated by double operand instruction ++ return msp430x_doubleoperand(info, opcode, addr, insn, (char *)0, op1, ++ (char *)0, comm1, op_width, repeats); ++ case V_RETA: // reta, substituted by mova ++ return 2; ++ case V_EMU_ADDR: // substituted by other address instruction ++ return msp430x_address(info, addr, insn, (char *)0, op1, ++ (char *)0, comm1); ++ case V_BRA: // bra, substituted by mova ++ return msp430x_address(info, addr, insn, op1, (char *)0, ++ comm1, (char *)0); ++ default: ++ break; ++ } ++ return 0; + } + + int +@@ -668,22 +668,32 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) + { + void *stream = info->stream; + fprintf_ftype prin = info->fprintf_func; +- struct msp430_opcode_s *opcode; ++ struct msp430_opcode_s const *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. */ +- ++ unsigned int insn; ++ int repeats = 0; ++ int cpu = (bfd_mach_msp430x == info->mach) ? MSP430_CPU_MSP430X : MSP430_CPU_MSP430; ++ ++ opwidth_t op_width = DEFAULT_OP; // word instruction by default ++ static char const *width_modifier[] = ++ {"", "", ".b", ".a" }; ++ + insn = msp430dis_opcode (addr, info); +- sprintf (dinfo, "0x%04x", insn); + +- if (((int) addr & 0xffff) > 0xffdf) ++#if 0 ++ if ( (core == CORE_430 && ((int) addr & 0xffff) >= 0xffe0) ++ || ( core == CORE_430X && (((int) addr & 0xfffff) >= 0xffc0) && ((int) addr & 0xfffff) < 0x10000) ++ || ( core == CORE_430X2 && (((int) addr & 0xfffff) >= 0xff80) && ((int) addr & 0xfffff) < 0x10000) ++ ) + { + (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn); + return 2; + } ++#endif ++ ++ if (cpu >= MSP430_CPU_MSP430X && ((insn & 0xf800) == 0x1800)) // Extended instruction ++ insn |= msp430dis_opcode(addr + 2, info) << 16; + + *comm1 = 0; + *comm2 = 0; +@@ -691,62 +701,107 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) + for (opcode = msp430_opcodes; opcode->name; opcode++) + { + if ((insn & opcode->bin_mask) == opcode->bin_opcode +- && opcode->bin_opcode != 0x9300) ++// && opcode->bin_opcode != 0x9300 // was disasm tst instruction as cmp #0, dst? ++ ) + { + *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) ++ /* unsupported instruction */ ++ if(opcode_format(opcode) >= FMT_X && cpu < MSP430_CPU_MSP430X) ++ break; ++ ++ /* r0 as destination. Ad should be zero. Rdst=0 and Ad=0 are encoded in opcode & opcode_mask */ ++ if (opcode_format(opcode) == FMT_EMULATED && opcode_variant(opcode) == V_BR) + { + cmd_len = +- msp430_branchinstr (info, opcode, addr, insn, op1, comm1, +- &cycles); ++ msp430_branchinstr (info, opcode, addr, insn, op1, comm1); + 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(opcode_format(opcode) < FMT_X) ++ switch (opcode->insn_opnumb) ++ { ++ case 0: ++ cmd_len = msp430_nooperands (opcode, addr, insn, comm1); ++ break; ++ case 2: ++ cmd_len = ++ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, ++ comm1, comm2); ++ if (insn & BYTE_OPERATION) ++ op_width = BYTE_OP; ++ break; ++ case 1: ++ cmd_len = ++ msp430_singleoperand (info, opcode, addr, insn, op1, comm1); ++ if (insn & BYTE_OPERATION && opcode_format(opcode) != FMT_JUMP) ++ op_width = BYTE_OP; ++ break; ++ default: ++ break; ++ } ++ else // 430x instruction ++ switch(opcode_format(opcode)) ++ { ++ case FMT_X_SINGLE_OPERAND: ++ if( opcode_variant(opcode) == V_SWPSXT // swpbx, sxtx ++ && (insn & (NON_ADDR_OPERATION | BYTE_OPERATION_X)) == 0) // .a, special case ++ insn ^= BYTE_OPERATION_X; // make A/L, B/W as ordinary ++ ++ op_width = msp430x_opwidth(insn); ++ ++ if( opcode_variant(opcode) == V_SWPSXT && op_width == BYTE_OP) // swpbx, sxtx ++ strcpy (comm1, _("Illegal A/L, B/W bits setting")); ++ ++ cmd_len = msp430x_singleoperand (info, opcode, addr, insn, op1, comm1, ++ &repeats); ++ break; ++ case FMT_X_EXCEPTION: ++ cmd_len = msp430x_exception (info, opcode, addr, insn, op1, op2, ++ comm1, comm2, &op_width); ++ break; ++ case FMT_X_DOUBLE_OPERAND: ++ cmd_len = msp430x_doubleoperand (info, opcode, addr, insn, op1, op2, ++ comm1, comm2, &op_width, &repeats); ++ break; ++ case FMT_X_EMULATED: ++ cmd_len = msp430x_emulated (info, opcode, addr, insn, op1, ++ comm1, &op_width, &repeats); ++ break; ++ ++ case FMT_X_ADDRESS: ++ cmd_len = msp430x_address (info, addr, insn, op1, op2, ++ comm1, comm2); ++ 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)); ++ (*prin) (stream, ".word 0x%04x; ????\t%s%s", PS (insn), comm1, comm2); + return 2; + } + +- (*prin) (stream, "%s%s", opcode->name, bc); ++ ++ if (repeats) ++ { ++ if (repeats < 0) ++ (*prin) (stream, ".rpt\t#%d\n\t\t\t\t", 0 - repeats); ++ else ++ (*prin) (stream, ".rpt\tr%d\n\t\t\t\t", repeats); ++ } ++ ++ (*prin) (stream, "%s%s", opcode->name, width_modifier[op_width]); + + if (*op1) + (*prin) (stream, "\t%s", op1); +@@ -765,23 +820,11 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) + + 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, ","); ++ (*prin) (stream, ", "); + if (*comm2) +- (*prin) (stream, " %s", comm2); ++ (*prin) (stream, "%s", comm2); + return cmd_len; + } diff -Nru binutils-msp430-2.21~msp20110716/lts-20110716.patch binutils-msp430-2.22~msp20110716p5/lts-20110716.patch --- binutils-msp430-2.21~msp20110716/lts-20110716.patch 2011-08-15 19:47:39.000000000 +0000 +++ binutils-msp430-2.22~msp20110716p5/lts-20110716.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,7327 +0,0 @@ -diff --git a/bfd/archures.c b/bfd/archures.c -index 44850e7..91f557f 100644 ---- a/bfd/archures.c -+++ b/bfd/archures.c -@@ -413,21 +413,8 @@ DESCRIPTION - . bfd_arch_xstormy16, - .#define bfd_mach_xstormy16 1 - . bfd_arch_msp430, {* Texas Instruments MSP430 architecture. *} --.#define bfd_mach_msp11 11 --.#define bfd_mach_msp110 110 --.#define bfd_mach_msp12 12 --.#define bfd_mach_msp13 13 --.#define bfd_mach_msp14 14 --.#define bfd_mach_msp15 15 --.#define bfd_mach_msp16 16 --.#define bfd_mach_msp21 21 --.#define bfd_mach_msp31 31 --.#define bfd_mach_msp32 32 --.#define bfd_mach_msp33 33 --.#define bfd_mach_msp41 41 --.#define bfd_mach_msp42 42 --.#define bfd_mach_msp43 43 --.#define bfd_mach_msp44 44 -+.#define bfd_mach_msp430 430 -+.#define bfd_mach_msp430x 431 - . bfd_arch_xc16x, {* Infineon's XC16X Series. *} - .#define bfd_mach_xc16x 1 - .#define bfd_mach_xc16xl 2 -diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index ac8145d..2b69aab 100644 ---- a/bfd/bfd-in2.h -+++ b/bfd/bfd-in2.h -@@ -2116,21 +2116,8 @@ enum bfd_architecture - bfd_arch_xstormy16, - #define bfd_mach_xstormy16 1 - bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ --#define bfd_mach_msp11 11 --#define bfd_mach_msp110 110 --#define bfd_mach_msp12 12 --#define bfd_mach_msp13 13 --#define bfd_mach_msp14 14 --#define bfd_mach_msp15 15 --#define bfd_mach_msp16 16 --#define bfd_mach_msp21 21 --#define bfd_mach_msp31 31 --#define bfd_mach_msp32 32 --#define bfd_mach_msp33 33 --#define bfd_mach_msp41 41 --#define bfd_mach_msp42 42 --#define bfd_mach_msp43 43 --#define bfd_mach_msp44 44 -+#define bfd_mach_msp430 430 -+#define bfd_mach_msp430x 431 - bfd_arch_xc16x, /* Infineon's XC16X Series. */ - #define bfd_mach_xc16x 1 - #define bfd_mach_xc16xl 2 -@@ -4645,6 +4632,25 @@ This is the 5 bits of a value. */ - BFD_RELOC_MSP430_16_BYTE, - BFD_RELOC_MSP430_2X_PCREL, - BFD_RELOC_MSP430_RL_PCREL, -+ BFD_RELOC_MSP430X_SRC_BYTE, -+ BFD_RELOC_MSP430X_SRC, -+ BFD_RELOC_MSP430X_DST_BYTE, -+ BFD_RELOC_MSP430X_DST, -+ BFD_RELOC_MSP430X_DST_2ND_BYTE, -+ BFD_RELOC_MSP430X_DST_2ND, -+ BFD_RELOC_MSP430X_PCREL_SRC_BYTE, -+ BFD_RELOC_MSP430X_PCREL_SRC, -+ BFD_RELOC_MSP430X_PCREL_DST_BYTE, -+ BFD_RELOC_MSP430X_PCREL_DST, -+ BFD_RELOC_MSP430X_PCREL_DST_2ND, -+ BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE, -+ BFD_RELOC_MSP430X_S_BYTE, -+ BFD_RELOC_MSP430X_S, -+ BFD_RELOC_MSP430X_D_BYTE, -+ BFD_RELOC_MSP430X_D, -+ BFD_RELOC_MSP430X_PCREL_D, -+ BFD_RELOC_MSP430X_INDXD, -+ BFD_RELOC_MSP430X_PCREL_INDXD, - - /* IQ2000 Relocations. */ - BFD_RELOC_IQ2000_OFFSET_16, -diff --git a/bfd/cpu-msp430.c b/bfd/cpu-msp430.c -index 63c301a..9e9fcdd 100644 ---- a/bfd/cpu-msp430.c -+++ b/bfd/cpu-msp430.c -@@ -23,86 +23,14 @@ - #include "bfd.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]), -- -- /* msp430x11x1. */ -- N (16, bfd_mach_msp110, "msp:110", FALSE, & arch_info_struct[2]), -- -- /* msp430x12x. */ -- N (16, bfd_mach_msp12, "msp:12", FALSE, & arch_info_struct[3]), -- -- /* msp430x13x. */ -- N (16, bfd_mach_msp13, "msp:13", FALSE, & arch_info_struct[4]), -- -- /* msp430x14x. */ -- N (16, bfd_mach_msp14, "msp:14", FALSE, & arch_info_struct[5]), -- -- /* msp430x15x. */ -- N (16, bfd_mach_msp15, "msp:15", FALSE, & arch_info_struct[6]), -- -- /* msp430x16x. */ -- N (16, bfd_mach_msp16, "msp:16", FALSE, & arch_info_struct[7]), -- -- /* msp430x21x. */ -- N (16, bfd_mach_msp21, "msp:21", FALSE, & arch_info_struct[8]), -- -- /* msp430x31x. */ -- N (16, bfd_mach_msp31, "msp:31", FALSE, & arch_info_struct[9]), -- -- /* msp430x32x. */ -- N (16, bfd_mach_msp32, "msp:32", FALSE, & arch_info_struct[10]), -- -- /* msp430x33x. */ -- N (16, bfd_mach_msp33, "msp:33", FALSE, & arch_info_struct[11]), -- -- /* msp430x41x. */ -- N (16, bfd_mach_msp41, "msp:41", FALSE, & arch_info_struct[12]), -- -- /* msp430x42x. */ -- N (16, bfd_mach_msp42, "msp:42", FALSE, & arch_info_struct[13]), -- -- /* msp430x43x. */ -- N (16, bfd_mach_msp43, "msp:43", FALSE, & arch_info_struct[14]), -- -- /* msp430x44x. */ -- N (16, bfd_mach_msp43, "msp:44", 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. */ -- -+ 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; -+compatible (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 & b are for different architectures we can do nothing */ - if (a->arch != b->arch) - return NULL; - -@@ -111,3 +39,35 @@ compatible (a,b) - - return a; - } -+ -+/* Architecture for MSP430X and MSP430XV2 */ -+static const bfd_arch_info_type bfd_msp430x_arch = { -+ 16, /* 16 bits in a word */ -+ 20, /* 20 bits in an address */ -+ 8, /* 8 bits in a byte */ -+ bfd_arch_msp430, -+ bfd_mach_msp430x, /* Machine number */ -+ "msp430", /* Architecture name. */ -+ "msp430:430X", /* Printable name */ -+ 1, /* Section align power */ -+ FALSE, /* The default machine */ -+ compatible, -+ bfd_default_scan, -+ 0 -+}; -+ -+/* Architecture for MSP430 */ -+const bfd_arch_info_type bfd_msp430_arch = { -+ 16, /* 16 bits in a word */ -+ 16, /* 16 bits in an address */ -+ 8, /* 8 bits in a byte */ -+ bfd_arch_msp430, -+ bfd_mach_msp430, /* Machine number */ -+ "msp430", /* Architecture name */ -+ "msp430:430", /* Printable name */ -+ 1, /* Section align power */ -+ TRUE, /* The default machine */ -+ compatible, -+ bfd_default_scan, -+ &bfd_msp430x_arch -+}; -diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c -index 9a5fb2a..8a217fa 100644 ---- a/bfd/elf32-msp430.c -+++ b/bfd/elf32-msp430.c -@@ -90,7 +90,7 @@ static reloc_howto_type elf_msp430_howto_table[] = - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - -- /* A 16 bit absolute relocation for command address. */ -+ /* A 16 bit PC relative relocation for command address. */ - HOWTO (R_MSP430_16_PCREL, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ -@@ -120,7 +120,7 @@ static reloc_howto_type elf_msp430_howto_table[] = - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - -- /* A 16 bit absolute relocation for command address. */ -+ /* A 16 bit PC relative relocation, byte operations. */ - HOWTO (R_MSP430_16_PCREL_BYTE,/* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ -@@ -163,7 +163,292 @@ static reloc_howto_type elf_msp430_howto_table[] = - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0xffff, /* dst_mask */ -- TRUE) /* pcrel_offset */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute src operand relocation, byte operations */ -+ HOWTO (R_MSP430X_SRC_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_SRC_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute src operand relocation */ -+ HOWTO (R_MSP430X_SRC, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_SRC", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute dst operand relocation, src is register mode, byte operations */ -+ HOWTO (R_MSP430X_DST_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_DST_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute dst operand relocation, src is register mode */ -+ HOWTO (R_MSP430X_DST, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_DST", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute dst operand relocation, byte operations */ -+ HOWTO (R_MSP430X_DST_2ND_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_DST_2ND_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x absolute dst operand relocation */ -+ HOWTO (R_MSP430X_DST_2ND, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_DST_2ND", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative src operand relocation, byte operations */ -+ HOWTO (R_MSP430X_PCREL_SRC_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_SRC_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative src operand relocation */ -+ HOWTO (R_MSP430X_PCREL_SRC, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_SRC", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative dst operand relocation, src is register mode, byte operations */ -+ HOWTO (R_MSP430X_PCREL_DST_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_DST_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative dst operand relocation, src is register mode */ -+ HOWTO (R_MSP430X_PCREL_DST, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_DST", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative dst operand relocation, byte operations */ -+ HOWTO (R_MSP430X_PCREL_DST_2ND_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_DST_2ND_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x PC relative dst operand relocation */ -+ HOWTO (R_MSP430X_PCREL_DST_2ND, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_DST_2ND", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x address instructions immediate src operand relocation */ -+ HOWTO (R_MSP430X_S_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_S_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x address instructions absolute src operand relocation */ -+ HOWTO (R_MSP430X_S, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_S", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x address instructions immediate dst operand relocation */ -+ HOWTO (R_MSP430X_D_BYTE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_D_BYTE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x address instructions absolute dst operand relocation */ -+ HOWTO (R_MSP430X_D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit msp430x address instructions absolute dst operand relocation */ -+ HOWTO (R_MSP430X_PCREL_D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_MSP430X_PCREL_D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 16 bit msp430x relocation *** for msp430x calla 16-bit PC-relative index ***/ -+ HOWTO (R_MSP430X_PCREL_INDXD, /* type */ -+ 0, /* 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_MSP430X_PCREL_INDXD", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 16 bit msp430x relocation *** for msp430x bra/calla 16-bit index ***/ -+ HOWTO (R_MSP430X_INDXD, /* 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_MSP430X_INDXD", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - }; - - /* Map BFD reloc types to MSP430 ELF reloc types. */ -@@ -185,7 +470,29 @@ static const struct msp430_reloc_map msp430_reloc_map[] = - {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE}, - {BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE}, - {BFD_RELOC_MSP430_2X_PCREL, R_MSP430_2X_PCREL}, -- {BFD_RELOC_MSP430_RL_PCREL, R_MSP430_RL_PCREL} -+ {BFD_RELOC_MSP430_RL_PCREL, R_MSP430_RL_PCREL}, -+ -+ {BFD_RELOC_MSP430X_SRC_BYTE, R_MSP430X_SRC_BYTE}, -+ {BFD_RELOC_MSP430X_SRC, R_MSP430X_SRC}, -+ {BFD_RELOC_MSP430X_DST_BYTE, R_MSP430X_DST_BYTE}, -+ {BFD_RELOC_MSP430X_DST, R_MSP430X_DST}, -+ {BFD_RELOC_MSP430X_DST_2ND_BYTE, R_MSP430X_DST_2ND_BYTE}, -+ {BFD_RELOC_MSP430X_DST_2ND, R_MSP430X_DST_2ND}, -+ -+ {BFD_RELOC_MSP430X_PCREL_SRC_BYTE, R_MSP430X_PCREL_SRC_BYTE}, -+ {BFD_RELOC_MSP430X_PCREL_SRC, R_MSP430X_PCREL_SRC}, -+ {BFD_RELOC_MSP430X_PCREL_DST_BYTE, R_MSP430X_PCREL_DST_BYTE}, -+ {BFD_RELOC_MSP430X_PCREL_DST, R_MSP430X_PCREL_DST}, -+ {BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE, R_MSP430X_PCREL_DST_2ND_BYTE}, -+ {BFD_RELOC_MSP430X_PCREL_DST_2ND, R_MSP430X_PCREL_DST_2ND}, -+ -+ {BFD_RELOC_MSP430X_S_BYTE, R_MSP430X_S_BYTE}, -+ {BFD_RELOC_MSP430X_S, R_MSP430X_S}, -+ {BFD_RELOC_MSP430X_D_BYTE, R_MSP430X_D_BYTE}, -+ {BFD_RELOC_MSP430X_D, R_MSP430X_D}, -+ {BFD_RELOC_MSP430X_PCREL_D, R_MSP430X_PCREL_D}, -+ {BFD_RELOC_MSP430X_INDXD, R_MSP430X_INDXD}, -+ {BFD_RELOC_MSP430X_PCREL_INDXD, R_MSP430X_PCREL_INDXD}, - }; - - static reloc_howto_type * -@@ -207,10 +514,7 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, - { - unsigned int i; - -- for (i = 0; -- i < (sizeof (elf_msp430_howto_table) -- / sizeof (elf_msp430_howto_table[0])); -- i++) -+ for (i = 0; i < ARRAY_SIZE (elf_msp430_howto_table); i++) - if (elf_msp430_howto_table[i].name != NULL - && strcasecmp (elf_msp430_howto_table[i].name, r_name) == 0) - return &elf_msp430_howto_table[i]; -@@ -282,18 +586,44 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, - { - bfd_reloc_status_type r = bfd_reloc_ok; - bfd_vma x; -- bfd_signed_vma srel; -+ bfd_signed_vma srel = 0; - -- switch (howto->type) -+ if (howto->type > R_MSP430_32 && howto->type < R_MSP430_max) - { -- case R_MSP430_10_PCREL: - contents += rel->r_offset; - srel = (bfd_signed_vma) relocation; - srel += rel->r_addend; -- srel -= rel->r_offset; -+ -+ if(howto->pc_relative) -+ { -+ srel -= rel->r_offset; -+ srel -= (input_section->output_section->vma + -+ input_section->output_offset); -+ } -+ -+ switch (howto->type) -+ { -+ case R_MSP430X_PCREL_D: // PC relative dst operand of calla -+ case R_MSP430X_PCREL_INDXD: // 16-bit idx in mova/bra instruction PC relative (symbolic) mode operand -+ srel -= 2; // operand located 2 bytes after opcode -+ break; -+ case R_MSP430X_PCREL_SRC: // PC-relative 20-bit address operand -+ case R_MSP430X_PCREL_SRC_BYTE: -+ case R_MSP430X_PCREL_DST: -+ case R_MSP430X_PCREL_DST_BYTE: -+ srel -= 4; // operand located 4 bytes after opcode -+ break; -+ case R_MSP430X_PCREL_DST_2ND: -+ case R_MSP430X_PCREL_DST_2ND_BYTE: -+ srel -= 6; // operand located 6 bytes after opcode -+ break; -+ } -+ } -+ -+ switch (howto->type) -+ { -+ case R_MSP430_10_PCREL: - 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; -@@ -311,13 +641,7 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, - break; - - case R_MSP430_2X_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; -@@ -341,13 +665,7 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, - - case R_MSP430_16_PCREL: - case R_MSP430_RL_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; -@@ -356,35 +674,138 @@ msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd, - 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; - -+ case R_MSP430X_SRC: // address operand -+ case R_MSP430X_PCREL_SRC: // PC-relative address operand -+ -+ // 20 bit reloc for msp430x -+ // src in Non-register mode extended instructions, -+ // imm/abs in bra instruction -+ -+ // src(19:16) located at positions 10:7 of extension word -+ // src(15:0) located just after opcode -+ -+ if (srel & 1) // odd address -+ return bfd_reloc_notsupported; -+ /* and fall trough, no break here!!! */ -+ case R_MSP430X_SRC_BYTE: // byte instructions or immediate operand -+ case R_MSP430X_PCREL_SRC_BYTE: -+ x = bfd_get_16 (input_bfd, contents); -+ /* 4 most-significant bits */ -+ x = (x & 0xf87f) | ((srel >> 9) & 0x0780); -+ bfd_put_16 (input_bfd, x, contents); -+ /* 16 least-significant bits */ -+ bfd_put_16 (input_bfd, srel & 0xffff, contents + 4); -+ break; -+ -+ case R_MSP430X_DST: // address operand -+ case R_MSP430X_PCREL_DST: -+ -+ // 20 bit reloc for msp430x -+ // dst in Non-register mode extended instructions, -+ // imm/abs/20-bit idx in calla instruction -+ -+ // dst(19:16) located at positions 3:0 of extension word -+ // dst(15:0) located just after opcode -+ -+ if (srel & 1) // odd address -+ return bfd_reloc_notsupported; -+ /* and fall trough, no break here!!! */ -+ case R_MSP430X_DST_BYTE: // byte instructions or immediate operand -+ case R_MSP430X_PCREL_DST_BYTE: -+ x = bfd_get_16 (input_bfd, contents); -+ /* 4 most-significant bits */ -+ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); -+ bfd_put_16 (input_bfd, x, contents); -+ /* 16 least-significant bits */ -+ bfd_put_16 (input_bfd, srel & 0xffff, contents + 4); -+ break; -+ -+ case R_MSP430X_DST_2ND: // address operand -+ case R_MSP430X_PCREL_DST_2ND: -+ -+ // 20 bit reloc for msp430x -+ // dst in Non-register mode extended instructions, -+ -+ // dst(19:16) located at positions 3:0 of extension word -+ // dst(15:0) located after src(15:0) -+ -+ if (srel & 1) // odd address -+ return bfd_reloc_notsupported; -+ /* and fall trough, no break here!!! */ -+ case R_MSP430X_DST_2ND_BYTE: // byte instructions or immediate operand -+ case R_MSP430X_PCREL_DST_2ND_BYTE: -+ x = bfd_get_16 (input_bfd, contents); -+ /* 4 most-significant bits */ -+ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); -+ bfd_put_16 (input_bfd, x, contents); -+ /* 16 least-significant bits */ -+ bfd_put_16 (input_bfd, srel & 0xffff, contents + 6); -+ break; -+ -+ case R_MSP430X_S: // absolute src operand of address instructions -+ // 20 bit reloc for msp430x -+ -+ // src(19:16) located at positions 11:8 of opcode -+ // src(15:0) located just after opcode -+ -+ if (srel & 1) //odd address -+ return bfd_reloc_notsupported; -+ /* and fall trough, no break here!!! */ -+ case R_MSP430X_S_BYTE: // immediate src operand of address instructions -+ x = bfd_get_16 (input_bfd, contents); -+ /* 4 most-significant bits */ -+ x = (x & 0xf0ff) | ((srel >> 8) & 0x0f00); -+ bfd_put_16 (input_bfd, x, contents); -+ /* 16 least-significant bits */ -+ bfd_put_16 (input_bfd, srel & 0xffff, contents + 2); -+ break; -+ -+ case R_MSP430X_D: // absolute dst operand of address instructions -+ case R_MSP430X_PCREL_D: // PC relative dst operand of calla -+ // 20 bit reloc for msp430x, -+ -+ // dst(19:16) located at positions 3:0 of opcode -+ // dst(15:0) located just after opcode -+ -+ if (srel & 1) //odd address -+ return bfd_reloc_notsupported; -+ /* and fall trough, no break here!!! */ -+ case R_MSP430X_D_BYTE: //immediate dst operand of address instructions -+ -+ x = bfd_get_16 (input_bfd, contents); -+ /* 4 most-significant bits */ -+ x = (x & 0xfff0) | ((srel >> 16) & 0x000f); -+ bfd_put_16 (input_bfd, x, contents); -+ /* 16 least-significant bits */ -+ bfd_put_16 (input_bfd, srel & 0xffff, contents + 2); -+ break; -+ -+ case R_MSP430X_PCREL_INDXD: // 16-bit idx in mova/bra instruction PC relative (symbolic) mode operand -+ -+ if (srel & 1) //odd address -+ return bfd_reloc_notsupported; -+ case R_MSP430X_INDXD: // 16-bit idx in calla/mova/bra instruction -+ -+ x = srel & 0xffff; -+ bfd_put_16 (input_bfd, x, contents + 2); //16 least-significant bits -+ break; -+ - default: - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, rel->r_offset, -@@ -459,7 +880,12 @@ elf32_msp430_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - rel, relend, howto, contents); - - if (info->relocatable) -- continue; -+ { -+ BFD_ASSERT (! howto->partial_inplace); -+ if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) -+ rel->r_addend += sec->output_offset; -+ continue; -+ } - - r = msp430_final_link_relocate (howto, input_bfd, input_section, - contents, rel, relocation); -@@ -517,150 +943,54 @@ elf32_msp430_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - number. */ - - static void --bfd_elf_msp430_final_write_processing (bfd * abfd, -- bfd_boolean linker ATTRIBUTE_UNUSED) -+msp430_elf_backend_final_write_processing (bfd * abfd, -+ bfd_boolean linker ATTRIBUTE_UNUSED) - { -- unsigned long val; -+ Elf_Internal_Ehdr * i_ehdrp; -+ unsigned long flags; - -+ i_ehdrp = elf_elfheader (abfd); -+ i_ehdrp->e_machine = EM_MSP430; -+ flags = 0; - switch (bfd_get_mach (abfd)) - { - default: -- case bfd_mach_msp110: -- val = E_MSP430_MACH_MSP430x11x1; -- break; -- -- case bfd_mach_msp11: -- val = E_MSP430_MACH_MSP430x11; -- break; -- -- case bfd_mach_msp12: -- val = E_MSP430_MACH_MSP430x12; -- break; -- -- case bfd_mach_msp13: -- val = E_MSP430_MACH_MSP430x13; -- break; -- -- case bfd_mach_msp14: -- val = E_MSP430_MACH_MSP430x14; -- break; -- -- case bfd_mach_msp15: -- val = E_MSP430_MACH_MSP430x15; -- break; -- -- case bfd_mach_msp16: -- val = E_MSP430_MACH_MSP430x16; -- 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_msp41: -- val = E_MSP430_MACH_MSP430x41; -- break; -- -- case bfd_mach_msp42: -- val = E_MSP430_MACH_MSP430x42; -- break; -- -- case bfd_mach_msp43: -- val = E_MSP430_MACH_MSP430x43; -+ case bfd_mach_msp430: -+ flags = EF_MSP430_ARCH_430; - break; -- -- case bfd_mach_msp44: -- val = E_MSP430_MACH_MSP430x44; -+ case bfd_mach_msp430x: -+ flags = EF_MSP430_ARCH_430X; - break; - } -- -- elf_elfheader (abfd)->e_machine = EM_MSP430; -- elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH; -- elf_elfheader (abfd)->e_flags |= val; -+ i_ehdrp->e_flags = EF_MSP430_UNIARCH | flags; - } - - /* Set the right machine number. */ - - static bfd_boolean --elf32_msp430_object_p (bfd * abfd) -+msp430_elf_backend_object_p (bfd * abfd ATTRIBUTE_UNUSED) - { -- 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_MSP430x11: -- e_set = bfd_mach_msp11; -- break; -- -- case E_MSP430_MACH_MSP430x11x1: -- e_set = bfd_mach_msp110; -- break; -- -- case E_MSP430_MACH_MSP430x12: -- e_set = bfd_mach_msp12; -- 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_MSP430x15: -- e_set = bfd_mach_msp15; -- break; -- -- case E_MSP430_MACH_MSP430x16: -- e_set = bfd_mach_msp16; -- 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_MSP430x41: -- e_set = bfd_mach_msp41; -- break; -- -- case E_MSP430_MACH_MSP430x42: -- e_set = bfd_mach_msp42; -- break; -- -- case E_MSP430_MACH_MSP430x43: -- e_set = bfd_mach_msp43; -- break; -- -- case E_MSP430_MACH_MSP430x44: -- e_set = bfd_mach_msp44; -- break; -- } -- } -- -- return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set); -+ Elf_Internal_Ehdr * i_ehdrp; -+ int bfd_mach; -+ -+ i_ehdrp = elf_elfheader (abfd); -+ if (EM_MSP430 != i_ehdrp->e_machine) -+ return FALSE; -+ if (EF_MSP430_UNIARCH & i_ehdrp->e_flags) { -+ switch (i_ehdrp->e_flags & EF_MSP430_ARCH) -+ { -+ default: -+ case EF_MSP430_ARCH_430: -+ bfd_mach = bfd_mach_msp430; -+ break; -+ case EF_MSP430_ARCH_430X: -+ bfd_mach = bfd_mach_msp430x; -+ break; -+ } -+ } else { -+ bfd_mach = bfd_mach_msp430; -+ } -+ return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, bfd_mach); - } - - /* These functions handle relaxing for the msp430. -@@ -1167,13 +1497,12 @@ error_return: - #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_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 _bfd_elf_set_osabi - #define bfd_elf32_bfd_relax_section msp430_elf_relax_section -+#define elf_backend_final_write_processing msp430_elf_backend_final_write_processing -+#define elf_backend_object_p msp430_elf_backend_object_p - - #include "elf32-target.h" -diff --git a/bfd/libbfd.h b/bfd/libbfd.h -index 33069b0..6b2fc35 100644 ---- a/bfd/libbfd.h -+++ b/bfd/libbfd.h -@@ -2229,6 +2229,25 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", - "BFD_RELOC_MSP430_16_BYTE", - "BFD_RELOC_MSP430_2X_PCREL", - "BFD_RELOC_MSP430_RL_PCREL", -+ "BFD_RELOC_MSP430X_SRC_BYTE", -+ "BFD_RELOC_MSP430X_SRC", -+ "BFD_RELOC_MSP430X_DST_BYTE", -+ "BFD_RELOC_MSP430X_DST", -+ "BFD_RELOC_MSP430X_DST_2ND_BYTE", -+ "BFD_RELOC_MSP430X_DST_2ND", -+ "BFD_RELOC_MSP430X_PCREL_SRC_BYTE", -+ "BFD_RELOC_MSP430X_PCREL_SRC", -+ "BFD_RELOC_MSP430X_PCREL_DST_BYTE", -+ "BFD_RELOC_MSP430X_PCREL_DST", -+ "BFD_RELOC_MSP430X_PCREL_DST_2ND", -+ "BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE", -+ "BFD_RELOC_MSP430X_S_BYTE", -+ "BFD_RELOC_MSP430X_S", -+ "BFD_RELOC_MSP430X_D_BYTE", -+ "BFD_RELOC_MSP430X_D", -+ "BFD_RELOC_MSP430X_PCREL_D", -+ "BFD_RELOC_MSP430X_INDXD", -+ "BFD_RELOC_MSP430X_PCREL_INDXD", - "BFD_RELOC_IQ2000_OFFSET_16", - "BFD_RELOC_IQ2000_OFFSET_21", - "BFD_RELOC_IQ2000_UHI16", -diff --git a/bfd/reloc.c b/bfd/reloc.c -index 6ac7148..94127d5 100644 ---- a/bfd/reloc.c -+++ b/bfd/reloc.c -@@ -5314,6 +5314,44 @@ ENUMX - BFD_RELOC_MSP430_2X_PCREL - ENUMX - BFD_RELOC_MSP430_RL_PCREL -+ENUMX -+ BFD_RELOC_MSP430X_SRC_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_SRC -+ENUMX -+ BFD_RELOC_MSP430X_DST_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_DST -+ENUMX -+ BFD_RELOC_MSP430X_DST_2ND_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_DST_2ND -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_SRC_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_SRC -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_DST_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_DST -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_DST_2ND -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_S_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_S -+ENUMX -+ BFD_RELOC_MSP430X_D_BYTE -+ENUMX -+ BFD_RELOC_MSP430X_D -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_D -+ENUMX -+ BFD_RELOC_MSP430X_INDXD -+ENUMX -+ BFD_RELOC_MSP430X_PCREL_INDXD - ENUMDOC - msp430 specific relocation codes - -diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c -index 98d90c6..15eefb1 100644 ---- a/gas/config/tc-msp430.c -+++ b/gas/config/tc-msp430.c -@@ -23,7 +23,6 @@ - - #include - --#define PUSH_1X_WORKAROUND - #include "as.h" - #include "subsegs.h" - #include "opcode/msp430.h" -@@ -69,6 +68,7 @@ - - int msp430_enable_relax; - int msp430_enable_polys; -+int msp430x_repeats; // It's not a right way to use global variable, but I don't know other way how to do it - - /* GCC uses the some condition codes which we'll - implement as new polymorph instructions. -@@ -99,12 +99,13 @@ int msp430_enable_polys; - Also, we add 'jump' instruction: - jump UNCOND -> jmp br lab - -- They will have fmt == 4, and insn_opnumb == number of instruction. */ -+ They will have opcode_format() == FMT_EMULATED_POLYMORPH_JUMP, -+ and opcode_variant() == number of instruction. */ - - struct rcodes_s - { - char * name; -- int index; /* Corresponding insn_opnumb. */ -+ int index; /* Corresponding opcode_variant(). */ - int sop; /* Opcode if jump length is short. */ - long lpos; /* Label position. */ - long lop0; /* Opcode 1 _word_ (16 bits). */ -@@ -143,7 +144,7 @@ static struct rcodes_s msp430_rcodes[] = - struct hcodes_s - { - char * name; -- int index; /* Corresponding insn_opnumb. */ -+ int index; /* Corresponding opcode_variant(). */ - int tlab; /* Number of labels in short mode. */ - int op0; /* Opcode for first word of short jump. */ - int op1; /* Opcode for second word of short jump. */ -@@ -228,116 +229,373 @@ relax_typeS md_relax_table[] = - }; - - --#define MAX_OP_LEN 256 -- --struct mcu_type_s -+/** List known silicon errata with a description of the problem (where -+ * this can be found). Errata descriptions are available in PDF files -+ * that can be found on the device-specific web page at TI. Errata -+ * numbers are consistent across the product line. -+ * -+ * Note that not all documented errata are currently recognized by the -+ * assembler. In fact, most are completely ignored. Future work... -+ * -+ * Legacy errata descriptions are from previous versions of -+ * binutils. */ -+typedef enum msp430_errata_e - { -- char * name; -- int isa; -- int mach; --}; -- --#define MSP430_ISA_11 11 --#define MSP430_ISA_110 110 --#define MSP430_ISA_12 12 --#define MSP430_ISA_13 13 --#define MSP430_ISA_14 14 --#define MSP430_ISA_15 15 --#define MSP430_ISA_16 16 --#define MSP430_ISA_21 21 --#define MSP430_ISA_31 31 --#define MSP430_ISA_32 32 --#define MSP430_ISA_33 33 --#define MSP430_ISA_41 41 --#define MSP430_ISA_42 42 --#define MSP430_ISA_43 43 --#define MSP430_ISA_44 44 -- --#define CHECK_RELOC_MSP430 ((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16) --#define CHECK_RELOC_MSP430_PCREL ((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL) -- --static struct mcu_type_s mcu_types[] = --{ -- {"msp1", MSP430_ISA_11, bfd_mach_msp11}, -- {"msp2", MSP430_ISA_14, bfd_mach_msp14}, -- {"msp430x110", MSP430_ISA_11, bfd_mach_msp11}, -- {"msp430x112", MSP430_ISA_11, bfd_mach_msp11}, -- {"msp430x1101", MSP430_ISA_110, bfd_mach_msp110}, -- {"msp430x1111", MSP430_ISA_110, bfd_mach_msp110}, -- {"msp430x1121", MSP430_ISA_110, bfd_mach_msp110}, -- {"msp430x1122", MSP430_ISA_11, bfd_mach_msp110}, -- {"msp430x1132", MSP430_ISA_11, bfd_mach_msp110}, -- -- {"msp430x122", MSP430_ISA_12, bfd_mach_msp12}, -- {"msp430x123", MSP430_ISA_12, bfd_mach_msp12}, -- {"msp430x1222", MSP430_ISA_12, bfd_mach_msp12}, -- {"msp430x1232", MSP430_ISA_12, bfd_mach_msp12}, -- -- {"msp430x133", MSP430_ISA_13, bfd_mach_msp13}, -- {"msp430x135", MSP430_ISA_13, bfd_mach_msp13}, -- {"msp430x1331", MSP430_ISA_13, bfd_mach_msp13}, -- {"msp430x1351", MSP430_ISA_13, bfd_mach_msp13}, -- {"msp430x147", MSP430_ISA_14, bfd_mach_msp14}, -- {"msp430x148", MSP430_ISA_14, bfd_mach_msp14}, -- {"msp430x149", MSP430_ISA_14, bfd_mach_msp14}, -- -- {"msp430x155", MSP430_ISA_15, bfd_mach_msp15}, -- {"msp430x156", MSP430_ISA_15, bfd_mach_msp15}, -- {"msp430x157", MSP430_ISA_15, bfd_mach_msp15}, -- {"msp430x167", MSP430_ISA_16, bfd_mach_msp16}, -- {"msp430x168", MSP430_ISA_16, bfd_mach_msp16}, -- {"msp430x169", MSP430_ISA_16, bfd_mach_msp16}, -- {"msp430x1610", MSP430_ISA_16, bfd_mach_msp16}, -- {"msp430x1611", MSP430_ISA_16, bfd_mach_msp16}, -- {"msp430x1612", MSP430_ISA_16, bfd_mach_msp16}, -- -- {"msp430x2101", MSP430_ISA_21, bfd_mach_msp21}, -- {"msp430x2111", MSP430_ISA_21, bfd_mach_msp21}, -- {"msp430x2121", MSP430_ISA_21, bfd_mach_msp21}, -- {"msp430x2131", MSP430_ISA_21, bfd_mach_msp21}, -+ /* CPU4: PUSH #4, PUSH #8 -+ * -+ * The single operand instruction PUSH cannot use the internal -+ * constants (CG) 4 and 8. The other internal constants (0, 1, 2, -+ * –1) can be used. The number of clock cycles is different: -+ * -+ * - PUSH #CG uses address mode 00, requiring 3 cycles, 1-word instruction -+ * - PUSH #4/#8 uses address mode 11, requiring 5 cycles, 2-word instruction -+ * -+ * Workaround: -+ * - Assembler generate code not referencing constant generator -+ */ -+ ERRATUM_CPU4 = 4, -+ -+ // CALL and PUSH with @SP+, @SP, and X(SP) uses the SP to calculate the address, then decrements it -+ ERRATUM_CPU7 = 7, -+ -+ /* CPU8: Using odd values in the SP register -+ * -+ * The SP can be written with odd values. In the original CPU, an -+ * odd SP value could be combined with an odd offset (for example, -+ * mov. #value, 5(SP)). In the new CPU, the SP can be written with -+ * an odd value, but the first time the SP is used, the LSB is -+ * forced to 0. -+ * -+ * Workaround: -+ * - Do not use odd values with the SP. -+ */ -+ ERRATUM_CPU8 = 8, /* UNHANDLED */ -+ -+ /* CPU11: Invalid status register after program counter access -+ * -+ * When addressing the program counter (PC) in register mode when -+ * the PC is the destination, the Status Register (SR) may be -+ * erroneous. The instructions BIS, BIC, and MOV do not affect SR -+ * contents. Only CPU flags are affected. This bug does not apply to -+ * LPMx control bits. -+ * -+ * Workaround: None -+ */ -+ ERRATUM_CPU11 = 11, /* UNHANDLED */ -+ -+ /* CPU12: CMP or BIT with PC destination -+ * -+ * Any instruction immediately following a CMP(.B) or BIT(.B) -+ * instruction when the PC is the destination address using register -+ * mode is ignored or erroneously executed. When the following -+ * instruction is longer than one word, the second word is fetched -+ * by the CPU and decoded as the instruction, leading to -+ * unpredictable behavior. Affected source-addressing modes are -+ * indexed and indirect addressing modes. -+ * -+ * Example: -+ * cmp &200,PC -+ * add #4,R8 -+ * The add command is not executed. -+ * -+ * Workaround: -+ * - Insert a NOP instruction after the BIT or CMP instruction. The -+ * NOP is ignored, and program execution continues as expected. -+ */ -+ ERRATUM_CPU12 = 12, /* UNHANDLED */ -+ -+ /* CPU13: Arithmetic operations and the SR -+ * -+ * Performing arithmetic operations with the Status Register (SR) as -+ * the destination address does not update the SR as intended. The -+ * result in SR can be invalid, leading to erroneous low-power mode -+ * entry. Arithmetic operations are defined as all instructions that -+ * modify the SR flag bits (RRA, SUB, XOR, and ADD, for example). -+ * -+ * Workaround: None -+ */ -+ ERRATUM_CPU13 = 13, /* UNHANDLED */ -+ -+ /* CPU15: Modifying the Program Counter (PC) behaves differently -+ * than in previous devices -+ * -+ * When using instructions with immediate or indirect addressing -+ * mode to modify the PC, a different value compared to previous -+ * devices must be added to get to the same destination. -+ * -+ * NOTE: The MOV instruction is not affected -+ * -+ * Example: Previous device (MSP430F4619) -+ * label_1 ADD.W #Branch1-label_1-4h,PC -+ * MSP430F5438: -+ * label_1 ADD.W #Branch1-label_1-2h,PC -+ * -+ * Workaround: -+ * - Additional NOP after the PC-modifying instruction; or -+ * - Change the offset value in software -+ */ -+ ERRATUM_CPU15 = 15, /* UNHANDLED */ -+ -+ /* CPU16 Indexed addressing with instructions calla, mova, and bra -+ * -+ * With indexed addressing mode and instructions calla, mova, and bra, it is not possible -+ * to reach memory above 64k if the register content is < 64k. -+ * Example: Assume R5 = FFFEh. The instruction calla 0004h(R5) results in a 20-bit call -+ * of address 0002h instead of 10002h. -+ * -+ * Workaround: -+ * - Use different addressing mode to reach memory above 64k. -+ * - First use adda [index],[Rx] to calculate address in upper memory and then use -+ * calla [Rx]. -+ */ -+ ERRATUM_CPU16 = 16, /* UNHANDLED */ -+ -+ /* CPU18: LPM instruction can corrupt PC/SR registers -+ * -+ * The PC and SR registers have the potential to be corrupted when: -+ * - An instruction using register, absolute, indexed, indirect, -+ * indirect auto-increment, or symbolic mode is used to set the -+ * LPM bits (for example, BIS &xyh, SR). -+ * and -+ * - This instruction is followed by a CALL or CALLA instruction. -+ * -+ * Upon servicing an interrupt service routine, the program counter -+ * (PC) is pushed twice onto the stack instead of the correct -+ * operation where the PC, then the SR registers are pushed onto the -+ * stack. This corrupts the SR and possibly the PC on RETI from the -+ * ISR. -+ * -+ * Workaround: -+ * - Insert a NOP or __no_operation() intrinsic function between the -+ * instruction to enter low-power mode and the CALL or CALLA -+ * instruction. -+ */ -+ ERRATUM_CPU18 = 18, /* UNHANDLED */ -+ -+ /* CPU19: CPUOFF can change register values -+ * -+ * If a CPUOFF command is followed by an instruction with an -+ * indirect addressed operand (for example, mov @R8, R9, and RET), -+ * an unintentional register-read operation can occur during the -+ * wakeup of the CPU. If the unintentional read occurs to a -+ * read-sensitive register (for example, UCB0RXBUF or TAIV), which -+ * changes its value or the value of other registers (IFGs), the bug -+ * leads to lost interrupts or wrong register read values. -+ * -+ * Workaround: -+ * - Insert a NOP instruction after each CPUOFF instruction. -+ */ -+ ERRATUM_CPU19 = 19, /* UNHANDLED */ -+ -+ /* CPU20: An unexpected Vacant Memory Access Flag (VMAIFG) can be -+ * triggered due to the CPU autoincrement of the MAB + 2 -+ * outside the range of a valid memory block. -+ * -+ * The VMAIFG is triggered if a PC-modifying instruction (for -+ * example, ret, push, call, pop, jmp, br) is fetched from the last -+ * address of a section of memory (for example, flash or RAM) that -+ * is not contiguous to a higher valid section on the memory map. -+ * -+ * Workaround: -+ * - If code is affected, edit the linker command file to make the -+ * last four bytes of affected memory sections unavailable. -+ */ -+ ERRATUM_CPU20 = 20, /* UNHANDLED */ -+ -+ /* NO DESCRIPTION */ -+ ERRATUM_CPU21 = 21, /* UNHANDLED */ -+ -+ /* NO DESCRIPTION */ -+ ERRATUM_CPU22 = 22, /* UNHANDLED */ -+ -+ /* NO DESCRIPTION */ -+ ERRATUM_CPU23 = 23, /* UNHANDLED */ -+ -+ /* CPU26: CALL SP does not behave as expected -+ * -+ * When the intention is to execute code from the stack, a CALL SP -+ * instruction skips the first piece of data (instruction) on the -+ * stack. The second piece of data at SP + 2 is used as the first -+ * executable instruction. -+ * -+ * Workaround: -+ * - Write the op code for a NOP as the first instruction on the -+ * stack. Begin the intended subroutine at address SP + 2. -+ */ -+ ERRATUM_CPU26 = 26, /* UNHANDLED */ -+ -+ /* CPU27: Program Counter (PC) is corrupted during the context save -+ * of a nested interrupt -+ * -+ * When a low-power mode is entered within an interrupt service -+ * routine that has enabled nested interrupts (by setting the GIE -+ * bit), and the instruction that sets the low-power mode is -+ * directly followed by a RETI instruction, an incorrect value of PC -+ * + 2 is pushed to the stack during the context save. Hence, the -+ * RETI instruction is not executed on return from the nested -+ * interrupt, and the PC becomes corrupted. -+ * -+ * Workaround: -+ * - Insert a NOP or __no_operation() intrinsic function between the -+ * instruction that sets the lower power mode and the RETI -+ * instruction. -+ */ -+ ERRATUM_CPU27 = 27, /* UNHANDLED */ -+ -+ /* CPU28: PC is corrupted when using certain extended addressing -+ * mode combinations -+ * -+ * An extended memory instruction that modifies the program counter -+ * executes incorrectly when preceded by an extended memory -+ * write-back instruction under the following conditions: -+ * -+ * - First instruction: -+ * 2-operand instruction, extended mode using (register,index), -+ * (register,absolute), or (register,symbolic) addressing modes -+ * - Second instruction: -+ * 2-operand instruction, extended mode using the (indirect,PC), -+ * (indirect auto-increment,PC), or (indexed [with ind 0], PC) -+ * addressing modes -+ * -+ * Example: -+ * BISX.A R6,&AABCD -+ * ANDX.A @R4+,PC -+ * -+ * Workaround: -+ * - Insert a NOP or a __no_operation() intrinsic function between -+ * the two instructions. -+ * or -+ * - Do not use an extended memory instruction to modify the PC. -+ */ -+ ERRATUM_CPU28 = 28, /* UNHANDLED */ -+ -+ /* CPU29: Using a certain instruction sequence to enter low-power -+ * mode(s) affects the instruction width of the first -+ * instruction in an NMI ISR -+ * -+ * If there is a pending NMI request when the CPU enters a low-power -+ * mode (LPMx) using an instruction of Indexed source addressing -+ * mode, and that instruction is followed by a 20-bit wide -+ * instruction of Register source and Destination addressing modes, -+ * the first instruction of the ISR is executed as a 20-bit wide -+ * instruction. -+ * -+ * Example: -+ * main: -+ * ... -+ * MOV.W [indexed],SR ; Enter LPMx -+ * MOVX.A [register],[register] ; 20-bit wide instruction -+ * ... -+ * ISR_start: -+ * MOV.B [indexed],[register] ; ERROR - Executed as a 20-bit instruction! -+ * -+ * Note: [ ] indicates addressing mode -+ * -+ * Workaround: -+ * - Insert a NOP or a __no_operation() intrinsic function following -+ * the instruction that enters the LPMx using indexed addressing -+ * mode. -+ * or -+ * - Use a NOP or a __no_operation() intrinsic function as first -+ * instruction in the ISR. -+ * or -+ * - Do not use the indexed mode to enter LPMx. -+ */ -+ ERRATUM_CPU29 = 29, /* UNHANDLED */ - -- {"msp430x311", MSP430_ISA_31, bfd_mach_msp31}, -- {"msp430x312", MSP430_ISA_31, bfd_mach_msp31}, -- {"msp430x313", MSP430_ISA_31, bfd_mach_msp31}, -- {"msp430x314", MSP430_ISA_31, bfd_mach_msp31}, -- {"msp430x315", MSP430_ISA_31, bfd_mach_msp31}, -- {"msp430x323", MSP430_ISA_32, bfd_mach_msp32}, -- {"msp430x325", MSP430_ISA_32, bfd_mach_msp32}, -- {"msp430x336", MSP430_ISA_33, bfd_mach_msp33}, -- {"msp430x337", MSP430_ISA_33, bfd_mach_msp33}, -- -- {"msp430x412", MSP430_ISA_41, bfd_mach_msp41}, -- {"msp430x413", MSP430_ISA_41, bfd_mach_msp41}, -- {"msp430x415", MSP430_ISA_41, bfd_mach_msp41}, -- {"msp430x417", MSP430_ISA_41, bfd_mach_msp41}, -- -- {"msp430xE423", MSP430_ISA_42, bfd_mach_msp42}, -- {"msp430xE425", MSP430_ISA_42, bfd_mach_msp42}, -- {"msp430xE427", MSP430_ISA_42, bfd_mach_msp42}, -- -- {"msp430xW423", MSP430_ISA_42, bfd_mach_msp42}, -- {"msp430xW425", MSP430_ISA_42, bfd_mach_msp42}, -- {"msp430xW427", MSP430_ISA_42, bfd_mach_msp42}, -- -- {"msp430xG437", MSP430_ISA_43, bfd_mach_msp43}, -- {"msp430xG438", MSP430_ISA_43, bfd_mach_msp43}, -- {"msp430xG439", MSP430_ISA_43, bfd_mach_msp43}, -- -- {"msp430x435", MSP430_ISA_43, bfd_mach_msp43}, -- {"msp430x436", MSP430_ISA_43, bfd_mach_msp43}, -- {"msp430x437", MSP430_ISA_43, bfd_mach_msp43}, -- {"msp430x447", MSP430_ISA_44, bfd_mach_msp44}, -- {"msp430x448", MSP430_ISA_44, bfd_mach_msp44}, -- {"msp430x449", MSP430_ISA_44, bfd_mach_msp44}, -- -- {NULL, 0, 0} -+ /* CPU30: ADDA, SUBA, CMPA [immediate],PC behave as if immediate -+ * value were offset by -2 -+ * -+ * The extended address instructions ADDA, SUBA, and CMPA in -+ * immediate addressing mode are represented by 4 bytes of opcode -+ * (see the MSP430F5xx Family User's Guide (SLAU208) for more -+ * details). In cases where the program counter (PC) is used as the -+ * destination register, only 2 bytes of the current instruction's -+ * 4-byte opcode are accounted for in the PC value. The resulting -+ * operation executes as if the immediate value were offset by a -+ * value of -2. -+ * -+ * Example: -+ * Ideal: ADDA #Immediate-4, PC -+ * ...is equivalent to... -+ * Actual: ADDA #Immediate-2, PC -+ * NOTE: The MOV instruction is not affected. -+ * -+ * Workaround: -+ * - Modify immediate value in software to account for the offset of 2. -+ * or -+ * - Use extended 20-bit instructions (addx.a, subx.a, cmpx.a) instead. -+ */ -+ ERRATUM_CPU30 = 30, /* UNHANDLED */ -+ -+ /* CPU40: PC is corrupted when executing jump/conditional jump -+ * instruction that is followed by instruction with PC as -+ * destination register or a data section -+ * -+ * If the value at the memory location immediately following a -+ * jump/conditional jump instruction is 0X40h or 0X50h (where X = -+ * don't care), which could either be an instruction opcode (for -+ * instructions like RRCM, RRAM, RLAM, RRUM) with PC as destination -+ * register or a data section (const data in flash memory or data -+ * variable in RAM), then the PC value gets auto-incremented by 2 -+ * after the jump instruction is executed; thus branching to a wrong -+ * address location in code and leading to wrong program execution. -+ * -+ * For example, a conditional jump instruction followed by data -+ * section (0140h). -+ * -+ * @0x8012 Loop DEC.W R6 -+ * @0x8014 DEC.W R7 -+ * @0x8016 JNZ Loop -+ * @0x8018 Value1 DW 0140h -+ * -+ * Workaround: -+ * - In assembly, insert a NOP between the jump/conditional jump -+ * instruction and program code with instruction that contains PC -+ * as destination register or the data section. -+ */ -+ ERRATUM_CPU40 = 40, /* UNHANDLED */ -+} msp430_errata_e; -+ -+/* sed -e '1,/enum msp430_errata/d' -e '/^\}/,$d' tc-msp430.c \ -+ | grep '^ *ERRATUM_*' \ -+ | cut -d= -f1 \ -+ | sed 's@ *$@,@' */ -+static const int recognized_errata[] = { -+ ERRATUM_CPU4, -+ ERRATUM_CPU7, -+ ERRATUM_CPU8, -+ ERRATUM_CPU11, -+ ERRATUM_CPU12, -+ ERRATUM_CPU13, -+ ERRATUM_CPU15, -+ ERRATUM_CPU16, -+ ERRATUM_CPU18, -+ ERRATUM_CPU19, -+ ERRATUM_CPU20, -+ ERRATUM_CPU21, -+ ERRATUM_CPU22, -+ ERRATUM_CPU23, -+ ERRATUM_CPU26, -+ ERRATUM_CPU27, -+ ERRATUM_CPU28, -+ ERRATUM_CPU29, -+ ERRATUM_CPU30, -+ ERRATUM_CPU40, - }; - -+#define CHECK_RELOC_MSP430 ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16) -+#define CHECK_RELOC_MSP430_PCREL ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430_16_PCREL_BYTE : BFD_RELOC_MSP430_16_PCREL) -+#define CHECK_RELOC_MSP430X_SRC ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_SRC_BYTE : BFD_RELOC_MSP430X_SRC) -+#define CHECK_RELOC_MSP430X_PCREL_SRC ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_SRC_BYTE : BFD_RELOC_MSP430X_PCREL_SRC) -+#define CHECK_RELOC_MSP430X_DST ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_DST_BYTE : BFD_RELOC_MSP430X_DST) -+#define CHECK_RELOC_MSP430X_PCREL_DST ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_DST_BYTE : BFD_RELOC_MSP430X_PCREL_DST) -+#define CHECK_RELOC_MSP430X_DST_2ND ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_DST_2ND_BYTE : BFD_RELOC_MSP430X_DST_2ND) -+#define CHECK_RELOC_MSP430X_PCREL_DST_2ND ((imm_op || op_width == BYTE_OP) ? BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE : BFD_RELOC_MSP430X_PCREL_DST_2ND) - --static struct mcu_type_s default_mcu = -- { "msp430x11", MSP430_ISA_11, bfd_mach_msp11 }; -- --static struct mcu_type_s * msp430_mcu = & default_mcu; -+static int msp430_cpu = MSP430_CPU_MSP430; -+static int msp430_mpy = MSP430_MPY_NONE; -+static int *msp430_errata = 0; - - /* Profiling capability: - It is a performance hit to use gcc's profiling approach for this tiny target. -@@ -446,32 +704,14 @@ pow2value (int y) - static char * - parse_exp (char * s, expressionS * op) - { -+ char * in_save = input_line_pointer; - input_line_pointer = s; - expression (op); -+ s = input_line_pointer; -+ input_line_pointer = in_save; - if (op->X_op == O_absent) - as_bad (_("missing operand")); -- return input_line_pointer; --} -- -- --/* Delete spaces from s: X ( r 1 2) => X(r12). */ -- --static void --del_spaces (char * s) --{ -- while (*s) -- { -- if (ISSPACE (*s)) -- { -- char *m = s + 1; -- -- while (ISSPACE (*m) && *m) -- m++; -- memmove (s, m, strlen (m) + 1); -- } -- else -- s++; -- } -+ return s; - } - - static inline char * -@@ -482,42 +722,46 @@ skip_space (char * s) - return s; - } - --/* Extract one word from FROM and copy it to TO. Delimiters are ",;\n" */ -- -+/* Extract one word from the input. Delimiters are ",;\n" */ - static char * --extract_operand (char * from, char * to, int limit) -+get_operand (void) - { -- int size = 0; -- -- /* Drop leading whitespace. */ -- from = skip_space (from); -+ char* sp = input_line_pointer; -+ char* end_ilp; -+ char* dest; -+ char* dp; -+ int operand_length = 0; - -- while (size < limit && *from) -+ while (*sp && ',' != *sp && ';' != *sp && '\n' != *sp) - { -- *(to + size) = *from; -- if (*from == ',' || *from == ';' || *from == '\n') -- break; -- from++; -- size++; -+ if (! ISSPACE(*sp)) -+ ++operand_length; -+ ++sp; - } -- -- *(to + size) = 0; -- del_spaces (to); -- -- from++; -- -- return from; -+ end_ilp = sp; -+ if (',' == *end_ilp) -+ ++end_ilp; -+ -+ dp = dest = xmalloc(operand_length + 1); -+ sp = input_line_pointer; -+ while (0 < operand_length) { -+ if (! ISSPACE(*sp)) { -+ *dp++ = *sp; -+ --operand_length; -+ } -+ ++sp; -+ } -+ *dp = 0; -+ input_line_pointer = end_ilp; -+ return dest; - } - - static void - msp430_profiler (int dummy ATTRIBUTE_UNUSED) - { -- char buffer[1024]; -- char f[32]; -- char * str = buffer; -- char * flags = f; -+ char * flag_token = 0; -+ char * flags; - int p_flags = 0; -- char * halt; - int ops = 0; - int left; - char * s; -@@ -549,8 +793,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) - return; - } - -- input_line_pointer = extract_operand (input_line_pointer, flags, 32); -- -+ flags = flag_token = get_operand (); - while (*flags) - { - switch (*flags) -@@ -608,6 +851,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) - } - flags++; - } -+ xfree (flag_token); - - if (p_flags - && ( ! pow2value (p_flags & ( MSP430_PROFILER_FLAG_ENTRY -@@ -658,11 +902,11 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) - while (ops--) - { - /* Now get profiling info. */ -- halt = extract_operand (input_line_pointer, str, 1024); -+ char *halt = get_operand (); - /* Process like ".word xxx" directive. */ -- parse_exp (str, & exp); -+ parse_exp (halt, & exp); - emit_expr (& exp, 2); -- input_line_pointer = halt; -+ xfree(halt); - } - - /* Fill the rest with zeros. */ -@@ -675,79 +919,178 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED) - subseg_set (seg, subseg); - } - --static char * --extract_word (char * from, char * to, int limit) -+struct tag_value_pair_t - { -- char *op_end; -- int size = 0; -+ const char *tag; -+ unsigned long value; -+}; - -- /* Drop leading whitespace. */ -- from = skip_space (from); -- *to = 0; -+static const struct tag_value_pair_t cpu_tag_value_map[] = { -+ {"430", MSP430_CPU_MSP430}, -+ {"430x", MSP430_CPU_MSP430X}, -+ {"430xv2", MSP430_CPU_MSP430XV2}, -+ {0, 0} -+}; -+ -+static const struct tag_value_pair_t mpy_tag_value_map[] = { -+ {"none", MSP430_MPY_NONE}, -+ {"16", MSP430_MPY_16}, -+ {"16se", MSP430_MPY_16SE}, -+ {"32", MSP430_MPY_32}, -+ {"32dw", MSP430_MPY_32DW}, -+ {0, 0} -+}; - -- /* Find the op code end. */ -- for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);) -+static const struct tag_value_pair_t * -+find_pair_by_tag (const char *tag, const struct tag_value_pair_t *map) -+{ -+ while (map->tag) - { -- to[size++] = *op_end++; -- if (size + 1 >= limit) -- break; -+ if (0 == strcmp (tag, map->tag)) -+ return map; -+ ++map; - } -+ return 0; -+} - -- to[size] = 0; -- return op_end; -+#if 0 -+static const struct tag_value_pair_t * -+find_pair_by_value (unsigned long value, const struct tag_value_pair_t *map) -+{ -+ while (map->tag) -+ { -+ if (map->value == value) -+ return map; -+ ++map; -+ } -+ return 0; - } -+#endif - --#define OPTION_MMCU 'm' --#define OPTION_RELAX 'Q' --#define OPTION_POLYMORPHS 'P' -+enum { -+ OPTION_MMCU = 'm', -+ OPTION_RELAX = 'Q', -+ OPTION_POLYMORPHS = 'P', -+ OPTION_CPU = OPTION_MD_BASE + 0, -+ OPTION_MPY, -+ OPTION_ERRATA, -+}; -+ -+static int -+erratum_applies (int erratum) -+{ -+ if (! msp430_errata) -+ if (ERRATUM_CPU4 == erratum) -+ return msp430_cpu < MSP430_CPU_MSP430X; -+ return 0; -+} -+ -+static int -+cpu_from_text (const char* text) -+{ -+ const struct tag_value_pair_t* mp = find_pair_by_tag(text, cpu_tag_value_map); -+ if (! mp) -+ as_fatal (_("unrecognized cpu type %s"), text); -+ return mp->value; -+} -+ -+static int -+mpy_from_text (const char* text) -+{ -+ const struct tag_value_pair_t* mp = find_pair_by_tag(text, mpy_tag_value_map); -+ if (! mp) -+ as_fatal (_("unrecognized hardware multiplier type %s"), text); -+ return mp->value; -+} - - static void --msp430_set_arch (int dummy ATTRIBUTE_UNUSED) -+set_arch_mach (int cpu, -+ int mpy ATTRIBUTE_UNUSED) - { -- char *str = (char *) alloca (32); /* 32 for good measure. */ -+ unsigned long mach = bfd_mach_msp430; -+ if (MSP430_CPU_MSP430X <= cpu) -+ mach = bfd_mach_msp430x; -+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach); -+} - -- input_line_pointer = extract_word (input_line_pointer, str, 32); -+/* Like get_symbol_end, but accepts sequences that start with -+ * digits and doesn't strip out name ends */ -+static char -+get_token_end (void) -+{ -+ char c; - -- md_parse_option (OPTION_MMCU, str); -- bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); -+ while (is_part_of_name (c = *input_line_pointer++)) -+ ; -+ *--input_line_pointer = 0; -+ return (c); - } - - static void --show_mcu_list (FILE * stream) -+msp430_set_mcu (int dummy ATTRIBUTE_UNUSED) - { -- int i; -+ SKIP_WHITESPACE(); -+ if (!is_end_of_line[(unsigned char) *input_line_pointer]) -+ { -+ char* tag_start = input_line_pointer; -+ int ch = get_token_end (); -+ md_parse_option (OPTION_MMCU, tag_start); -+ *input_line_pointer = ch; -+ demand_empty_rest_of_line (); -+ } -+ else -+ as_bad (_("missing value for arch")); -+} -+ -+static void -+msp430_set (int option) -+{ -+ char* tag = 0; -+ -+ SKIP_WHITESPACE (); -+ if (!is_end_of_line[(unsigned char) *input_line_pointer]) -+ { -+ char *tag_start = input_line_pointer; -+ char e = get_token_end (); -+ int tag_len = input_line_pointer + 1 - tag_start; -+ tag = (char *) xmalloc(tag_len); -+ memcpy (tag, tag_start, tag_len); -+ *input_line_pointer = e; -+ demand_empty_rest_of_line (); -+ } -+ -+ switch (option) -+ { -+ case OPTION_CPU: -+ if (! tag) -+ as_bad (_("missing value for cpu")); -+ msp430_cpu = cpu_from_text(tag); -+ break; -+ case OPTION_MPY: -+ if (! tag) -+ as_bad (_("missing value for mpy")); -+ msp430_mpy = mpy_from_text(tag); -+ break; -+ default: -+ abort(); -+ } - -- fprintf (stream, _("Known MCU names:\n")); -+ set_arch_mach (msp430_cpu, msp430_mpy); - -- for (i = 0; mcu_types[i].name; i++) -- fprintf (stream, _("\t %s\n"), mcu_types[i].name); -+} - -- fprintf (stream, "\n"); -+static void -+msp430_set_errata (int dummy ATTRIBUTE_UNUSED) -+{ - } - - int - md_parse_option (int c, char * arg) - { -- int i; -- - switch (c) - { - case OPTION_MMCU: -- for (i = 0; mcu_types[i].name; ++i) -- if (strcmp (mcu_types[i].name, arg) == 0) -- break; -- -- if (!mcu_types[i].name) -- { -- show_mcu_list (stderr); -- as_fatal (_("unknown MCU: %s\n"), arg); -- } -- -- if (msp430_mcu == &default_mcu || msp430_mcu->mach == mcu_types[i].mach) -- msp430_mcu = &mcu_types[i]; -- else -- as_fatal (_("redefinition of mcu type %s' to %s'"), -- msp430_mcu->name, mcu_types[i].name); -+ //as_tsktsk(_("mcu option ignored")); - return 1; - break; - -@@ -760,16 +1103,35 @@ md_parse_option (int c, char * arg) - msp430_enable_polys = 1; - return 1; - break; -+ -+ case OPTION_CPU: -+ msp430_cpu = cpu_from_text(arg); -+ return 1; -+ break; -+ -+ case OPTION_MPY: -+ msp430_mpy = mpy_from_text(arg); -+ return 1; -+ break; -+ -+ case OPTION_ERRATA: -+ break; - } - - return 0; - } - -+static void -+msp430_repeat_insn (int dummy ATTRIBUTE_UNUSED); - - const pseudo_typeS md_pseudo_table[] = - { -- {"arch", msp430_set_arch, 0}, -+ {"arch", msp430_set_mcu, 0}, - {"profiler", msp430_profiler, 0}, -+ {"rpt", msp430_repeat_insn, 0}, -+ {"cpu", msp430_set, OPTION_CPU}, -+ {"mpy", msp430_set, OPTION_MPY}, -+ {"errata", msp430_set_errata, 0}, - {NULL, NULL, 0} - }; - -@@ -780,6 +1142,9 @@ struct option md_longopts[] = - {"mmcu", required_argument, NULL, OPTION_MMCU}, - {"mP", no_argument, NULL, OPTION_POLYMORPHS}, - {"mQ", no_argument, NULL, OPTION_RELAX}, -+ {"mcpu", required_argument, NULL, OPTION_CPU }, -+ {"mmpy", required_argument, NULL, OPTION_MPY }, -+ {"merrata", required_argument, NULL, OPTION_ERRATA }, - {NULL, no_argument, NULL, 0} - }; - -@@ -789,33 +1154,13 @@ void - md_show_usage (FILE * stream) - { - fprintf (stream, -- _("MSP430 options:\n" -- " -mmcu=[msp430-name] select microcontroller type\n" -- " msp430x110 msp430x112\n" -- " msp430x1101 msp430x1111\n" -- " msp430x1121 msp430x1122 msp430x1132\n" -- " msp430x122 msp430x123\n" -- " msp430x1222 msp430x1232\n" -- " msp430x133 msp430x135\n" -- " msp430x1331 msp430x1351\n" -- " msp430x147 msp430x148 msp430x149\n" -- " msp430x155 msp430x156 msp430x157\n" -- " msp430x167 msp430x168 msp430x169\n" -- " msp430x1610 msp430x1611 msp430x1612\n" -- " msp430x311 msp430x312 msp430x313 msp430x314 msp430x315\n" -- " msp430x323 msp430x325\n" -- " msp430x336 msp430x337\n" -- " msp430x412 msp430x413 msp430x415 msp430x417\n" -- " msp430xE423 msp430xE425 msp430E427\n" -- " msp430xW423 msp430xW425 msp430W427\n" -- " msp430xG437 msp430xG438 msp430G439\n" -- " msp430x435 msp430x436 msp430x437\n" -- " msp430x447 msp430x448 msp430x449\n")); -- fprintf (stream, -- _(" -mQ - enable relaxation at assembly time. DANGEROUS!\n" -+ _("MSP430 as-specific options:\n" -+ " -mmcu=[msp430-name] select microcontroller type (ignored)\n" -+ " -mcpu={430,430x,430xv2} select cpu model\n" -+ " -mmpy={none,16,16se,32,32dw} select hardware multiplier type\n" -+ " -merrata=[cpuX,...] list relevant errata\n" -+ " -mQ - enable relaxation at assembly time. DANGEROUS!\n" - " -mP - enable polymorph instructions\n")); -- -- show_mcu_list (stream); - } - - symbolS * -@@ -824,23 +1169,6 @@ md_undefined_symbol (char * name ATTRIBUTE_UNUSED) - return 0; - } - --static char * --extract_cmd (char * from, char * to, int limit) --{ -- int size = 0; -- -- while (*from && ! ISSPACE (*from) && *from != '.' && limit > size) -- { -- *(to + size) = *from; -- from++; -- size++; -- } -- -- *(to + size) = 0; -- -- return from; --} -- - char * - md_atof (int type, char * litP, int * sizeP) - { -@@ -850,13 +1178,13 @@ md_atof (int type, char * litP, int * sizeP) - void - md_begin (void) - { -- struct msp430_opcode_s * opcode; -+ struct msp430_opcode_s const * opcode; - msp430_hash = hash_new (); - - for (opcode = msp430_opcodes; opcode->name; opcode++) - hash_insert (msp430_hash, opcode->name, (char *) opcode); - -- bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); -+ set_arch_mach (msp430_cpu, msp430_mpy); - } - - static int -@@ -880,13 +1208,74 @@ check_reg (char * t) - return 0; - } - -+static void -+msp430_substitute_CG(struct msp430_operand_s * op, int workaround) -+{ -+ /* Substitute register mode with a constant generator if applicable. */ -+ if( op->mode != OP_EXP || ( op->exp.X_op != O_constant && op->exp.X_op != O_big )) -+ return; -+ if( op->am != 3 || op->reg != 0 ) // not #N -+ return; -+ int x = (short) op->exp.X_add_number; /* Extend sign. */ -+ -+ if (x == 0) -+ { -+ op->reg = 3; -+ op->am = 0; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+ else if (x == 1) -+ { -+ op->reg = 3; -+ op->am = 1; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+ else if (x == 2) -+ { -+ op->reg = 3; -+ op->am = 2; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+ else if (x == -1) -+ { -+ op->reg = 3; -+ op->am = 3; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+ else if (x == 4 && !workaround) -+ { -+ op->reg = 2; -+ op->am = 2; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+ else if (x == 8 && ! workaround) -+ { -+ op->reg = 2; -+ op->am = 3; -+ op->ol = 0; -+ op->mode = OP_REG; -+ } -+} - - static int - msp430_srcoperand (struct msp430_operand_s * op, -- char * l, int bin, int * imm_op) -+ const char * operand_string, int * imm_op, int imm_min, int imm_max) - { -- char *__tl = l; -+ char *l = ""; -+ char *__tl; - -+ if (operand_string) -+ { -+ l = alloca(strlen(operand_string) + 1); -+ strcpy(l, operand_string); -+ } -+ __tl = l; -+ - /* Check if an immediate #VALUE. The hash sign should be only at the beginning! */ - if (*l == '#') - { -@@ -943,100 +1332,27 @@ msp430_srcoperand (struct msp430_operand_s * op, - parse_exp (__tl, &(op->exp)); - if (op->exp.X_op == O_constant) - { -- int x = op->exp.X_add_number; -+ offsetT x = op->exp.X_add_number; -+ int is_negative = 0 > x; - -- if (vshift == 0) -- { -- x = x & 0xffff; -- op->exp.X_add_number = x; -- } -- else if (vshift == 1) -+ if (0 <= vshift) - { -- x = (x >> 16) & 0xffff; -- op->exp.X_add_number = x; -- } -- else if (vshift > 1) -- { -- if (x < 0) -- op->exp.X_add_number = -1; -+ unsigned int shift_bits = vshift * 16; -+ if (shift_bits < (8 * sizeof (x))) -+ x >>= shift_bits; -+ else -+ x = 0; -+ if (0 == x) -+ op->exp.X_add_number = is_negative ? -1 : 0; - else -- op->exp.X_add_number = 0; /* Nothing left. */ -+ op->exp.X_add_number = x & 0xFFFF; - x = op->exp.X_add_number; - } -- -- if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768) -+ if (x >= imm_max || x < imm_min) - { -- as_bad (_("value %d out of range. Use #lo() or #hi()"), x); -+ as_bad (_("value %ld out of %d...%d (0x%X...0x%X) range."), (long int)x, imm_min, imm_max - 1, imm_min, imm_max - 1); - return 1; - } -- -- /* Now check constants. */ -- /* Substitute register mode with a constant generator if applicable. */ -- -- x = (short) x; /* Extend sign. */ -- -- if (x == 0) -- { -- op->reg = 3; -- op->am = 0; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 1) -- { -- op->reg = 3; -- op->am = 1; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 2) -- { -- op->reg = 3; -- op->am = 2; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == -1) -- { -- op->reg = 3; -- op->am = 3; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 4) -- { --#ifdef PUSH_1X_WORKAROUND -- if (bin == 0x1200) -- { -- /* Remove warning as confusing. -- as_warn (_("Hardware push bug workaround")); */ -- } -- else --#endif -- { -- op->reg = 2; -- op->am = 2; -- op->ol = 0; -- op->mode = OP_REG; -- } -- } -- else if (x == 8) -- { --#ifdef PUSH_1X_WORKAROUND -- if (bin == 0x1200) -- { -- /* Remove warning as confusing. -- as_warn (_("Hardware push bug workaround")); */ -- } -- else --#endif -- { -- op->reg = 2; -- op->am = 3; -- op->ol = 0; -- op->mode = OP_REG; -- } -- } - } - else if (op->exp.X_op == O_symbol) - { -@@ -1044,12 +1360,10 @@ msp430_srcoperand (struct msp430_operand_s * op, - } - else if (op->exp.X_op == O_big) - { -- short x; - if (vshift != -1) - { - op->exp.X_op = O_constant; - op->exp.X_add_number = 0xffff & generic_bignum[vshift]; -- x = op->exp.X_add_number; - } - else - { -@@ -1058,49 +1372,6 @@ msp430_srcoperand (struct msp430_operand_s * op, - l); - return 1; - } -- -- if (x == 0) -- { -- op->reg = 3; -- op->am = 0; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 1) -- { -- op->reg = 3; -- op->am = 1; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 2) -- { -- op->reg = 3; -- op->am = 2; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == -1) -- { -- op->reg = 3; -- op->am = 3; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 4) -- { -- op->reg = 2; -- op->am = 2; -- op->ol = 0; -- op->mode = OP_REG; -- } -- else if (x == 8) -- { -- op->reg = 2; -- op->am = 3; -- op->ol = 0; -- op->mode = OP_REG; -- } - } - /* Redundant (yet) check. */ - else if (op->exp.X_op == O_register) -@@ -1127,7 +1398,7 @@ msp430_srcoperand (struct msp430_operand_s * op, - { - int x = op->exp.X_add_number; - -- if (x > 65535 || x < -32768) -+ if (x >= imm_max || x < imm_min) - { - as_bad (_("value out of range: %d"), x); - return 1; -@@ -1262,7 +1533,7 @@ msp430_srcoperand (struct msp430_operand_s * op, - { - int x = op->exp.X_add_number; - -- if (x > 65535 || x < -32768) -+ if (x > imm_max || x < imm_min) - { - as_bad (_("value out of range: %d"), x); - return 1; -@@ -1338,10 +1609,10 @@ msp430_srcoperand (struct msp430_operand_s * op, - - - static int --msp430_dstoperand (struct msp430_operand_s * op, char * l, int bin) -+msp430_dstoperand (struct msp430_operand_s * op, const char * l, int imm_min, int imm_max) - { - int dummy; -- int ret = msp430_srcoperand (op, l, bin, & dummy); -+ int ret = msp430_srcoperand (op, l, & dummy, imm_min, imm_max); - - if (ret) - return ret; -@@ -1373,39 +1644,139 @@ msp430_dstoperand (struct msp430_operand_s * op, char * l, int bin) - return 0; - } - -+static void -+msp430_repeat_insn (int dummy ATTRIBUTE_UNUSED) -+{ -+ char *operand = 0; -+ struct msp430_operand_s op; -+ int imm_op = 0; -+ char *line = input_line_pointer; -+ -+ if (msp430_cpu < MSP430_CPU_MSP430X) -+ { -+ as_bad (_("Repeatable instructions require 430X-based mcu")); -+ goto done; -+ } -+ -+ if (msp430x_repeats) -+ as_warn (_("two consecutive .rpt pseudo-ops. Previous .rpt discarded")); -+ -+ if (!*line || *line == '\n') -+ { -+ as_bad (_("rpt pseudo-op requires 1 operand")); -+ goto done; -+ } -+ -+ memset (&op, 0, sizeof (op)); -+ operand = get_operand (); -+ -+ if (msp430_srcoperand(&op, operand, &imm_op, 1, 15) != 0) -+ goto done; -+ -+ if ( !(op.mode == OP_REG && op.am == 0) // Rn -+ && !(op.mode == OP_EXP && op.am == 3) // #N -+ ) -+ { -+ as_bad (_("rpt pseudo-op requires immediate or register operand")); -+ goto done; -+ } -+ -+ if (op.am == 0) // rpt Rn -+ msp430x_repeats = (((1 << 7) | op.reg) << 1) | 1; // last bit as .rpt flag -+ else // rpt #N -+ msp430x_repeats = ((op.exp.X_add_number - 1) << 1) | 1; // last bit as .rpt flag -+ -+ done: -+ if (operand) -+ xfree(operand); -+} - - /* Parse instruction operands. - Return binary opcode. */ - - static unsigned int --msp430_operands (struct msp430_opcode_s * opcode, char * line) -+msp430_operands (struct msp430_opcode_s const * opcode, char * line) - { - int bin = opcode->bin_opcode; /* Opcode mask. */ - int __is = 0; -- char l1[MAX_OP_LEN], l2[MAX_OP_LEN]; -- char *frag; -- int where; -+ char *l1 = 0; -+ char *l2 = 0; -+ char *frag = 0; -+ int where = 0; - struct msp430_operand_s op1, op2; - int res = 0; - static short ZEROS = 0; -- int byte_op, imm_op; -- -+ int imm_op; -+ opwidth_t op_width = DEFAULT_OP; -+ - /* Opcode is the one from opcodes table - line contains something like - [.w] @r2+, 5(R1) - or -- .b @r2+, 5(R1). */ -+ .b @r2+, 5(R1) -+ or -+ .a @r2+, 5(R1) */ - - /* Check if byte or word operation. */ -+ - if (*line == '.' && TOLOWER (*(line + 1)) == 'b') - { -- bin |= BYTE_OPERATION; -- byte_op = 1; -+ op_width = BYTE_OP; -+ } -+ else if (*line == '.' && TOLOWER (*(line + 1)) == 'w') -+ { -+ op_width = WORD_OP; -+ } -+ else if (*line == '.' && TOLOWER (*(line + 1)) == 'a') -+ { -+ op_width = ADDR_OP; - } -- else -- byte_op = 0; - -- /* skip .[bwBW]. */ -+ if ((op_width == WORD_OP && !(opcode_modifier(opcode) & MOD_W)) -+ || (op_width == BYTE_OP && !(opcode_modifier(opcode) & MOD_B)) -+ || (op_width == ADDR_OP && !(opcode_modifier(opcode) & MOD_A)) -+ ) -+ { -+ static char* const modifier[] = { "", ".w", ".b", ".a" }; -+ as_bad (_("%s not allowed with %s instruction"), -+ modifier[op_width], opcode->name); -+ return 0; -+ } -+ -+ if ( opcode_format(opcode) == FMT_X_DOUBLE_OPERAND -+ || opcode_format(opcode) == FMT_X_SINGLE_OPERAND -+ || opcode_format(opcode) == FMT_X_EMULATED -+ ) -+ { -+ switch(op_width) -+ { -+ case DEFAULT_OP: -+ case WORD_OP: -+ bin |= NON_ADDR_OPERATION; -+ break; -+ case BYTE_OP: -+ bin |= NON_ADDR_OPERATION; -+ bin |= BYTE_OPERATION_X; -+ break; -+ case ADDR_OP: -+ bin |= BYTE_OPERATION_X; -+ break; -+ } -+ } -+ else -+ { -+ if(msp430x_repeats) -+ { -+ as_bad (_("%s instruction is not repeatable"), opcode->name); -+ return 0; -+ } -+ -+ if ( opcode_format(opcode) < FMT_X && op_width == BYTE_OP ) // 430 instructions -+ { -+ bin |= BYTE_OPERATION; -+ } -+ } -+ /* skip .[abwABW]. */ - while (! ISSPACE (*line) && *line) - line++; - -@@ -1416,29 +1787,29 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - return 0; - } - -- memset (l1, 0, sizeof (l1)); -- memset (l2, 0, sizeof (l2)); -+ input_line_pointer = line; -+ - memset (&op1, 0, sizeof (op1)); - memset (&op2, 0, sizeof (op2)); - - imm_op = 0; - -- switch (opcode->fmt) -+ switch (opcode_format(opcode)) - { -- case 0: /* Emulated. */ -- switch (opcode->insn_opnumb) -+ case FMT_EMULATED: /* Emulated. */ -+ switch (opcode_variant(opcode)) - { -- case 0: -- /* Set/clear bits instructions. */ -+ case V_NOOP: -+ /* Set/clear SR bits instructions, ret, nop */ - __is = 2; - frag = frag_more (__is); - bfd_putl16 ((bfd_vma) bin, frag); - dwarf2_emit_insn (__is); - break; -- case 1: -+ case V_NONE: - /* Something which works with destination operand. */ -- line = extract_operand (line, l1, sizeof (l1)); -- res = msp430_dstoperand (&op1, l1, opcode->bin_opcode); -+ l1 = get_operand (); -+ res = msp430_dstoperand (&op1, l1, -(1<<15), (1<<16) ); - if (res) - break; - -@@ -1463,14 +1834,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - -- case 2: -+ case V_SHIFT: - { - /* Shift instruction. */ -- line = extract_operand (line, l1, sizeof (l1)); -- strncpy (l2, l1, sizeof (l2)); -- l2[sizeof (l2) - 1] = '\0'; -- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); -- res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); -+ msp430_substitute_CG(&op1, 0); -+ res += msp430_dstoperand (&op2, l1, -(1<<15), (1<<16)); - - if (res) - break; /* An error occurred. All warnings were done before. */ -@@ -1498,7 +1868,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - - if (op2.mode == OP_EXP) - { -- imm_op = 0; -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &TONI and x(PC) = TONI -+ */ -+ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); -+ - bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); - - if (op2.reg) /* Not PC relative. */ -@@ -1510,16 +1885,20 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - } -- case 3: -+ case V_BR: - /* Branch instruction => mov dst, r0. */ -- line = extract_operand (line, l1, sizeof (l1)); -- -- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); -+ msp430_substitute_CG(&op1, 0); - if (res) - break; - -- byte_op = 0; -- imm_op = 0; -+ if (op1.mode == 1 && (op1.reg == 2 || op1.reg == 0)) -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &EDE and x(PC) = EDE -+ */ -+ imm_op = 0; - - bin |= ((op1.reg << 8) | (op1.am << 4)); - __is = 1 + op1.ol; -@@ -1544,11 +1923,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - -- case 1: /* Format 1, double operand. */ -- line = extract_operand (line, l1, sizeof (l1)); -- line = extract_operand (line, l2, sizeof (l2)); -- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); -- res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); -+ case FMT_DOUBLE_OPERAND: /* Format 1, double operand. */ -+ l1 = get_operand (); -+ l2 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); -+ msp430_substitute_CG(&op1, 0); -+ res += msp430_dstoperand (&op2, l2, -(1<<15), (1<<16)); - - if (res) - break; /* Error occurred. All warnings were done before. */ -@@ -1576,7 +1956,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - - if (op2.mode == OP_EXP) - { -- imm_op = 0; -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &TONI and x(PC) = TONI -+ */ -+ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); -+ - bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); - - if (op2.reg) /* Not PC relative. */ -@@ -1588,8 +1973,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - -- case 2: /* Single-operand mostly instr. */ -- if (opcode->insn_opnumb == 0) -+ case FMT_SINGLE_OPERAND: /* Single-operand mostly instr. */ -+ if (opcode_variant(opcode) == V_RETI) - { - /* reti instruction. */ - frag = frag_more (2); -@@ -1598,10 +1983,11 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - break; - } - -- line = extract_operand (line, l1, sizeof (l1)); -- res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<15), (1<<16)); - if (res) - break; /* Error in operand. */ -+ msp430_substitute_CG(&op1, erratum_applies(ERRATUM_CPU4) && (opcode->bin_opcode == 0x1200)); - - bin |= op1.reg | (op1.am << 4); - __is = 1 + op1.ol; -@@ -1623,8 +2009,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - -- case 3: /* Conditional jumps instructions. */ -- line = extract_operand (line, l1, sizeof (l1)); -+ case FMT_JUMP: /* Conditional jumps instructions. */ -+ l1 = get_operand (); - /* l1 is a label. */ - if (l1[0]) - { -@@ -1693,11 +2079,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - else if (*l1 == '$') - { - as_bad (_("instruction requires label sans '$'")); -+ break; - } - else - { - as_bad (_ - ("instruction requires label or value in range -511:512")); -+ break; - } - dwarf2_emit_insn (2 * __is); - break; -@@ -1709,14 +2097,14 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - } - break; - -- case 4: /* Extended jumps. */ -+ case FMT_EMULATED_POLYMORPH_JUMP: /* Extended jumps. */ - if (!msp430_enable_polys) - { - as_bad (_("polymorphs are not enabled. Use -mP option to enable.")); - break; - } - -- line = extract_operand (line, l1, sizeof (l1)); -+ l1 = get_operand (); - if (l1[0]) - { - char *m = l1; -@@ -1730,7 +2118,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - if (exp.X_op == O_symbol) - { - /* Relaxation required. */ -- struct rcodes_s rc = msp430_rcodes[opcode->insn_opnumb]; -+ struct rcodes_s rc = msp430_rcodes[opcode_variant(opcode)]; - - /* The parameter to dwarf2_emit_insn is actually the offset to the start - of the insn from the fix piece of instruction that was emitted. -@@ -1751,13 +2139,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - as_bad (_("instruction requires label")); - break; - -- case 5: /* Emulated extended branches. */ -+ case FMT_EMULATED_LONG_POLYMORPH_JUMP: /* Emulated extended branches. */ - if (!msp430_enable_polys) - { - as_bad (_("polymorphs are not enabled. Use -mP option to enable.")); - break; - } -- line = extract_operand (line, l1, sizeof (l1)); -+ l1 = get_operand (); - if (l1[0]) - { - char * m = l1; -@@ -1771,7 +2159,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - if (exp.X_op == O_symbol) - { - /* Relaxation required. */ -- struct hcodes_s hc = msp430_hcodes[opcode->insn_opnumb]; -+ struct hcodes_s hc = msp430_hcodes[opcode_variant(opcode)]; - - frag = frag_more (8); - dwarf2_emit_insn (0); -@@ -1790,42 +2178,716 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) - as_bad (_("instruction requires label")); - break; - -+ case FMT_X_DOUBLE_OPERAND: /* Extended Format 1 ( double operand). */ -+ l1 = get_operand (); -+ l2 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ msp430_substitute_CG(&op1, 0); -+ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); -+ -+ if (res) -+ break; /* Error occurred. All warnings were done before. */ -+ -+ if (msp430x_repeats) -+ { -+ if (op1.mode != OP_REG || op2.mode != OP_REG) -+ { -+ as_bad(_("Repeated instruction must have register mode operands")); -+ break; -+ } -+ bin |= msp430x_repeats >> 1; -+ msp430x_repeats = 0; -+ } -+ -+ bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)) << 16; -+ -+ __is = 2 + op1.ol + op2.ol; /* insn size in words, opcode is 2 words wide. */ -+ frag = frag_more (2 * __is); -+ where = frag - frag_now->fr_literal; -+ bfd_putl32 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2 * __is); -+ -+ if (op1.mode == OP_EXP) -+ { -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); -+ -+ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_SRC); -+ else -+ fix_new_exp (frag_now, where , 2, -+ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_SRC); -+ } -+ -+ if (op2.mode == OP_EXP) -+ { -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &TONI and x(PC) = TONI -+ */ -+ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4 + ((__is == 4) ? 2 : 0)); -+ -+ if (op1.mode == OP_EXP) -+ { -+ if (op2.reg) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST_2ND); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST_2ND); -+ } -+ else -+ { -+ if (op2.reg) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); -+ } -+ } -+ break; -+ -+ case FMT_X_SINGLE_OPERAND: /* Extended format 2 (single-operand). */ -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ msp430_substitute_CG(&op1, 0); -+ if (res) -+ break; /* Error in operand. */ -+ -+ if (opcode_variant(opcode) != V_PUSHX && op1.mode == OP_EXP && op1.am == 3) // #N -+ { -+ as_bad (_("bad operand [%s]"), l1); -+ break; -+ } -+ -+ if (msp430x_repeats) -+ { -+ if (op1.mode != OP_REG) -+ { -+ as_bad(_("Repeated instruction must have register mode operand")); -+ break; -+ } -+ bin |= msp430x_repeats >> 1; -+ msp430x_repeats = 0; -+ } -+ -+ if(opcode_variant(opcode) == V_SWPSXT && op_width == ADDR_OP) -+ { // sxtx.a | swpbx.a opcode -+ bin ^= BYTE_OPERATION_X; -+ } -+ -+ bin |= (op1.reg | (op1.am << 4)) << 16; -+ __is = 2 + op1.ol; /* insn size in words, opcode is 2 words wide. */ -+ frag = frag_more (2 * __is); -+ where = frag - frag_now->fr_literal; -+ bfd_putl32 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2 * __is); -+ -+ if (op1.mode == OP_EXP) -+ { -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); -+ -+ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_DST); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); -+ } -+ break; -+ -+ case FMT_X_EXCEPTION: -+ /* calla, pushm, popm, rrcm, rrum, rram, rlam */ -+ bin = opcode->bin_opcode; // remove WB/AL bits -+ l1 = get_operand (); -+ switch(opcode_variant(opcode)) -+ { -+ case V_CALLA: // calla -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ if (res) -+ break; /* Error in operand. */ -+ __is = 1 + op1.ol; -+ frag = frag_more(__is * 2); -+ -+ if (op1.mode == OP_REG) -+ { -+ bin |= op1.reg; -+ switch (op1.am) -+ { -+ case 0: // Rdst -+ bin |= 0x0040; -+ break; -+ case 2: // @Rdst -+ bin |= 0x0060; -+ break; -+ case 3: // @Rdst+ -+ bin |= 0x0070; -+ break; -+ } -+ bin |= op1.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_EXP) -+ { -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ where = frag - frag_now->fr_literal; -+ switch (op1.am) -+ { -+ case 1: -+ switch(op1.reg) -+ { -+ case 0: // x(PC) = EDE -+ bin |= 0x0090; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), TRUE, BFD_RELOC_MSP430X_PCREL_D); -+ break; -+ case 2: // &abs20 -+ bin |= 0x0080; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_D); -+ break; -+ default: //z16(Rdst) -+ bin |= 0x0050 | op1.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); -+ break; -+ } -+ break; -+ case 3: // calla #imm -+ bin |= 0x00b0; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_D); -+ break; -+ } -+ dwarf2_emit_insn (__is * 2); -+ } -+ break; -+ case V_ROTM: // rxxm -+ l2 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, 1, 5); -+ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); -+ if(res) -+ break; /* An error occurred. All warnings were done before. */ -+ -+ if(op_width != ADDR_OP) -+ bin |= (1 << 4); -+ -+ if(op1.mode != OP_EXP || op1.am != 3) // not #imm -+ { -+ as_bad (_("bad operand [%s]"), l1); -+ break; -+ } -+ -+ bin |= ((op1.exp.X_add_number - 1) & 0x0003) << 10; -+ -+ if(op2.mode != OP_REG) -+ { -+ as_bad (_("bad operand [%s]"), l2); -+ break; -+ } -+ bin |= op2.reg; -+ -+ frag = frag_more (2); -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2); -+ break; -+ case V_PUSHM: -+ case V_POPM: -+ l2 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, 1, 17); -+ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); -+ if(res) -+ break; /* An error occurred. All warnings were done before. */ -+ -+ -+ if(imm_op == 0) -+ { -+ as_bad (_("bad operand [%s]"), l1); -+ break; -+ } -+ -+ if(op_width != ADDR_OP) -+ { -+ bin |= (1 << 8); -+ } -+ bin |= ((op1.exp.X_add_number - 1) & 0x000F) << 4; -+ -+ if(op2.mode != OP_REG) -+ { -+ as_bad (_("bad operand [%s]"), l2); -+ break; -+ } -+ if(opcode_variant(opcode) == V_POPM) -+ { -+ /* popm */ -+ bin |= (op2.reg - op1.exp.X_add_number + 1) & 0x000F; -+ } -+ else -+ { -+ /* pushm */ -+ bin |= op2.reg; -+ } -+ -+ frag = frag_more (2); -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2); -+ break; -+ } -+ break; -+ case FMT_X_ADDRESS: -+ /* mova, adda, suba, cmpa */ -+ l1 = get_operand (); -+ l2 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ res += msp430_dstoperand (&op2, l2, -(1<<19), (1<<20)); -+ if (res) -+ break; /* Error in operand. */ -+ -+ __is = 1 + op1.ol + op2.ol; -+ frag = frag_more(__is * 2); -+ where = frag - frag_now->fr_literal; -+ bin = opcode->bin_opcode; // remove WB/AL bits -+ if( opcode_variant(opcode) == V_MOVA) -+ { -+ if (op1.mode == OP_REG && op1.am == 0) -+ { // Rsrc -+ if(op2.mode == OP_REG && op2.am == 0) -+ { -+ // mova Rsrc, Rdst -+ bin |= 0x00c0 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if(op2.mode == OP_EXP && op2.am == 1 && op2.reg == 2) -+ { -+ // mova Rsrc, &abs20 -+ bin |= 0x0060 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, BFD_RELOC_MSP430X_D); -+ } -+ else if(op2.mode == OP_EXP && op2.am == 1 && op2.reg == 0) -+ { -+ bin |= 0x0070 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, BFD_RELOC_MSP430X_PCREL_D); -+ } -+ else if(op2.mode == OP_EXP && op2.am == 1) -+ { -+ // mova Rsrc, z16(Rdst) -+ bin |= 0x0070 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ if(op2.reg == 0) -+ // mova Rsrc, TONI == mova Rsrc, z16(PC) -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, BFD_RELOC_MSP430X_PCREL_INDXD); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, BFD_RELOC_MSP430X_INDXD); -+ } -+ else -+ as_bad (_("destination operand address mode not allowed with mova instruction")); -+ -+ } -+ else if (op2.mode == OP_REG && op2.am == 0) -+ { // Rdst -+ if(op1.mode == OP_REG && op1.am == 2) -+ { -+ // mova @Rsrc, Rdst -+ bin |= 0x0000 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_REG && op1.am == 3) -+ { -+ // mova @Rsrc+, Rdst -+ bin |= 0x0010 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_EXP && op1.am == 1 && op1.reg == 2) -+ { -+ if (op1.reg == 2) -+ { -+ // mova &abs20, Rdst -+ bin |= 0x0020 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); -+ } -+ else -+ { -+ // mova z16(Rsrc), Rdst -+ bin |= 0x0030 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ if (op1.reg == 0) -+ // mova TONI, Rdst -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_PCREL_INDXD); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); -+ } -+ } -+ else if (op1.mode == OP_EXP && op1.am == 3) -+ { -+ // mova #imm20, Rdst -+ bin |= 0x0080 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ if (op2.reg == 0) -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S_BYTE); -+ } -+ else -+ as_bad (_("source operand address mode not allowed with mova instruction")); -+ } -+ break; -+ } -+ else -+ /* adda, suba, cmpa */ -+ { -+ if(op2.mode == OP_REG && op2.am == 0) -+ { -+ if (op1.mode == OP_REG && op1.am == 0) -+ { // Rsrc, Rdst -+ bin |= 0x0040 | op1.reg << 8 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_EXP && op1.am == 3) -+ { -+ // #imm20, Rdst -+ bin |= 0x0080 | op2.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ if (op2.reg == 0) -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S_BYTE); -+ } -+ else -+ as_bad (_("source operand address mode not allowed with %s instruction"), opcode->name); -+ } -+ else -+ as_bad (_("destination operand address mode not allowed with %s instruction"), opcode->name); -+ break; -+ } -+ break; -+ -+ case FMT_X_EMULATED: /* Extended emulated. */ -+ switch (opcode_variant(opcode)) -+ { -+ case V_NONE: -+ /* single operand instruction emulated with Extended type 1 (double operand) instructions. */ -+ l1 = get_operand (); -+ res = msp430_dstoperand (&op1, l1, -(1<<19), (1<<20) ); -+ if (res) -+ break; -+ -+ if (msp430x_repeats) -+ { -+ if ((bin >> 20) && 0x3 == 1) -+ { -+ as_bad (_("%s instruction is not repeatable"), opcode->name); -+ break; -+ } -+ if (op1.mode != OP_REG) -+ { -+ as_bad(_("Repeated instruction must have register mode operand")); -+ break; -+ } -+ bin |= msp430x_repeats >> 1; -+ msp430x_repeats = 0; -+ } -+ -+ bin |= (op1.reg | (op1.am << 7)) << 16; -+ __is = 2 + op1.ol; -+ frag = frag_more (2 * __is); -+ where = frag - frag_now->fr_literal; -+ bfd_putl32 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2 * __is); -+ -+ if (op1.mode == OP_EXP) -+ { -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &TONI and x(PC) = TONI -+ */ -+ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); -+ -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); -+ if (op1.reg || (op1.reg == 0 && op1.am == 3)) -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_DST); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); -+ } -+ break; -+ case V_X_SHIFT: -+ { -+ /* Shift instruction. */ -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ msp430_substitute_CG(&op1, 0); -+ res += msp430_dstoperand (&op2, l1, -(1<<19), (1<<20)); -+ -+ if (res) -+ break; /* An error occurred. All warnings were done before. */ -+ -+ if (msp430x_repeats) -+ { -+ if (op2.mode != OP_REG) -+ { -+ as_bad(_("Repeated instruction must have register mode operands")); -+ break; -+ } -+ bin |= msp430x_repeats >> 1; -+ msp430x_repeats = 0; -+ } -+ -+ bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)) << 16; -+ -+ __is = 2 + op1.ol + op2.ol; /* insn size in words. */ -+ frag = frag_more (2 * __is); -+ where = frag - frag_now->fr_literal; -+ bfd_putl32 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2 * __is); -+ -+ if (op1.mode == OP_EXP) -+ { -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4); -+ -+ if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, CHECK_RELOC_MSP430X_SRC); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_SRC); -+ } -+ -+ if (op2.mode == OP_EXP) -+ { -+ /* -+ x(Rn). x can be odd in non-byte operations -+ except x(R2) = x(0) = &TONI and x(PC) = TONI -+ */ -+ imm_op = (op2.mode == 1 && op2.reg != 2 && op2.reg != 0); -+ -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 4 + ((__is == 4) ? 2 : 0)); -+ if (op1.mode == OP_EXP) -+ { -+ -+ if (op2.reg) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST_2ND); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST_2ND); -+ } -+ else -+ { -+ -+ if (op2.reg) /* Not PC relative. */ -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), FALSE, CHECK_RELOC_MSP430X_DST); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op2.exp), TRUE, CHECK_RELOC_MSP430X_PCREL_DST); -+ } -+ } -+ } -+ break; -+ case V_RETA: -+ /* reta */ -+ if (msp430x_repeats) -+ { -+ as_bad (_("%s instruction is not repeatable"), opcode->name); -+ break; -+ } -+ bin = opcode->bin_opcode; // remove WB/AL bits -+ frag = frag_more (2); -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2); -+ break; -+ case V_EMU_ADDR: // incda, decda, tsta -+ if (msp430x_repeats) -+ { -+ as_bad (_("%s instruction is not repeatable"), opcode->name); -+ break; -+ } -+ bin = opcode->bin_opcode; // remove WB/AL bits -+ l1 = get_operand (); -+ res = msp430_dstoperand (&op1, l1, -(1<<19), (1<<20) ); -+ if (res) -+ break; -+ -+ if(op1.mode == OP_REG && op1.am == 0) -+ { -+ frag = frag_more(2); -+ bin |= op1.reg; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (2); -+ } -+ else -+ as_bad (_("destination operand address mode not allowed with %s instruction"), opcode->name); -+ break; -+ case V_BRA: // bra, emulated with Address type instruction -+ if (msp430x_repeats) -+ { -+ as_bad (_("%s instruction is not repeatable"), opcode->name); -+ break; -+ } -+ -+ bin = opcode->bin_opcode; // remove WB/AL bits -+ l1 = get_operand (); -+ res = msp430_srcoperand (&op1, l1, &imm_op, -(1<<19), (1<<20)); -+ if (res) -+ break; /* Error in operand. */ -+ -+ __is = 1 + op1.ol; -+ frag = frag_more(__is * 2); -+ where = frag - frag_now->fr_literal; -+ if (op1.mode == OP_REG && op1.am == 0) -+ { -+ // mova Rsrc, PC -+ bin |= 0x00C0 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if(op1.mode == OP_REG && op1.am == 2) -+ { -+ // mova @Rsrc, PC -+ bin |= 0x0000 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_REG && op1.am == 3) -+ { -+ // mova @Rsrc+, PC -+ bin |= 0x0010 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ } -+ else if (op1.mode == OP_EXP && op1.am == 1) -+ { -+ if (op1.reg == 2) -+ { -+ // mova &abs20, PC -+ bin |= 0x0020; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); -+ } -+ else -+ { -+ // mova z16(Rsrc), PC -+ bin |= 0x0030 | op1.reg << 8; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ if (op1.reg == 0) -+ // mova z16(PC), PC = mova TONI, PC -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), TRUE, BFD_RELOC_MSP430X_PCREL_INDXD); -+ else -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_INDXD); -+ } -+ } -+ else if (op1.mode == OP_EXP && op1.am == 3) -+ { -+ // mova #imm20, Rdst -+ bin |= 0x0080; -+ bfd_putl16 ((bfd_vma) bin, frag); -+ dwarf2_emit_insn (__is * 2); -+ bfd_putl16 ((bfd_vma) ZEROS, frag + 2); -+ fix_new_exp (frag_now, where, 2, -+ &(op1.exp), FALSE, BFD_RELOC_MSP430X_S); -+ } -+ else -+ as_bad (_("source operand address mode not allowed with bra instruction")); -+ } -+ break; -+ - default: - as_bad (_("Illegal instruction or not implemented opcode.")); - } - -- input_line_pointer = line; -+ if (l1) -+ xfree(l1); -+ if (l2) -+ xfree(l2); -+ - return 0; - } - - void - md_assemble (char * str) - { -- struct msp430_opcode_s * opcode; -- char cmd[32]; -- unsigned int i = 0; -- -- str = skip_space (str); /* Skip leading spaces. */ -- str = extract_cmd (str, cmd, sizeof (cmd)); -- -- while (cmd[i] && i < sizeof (cmd)) -- { -- char a = TOLOWER (cmd[i]); -- cmd[i] = a; -- i++; -- } -- -- if (!cmd[0]) -+ struct msp430_opcode_s const * opcode; -+ char* cmda; -+ char* cmd; -+ int i = 0; -+ int cmd_length; -+ -+ while (ISSPACE (*str)) -+ ++str; -+ cmd = str; -+ while (*str && (! ISSPACE (*str)) && '.' != *str) -+ ++str; -+ cmd_length = str - cmd; -+ if (0 == cmd_length) - { - as_bad (_("can't find opcode ")); - return; - } - -- opcode = (struct msp430_opcode_s *) hash_find (msp430_hash, cmd); -+ cmda = alloca(1+cmd_length); -+ do { -+ cmda[i] = TOLOWER(cmd[i]); -+ } while (++i < cmd_length); -+ cmda[i] = 0; -+ -+ opcode = (struct msp430_opcode_s const *) hash_find (msp430_hash, cmda); - - if (opcode == NULL) - { -- as_bad (_("unknown opcode `%s'"), cmd); -+ as_bad (_("unknown opcode `%s'"), cmda); -+ return; -+ } -+ -+ if (msp430_cpu < MSP430_CPU_MSP430X && opcode_format(opcode) >= FMT_X) -+ { -+ as_bad (_("Extended instruction (%s) requires 430X-based mcu"), opcode->name); - return; - } - -@@ -1963,6 +3025,26 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) - - switch (fixp->fx_r_type) - { -+ case BFD_RELOC_MSP430X_PCREL_D: -+ case BFD_RELOC_MSP430X_PCREL_INDXD: -+ value -= 2; // operand located 2 bytes after opcode -+ break; -+ case BFD_RELOC_MSP430X_PCREL_SRC: -+ case BFD_RELOC_MSP430X_PCREL_SRC_BYTE: -+ case BFD_RELOC_MSP430X_PCREL_DST: -+ case BFD_RELOC_MSP430X_PCREL_DST_BYTE: -+ value -= 4; // operand located 4 bytes after opcode -+ break; -+ case BFD_RELOC_MSP430X_PCREL_DST_2ND: -+ case BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE: -+ value -= 6; // operand located 6 bytes after opcode -+ break; -+ default: -+ break; -+ } -+ -+ switch (fixp->fx_r_type) -+ { - case BFD_RELOC_MSP430_10_PCREL: - if (value & 1) - as_bad_where (fixp->fx_file, fixp->fx_line, -@@ -1987,7 +3069,7 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) - _("odd address operand: %ld"), value); - - /* Nothing to be corrected here. */ -- if (value < -32768 || value > 65536) -+ if (value < -32768 || value > 65535) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("operand out of range: %ld"), value); - -@@ -1997,7 +3079,7 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) - - case BFD_RELOC_MSP430_16_PCREL_BYTE: - /* Nothing to be corrected here. */ -- if (value < -32768 || value > 65536) -+ if (value < -32768 || value > 65535) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("operand out of range: %ld"), value); - -@@ -2016,6 +3098,76 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg) - bfd_putl16 ((bfd_vma) value, where); - break; - -+ case BFD_RELOC_MSP430X_SRC: -+ case BFD_RELOC_MSP430X_PCREL_SRC: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_SRC_BYTE: -+ case BFD_RELOC_MSP430X_PCREL_SRC_BYTE: -+ value &= 0xfffff; -+ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xf87f) | ((value >> 9) & 0x0780), where); -+ /* 16 least-significant bits */ -+ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 4); -+ break; -+ case BFD_RELOC_MSP430X_DST: -+ case BFD_RELOC_MSP430X_PCREL_DST: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_DST_BYTE: -+ case BFD_RELOC_MSP430X_PCREL_DST_BYTE: -+ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); -+ /* 16 least-significant bits */ -+ value &= 0xfffff; -+ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 4); -+ break; -+ case BFD_RELOC_MSP430X_DST_2ND: -+ case BFD_RELOC_MSP430X_PCREL_DST_2ND: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_DST_2ND_BYTE: -+ case BFD_RELOC_MSP430X_PCREL_DST_2ND_BYTE: -+ value &= 0xfffff; -+ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); -+ /* 16 least-significant bits */ -+ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 6); -+ break; -+ case BFD_RELOC_MSP430X_S: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_S_BYTE: -+ value &= 0xfffff; -+ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xf0ff) | ((value >> 8) & 0x0f00), where); -+ /* 16 least-significant bits */ -+ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 2); -+ break; -+ case BFD_RELOC_MSP430X_D: -+ case BFD_RELOC_MSP430X_PCREL_D: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_D_BYTE: -+ value &= 0xfffff; -+ bfd_putl16 ((bfd_vma)(bfd_getl16 (where) & 0xfff0) | ((value >> 16) & 0x000f), where); -+ /* 16 least-significant bits */ -+ bfd_putl16 ((bfd_vma) (value & 0xffff), where + 2); -+ break; -+ case BFD_RELOC_MSP430X_PCREL_INDXD: -+ if (value & 1) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("odd operand: %ld"), value); -+ case BFD_RELOC_MSP430X_INDXD: -+ if (value < -32768 || value > 65535) -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("operand out of range: %ld"), value); -+ -+ value &= 0xffff; /* Get rid of extended sign. */ -+ bfd_putl16 ((bfd_vma) value, where + 2); -+ break; -+ - default: - as_fatal (_("line %d: unknown relocation type: 0x%x"), - fixp->fx_line, fixp->fx_r_type); -diff --git a/gas/testsuite/gas/msp430/opcode.d b/gas/testsuite/gas/msp430/opcode.d -index 22df51c..297d3e1 100644 ---- a/gas/testsuite/gas/msp430/opcode.d -+++ b/gas/testsuite/gas/msp430/opcode.d -@@ -5,41 +5,49 @@ - - Disassembly of section .text: - 0+000 <[^>]*> 1b f3 and #1, r11 ;r3 As==01 --0+002 <[^>]*> 3a e3 inv r10 ; -+0+002 <[^>]*> 3a e3 inv r10 - 0+004 <[^>]*> 3b e0 ff 00 xor #255, r11 ;#0x00ff - 0+008 <[^>]*> 3c d2 bis #8, r12 ;r2 As==11 - 0+00a <[^>]*> 3d b0 10 00 bit #16, r13 ;#0x0010 - 0+00e <[^>]*> 3e c0 a0 00 bic #160, r14 ;#0x00a0 --0+012 <[^>]*> 0f 93 cmp #0, r15 ;r3 As==00 --0+014 <[^>]*> 1a 83 dec r10 ; --0+016 <[^>]*> 0b 73 sbc r11 ; --0+018 <[^>]*> 1c 53 inc r12 ; -+0+012 <[^>]*> 0f 93 tst r15 -+0+014 <[^>]*> 1a 83 dec r10 -+0+016 <[^>]*> 0b 73 sbc r11 -+0+018 <[^>]*> 1c 53 inc r12 - 0+01a <[^>]*> 2d 63 addc #2, r13 ;r3 As==10 --0+01c <[^>]*> 0e 12 push r14 ; --0+01e <[^>]*> 3f 41 pop r15 ; --0+020 <[^>]*> 8a 11 sxt r10 ; --0+022 <[^>]*> 0b 11 rra r11 ; --0+024 <[^>]*> 8c 10 swpb r12 ; --0+026 <[^>]*> 0d 10 rrc r13 ; -+0+01c <[^>]*> 0e 12 push r14 -+0+01e <[^>]*> 3f 41 pop r15 -+0+020 <[^>]*> 8a 11 sxt r10 -+0+022 <[^>]*> 0b 11 rra r11 -+0+024 <[^>]*> 8c 10 swpb r12 -+0+026 <[^>]*> 0d 10 rrc r13 - 0+028 <[^>]*> 30 41 ret - 0+02a <[^>]*> 31 40 00 00 mov #0, r1 ;#0x0000 --0+02e <[^>]*> b0 12 00 00 call #0 ;#0x0000 --0+032 <[^>]*> 1e 42 00 00 mov &0x0000,r14 ;0x0000 --0+036 <[^>]*> 0f 4e mov r14, r15 ; --0+038 <[^>]*> 0f 5f rla r15 ; --0+03a <[^>]*> 0f 7f subc r15, r15 ; --0+03c <[^>]*> 3f e3 inv r15 ; --0+03e <[^>]*> b0 12 00 00 call #0 ;#0x0000 --0+042 <[^>]*> 82 4e 00 00 mov r14, &0x0000 ; --0+046 <[^>]*> 82 4f 00 00 mov r15, &0x0000 ; --0+04a <[^>]*> 1e 42 00 00 mov &0x0000,r14 ;0x0000 --0+04e <[^>]*> 0f 4e mov r14, r15 ; --0+050 <[^>]*> 0f 5f rla r15 ; --0+052 <[^>]*> 0f 7f subc r15, r15 ; --0+054 <[^>]*> 3f e3 inv r15 ; --0+056 <[^>]*> b0 12 00 00 call #0 ;#0x0000 --0+05a <[^>]*> 82 4e 00 00 mov r14, &0x0000 ; --0+05e <[^>]*> 82 4f 00 00 mov r15, &0x0000 ; -+0+02e <[^>]*> b0 12 00 00 call #0x0000 -+0+032 <[^>]*> 1e 42 00 00 mov &0x0000,r14 -+0+036 <[^>]*> 0f 4e mov r14, r15 -+0+038 <[^>]*> 0f 5f rla r15 -+0+03a <[^>]*> 0f 7f subc r15, r15 -+0+03c <[^>]*> 3f e3 inv r15 -+0+03e <[^>]*> b0 12 00 00 call #0x0000 -+0+042 <[^>]*> 82 4e 00 00 mov r14, &0x0000 -+0+046 <[^>]*> 82 4f 00 00 mov r15, &0x0000 -+0+04a <[^>]*> 1e 42 00 00 mov &0x0000,r14 -+0+04e <[^>]*> 0f 4e mov r14, r15 -+0+050 <[^>]*> 0f 5f rla r15 -+0+052 <[^>]*> 0f 7f subc r15, r15 -+0+054 <[^>]*> 3f e3 inv r15 -+0+056 <[^>]*> b0 12 00 00 call #0x0000 -+0+05a <[^>]*> 82 4e 00 00 mov r14, &0x0000 -+0+05e <[^>]*> 82 4f 00 00 mov r15, &0x0000 - 0+062 <[^>]*> 3f 40 f0 00 mov #240, r15 ;#0x00f0 --0+066 <[^>]*> 30 40 00 00 br #0x0000 ; --0+06a <[^>]*> 92 52 00 02 72 01 add &0x0200,&0x0172 ;0x0200 -+0+066 <[^>]*> 30 40 00 00 br #0x0000 -+0+06a <[^>]*> 92 52 00 02 72 01 add &0x0200,&0x0172 -+0+070 3a 40 f0 de mov #-8464, r10 ;#0xdef0 -+0+074 3b 40 bc 9a mov #-25924,r11 ;#0x9abc -+0+078 3c 40 78 56 mov #22136, r12 ;#0x5678 -+0+07c 3d 40 34 12 mov #4660, r13 ;#0x1234 -+0+080 3a 40 7b 00 mov #123, r10 ;#0x007b -+0+084 0b 43 clr r11 -+0+086 0c 43 clr r12 -+0+088 0d 43 clr r13 -diff --git a/gas/testsuite/gas/msp430/opcode.s b/gas/testsuite/gas/msp430/opcode.s -index b85a463..8fa444f 100644 ---- a/gas/testsuite/gas/msp430/opcode.s -+++ b/gas/testsuite/gas/msp430/opcode.s -@@ -55,3 +55,19 @@ main: - ;; This next instruction triggered a bug which - ;; was fixed by a patch to msp430-dis.c on Jan 2, 2004 - add &0x200, &0x172 -+ -+.global extract -+ .type extract,@function -+extract: -+ mov #llo(0x123456789abcdef0), r10 -+ mov #lhi(0x123456789abcdef0), r11 -+ mov #hlo(0x123456789abcdef0), r12 -+ mov #hhi(0x123456789abcdef0), r13 -+ -+.global extract0 -+ .type extract,@function -+extract0: -+ mov #llo(123), r10 -+ mov #lhi(123), r11 -+ mov #hlo(123), r12 -+ mov #hhi(123), r13 -diff --git a/include/elf/msp430.h b/include/elf/msp430.h -index 44f5c51..1eeb56b 100644 ---- a/include/elf/msp430.h -+++ b/include/elf/msp430.h -@@ -23,24 +23,6 @@ - - #include "elf/reloc-macros.h" - --/* Processor specific flags for the ELF header e_flags field. */ --#define EF_MSP430_MACH 0xff -- --#define E_MSP430_MACH_MSP430x11 11 --#define E_MSP430_MACH_MSP430x11x1 110 --#define E_MSP430_MACH_MSP430x12 12 --#define E_MSP430_MACH_MSP430x13 13 --#define E_MSP430_MACH_MSP430x14 14 --#define E_MSP430_MACH_MSP430x15 15 --#define E_MSP430_MACH_MSP430x16 16 --#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_MSP430x42 42 --#define E_MSP430_MACH_MSP430x43 43 --#define E_MSP430_MACH_MSP430x44 44 -- - /* Relocations. */ - START_RELOC_NUMBERS (elf_msp430_reloc_type) - RELOC_NUMBER (R_MSP430_NONE, 0) -@@ -52,7 +34,71 @@ START_RELOC_NUMBERS (elf_msp430_reloc_type) - RELOC_NUMBER (R_MSP430_16_PCREL_BYTE, 6) - RELOC_NUMBER (R_MSP430_2X_PCREL, 7) - RELOC_NUMBER (R_MSP430_RL_PCREL, 8) -+ RELOC_NUMBER (R_MSP430X_SRC_BYTE, 9) -+ RELOC_NUMBER (R_MSP430X_SRC, 10) -+ RELOC_NUMBER (R_MSP430X_DST_BYTE, 11) -+ RELOC_NUMBER (R_MSP430X_DST, 12) -+ RELOC_NUMBER (R_MSP430X_DST_2ND_BYTE, 13) -+ RELOC_NUMBER (R_MSP430X_DST_2ND, 14) -+ RELOC_NUMBER (R_MSP430X_PCREL_SRC_BYTE, 15) -+ RELOC_NUMBER (R_MSP430X_PCREL_SRC, 16) -+ RELOC_NUMBER (R_MSP430X_PCREL_DST_BYTE, 17) -+ RELOC_NUMBER (R_MSP430X_PCREL_DST, 18) -+ RELOC_NUMBER (R_MSP430X_PCREL_DST_2ND, 19) -+ RELOC_NUMBER (R_MSP430X_PCREL_DST_2ND_BYTE, 20) -+ RELOC_NUMBER (R_MSP430X_S_BYTE, 21) -+ RELOC_NUMBER (R_MSP430X_S, 22) -+ RELOC_NUMBER (R_MSP430X_D_BYTE, 23) -+ RELOC_NUMBER (R_MSP430X_D, 24) -+ RELOC_NUMBER (R_MSP430X_PCREL_D, 25) -+ RELOC_NUMBER (R_MSP430X_INDXD, 26) -+ RELOC_NUMBER (R_MSP430X_PCREL_INDXD, 27) - - END_RELOC_NUMBERS (R_MSP430_max) - -+/* TODO: Define a set of flags that are appropriate for storage in the e_flags field. -+ * Potential members include: -+ * - Whether CPUX instructions are present -+ * - Whether hardware multiply register references are present (which kind) -+ * - The code addressing mode -+ * - The data addressing mode -+ */ -+ -+/* Pre-uniarch versions of binutils stored machine types in the -+ * e_flags field, with values up to 471 decimal. Now we store the -+ * machine type in the e_mach field, and use e_flags to identify the -+ * characteristics of the code. -+ * -+ * Use the following flag to indicate that this object file uses the -+ * uniarch flag layout. */ -+#define EF_MSP430_UNIARCH 0x10000000 -+ -+#define EF_MSP430_ARCH_430 0x00000000 -+#define EF_MSP430_ARCH_430X 0x00000001 -+#define EF_MSP430_ARCH 0x000000FF -+#if 0 -+/* These are symbol-associated, not archive-associated, attributes. -+ * Not sure what to do with them. */ -+#define EF_MSP430_CPU_430 0x00000000 -+#define EF_MSP430_CPU_430X 0x00000200 -+#define EF_MSP430_CPU_430XV2 0x00000300 -+#define EF_MSP430_CPU 0x00000300 -+#define EF_MSP430_MPY_NONE 0x00000000 -+#define EF_MSP430_MPY_16 0x00001000 -+#define EF_MSP430_MPY_16_SE (0x00008000 + EF_MSP430_MPY_16) -+#define EF_MSP430_MPY_32 0x00002000 -+#define EF_MSP430_MPY_32_DW (0x00008000 + EF_MSP430_MPY_32) -+#define EF_MSP430_MPY_CLASS 0x00003000 -+#define EF_MSP430_MPY 0x0000F000 -+#define EF_MSP430_CODE_NEAR 0x00010000 -+#define EF_MSP430_CODE_FAR 0x00020000 -+#define EF_MSP430_CODE_MIXED 0x00030000 -+#define EF_MSP430_CODE 0x00030000 -+#define EF_MSP430_DATA_NEAR 0x00040000 -+#define EF_MSP430_DATA_FAR 0x00080000 -+#define EF_MSP430_DATA_MIXED 0x000c0000 -+#define EF_MSP430_DATA 0x000c0000 -+#define EF_MSP430_A20 0x000F0000 -+#endif -+ - #endif /* _ELF_MSP430_H */ -diff --git a/include/opcode/msp430.h b/include/opcode/msp430.h -index d3bf130..c281a49 100644 ---- a/include/opcode/msp430.h -+++ b/include/opcode/msp430.h -@@ -26,7 +26,7 @@ struct msp430_operand_s - int ol; /* Operand length words. */ - int am; /* Addr mode. */ - int reg; /* Register. */ -- int mode; /* Pperand mode. */ -+ int mode; /* Operand mode. */ - #define OP_REG 0 - #define OP_EXP 1 - #ifndef DASM_SECTION -@@ -34,91 +34,252 @@ struct msp430_operand_s - #endif - }; - --#define BYTE_OPERATION (1 << 6) /* Byte operation flag for all instructions. */ -+#define BYTE_OPERATION (1 << 6) /* Byte operation flag for 430 instructions. */ -+#define BYTE_OPERATION_X (1 << 22) /* Byte operation flag for 430x instructions. */ -+#define NON_ADDR_OPERATION (1 << 6) /* Address operation flag for 430x instructions. */ -+ -+typedef enum -+{ -+ DEFAULT_OP, // instruction has no modifier -+ WORD_OP, // .w -+ BYTE_OP, // .b -+ ADDR_OP // .a -+} -+opwidth_t; -+ -+/** Bit-markers for type of CPU present. */ -+typedef enum msp430_cpu_e -+{ -+ MSP430_CPU_MSP430 = 0x0000, -+ MSP430_CPU_MSP430X = 0x0002, -+ MSP430_CPU_MSP430XV2 = 0x0003, -+ MSP430_CPU = 0x0003, -+} msp430_cpu_e; -+ -+/** Bit-markers for type of hardware multiplier present. */ -+typedef enum msp430_mpy_e -+{ -+ MSP430_MPY_NONE = 0x0000, -+ MSP430_MPY_16 = 0x0010, -+ MSP430_MPY_16SE = 0x0011, -+ MSP430_MPY_32 = 0x0020, -+ MSP430_MPY_32DW = 0x0022, -+ MSP430_MPY = 0x0030 -+} msp430_mpy_e; -+ -+typedef enum -+{ -+ FMT_EMULATED = 0, -+ FMT_DOUBLE_OPERAND, -+ FMT_SINGLE_OPERAND, -+ FMT_JUMP, -+ FMT_EMULATED_POLYMORPH_JUMP, -+ FMT_EMULATED_LONG_POLYMORPH_JUMP, -+ FMT_X_DOUBLE_OPERAND, -+ FMT_X_SINGLE_OPERAND, -+ FMT_X_EXCEPTION, -+ FMT_X_EMULATED, -+ FMT_X_ADDRESS, -+ -+ FMT_X = FMT_X_DOUBLE_OPERAND, -+ FMT_MASK = 0x000f, -+ -+ /* allowed modifiers: .b, .w, .a */ -+ MOD_NONE = 0, -+ MOD_W = 1 << 4, -+ MOD_B = 1 << 5, -+ MOD_A = 1 << 6, -+ MOD_MASK = 0x0070, -+ -+ /* opcode variant */ -+ VAR_MASK = 0x0380, -+} -+format_t; -+ -+#define OP_V(x) (x << 7) - - struct msp430_opcode_s - { - char *name; -- int fmt; -- int insn_opnumb; -- int bin_opcode; -- int bin_mask; -+ format_t fmt; -+ unsigned int insn_opnumb; -+ unsigned int bin_opcode; -+ unsigned int bin_mask; - }; - --#define MSP_INSN(name, size, numb, bin, mask) { #name, size, numb, bin, mask } -+#define opcode_format(opcode) (opcode->fmt & FMT_MASK) -+#define opcode_modifier(opcode) (opcode->fmt & MOD_MASK) -+#define opcode_variant(opcode) ((opcode->fmt & VAR_MASK) >> 7) -+ -+/* opcode variants: */ -+enum -+{ -+ V_NONE = 0, // ordinary instruction -+ -+ /* FMT_EMULATED: */ -+ V_NOOP, // no operands: set/clear bit instructions, reti -+ V_SHIFT, // shift instructions -+ V_BR, // br instruction -+ -+ /* FMT_SINGLE_OPERAND: */ -+ V_RETI = 1, // reti -+ V_CALL = 2, // hex operand in disassembly -+ -+ /* FMT_X_SINGLE_OPERAND: */ -+ // V_NONE - #N operand disallowed -+ V_SWPSXT = 1, // #N operand disallowed, special A/L, B/W bits case with .a modifier -+ V_PUSHX, // #N operand allowed - --static struct msp430_opcode_s msp430_opcodes[] = -+ /* FMT_X_EXCEPTIONS: */ -+ V_CALLA = 0, // calla -+ V_ROTM, // two operands, rotations -+ V_POPM, // two operands, popm -+ V_PUSHM, // two operands, pushm -+ -+ /* FMT_X_EMULATED: */ -+ // V_NONE - substituted by 430x double operand instruction -+ V_X_SHIFT, // shifts -+ V_RETA, // reta, short instruction, no operands -+ V_EMU_ADDR, // substituted by address instruction other than mova -+ V_BRA, // bra, substituted by mova address instruction == format II exception instruction -+ // clra emulated by msp430 instruction -+ -+ /* FMT_X_ADDRESS: */ -+ V_MOVA = 1, // mova, more address modes allowed -+}; -+ -+#define MSP_INSN(name, format, opnumb, bin, mask) { #name, format, opnumb, bin, mask } -+ -+static struct msp430_opcode_s const 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), -+ MSP_INSN (and, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xf000, 0xfffff000), -+ MSP_INSN (inv, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0xe330, 0xfffffff0), -+ MSP_INSN (xor, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xe000, 0xfffff000), -+ MSP_INSN (setz, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd322, 0xffffffff), -+ MSP_INSN (setc, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd312, 0xffffffff), -+ MSP_INSN (eint, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd232, 0xffffffff), -+ MSP_INSN (setn, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xd222, 0xffffffff), -+ MSP_INSN (bis, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xd000, 0xfffff000), -+ MSP_INSN (clrz, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc322, 0xffffffff), -+ MSP_INSN (clrc, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc312, 0xffffffff), -+ MSP_INSN (dint, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc232, 0xffffffff), -+ MSP_INSN (clrn, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0xc222, 0xffffffff), -+ MSP_INSN (bic, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xc000, 0xfffff000), -+ MSP_INSN (bit, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xb000, 0xfffff000), -+ MSP_INSN (dadc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0xa300, 0xffffff30), -+ MSP_INSN (dadd, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0xa000, 0xfffff000), -+ MSP_INSN (tst, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x9300, 0xffffff30), -+ MSP_INSN (cmp, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x9000, 0xfffff000), -+ MSP_INSN (decd, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x8320, 0xffffff30), -+ MSP_INSN (dec, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x8310, 0xffffff30), -+ MSP_INSN (sub, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x8000, 0xfffff000), -+ MSP_INSN (sbc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x7300, 0xffffff30), -+ MSP_INSN (subc, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x7000, 0xfffff000), -+ MSP_INSN (adc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x6300, 0xffffff30), -+ MSP_INSN (rlc, FMT_EMULATED | MOD_W|MOD_B | OP_V(V_SHIFT), 2, 0x6000, 0xfffff000), -+ MSP_INSN (addc, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x6000, 0xfffff000), -+ MSP_INSN (incd, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x5320, 0xffffff30), -+ MSP_INSN (inc, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x5310, 0xffffff30), -+ MSP_INSN (rla, FMT_EMULATED | MOD_W|MOD_B | OP_V(V_SHIFT), 2, 0x5000, 0xfffff000), -+ MSP_INSN (add, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x5000, 0xfffff000), -+ MSP_INSN (nop, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0x4303, 0xffffffff), -+ MSP_INSN (clr, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x4300, 0xffffff30), -+ MSP_INSN (clra, FMT_EMULATED | MOD_NONE | OP_V(0), 1, 0x4300, 0xffffff30), // MOV #0, Rdst -+ MSP_INSN (ret, FMT_EMULATED | MOD_NONE | OP_V(V_NOOP), 0, 0x4130, 0xffffffff), -+ MSP_INSN (pop, FMT_EMULATED | MOD_W|MOD_B | OP_V(0), 1, 0x4130, 0xffffff30), -+ MSP_INSN (br, FMT_EMULATED | MOD_NONE | OP_V(V_BR), 1, 0x4000, 0xfffff08f), -+ MSP_INSN (mov, FMT_DOUBLE_OPERAND | MOD_W|MOD_B | OP_V(0), 2, 0x4000, 0xfffff000), -+ -+ MSP_INSN (jmp, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3c00, 0xfffffc00), -+ MSP_INSN (jl, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3800, 0xfffffc00), -+ MSP_INSN (jge, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3400, 0xfffffc00), -+ MSP_INSN (jn, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x3000, 0xfffffc00), -+ MSP_INSN (jc, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2c00, 0xfffffc00), -+ MSP_INSN (jhs, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2c00, 0xfffffc00), -+ MSP_INSN (jnc, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2800, 0xfffffc00), -+ MSP_INSN (jlo, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2800, 0xfffffc00), -+ MSP_INSN (jz, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2400, 0xfffffc00), -+ MSP_INSN (jeq, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2400, 0xfffffc00), -+ MSP_INSN (jnz, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2000, 0xfffffc00), -+ MSP_INSN (jne, FMT_JUMP | MOD_NONE | OP_V(0), 1, 0x2000, 0xfffffc00), -+ -+ MSP_INSN (reti, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(V_RETI), 0, 0x1300, 0xffffffc0), -+ MSP_INSN (call, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(V_CALL), 1, 0x1280, 0xffffffc0), -+ MSP_INSN (push, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1200, 0xffffff80), -+ MSP_INSN (sxt, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(0), 1, 0x1180, 0xffffffc0), -+ MSP_INSN (rra, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1100, 0xffffff80), -+ MSP_INSN (swpb, FMT_SINGLE_OPERAND | MOD_NONE | OP_V(0), 1, 0x1080, 0xffffffc0), -+ MSP_INSN (rrc, FMT_SINGLE_OPERAND | MOD_W|MOD_B | OP_V(0), 1, 0x1000, 0xffffff80), -+ -+ -+ /* emulated instructions placed just before instruction emulated by for disassembly search */ -+ MSP_INSN (popx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x41301800, 0xff30f800), // MOVX @SP+, dst -+ MSP_INSN (clrx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x43001800, 0xff30f800), // MOVX #0, dst -+ MSP_INSN (movx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x40001800, 0xf000f800), -+ MSP_INSN (incx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x53101800, 0xff30f800), // ADDX #1, dst -+ MSP_INSN (incdx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x53201800, 0xff30f800), // ADDX #2, dst -+ MSP_INSN (rlax, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(V_X_SHIFT), 1, 0x50001800, 0xf000f800), // ADDX dst, dst -+ MSP_INSN (addx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x50001800, 0xf000f800), -+ MSP_INSN (adcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x63001800, 0xff30f800), // ADDCX #0, dst -+ MSP_INSN (rlcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(V_X_SHIFT), 1, 0x60001800, 0xf000f800), // ADDCX dst, dst -+ MSP_INSN (addcx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x60001800, 0xf000f800), -+ MSP_INSN (sbcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x73001800, 0xff30f800), // SUBCX #0, dst -+ MSP_INSN (subcx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x70001800, 0xf000f800), -+ MSP_INSN (decx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x83101800, 0xff30f800), // SUBX #1, dst -+ MSP_INSN (decdx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x83201800, 0xff30f800), // SUBX #2, dst -+ MSP_INSN (subx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x80001800, 0xf000f800), -+ MSP_INSN (tstx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x93001800, 0xff30f800), // CMPX #0, dst -+ MSP_INSN (cmpx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0x90001800, 0xf000f800), -+ MSP_INSN (dadcx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0xa3001800, 0xff30f800), // DADDX #0, dst -+ MSP_INSN (daddx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xa0001800, 0xf000f800), -+ MSP_INSN (bitx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xb0001800, 0xf000f800), -+ MSP_INSN (bicx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xc0001800, 0xf000f800), -+ MSP_INSN (bisx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xd0001800, 0xf000f800), -+ MSP_INSN (invx, FMT_X_EMULATED | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0xe3301800, 0xff30f800), // XORX #-1, dst -+ MSP_INSN (xorx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xe0001800, 0xf000f800), -+ MSP_INSN (andx, FMT_X_DOUBLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 2, 0xf0001800, 0xf000f800), -+ -+ MSP_INSN (rrcx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x10001800, 0xff80f800), -+ MSP_INSN (swpbx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_A | OP_V(V_SWPSXT), 1, 0x10801800, 0xffc0f800), -+ MSP_INSN (rrax, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(0), 1, 0x11001800, 0xff80f800), -+ MSP_INSN (sxtx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_A | OP_V(V_SWPSXT), 1, 0x11801800, 0xffc0f800), -+ MSP_INSN (pushx, FMT_X_SINGLE_OPERAND | MOD_W|MOD_B|MOD_A | OP_V(V_PUSHX), 1, 0x12001800, 0xff80f800), -+ -+ MSP_INSN (calla, FMT_X_EXCEPTION | MOD_NONE | OP_V(V_CALLA), 1, 0x1300, 0xffffff00), -+ MSP_INSN (pushm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_PUSHM), 2, 0x1400, 0xfffffe00), -+ MSP_INSN (popm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_POPM), 2, 0x1600, 0xfffffe00), -+ MSP_INSN (rrcm, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0040, 0xfffff3e0), -+ MSP_INSN (rram, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0140, 0xfffff3e0), -+ MSP_INSN (rlam, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0240, 0xfffff3e0), -+ MSP_INSN (rrum, FMT_X_EXCEPTION | MOD_W|MOD_A | OP_V(V_ROTM), 2, 0x0340, 0xfffff3e0), -+ -+ /* Address. */ -+ MSP_INSN (incda, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03e0, 0xfffffff0), // ADDA #2, Rdst = ADDA R3, Rdst -+ MSP_INSN (adda, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x00a0, 0xfffff0b0), -+ MSP_INSN (tsta, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03d0, 0xfffffff0), // CMPA #0, Rdst = CMPA R3, Rdst -+ MSP_INSN (cmpa, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x0090, 0xfffff0b0), -+ MSP_INSN (decda, FMT_X_EMULATED | MOD_NONE | OP_V(V_EMU_ADDR), 1, 0x03f0, 0xfffffff0), // SUBA #2, Rdst = SUBA R3, Rdst -+ MSP_INSN (suba, FMT_X_ADDRESS | MOD_NONE | OP_V(0), 2, 0x00b0, 0xfffff0b0), -+ MSP_INSN (reta, FMT_X_EMULATED | MOD_NONE | OP_V(V_RETA), 0, 0x0110, 0xffffffff), // MOVA @SP+, PC -+ MSP_INSN (bra, FMT_X_EMULATED | MOD_NONE | OP_V(V_BRA), 1, 0x0000, 0xfffff0cf), // MOVA dst, PC -+ MSP_INSN (bra, FMT_X_EMULATED | MOD_NONE | OP_V(V_BRA), 1, 0x0080, 0xfffff0bf), // MOVA #imm20, PC; MOVA Rsrc, Rdst -+ MSP_INSN (mova, FMT_X_ADDRESS | MOD_NONE | OP_V(V_MOVA), 1, 0x0000, 0xfffff000), -+ - /* Simple polymorphs. */ -- MSP_INSN (beq, 4, 0, 0, 0xffff), -- MSP_INSN (bne, 4, 1, 0, 0xffff), -- MSP_INSN (blt, 4, 2, 0, 0xffff), -- MSP_INSN (bltu, 4, 3, 0, 0xffff), -- MSP_INSN (bge, 4, 4, 0, 0xffff), -- MSP_INSN (bgeu, 4, 5, 0, 0xffff), -- MSP_INSN (bltn, 4, 6, 0, 0xffff), -- MSP_INSN (jump, 4, 7, 0, 0xffff), -- /* Long polymorphs. */ -- MSP_INSN (bgt, 5, 0, 0, 0xffff), -- MSP_INSN (bgtu, 5, 1, 0, 0xffff), -- MSP_INSN (bleu, 5, 2, 0, 0xffff), -- MSP_INSN (ble, 5, 3, 0, 0xffff), -+ MSP_INSN (beq, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(0), 1, 0, 0xffff), -+ MSP_INSN (bne, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(1), 1, 0, 0xffff), -+ MSP_INSN (blt, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(2), 1, 0, 0xffff), -+ MSP_INSN (bltu, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(3), 1, 0, 0xffff), -+ MSP_INSN (bge, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(4), 1, 0, 0xffff), -+ MSP_INSN (bgeu, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(5), 1, 0, 0xffff), -+ MSP_INSN (bltn, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(6), 1, 0, 0xffff), -+ MSP_INSN (jump, FMT_EMULATED_POLYMORPH_JUMP | MOD_NONE | OP_V(7), 1, 0, 0xffff), - -+ /* Long polymorphs. */ -+ MSP_INSN (bgt, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(0), 1, 0, 0xffff), -+ MSP_INSN (bgtu, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(1), 1, 0, 0xffff), -+ MSP_INSN (bleu, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(2), 1, 0, 0xffff), -+ MSP_INSN (ble, FMT_EMULATED_LONG_POLYMORPH_JUMP | MOD_NONE | OP_V(3), 1, 0, 0xffff), - /* End of instruction set. */ - { NULL, 0, 0, 0, 0 } - }; -diff --git a/ld/Makefile.am b/ld/Makefile.am -index b676801..0345374 100644 ---- a/ld/Makefile.am -+++ b/ld/Makefile.am -@@ -335,65 +335,7 @@ ALL_EMULATION_SOURCES = \ - emipspe.c \ - emn10200.c \ - emn10300.c \ -- emsp430x110.c \ -- emsp430x1101.c \ -- emsp430x1111.c \ -- emsp430x112.c \ -- emsp430x1121.c \ -- emsp430x1122.c \ -- emsp430x1132.c \ -- emsp430x122.c \ -- emsp430x1222.c \ -- emsp430x123.c \ -- emsp430x1232.c \ -- emsp430x133.c \ -- emsp430x1331.c \ -- emsp430x135.c \ -- emsp430x1351.c \ -- emsp430x147.c \ -- emsp430x148.c \ -- emsp430x149.c \ -- emsp430x155.c \ -- emsp430x156.c \ -- emsp430x157.c \ -- emsp430x1610.c \ -- emsp430x1611.c \ -- emsp430x1612.c \ -- emsp430x167.c \ -- emsp430x168.c \ -- emsp430x169.c \ -- emsp430x2101.c \ -- emsp430x2111.c \ -- emsp430x2121.c \ -- emsp430x2131.c \ -- emsp430x311.c \ -- emsp430x312.c \ -- emsp430x313.c \ -- emsp430x314.c \ -- emsp430x315.c \ -- emsp430x323.c \ -- emsp430x325.c \ -- emsp430x336.c \ -- emsp430x337.c \ -- emsp430x412.c \ -- emsp430x413.c \ -- emsp430x415.c \ -- emsp430x417.c \ -- emsp430x435.c \ -- emsp430x436.c \ -- emsp430x437.c \ -- emsp430x447.c \ -- emsp430x448.c \ -- emsp430x449.c \ -- emsp430xE423.c \ -- emsp430xE425.c \ -- emsp430xE427.c \ -- emsp430xG437.c \ -- emsp430xG438.c \ -- emsp430xG439.c \ -- emsp430xW423.c \ -- emsp430xW425.c \ -- emsp430xW427.c \ -+ emsp430.c \ - enews.c \ - ens32knbsd.c \ - eor32.c \ -@@ -1436,242 +1378,10 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ - $(srcdir)/emulparams/mn10200.sh \ - $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} - ${GENSCRIPTS} mn10300 "$(tdir_mn10300)" --emsp430x110.c: $(srcdir)/emulparams/msp430all.sh \ -+emsp430.c: $(srcdir)/emulparams/msp430uni.sh \ - $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ - ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x110 "$(tdir_msp430x110)" msp430all --emsp430x1101.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1101 "$(tdir_msp430x1101)" msp430all --emsp430x1111.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1111 "$(tdir_msp430x1111)" msp430all --emsp430x112.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x112 "$(tdir_msp430x112)" msp430all --emsp430x1121.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1121 "$(tdir_msp430x1121)" msp430all --emsp430x1122.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1122 "$(tdir_msp430x1122)" msp430all --emsp430x1132.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1132 "$(tdir_msp430x1132)" msp430all --emsp430x122.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x122 "$(tdir_msp430x122)" msp430all --emsp430x1222.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1222 "$(tdir_msp430x1222)" msp430all --emsp430x123.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x123 "$(tdir_msp430x123)" msp430all --emsp430x1232.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1232 "$(tdir_msp430x1232)" msp430all --emsp430x133.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x133 "$(tdir_msp430x133)" msp430all --emsp430x1331.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1331 "$(tdir_msp430x1331)" msp430all --emsp430x135.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x135 "$(tdir_msp430x135)" msp430all --emsp430x1351.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1351 "$(tdir_msp430x1351)" msp430all --emsp430x147.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x147 "$(tdir_msp430x147)" msp430all --emsp430x148.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x148 "$(tdir_msp430x148)" msp430all --emsp430x149.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x149 "$(tdir_msp430x149)" msp430all --emsp430x155.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x155 "$(tdir_msp430x155)" msp430all --emsp430x156.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x156 "$(tdir_msp430x156)" msp430all --emsp430x157.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x157 "$(tdir_msp430x157)" msp430all --emsp430x1610.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1610 "$(tdir_msp430x1610)" msp430all --emsp430x1611.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1611 "$(tdir_msp430x1611)" msp430all --emsp430x1612.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1612 "$(tdir_msp430x1612)" msp430all --emsp430x167.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x167 "$(tdir_msp430x167)" msp430all --emsp430x168.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x168 "$(tdir_msp430x168)" msp430all --emsp430x169.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x169 "$(tdir_msp430x169)" msp430all --emsp430x2101.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2101 "$(tdir_msp430x2101)" msp430all --emsp430x2111.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2111 "$(tdir_msp430x2111)" msp430all --emsp430x2121.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2121 "$(tdir_msp430x2121)" msp430all --emsp430x2131.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2131 "$(tdir_msp430x2131)" msp430all --emsp430x311.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x311 "$(tdir_msp430x311)" msp430all --emsp430x312.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x312 "$(tdir_msp430x312)" msp430all --emsp430x313.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x313 "$(tdir_msp430x313)" msp430all --emsp430x314.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x314 "$(tdir_msp430x314)" msp430all --emsp430x315.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x315 "$(tdir_msp430x315)" msp430all --emsp430x323.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x323 "$(tdir_msp430x323)" msp430all --emsp430x325.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x325 "$(tdir_msp430x325)" msp430all --emsp430x336.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x336 "$(tdir_msp430x336)" msp430all --emsp430x337.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x337 "$(tdir_msp430x337)" msp430all --emsp430x412.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x412 "$(tdir_msp430x412)" msp430all --emsp430x413.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x413 "$(tdir_msp430x413)" msp430all --emsp430x415.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x415 "$(tdir_msp430x415)" msp430all --emsp430x417.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x417 "$(tdir_msp430x417)" msp430all --emsp430x435.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x435 "$(tdir_msp430x435)" msp430all --emsp430x436.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x436 "$(tdir_msp430x436)" msp430all --emsp430x437.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x437 "$(tdir_msp430x437)" msp430all --emsp430x447.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x447 "$(tdir_msp430x447)" msp430all --emsp430x448.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x448 "$(tdir_msp430x448)" msp430all --emsp430x449.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x449 "$(tdir_msp430x449)" msp430all --emsp430xE423.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE423 "$(tdir_msp430xE423)" msp430all --emsp430xE425.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE425 "$(tdir_msp430xE425)" msp430all --emsp430xE427.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE427 "$(tdir_msp430xE427)" msp430all --emsp430xG437.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG437 "$(tdir_msp430xG437)" msp430all --emsp430xG438.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG438 "$(tdir_msp430xG438)" msp430all --emsp430xG439.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG439 "$(tdir_msp430xG439)" msp430all --emsp430xW423.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW423 "$(tdir_msp430xW423)" msp430all --emsp430xW425.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW425 "$(tdir_msp430xW425)" msp430all --emsp430xW427.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW427 "$(tdir_msp430xW427)" msp430all -+ ${GENSCRIPTS} msp430 "$(tdir_msp430)" msp430uni - enews.c: $(srcdir)/emulparams/news.sh \ - $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} - ${GENSCRIPTS} news "$(tdir_news)" -diff --git a/ld/Makefile.in b/ld/Makefile.in -index dd4e407..d834888 100644 ---- a/ld/Makefile.in -+++ b/ld/Makefile.in -@@ -641,65 +641,7 @@ ALL_EMULATION_SOURCES = \ - emipspe.c \ - emn10200.c \ - emn10300.c \ -- emsp430x110.c \ -- emsp430x1101.c \ -- emsp430x1111.c \ -- emsp430x112.c \ -- emsp430x1121.c \ -- emsp430x1122.c \ -- emsp430x1132.c \ -- emsp430x122.c \ -- emsp430x1222.c \ -- emsp430x123.c \ -- emsp430x1232.c \ -- emsp430x133.c \ -- emsp430x1331.c \ -- emsp430x135.c \ -- emsp430x1351.c \ -- emsp430x147.c \ -- emsp430x148.c \ -- emsp430x149.c \ -- emsp430x155.c \ -- emsp430x156.c \ -- emsp430x157.c \ -- emsp430x1610.c \ -- emsp430x1611.c \ -- emsp430x1612.c \ -- emsp430x167.c \ -- emsp430x168.c \ -- emsp430x169.c \ -- emsp430x2101.c \ -- emsp430x2111.c \ -- emsp430x2121.c \ -- emsp430x2131.c \ -- emsp430x311.c \ -- emsp430x312.c \ -- emsp430x313.c \ -- emsp430x314.c \ -- emsp430x315.c \ -- emsp430x323.c \ -- emsp430x325.c \ -- emsp430x336.c \ -- emsp430x337.c \ -- emsp430x412.c \ -- emsp430x413.c \ -- emsp430x415.c \ -- emsp430x417.c \ -- emsp430x435.c \ -- emsp430x436.c \ -- emsp430x437.c \ -- emsp430x447.c \ -- emsp430x448.c \ -- emsp430x449.c \ -- emsp430xE423.c \ -- emsp430xE425.c \ -- emsp430xE427.c \ -- emsp430xG437.c \ -- emsp430xG438.c \ -- emsp430xG439.c \ -- emsp430xW423.c \ -- emsp430xW425.c \ -- emsp430xW427.c \ -+ emsp430.c \ - enews.c \ - ens32knbsd.c \ - eor32.c \ -@@ -1270,65 +1212,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10300.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x110.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1101.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1111.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x112.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1121.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1122.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1132.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x122.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1222.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x123.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1232.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x133.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1331.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x135.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1351.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x147.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x148.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x149.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x155.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x156.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x157.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1610.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1611.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x1612.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x167.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x168.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x169.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2101.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2111.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2121.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x2131.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x311.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x312.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x313.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x314.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x315.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x323.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x325.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x336.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x337.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x412.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x413.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x415.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x417.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x435.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x436.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x437.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x447.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x448.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430x449.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE423.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE425.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xE427.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG437.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG438.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xG439.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW423.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW425.Po@am__quote@ --@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430xW427.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enews.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ens32knbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eor32.Po@am__quote@ -@@ -2889,242 +2773,10 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ - $(srcdir)/emulparams/mn10200.sh \ - $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} - ${GENSCRIPTS} mn10300 "$(tdir_mn10300)" --emsp430x110.c: $(srcdir)/emulparams/msp430all.sh \ -+emsp430.c: $(srcdir)/emulparams/msp430uni.sh \ - $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ - ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x110 "$(tdir_msp430x110)" msp430all --emsp430x1101.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1101 "$(tdir_msp430x1101)" msp430all --emsp430x1111.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1111 "$(tdir_msp430x1111)" msp430all --emsp430x112.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x112 "$(tdir_msp430x112)" msp430all --emsp430x1121.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1121 "$(tdir_msp430x1121)" msp430all --emsp430x1122.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1122 "$(tdir_msp430x1122)" msp430all --emsp430x1132.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1132 "$(tdir_msp430x1132)" msp430all --emsp430x122.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x122 "$(tdir_msp430x122)" msp430all --emsp430x1222.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1222 "$(tdir_msp430x1222)" msp430all --emsp430x123.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x123 "$(tdir_msp430x123)" msp430all --emsp430x1232.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1232 "$(tdir_msp430x1232)" msp430all --emsp430x133.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x133 "$(tdir_msp430x133)" msp430all --emsp430x1331.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1331 "$(tdir_msp430x1331)" msp430all --emsp430x135.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x135 "$(tdir_msp430x135)" msp430all --emsp430x1351.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1351 "$(tdir_msp430x1351)" msp430all --emsp430x147.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x147 "$(tdir_msp430x147)" msp430all --emsp430x148.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x148 "$(tdir_msp430x148)" msp430all --emsp430x149.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x149 "$(tdir_msp430x149)" msp430all --emsp430x155.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x155 "$(tdir_msp430x155)" msp430all --emsp430x156.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x156 "$(tdir_msp430x156)" msp430all --emsp430x157.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x157 "$(tdir_msp430x157)" msp430all --emsp430x1610.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1610 "$(tdir_msp430x1610)" msp430all --emsp430x1611.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1611 "$(tdir_msp430x1611)" msp430all --emsp430x1612.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x1612 "$(tdir_msp430x1612)" msp430all --emsp430x167.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x167 "$(tdir_msp430x167)" msp430all --emsp430x168.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x168 "$(tdir_msp430x168)" msp430all --emsp430x169.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x169 "$(tdir_msp430x169)" msp430all --emsp430x2101.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2101 "$(tdir_msp430x2101)" msp430all --emsp430x2111.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2111 "$(tdir_msp430x2111)" msp430all --emsp430x2121.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2121 "$(tdir_msp430x2121)" msp430all --emsp430x2131.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x2131 "$(tdir_msp430x2131)" msp430all --emsp430x311.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x311 "$(tdir_msp430x311)" msp430all --emsp430x312.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x312 "$(tdir_msp430x312)" msp430all --emsp430x313.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x313 "$(tdir_msp430x313)" msp430all --emsp430x314.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x314 "$(tdir_msp430x314)" msp430all --emsp430x315.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x315 "$(tdir_msp430x315)" msp430all --emsp430x323.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x323 "$(tdir_msp430x323)" msp430all --emsp430x325.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x325 "$(tdir_msp430x325)" msp430all --emsp430x336.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x336 "$(tdir_msp430x336)" msp430all --emsp430x337.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430_3.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x337 "$(tdir_msp430x337)" msp430all --emsp430x412.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x412 "$(tdir_msp430x412)" msp430all --emsp430x413.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x413 "$(tdir_msp430x413)" msp430all --emsp430x415.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x415 "$(tdir_msp430x415)" msp430all --emsp430x417.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x417 "$(tdir_msp430x417)" msp430all --emsp430x435.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x435 "$(tdir_msp430x435)" msp430all --emsp430x436.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x436 "$(tdir_msp430x436)" msp430all --emsp430x437.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x437 "$(tdir_msp430x437)" msp430all --emsp430x447.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x447 "$(tdir_msp430x447)" msp430all --emsp430x448.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x448 "$(tdir_msp430x448)" msp430all --emsp430x449.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430x449 "$(tdir_msp430x449)" msp430all --emsp430xE423.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE423 "$(tdir_msp430xE423)" msp430all --emsp430xE425.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE425 "$(tdir_msp430xE425)" msp430all --emsp430xE427.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xE427 "$(tdir_msp430xE427)" msp430all --emsp430xG437.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG437 "$(tdir_msp430xG437)" msp430all --emsp430xG438.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG438 "$(tdir_msp430xG438)" msp430all --emsp430xG439.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xG439 "$(tdir_msp430xG439)" msp430all --emsp430xW423.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW423 "$(tdir_msp430xW423)" msp430all --emsp430xW425.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW425 "$(tdir_msp430xW425)" msp430all --emsp430xW427.c: $(srcdir)/emulparams/msp430all.sh \ -- $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc \ -- ${GEN_DEPENDS} -- ${GENSCRIPTS} msp430xW427 "$(tdir_msp430xW427)" msp430all -+ ${GENSCRIPTS} msp430 "$(tdir_msp430)" msp430uni - enews.c: $(srcdir)/emulparams/news.sh \ - $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} - ${GENSCRIPTS} news "$(tdir_news)" -diff --git a/ld/configure.tgt b/ld/configure.tgt -index 23cf347..26a6db8 100644 ---- a/ld/configure.tgt -+++ b/ld/configure.tgt -@@ -436,8 +436,7 @@ mn10300-*-*) targ_emul=mn10300 - ;; - mt-*elf) targ_emul=elf32mt - ;; --msp430-*-*) targ_emul=msp430x110 -- targ_extra_emuls="msp430x112 msp430x1101 msp430x1111 msp430x1121 msp430x1122 msp430x1132 msp430x122 msp430x123 msp430x1222 msp430x1232 msp430x133 msp430x135 msp430x1331 msp430x1351 msp430x147 msp430x148 msp430x149 msp430x155 msp430x156 msp430x157 msp430x167 msp430x168 msp430x169 msp430x1610 msp430x1611 msp430x1612 msp430x2101 msp430x2111 msp430x2121 msp430x2131 msp430x311 msp430x312 msp430x313 msp430x314 msp430x315 msp430x323 msp430x325 msp430x336 msp430x337 msp430x412 msp430x413 msp430x415 msp430x417 msp430xE423 msp430xE425 msp430xE427 msp430xW423 msp430xW425 msp430xW427 msp430xG437 msp430xG438 msp430xG439 msp430x435 msp430x436 msp430x437 msp430x447 msp430x448 msp430x449" -+msp430-*-*) targ_emul=msp430 - ;; - ns32k-pc532-mach* | ns32k-pc532-ux*) targ_emul=pc532macha ;; - ns32k-*-netbsd* | ns32k-pc532-lites*) targ_emul=ns32knbsd -diff --git a/ld/emulparams/msp430all.sh b/ld/emulparams/msp430all.sh -deleted file mode 100644 -index 57d21c2..0000000 ---- a/ld/emulparams/msp430all.sh -+++ /dev/null -@@ -1,553 +0,0 @@ --#!/bin/sh -- --# This called by genscripts_extra.sh -- --MSP430_NAME=${EMULATION_NAME} -- --SCRIPT_NAME=elf32msp430 --TEMPLATE_NAME=generic --EXTRA_EM_FILE=genelf --OUTPUT_FORMAT="elf32-msp430" --MACHINE= --MAXPAGESIZE=1 --EMBEDDED=yes -- --if [ "${MSP430_NAME}" = "msp430x110" ] ; then --ARCH=msp:11 --ROM_START=0xfc00 --ROM_SIZE=0x3e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x1101" ] ; then --ARCH=msp:110 --ROM_START=0xfc00 --ROM_SIZE=0x3e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x1111" ] ; then --ARCH=msp:110 --ROM_START=0xf800 --ROM_SIZE=0x07e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x112" ] ; then --ARCH=msp:11 --ROM_START=0xf000 --ROM_SIZE=0xfe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1121" ] ; then --ARCH=msp:110 --ROM_START=0xf000 --ROM_SIZE=0x0fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1122" ] ; then --ARCH=msp:110 --ROM_START=0xf000 --ROM_SIZE=0x0fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1132" ] ; then --ARCH=msp:110 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x122" ] ; then --ARCH=msp:12 --ROM_START=0xf000 --ROM_SIZE=0xfe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1222" ] ; then --ARCH=msp:12 --ROM_START=0xf000 --ROM_SIZE=0xfe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x123" ] ; then --ARCH=msp:12 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1232" ] ; then --ARCH=msp:12 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x133" ] ; then --ARCH=msp:13 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x1331" ] ; then --ARCH=msp:13 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x135" ] ; then --ARCH=msp:13 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x1351" ] ; then --ARCH=msp:13 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x147" ] ; then --ARCH=msp:14 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1K --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x148" ] ; then --ARCH=msp:14 --ROM_START=0x4000 --ROM_SIZE=0xbfe0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430x149" ] ; then --ARCH=msp:14 --ROM_START=0x1100 --ROM_SIZE=0xeee0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430x155" ] ; then --ARCH=msp:15 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x156" ] ; then --ARCH=msp:15 --ROM_START=0xa000 --ROM_SIZE=0x5fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x157" ] ; then --ARCH=msp:15 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1K --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x167" ] ; then --ARCH=msp:16 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1K --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x168" ] ; then --ARCH=msp:16 --ROM_START=0x4000 --ROM_SIZE=0xbfe0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430x169" ] ; then --ARCH=msp:16 --ROM_START=0x1100 --ROM_SIZE=0xeee0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430x1610" ] ; then --ARCH=msp:16 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x1100 --RAM_SIZE=0x1400 --STACK=0x2500 --fi -- --if [ "${MSP430_NAME}" = "msp430x1611" ] ; then --ARCH=msp:16 --ROM_START=0x4000 --ROM_SIZE=0xbfe0 --RAM_START=0x1100 --RAM_SIZE=0x2800 --STACK=0x3900 --fi -- --if [ "${MSP430_NAME}" = "msp430x1612" ] ; then --ARCH=msp:16 --ROM_START=0x2500 --ROM_SIZE=0xdae0 --RAM_START=0x1100 --RAM_SIZE=0x1400 --STACK=0x2500 --fi -- --if [ "${MSP430_NAME}" = "msp430x2101" ] ; then --ARCH=msp:21 --ROM_START=0xFC00 --ROM_SIZE=0x03e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x2111" ] ; then --ARCH=msp:21 --ROM_START=0xF800 --ROM_SIZE=0x07e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x2121" ] ; then --ARCH=msp:21 --ROM_START=0xf000 --ROM_SIZE=0x0fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x2131" ] ; then --ARCH=msp:21 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x311" ] ; then --ARCH=msp:31 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xf800 --ROM_SIZE=0x07e0 --RAM_START=0x0200 --RAM_SIZE=128 --STACK=0x280 --fi -- --if [ "${MSP430_NAME}" = "msp430x312" ] ; then --ARCH=msp:31 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xf000 --ROM_SIZE=0x0fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x313" ] ; then --ARCH=msp:31 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x314" ] ; then --ARCH=msp:31 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xd000 --ROM_SIZE=0x2fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x315" ] ; then --ARCH=msp:31 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x323" ] ; then --ARCH=msp:32 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x325" ] ; then --ARCH=msp:32 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x336" ] ; then --ARCH=msp:33 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0xa000 --ROM_SIZE=0x5fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x337" ] ; then --ARCH=msp:33 --SCRIPT_NAME=elf32msp430_3 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x412" ] ; then --ARCH=msp:41 --ROM_START=0xf000 --ROM_SIZE=0x0fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x413" ] ; then --ARCH=msp:41 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430x415" ] ; then --ARCH=msp:41 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x417" ] ; then --ARCH=msp:41 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x435" ] ; then --ARCH=msp:43 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430x436" ] ; then --ARCH=msp:43 --ROM_START=0xa000 --ROM_SIZE=0x5fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x437" ] ; then --ARCH=msp:43 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x447" ] ; then --ARCH=msp:44 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430x448" ] ; then --ARCH=msp:44 --ROM_START=0x4000 --ROM_SIZE=0xbfe0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430x449" ] ; then --ARCH=msp:44 --ROM_START=0x1100 --ROM_SIZE=0xeee0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430xE423" ] ; then --ARCH=msp:42 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430xE425" ] ; then --ARCH=msp:42 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430xE427" ] ; then --ARCH=msp:42 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430xG437" ] ; then --ARCH=msp:43 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=1024 --STACK=0x600 --fi -- --if [ "${MSP430_NAME}" = "msp430xG438" ] ; then --ARCH=msp:43 --ROM_START=0x4000 --ROM_SIZE=0xbef0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430xG439" ] ; then --ARCH=msp:43 --ROM_START=0x1100 --ROM_SIZE=0xeee0 --RAM_START=0x0200 --RAM_SIZE=0x0800 --STACK=0xa00 --fi -- --if [ "${MSP430_NAME}" = "msp430xW423" ] ; then --ARCH=msp:42 --ROM_START=0xe000 --ROM_SIZE=0x1fe0 --RAM_START=0x0200 --RAM_SIZE=256 --STACK=0x300 --fi -- --if [ "${MSP430_NAME}" = "msp430xW425" ] ; then --ARCH=msp:42 --ROM_START=0xc000 --ROM_SIZE=0x3fe0 --RAM_START=0x0200 --RAM_SIZE=512 --STACK=0x400 --fi -- --if [ "${MSP430_NAME}" = "msp430xW427" ] ; then --ARCH=msp:42 --ROM_START=0x8000 --ROM_SIZE=0x7fe0 --RAM_START=0x0200 --RAM_SIZE=0x400 --STACK=0x600 --fi -diff --git a/ld/emulparams/msp430uni.sh b/ld/emulparams/msp430uni.sh -new file mode 100644 -index 0000000..949fe85 ---- /dev/null -+++ b/ld/emulparams/msp430uni.sh -@@ -0,0 +1,14 @@ -+#!/bin/sh -+ -+# This called by genscripts_extra.sh -+ -+MSP430_NAME=${EMULATION_NAME} -+ARCH=msp430 -+SCRIPT_NAME=elf32msp430 -+TEMPLATE_NAME=generic -+EXTRA_EM_FILE=msp430 -+OUTPUT_FORMAT="elf32-msp430" -+MACHINE= -+MAXPAGESIZE=1 -+EMBEDDED=yes -+ -diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em -new file mode 100644 -index 0000000..f4586f8 ---- /dev/null -+++ b/ld/emultempl/msp430.em -@@ -0,0 +1,107 @@ -+# This shell script emits a C file. -*- C -*- -+# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. -+# -+# This file is part of the GNU Binutils. -+# -+# 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 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+# MA 02110-1301, USA. -+# -+ -+# Adapt genelf.em for MSP430 -+# This file is sourced from generic.em -+# -+fragment <link_next) -+ if ((syms = bfd_get_outsymbols (ibfd)) != NULL -+ && bfd_get_flavour (ibfd) == bfd_target_elf_flavour) -+ for (sec = ibfd->sections; sec != NULL; sec = sec->next) -+ if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP) -+ { -+ struct bfd_elf_section_data *sec_data = elf_section_data (sec); -+ elf_group_id (sec) = syms[sec_data->this_hdr.sh_info - 1]; -+ } -+} -+ -+static void -+gld${EMULATION_NAME}_before_allocation (void) -+{ -+ if (link_info.relocatable -+ && !_bfd_elf_size_group_sections (&link_info)) -+ einfo ("%X%P: can not size group sections: %E\n"); -+ before_allocation_default (); -+} -+ -+static void -+gld${EMULATION_NAME}_after_allocation (void) -+{ -+ gld${EMULATION_NAME}_map_segments (FALSE); -+} -+ -+static void -+gld${EMULATION_NAME}_finish (void) -+{ -+ bfd *obfd = link_info.output_bfd; -+ Elf_Internal_Ehdr *o_ehdrp = elf_elfheader (obfd); -+ unsigned long flags = 0; -+ bfd *ibfd; -+ -+ for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { -+ Elf_Internal_Ehdr * i_ehdrp = elf_elfheader (ibfd); -+ -+ if (EF_MSP430_UNIARCH & i_ehdrp->e_flags) -+ flags |= i_ehdrp->e_flags; -+ } -+ if (EF_MSP430_UNIARCH & flags) { -+ int bfd_mach; -+ switch (flags & EF_MSP430_ARCH) -+ { -+ default: -+ case EF_MSP430_ARCH_430: -+ bfd_mach = bfd_mach_msp430; -+ break; -+ case EF_MSP430_ARCH_430X: -+ bfd_mach = bfd_mach_msp430x; -+ break; -+ } -+ bfd_default_set_arch_mach (obfd, bfd_arch_msp430, bfd_mach); -+ o_ehdrp->e_flags = flags; -+ } -+ finish_default(); -+} -+EOF -+# Put these extra routines in ld_${EMULATION_NAME}_emulation -+# -+LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open -+LDEMUL_BEFORE_ALLOCATION=gld${EMULATION_NAME}_before_allocation -+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation -+LDEMUL_FINISH=gld${EMULATION_NAME}_finish -diff --git a/ld/scripttempl/elf32msp430.sc b/ld/scripttempl/elf32msp430.sc -index cbffe48..abce597 100644 ---- a/ld/scripttempl/elf32msp430.sc -+++ b/ld/scripttempl/elf32msp430.sc -@@ -1,37 +1,11 @@ - #!/bin/sh - --HEAP_SECTION_MSP430=" " --HEAP_MEMORY_MSP430=" " -- --if test ${GOT_HEAP_MSP-0} -ne 0 --then --HEAP_SECTION_MSP430=".heap ${RELOCATING-0} : -- { -- ${RELOCATING+ PROVIDE (__heap_data_start = .) ; } -- *(.heap*) -- ${RELOCATING+ PROVIDE (_heap_data_end = .) ; } -- ${RELOCATING+. = ALIGN(2);} -- ${RELOCATING+ PROVIDE (__heap_bottom = .) ; } -- ${RELOCATING+ PROVIDE (__heap_top = ${HEAP_START} + ${HEAP_LENGTH}) ; } -- } ${RELOCATING+ > heap}" --HEAP_MEMORY_MSP430="heap(rwx) : ORIGIN = $HEAP_START, LENGTH = $HEAP_LENGTH" --fi -- -- - cat < text} -- -- .data ${RELOCATING-0} : ${RELOCATING+AT (ADDR (.text) + SIZEOF (.text))} -+ ${RELOCATING+ . = ALIGN(2);} -+ *(.text${RELOCATING+ .text.* .gnu.linkonce.t.*}) -+ ${RELOCATING+ . = ALIGN(2);} -+ } ${RELOCATING+ > REGION_TEXT} -+ -+ .rodata ${RELOCATING-0} : -+ { -+ ${RELOCATING+ . = ALIGN(2);} -+ *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) -+ ${RELOCATING+ . = ALIGN(2);} -+ } ${RELOCATING+ > REGION_TEXT} -+ -+ ${RELOCATING+ _etext = .;} -+ -+ .data ${RELOCATING-0} : - { -+ ${RELOCATING+ . = ALIGN(2);} - ${RELOCATING+ PROVIDE (__data_start = .) ; } -- ${RELOCATING+. = ALIGN(2);} - *(.data) -- ${RELOCATING+. = ALIGN(2);} -+ *(SORT_BY_ALIGNMENT(.data.*)) -+ ${RELOCATING+ . = ALIGN(2);} - *(.gnu.linkonce.d*) -- ${RELOCATING+. = ALIGN(2);} -+ ${RELOCATING+ . = ALIGN(2);} - ${RELOCATING+ _edata = . ; } -- } ${RELOCATING+ > data} -- -- /* Bootloader. */ -- .bootloader ${RELOCATING-0} : -- { -- ${RELOCATING+ PROVIDE (__boot_start = .) ; } -- *(.bootloader) -- ${RELOCATING+. = ALIGN(2);} -- *(.bootloader.*) -- } ${RELOCATING+ > bootloader} -+ } ${RELOCATING+ > REGION_DATA AT > REGION_TEXT} -+ ${RELOCATING+ PROVIDE (__data_load_start = LOADADDR(.data) ); } -+ ${RELOCATING+ PROVIDE (__data_size = SIZEOF(.data) ); } - -- /* Information memory. */ -- .infomem ${RELOCATING-0} : -- { -- *(.infomem) -- ${RELOCATING+. = ALIGN(2);} -- *(.infomem.*) -- } ${RELOCATING+ > infomem} -- -- /* Information memory (not loaded into MPU). */ -- .infomemnobits ${RELOCATING-0} : -- { -- *(.infomemnobits) -- ${RELOCATING+. = ALIGN(2);} -- *(.infomemnobits.*) -- } ${RELOCATING+ > infomemnobits} -- -- .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : -+ .bss ${RELOCATING-0} : - { - ${RELOCATING+ PROVIDE (__bss_start = .) ; } - *(.bss) -+ *(SORT_BY_ALIGNMENT(.bss.*)) - *(COMMON) - ${RELOCATING+ PROVIDE (__bss_end = .) ; } - ${RELOCATING+ _end = . ; } -- } ${RELOCATING+ > data} -+ } ${RELOCATING+ > REGION_DATA} -+ ${RELOCATING+ PROVIDE (__bss_size = SIZEOF(.bss) ); } - -- .noinit ${RELOCATING+ SIZEOF(.bss) + ADDR(.bss)} : -+ .noinit ${RELOCATING-0} : - { - ${RELOCATING+ PROVIDE (__noinit_start = .) ; } - *(.noinit) -+ *(.noinit.*) - *(COMMON) - ${RELOCATING+ PROVIDE (__noinit_end = .) ; } - ${RELOCATING+ _end = . ; } -- } ${RELOCATING+ > data} -+ } ${RELOCATING+ > REGION_DATA} -+ -+ /* Information memory. */ -+ .infomem ${RELOCATING-0} : -+ { -+ *(.infomem) -+ ${RELOCATING+ . = ALIGN(2);} -+ *(.infomem.*) -+ } ${RELOCATING+ > infomem} - - .vectors ${RELOCATING-0}: - { - ${RELOCATING+ PROVIDE (__vectors_start = .) ; } -- *(.vectors*) -+ KEEP(*(.vectors*)) - ${RELOCATING+ _vectors_end = . ; } - } ${RELOCATING+ > vectors} - -- ${HEAP_SECTION_MSP430} -+ .fartext : -+ { -+ ${RELOCATING+ . = ALIGN(2);} -+ *(.fartext) -+ ${RELOCATING+ . = ALIGN(2);} -+ *(.fartext.*) -+ ${RELOCATING+ _efartext = .;} -+ } ${RELOCATING+ > REGION_FAR_ROM} - - /* Stabs for profiling information*/ - .profiler 0 : { *(.profiler) } -@@ -239,11 +214,12 @@ SECTIONS - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - -- PROVIDE (__stack = ${STACK}) ; -- PROVIDE (__data_start_rom = _etext) ; -- PROVIDE (__data_end_rom = _etext + SIZEOF (.data)) ; -- PROVIDE (__noinit_start_rom = _etext + SIZEOF (.data)) ; -- PROVIDE (__noinit_end_rom = _etext + SIZEOF (.data) + SIZEOF (.noinit)) ; -- PROVIDE (__subdevice_has_heap = ${GOT_HEAP_MSP-0}) ; -+ /* DWARF 3 */ -+ .debug_pubtypes 0 : { *(.debug_pubtypes) } -+ .debug_ranges 0 : { *(.debug_ranges) } -+ -+ ${RELOCATING+ PROVIDE (__stack = ORIGIN(ram) + LENGTH(ram));} -+ ${RELOCATING+ PROVIDE (__data_start_rom = _etext);} -+ ${RELOCATING+ PROVIDE (__data_end_rom = _etext + SIZEOF (.data));} - } - EOF -diff --git a/ld/scripttempl/elf32msp430_3.sc b/ld/scripttempl/elf32msp430_3.sc -deleted file mode 100644 -index 15eb517..0000000 ---- a/ld/scripttempl/elf32msp430_3.sc -+++ /dev/null -@@ -1,192 +0,0 @@ --cat < text} -- -- .data ${RELOCATING-0} : ${RELOCATING+AT (ADDR (.text) + SIZEOF (.text))} -- { -- ${RELOCATING+ PROVIDE (__data_start = .) ; } -- *(.data) -- *(.gnu.linkonce.d*) -- ${RELOCATING+. = ALIGN(2);} -- ${RELOCATING+ _edata = . ; } -- } ${RELOCATING+ > data} -- -- .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : -- { -- ${RELOCATING+ PROVIDE (__bss_start = .) ; } -- *(.bss) -- *(COMMON) -- ${RELOCATING+ PROVIDE (__bss_end = .) ; } -- ${RELOCATING+ _end = . ; } -- } ${RELOCATING+ > data} -- -- .noinit ${RELOCATING+ SIZEOF(.bss) + ADDR(.bss)} : -- { -- ${RELOCATING+ PROVIDE (__noinit_start = .) ; } -- *(.noinit) -- *(COMMON) -- ${RELOCATING+ PROVIDE (__noinit_end = .) ; } -- ${RELOCATING+ _end = . ; } -- } ${RELOCATING+ > data} -- -- .vectors ${RELOCATING-0}: -- { -- ${RELOCATING+ PROVIDE (__vectors_start = .) ; } -- *(.vectors*) -- ${RELOCATING+ _vectors_end = . ; } -- } ${RELOCATING+ > vectors} -- -- /* Stabs debugging sections. */ -- .stab 0 : { *(.stab) } -- .stabstr 0 : { *(.stabstr) } -- .stab.excl 0 : { *(.stab.excl) } -- .stab.exclstr 0 : { *(.stab.exclstr) } -- .stab.index 0 : { *(.stab.index) } -- .stab.indexstr 0 : { *(.stab.indexstr) } -- .comment 0 : { *(.comment) } -- -- /* DWARF debug sections. -- Symbols in the DWARF debugging sections are relative to the beginning -- of the section so we begin them at 0. */ -- -- /* DWARF 1 */ -- .debug 0 : { *(.debug) } -- .line 0 : { *(.line) } -- -- /* GNU DWARF 1 extensions */ -- .debug_srcinfo 0 : { *(.debug_srcinfo) } -- .debug_sfnames 0 : { *(.debug_sfnames) } -- -- /* DWARF 1.1 and DWARF 2 */ -- .debug_aranges 0 : { *(.debug_aranges) } -- .debug_pubnames 0 : { *(.debug_pubnames) } -- -- /* DWARF 2 */ -- .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } -- .debug_abbrev 0 : { *(.debug_abbrev) } -- .debug_line 0 : { *(.debug_line) } -- .debug_frame 0 : { *(.debug_frame) } -- .debug_str 0 : { *(.debug_str) } -- .debug_loc 0 : { *(.debug_loc) } -- .debug_macinfo 0 : { *(.debug_macinfo) } -- -- PROVIDE (__stack = ${STACK}) ; -- PROVIDE (__data_start_rom = _etext) ; -- PROVIDE (__data_end_rom = _etext + SIZEOF (.data)) ; -- PROVIDE (__noinit_start_rom = _etext + SIZEOF (.data)) ; -- PROVIDE (__noinit_end_rom = _etext + SIZEOF (.data) + SIZEOF (.noinit)) ; --} --EOF -diff --git a/opcodes/msp430-dis.c b/opcodes/msp430-dis.c -index 9d7edbe..a00c718 100644 ---- a/opcodes/msp430-dis.c -+++ b/opcodes/msp430-dis.c -@@ -52,12 +52,153 @@ msp430dis_opcode (bfd_vma addr, disassemble_info *info) - return bfd_getl16 (buffer); - } - -+static unsigned short -+msp430dis_operand (bfd_vma addr, disassemble_info *info, int reg, int am, int *cmd_len) -+{ -+ static int const op_length [][5] = -+ { -+ // am | reg 0 1 2 3 >3 -+ /* 0 */ { 0, 0, 0, 0, 0 }, // Rn -+ /* 1 */ { 2, 2, 2, 0, 2 }, // x(Rn) -+ /* 2 */ { 0, 0, 0, 0, 0 }, // @Rn -+ /* 3 */ { 2, 0, 0, 0, 0 }, // @Rn+ -+ }; -+ if (reg >= (int)(sizeof(op_length[0]) / sizeof(op_length[0][0]))) -+ reg = sizeof(op_length[0]) / sizeof(op_length[0][0])- 1; -+ -+ if (op_length[am][reg]) -+ { -+ bfd_byte buffer[2]; -+ int status = info->read_memory_func (addr, buffer, 2, info); -+ if (status != 0) -+ { -+ info->memory_error_func (status, addr, info); -+ return -1; -+ } -+ *cmd_len += 2; -+ return bfd_getl16 (buffer); -+ } -+ return 0; -+} -+ -+typedef enum -+{ -+ OP_20BIT, -+ OP_16BIT, -+ OP_20BIT_HEX, -+ OP_16BIT_HEX, -+ OP_DECIMAL, -+} operand_t; -+ -+static void -+msp430x_decode_operand(int reg, int am, int addr, int dst, operand_t size, char *op, char *comm) -+{ -+ if (op) // if operand not hidden in emulated instruction -+ switch (am) -+ { -+ case 0: // Rn -+ if (reg == 3) -+ { -+ sprintf (op, "#0"); // constant #0 -+ sprintf (comm, "r3 As==00"); -+ } -+ else -+ { -+ sprintf (op, "r%d", reg); -+ } -+ break; -+ case 1: // x(Rn) -+ if (reg == 0) // Symbolic, ADDR -+ { -+ if (size == OP_20BIT || size == OP_20BIT_HEX) -+ sprintf (op, "0x%05x", dst & 0xfffff); -+ else -+ sprintf (op, "0x%04x", dst & 0xffff); -+ sprintf (comm, "PC rel. 0x%05x", ((int)addr + dst) & 0xfffff); -+ } -+ else if (reg == 2) // Absolute, &ADDR -+ { -+ if (size == OP_20BIT || size == OP_20BIT_HEX) -+ sprintf (op, "&0x%05x", dst & 0xfffff); -+ else -+ sprintf (op, "&0x%04x", dst & 0xffff); -+ } -+ else if (reg == 3) // constant #1 -+ { -+ sprintf (op, "#1"); -+ sprintf (comm, "r3 As==01"); -+ } -+ else // Indexed, x(Rn) -+ { -+ sprintf (op, "%d(r%d)", dst, reg); -+ if (size == OP_20BIT || size == OP_20BIT_HEX) -+ sprintf (comm, "0x%05x(r%d)", dst & 0xfffff, reg); -+ else -+ sprintf (comm, "0x%04x(r%d)", dst & 0xffff, reg); -+ } -+ break; -+ case 2: // @Rn -+ if (reg == 2) // constant #4 -+ { -+ sprintf (op, "#4"); -+ sprintf (comm, "r2 As==10"); -+ } -+ else if(reg == 3) // constant #2 -+ { -+ sprintf (op, "#2"); -+ sprintf (comm, "r3 As==10"); -+ } -+ else -+ { -+ sprintf (op, "@r%d", reg); -+ } -+ break; -+ case 3: // @Rn+ -+ switch (reg) -+ { -+ case 0: // immediate, #N -+ switch (size) -+ { -+ case OP_16BIT: -+ sprintf (op, "#%d", dst); -+ sprintf (comm, "#0x%04x", dst & 0xffff); -+ break; -+ case OP_16BIT_HEX: -+ sprintf (op, "#0x%04x", dst & 0xffff); -+ break; -+ case OP_20BIT: -+ sprintf (op, "#%d", dst); -+ sprintf (comm, "#0x%05x", dst & 0xfffff); -+ break; -+ case OP_20BIT_HEX: -+ sprintf (op, "#0x%05x", dst & 0xfffff); -+ break; -+ default: // #n in rxxm -+ sprintf (op, "#%d", dst); -+ break; -+ } -+ break; -+ case 2: // constant #8 -+ sprintf (op, "#8"); -+ sprintf (comm, "r2 As==11"); -+ break; -+ case 3: // constant #-1 -+ sprintf (op, "#-1"); -+ sprintf (comm, "r3 As==11"); -+ break; -+ default: -+ sprintf (op, "@r%d+", reg); -+ break; -+ } -+ break; -+ } -+} -+ - static int --msp430_nooperands (struct msp430_opcode_s *opcode, -+msp430_nooperands (struct msp430_opcode_s const *opcode, - bfd_vma addr ATTRIBUTE_UNUSED, - unsigned short insn ATTRIBUTE_UNUSED, -- char *comm, -- int *cycles) -+ char *comm) - { - /* Pop with constant. */ - if (insn == 0x43b2) -@@ -65,18 +206,16 @@ msp430_nooperands (struct msp430_opcode_s *opcode, - if (insn == opcode->bin_opcode) - return 2; - -- if (opcode->fmt == 0) -+ if (opcode_format(opcode) == FMT_EMULATED) - { - if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2) - return 0; - - strcpy (comm, "emulated..."); -- *cycles = 1; - } - else - { - strcpy (comm, "return from interupt"); -- *cycles = 5; - } - - return 2; -@@ -84,16 +223,14 @@ msp430_nooperands (struct msp430_opcode_s *opcode, - - static int - msp430_singleoperand (disassemble_info *info, -- struct msp430_opcode_s *opcode, -+ struct msp430_opcode_s const *opcode, - bfd_vma addr, - unsigned short insn, - char *op, -- char *comm, -- int *cycles) -+ char *comm) - { - int regs = 0, regd = 0; - int ad = 0, as = 0; -- int where = 0; - int cmd_len = 2; - short dst = 0; - -@@ -102,9 +239,9 @@ msp430_singleoperand (disassemble_info *info, - as = (insn & 0x0030) >> 4; - ad = (insn & 0x0080) >> 7; - -- switch (opcode->fmt) -+ switch (opcode_format(opcode)) - { -- case 0: /* Emulated work with dst register. */ -+ case FMT_EMULATED: /* Emulated work with dst register. */ - if (regs != 2 && regs != 3 && regs != 1) - return 0; - -@@ -116,167 +253,23 @@ msp430_singleoperand (disassemble_info *info, - 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); -- } -- } -+ dst = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); -+ msp430x_decode_operand (regd, ad, addr + cmd_len, dst, OP_16BIT, op, comm); - 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); -- } -- } -+ case FMT_SINGLE_OPERAND: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */ -+ dst = msp430dis_operand (addr + cmd_len, info, regd, as, &cmd_len); -+ if(opcode_variant(opcode) != V_CALL) -+ msp430x_decode_operand (regd, as, addr + cmd_len, dst, OP_16BIT, op, comm); -+ else -+ msp430x_decode_operand (regd, as, addr + cmd_len, dst, OP_16BIT_HEX, op, comm); - 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; -+ case FMT_JUMP: /* Jumps. */ -+ dst = (short)((insn & 0x03ff) << 6) >> 5; // sign extension, word addr to byte addr conversion -+ sprintf (op, "$%+-8d", dst + 2); -+ sprintf (comm, "abs 0x%x", PS ((short) (addr) + 2 + dst)); - return 2; -- break; - default: - cmd_len = 0; - } -@@ -286,26 +279,26 @@ msp430_singleoperand (disassemble_info *info, - - static int - msp430_doubleoperand (disassemble_info *info, -- struct msp430_opcode_s *opcode, -+ struct msp430_opcode_s const *opcode, - bfd_vma addr, - unsigned short insn, - char *op1, - char *op2, - char *comm1, -- char *comm2, -- int *cycles) -+ char *comm2) - { - int regs = 0, regd = 0; - int ad = 0, as = 0; - int cmd_len = 2; -- short dst = 0; -+ short ops; -+ short opd; - - regd = insn & 0x0f; - regs = (insn & 0x0f00) >> 8; - as = (insn & 0x0030) >> 4; - ad = (insn & 0x0080) >> 7; - -- if (opcode->fmt == 0) -+ if (opcode_format(opcode) == FMT_EMULATED) - { - /* Special case: rla and rlc are the only 2 emulated instructions that - fall into two operand instructions. */ -@@ -320,347 +313,354 @@ msp430_doubleoperand (disassemble_info *info, - 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 (ad == 0 && regd == 3) // #N - { -- 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); -- /* If the 'src' field is not the same as the dst -- then this is not an rla instruction. */ -- if (dst != msp430dis_opcode (addr + 4, info)) -- return 0; -- 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); -- } -+ strcpy (comm1, _("Illegal as emulation instr")); -+ return -1; - } -+ ops = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); -+ opd = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); -+ /* If the 'src' field is not the same as the dst -+ then this is not an rla instruction. */ -+ if (ops != opd) -+ return 0; -+ msp430x_decode_operand (regs, as, addr + cmd_len, ops, OP_16BIT, op1, comm1); - - *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; - } -+ ops = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); -+ msp430x_decode_operand (regs, as, addr + cmd_len, ops, OP_16BIT, op1, comm1); - -- /* 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; -+ opd = msp430dis_operand (addr + cmd_len, info, regd, ad, &cmd_len); -+ msp430x_decode_operand (regd, ad, addr + cmd_len, opd, OP_16BIT, op2, comm2); -+ return cmd_len; -+} - -- 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; -+static int -+msp430_branchinstr (disassemble_info *info, -+ struct msp430_opcode_s const *opcode ATTRIBUTE_UNUSED, -+ bfd_vma addr ATTRIBUTE_UNUSED, -+ unsigned short insn, -+ char *op1, -+ char *comm1) -+{ -+ int regs = (insn & 0x0f00) >> 8; -+ int as = (insn & 0x0030) >> 4; -+ int cmd_len = 2; -+ short dst; - -- /* Indexed register mode @Rn. */ -- sprintf (op1, "@r%d", regs); -- } -- if (!regs) -- *cycles = 3; -- } -- else if (as == 3) -+ dst = msp430dis_operand (addr + cmd_len, info, regs, as, &cmd_len); -+ msp430x_decode_operand(regs, as, addr + cmd_len, dst, OP_16BIT_HEX, op1, comm1); -+ -+ return cmd_len; -+} -+ -+static opwidth_t -+msp430x_opwidth(unsigned int insn) -+{ -+ insn &= NON_ADDR_OPERATION | BYTE_OPERATION_X; -+ -+ if(insn == (NON_ADDR_OPERATION | BYTE_OPERATION_X)) -+ return BYTE_OP; -+ if(insn == NON_ADDR_OPERATION) -+ return WORD_OP; -+ if(insn == BYTE_OPERATION_X) -+ return ADDR_OP; -+ -+ return 0; // reserved -+} -+ -+static int -+msp430x_singleoperand (disassemble_info *info, -+ struct msp430_opcode_s const *opcode, -+ bfd_vma addr, -+ unsigned int insn, -+ char *op, -+ char *comm, -+ int *repeats) -+{ -+ int reg = (insn >> 16) & 0xf; -+ int am = (insn >> 20) & 0x3; -+ int cmd_len = 4; -+ int dst = 0; -+ -+ if ( opcode_variant(opcode) < V_PUSHX ) -+ if ((am == 3 && reg == 0) // #N operand -+ || (am == 0 && reg == 3) // R3 is illegal as dest: may be data section. -+ ) -+ { -+ strcpy (comm, _("Illegal as 1-op instr")); -+ return -1; -+ } -+ -+ // extract repeat count if any -+ if ( am == 0 ) // extension word for register mode - { -- 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); -- } -+ if (insn & 0x008f) // repetitions -+ { -+ if (insn & 0x0080) -+ *repeats = insn & 0xf; // positive number is Rn -+ else -+ *repeats = 0 - (insn & 0xf); // negative number is #N -+ } - } - -- /* Destination. Special care needed on addr + XXXX. */ -+ // extract operands -+ dst = msp430dis_operand(addr + cmd_len, info, reg, am, &cmd_len) | ((insn & 0x0000000f) << 16); -+ dst = (dst << 12) >> 12; // sign extension -+ msp430x_decode_operand(reg, am, addr + cmd_len, dst, OP_20BIT, op, comm); -+ -+ return cmd_len; -+} -+ -+static int -+msp430x_exception (disassemble_info *info, -+ struct msp430_opcode_s const *opcode, -+ bfd_vma addr, -+ unsigned int insn, -+ char *op1, -+ char *op2, -+ char *comm1, -+ char *comm2, -+ opwidth_t *op_width) -+{ -+ int reg = 0; -+ int cmd_len = 2; -+ int n = 0; -+ int dst = 0; -+ -+ reg = insn & 0xf; - -- if (ad == 0) -+ switch(opcode_variant(opcode)) - { -- /* Register. */ -- if (regd == 0) -- { -- *cycles += 1; -- sprintf (op2, "r0"); -- } -- else if (regd == 1) -- sprintf (op2, "r1"); -+ case V_CALLA: -+ switch((insn >> 4) & 0xf) -+ { -+ case 4: // Rdst -+ msp430x_decode_operand(reg, 0, 0, 0, 0, op1, comm1); -+ break; -+ case 5: // x(Rdst) -+ dst = (short)msp430dis_operand(addr + cmd_len, info, reg, 1, &cmd_len); -+ msp430x_decode_operand(reg, 1, addr + cmd_len, dst, OP_16BIT, op1, comm1); -+ break; -+ case 6: // @Rdst -+ msp430x_decode_operand(reg, 2, 0, 0, 0, op1, comm1); -+ break; -+ case 7: // @Rdst+ -+ msp430x_decode_operand(reg, 3, 0, 0, 0, op1, comm1); -+ break; -+ case 8: // &abs20 -+ dst = msp430dis_operand(addr + cmd_len, info, 2, 1, &cmd_len) | ((insn & 0x000f) << 16); -+ msp430x_decode_operand(2, 1, addr + cmd_len, dst, OP_20BIT_HEX, op1, comm1); -+ break; -+ case 9: // EDE -+ dst = msp430dis_operand(addr + cmd_len, info, 0, 1, &cmd_len) | ((insn & 0x000f) << 16); -+ msp430x_decode_operand(0, 1, addr + cmd_len, dst, OP_20BIT, op1, comm1); -+ break; -+ case 0xb: // #imm20 -+ dst = msp430dis_operand(addr + cmd_len, info, 0, 3, &cmd_len) | ((insn & 0x000f) << 16); -+ msp430x_decode_operand(0, 3, addr + cmd_len, dst, OP_20BIT_HEX, op1, comm1); -+ break; -+ } -+ break; -+ case V_PUSHM: -+ n = ((insn >> 4) & 0xf) + 1; -+ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N -+ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst -+ if ((insn & 0x0100) == 0) -+ *op_width = ADDR_OP; -+ break; -+ case V_POPM: -+ n = ((insn >> 4) & 0xf) + 1; -+ reg = (reg + n - 1) & 0xf; -+ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N -+ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst -+ if ((insn & 0x0100) == 0) -+ *op_width = ADDR_OP; -+ break; -+ case V_ROTM: -+ n = ((insn >> 10) & 0x3) + 1; -+ msp430x_decode_operand(0, 3, 0, n, OP_DECIMAL, op1, comm1); // #N -+ msp430x_decode_operand(reg, 0, 0, 0, 0, op2, comm2); // Rdst -+ if ((insn & 0x0010) == 0) -+ *op_width = ADDR_OP; -+ break; -+ default: -+ break; -+ } -+ return cmd_len; -+} -+ -+static int -+msp430x_doubleoperand (disassemble_info *info, -+ struct msp430_opcode_s const *opcode, -+ bfd_vma addr, -+ unsigned int insn, -+ char *op1, -+ char *op2, -+ char *comm1, -+ char *comm2, -+ opwidth_t *op_width, -+ int *repeats) -+{ -+ int regs, regd; -+ int as, ad; -+ int ops, opd; -+ int cmd_len = 4; - -- else if (regd == 2) -- sprintf (op2, "r2"); -+ regd = (insn >> 16) & 0xf; -+ regs = (insn >> 24) & 0xf; -+ as = (insn >> 20) & 0x3; -+ ad = (insn >> 23) & 0x1; - -- else -- sprintf (op2, "r%d", regd); -+ if (ad == 0 && regd == 3) -+ { -+ // R3 is illegal as dest: may be data section. -+ if (comm1) -+ strcpy (comm1, _("Illegal as 2-op instr")); -+ else if (comm2) -+ strcpy (comm2, _("Illegal as 2-op instr")); -+ return -1; - } -- else /* ad == 1. */ -+ *op_width = msp430x_opwidth(insn); -+ -+ // extract repeat count if any -+ if ( as == 0 && ad == 0 ) // extension word for register mode - { -- * 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); -- } -+ if (insn & 0x008f) // repetitions -+ { -+ if (insn & 0x0080) -+ *repeats = insn & 0xf; // positive number is Rn -+ else -+ *repeats = 0 - (insn & 0xf); // negative number is #N -+ } - } -+ // extract operands -+ ops = msp430dis_operand(addr + cmd_len, info, regs, as, &cmd_len) | ((insn & 0x00000780) << 9); -+ ops = (ops << 12) >> 12; // sign extension -+ msp430x_decode_operand(regs, as, addr + cmd_len, ops, OP_20BIT, op1, comm1); -+ -+ opd = msp430dis_operand(addr + cmd_len, info, regd, ad, &cmd_len) | ((insn & 0x0000000f) << 16); -+ opd = (opd << 12) >> 12; // sign extension -+ if (opcode_variant(opcode) == V_X_SHIFT -+ && ((0 == (as | ad) && ops != opd) /* non-register extension different ops */ -+ || regs != regd)) /* register extension different regs */ -+ return 0; // different operand => not emulated shift -+ -+ msp430x_decode_operand(regd, ad, addr + cmd_len, opd, OP_20BIT, op2, comm2); - - return cmd_len; - } - - static int --msp430_branchinstr (disassemble_info *info, -- struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED, -- bfd_vma addr ATTRIBUTE_UNUSED, -+msp430x_address (disassemble_info *info, -+ bfd_vma addr, - unsigned short insn, - char *op1, -+ char *op2, - char *comm1, -- int *cycles) -+ char *comm2) - { -- int regs = 0, regd = 0; -- int as = 0; - int cmd_len = 2; -- short dst = 0; -- -- regd = insn & 0x0f; -- regs = (insn & 0x0f00) >> 8; -- as = (insn & 0x0030) >> 4; -- -- if (regd != 0) /* Destination register is not a PC. */ -- return 0; -- -- /* dst is a source register. */ -- if (as == 0) -+ int dst = 0; -+ typedef struct - { -- /* Constants. */ -- if (regs == 3) -- { -- *cycles = 1; -- sprintf (op1, "#0"); -- sprintf (comm1, "r3 As==00"); -- } -- else -- { -- /* Register. */ -- *cycles = 1; -- sprintf (op1, "r%d", regs); -- } -+ int as, regs; -+ int ad, regd; -+ int length; - } -- else if (as == 2) -+ operands_t; -+ -+ static operands_t const operands_table[] = - { -- 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) -+ { 2, -1, 0, -1, 0 }, // 0 @Rsrc, Rdst -+ { 3, -1, 0, -1, 0 }, // 1 @Rsrc+, Rdst -+ { 1, 2, 0, -1, 2 }, // 2 &abs20, Rdst -+ { 1, -1, 0, -1, 2 }, // 3 x(Rsrc), Rdst -+ { 0, 0, 0, 0, 0 }, // 4 -+ { 0, 0, 0, 0, 0 }, // 5 -+ { 0, -1, 1, 2, 2 }, // 6 Rsrc, &abs20 -+ { 0, -1, 1, -1, 2 }, // 7 Rsrc, x(Rdst) -+ { 3, 0, 0, -1, 2 }, // 8 #imm20, Rdst -+ { 3, 0, 0, -1, 2 }, // 9 #imm20, Rdst -+ { 3, 0, 0, -1, 2 }, // a #imm20, Rdst -+ { 3, 0, 0, -1, 2 }, // b #imm20, Rdst -+ { 0, -1, 0, -1, 0 }, // c Rsrc, Rdst -+ { 0, -1, 0, -1, 0 }, // d Rsrc, Rdst -+ { 0, -1, 0, -1, 0 }, // e Rsrc, Rdst -+ { 0, -1, 0, -1, 0 }, // f Rsrc, Rdst -+ }; -+ -+ operands_t operands = operands_table[(insn >> 4) & 0xf]; -+ if(((insn >> 4) & 0xf) == 6) -+ dst = msp430dis_opcode (addr + cmd_len, info) | ((insn & 0x000f) << 16); -+ else if(((insn >> 4) & 0xb) == 3) -+ dst = (short)msp430dis_opcode (addr + cmd_len, info); -+ else if(operands.length != 0) -+ dst = msp430dis_opcode(addr + cmd_len, info) | ((insn & 0x0f00) << 8); -+ -+ if(operands.regs == -1) -+ operands.regs = (insn >> 8 ) & 0x000f; -+ if(operands.regd == -1) -+ operands.regd = (insn >> 0 ) & 0x000f; -+ -+ if (operands.regd == 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); -- } -+ // R3 is illegal as dest: may be data section. -+ if (comm1) -+ strcpy (comm1, _("Illegal as address instr")); -+ else if (comm2) -+ strcpy (comm2, _("Illegal as address instr")); -+ return -1; - } -- else if (as == 1) -- { -- * cycles = 3; -+ // extract operands -+ msp430x_decode_operand(operands.regs, operands.as, addr + cmd_len, dst, -+ ((insn >> 4) & 0xf) == 3 ? OP_16BIT_HEX : OP_20BIT_HEX, op1, comm1); -+ msp430x_decode_operand(operands.regd, operands.ad, addr + cmd_len, dst, -+ ((insn >> 4) & 0xf) == 7 ? OP_16BIT_HEX : OP_20BIT_HEX, op2, comm2); -+ return cmd_len + operands.length; -+} - -- 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); -- } -- } -+static int -+msp430x_emulated (disassemble_info *info, -+ struct msp430_opcode_s const *opcode, -+ bfd_vma addr, -+ unsigned int insn, -+ char *op1, -+ char *comm1, -+ opwidth_t *op_width, -+ int *repeats) -+{ - -- return cmd_len; -+ switch(opcode_variant(opcode)) -+ { -+ case V_NONE: -+ case V_X_SHIFT: -+ // emulated by double operand instruction -+ return msp430x_doubleoperand(info, opcode, addr, insn, (char *)0, op1, -+ (char *)0, comm1, op_width, repeats); -+ case V_RETA: // reta, substituted by mova -+ return 2; -+ case V_EMU_ADDR: // substituted by other address instruction -+ return msp430x_address(info, addr, insn, (char *)0, op1, -+ (char *)0, comm1); -+ case V_BRA: // bra, substituted by mova -+ return msp430x_address(info, addr, insn, op1, (char *)0, -+ comm1, (char *)0); -+ default: -+ break; -+ } -+ return 0; - } - - int -@@ -668,22 +668,32 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) - { - void *stream = info->stream; - fprintf_ftype prin = info->fprintf_func; -- struct msp430_opcode_s *opcode; -+ struct msp430_opcode_s const *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. */ -- -+ unsigned int insn; -+ int repeats = 0; -+ int cpu = (bfd_mach_msp430x == info->mach) ? MSP430_CPU_MSP430X : MSP430_CPU_MSP430; -+ -+ opwidth_t op_width = DEFAULT_OP; // word instruction by default -+ static char const *width_modifier[] = -+ {"", "", ".b", ".a" }; -+ - insn = msp430dis_opcode (addr, info); -- sprintf (dinfo, "0x%04x", insn); - -- if (((int) addr & 0xffff) > 0xffdf) -+#if 0 -+ if ( (core == CORE_430 && ((int) addr & 0xffff) >= 0xffe0) -+ || ( core == CORE_430X && (((int) addr & 0xfffff) >= 0xffc0) && ((int) addr & 0xfffff) < 0x10000) -+ || ( core == CORE_430X2 && (((int) addr & 0xfffff) >= 0xff80) && ((int) addr & 0xfffff) < 0x10000) -+ ) - { - (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn); - return 2; - } -+#endif -+ -+ if (cpu >= MSP430_CPU_MSP430X && ((insn & 0xf800) == 0x1800)) // Extended instruction -+ insn |= msp430dis_opcode(addr + 2, info) << 16; - - *comm1 = 0; - *comm2 = 0; -@@ -691,62 +701,107 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) - for (opcode = msp430_opcodes; opcode->name; opcode++) - { - if ((insn & opcode->bin_mask) == opcode->bin_opcode -- && opcode->bin_opcode != 0x9300) -+// && opcode->bin_opcode != 0x9300 // was disasm tst instruction as cmp #0, dst? -+ ) - { - *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) -+ /* unsupported instruction */ -+ if(opcode_format(opcode) >= FMT_X && cpu < MSP430_CPU_MSP430X) -+ break; -+ -+ /* r0 as destination. Ad should be zero. Rdst=0 and Ad=0 are encoded in opcode & opcode_mask */ -+ if (opcode_format(opcode) == FMT_EMULATED && opcode_variant(opcode) == V_BR) - { - cmd_len = -- msp430_branchinstr (info, opcode, addr, insn, op1, comm1, -- &cycles); -+ msp430_branchinstr (info, opcode, addr, insn, op1, comm1); - 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(opcode_format(opcode) < FMT_X) -+ switch (opcode->insn_opnumb) -+ { -+ case 0: -+ cmd_len = msp430_nooperands (opcode, addr, insn, comm1); -+ break; -+ case 2: -+ cmd_len = -+ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, -+ comm1, comm2); -+ if (insn & BYTE_OPERATION) -+ op_width = BYTE_OP; -+ break; -+ case 1: -+ cmd_len = -+ msp430_singleoperand (info, opcode, addr, insn, op1, comm1); -+ if (insn & BYTE_OPERATION && opcode_format(opcode) != FMT_JUMP) -+ op_width = BYTE_OP; -+ break; -+ default: -+ break; -+ } -+ else // 430x instruction -+ switch(opcode_format(opcode)) -+ { -+ case FMT_X_SINGLE_OPERAND: -+ if( opcode_variant(opcode) == V_SWPSXT // swpbx, sxtx -+ && (insn & (NON_ADDR_OPERATION | BYTE_OPERATION_X)) == 0) // .a, special case -+ insn ^= BYTE_OPERATION_X; // make A/L, B/W as ordinary -+ -+ op_width = msp430x_opwidth(insn); -+ -+ if( opcode_variant(opcode) == V_SWPSXT && op_width == BYTE_OP) // swpbx, sxtx -+ strcpy (comm1, _("Illegal A/L, B/W bits setting")); -+ -+ cmd_len = msp430x_singleoperand (info, opcode, addr, insn, op1, comm1, -+ &repeats); -+ break; -+ case FMT_X_EXCEPTION: -+ cmd_len = msp430x_exception (info, opcode, addr, insn, op1, op2, -+ comm1, comm2, &op_width); -+ break; -+ case FMT_X_DOUBLE_OPERAND: -+ cmd_len = msp430x_doubleoperand (info, opcode, addr, insn, op1, op2, -+ comm1, comm2, &op_width, &repeats); -+ break; -+ case FMT_X_EMULATED: -+ cmd_len = msp430x_emulated (info, opcode, addr, insn, op1, -+ comm1, &op_width, &repeats); -+ break; -+ -+ case FMT_X_ADDRESS: -+ cmd_len = msp430x_address (info, addr, insn, op1, op2, -+ comm1, comm2); -+ 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)); -+ (*prin) (stream, ".word 0x%04x; ????\t%s%s", PS (insn), comm1, comm2); - return 2; - } - -- (*prin) (stream, "%s%s", opcode->name, bc); -+ -+ if (repeats) -+ { -+ if (repeats < 0) -+ (*prin) (stream, ".rpt\t#%d\n\t\t\t\t", 0 - repeats); -+ else -+ (*prin) (stream, ".rpt\tr%d\n\t\t\t\t", repeats); -+ } -+ -+ (*prin) (stream, "%s%s", opcode->name, width_modifier[op_width]); - - if (*op1) - (*prin) (stream, "\t%s", op1); -@@ -765,23 +820,11 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) - - 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, ","); -+ (*prin) (stream, ", "); - if (*comm2) -- (*prin) (stream, " %s", comm2); -+ (*prin) (stream, "%s", comm2); - return cmd_len; - }