Opcodes and assembler support for Nios II R2
[deliverable/binutils-gdb.git] / gas / config / tc-msp430.c
index e16fcd9527877c242690ffff85d7b8f919d86d8b..530774698f81f827626411af6a1eaa45d1e7b891 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-msp430.c -- Assembler code for the Texas Instruments MSP430
 
-  Copyright (C) 2002-2013 Free Software Foundation, Inc.
+  Copyright (C) 2002-2015 Free Software Foundation, Inc.
   Contributed by Dmitry Diky <diwil@mail.ru>
 
   This file is part of GAS, the GNU Assembler.
@@ -255,7 +255,7 @@ relax_typeS md_relax_table[] =
 };
 
 
-#define MAX_OP_LEN     256
+#define MAX_OP_LEN     4096
 
 typedef enum msp_isa
 {
@@ -264,486 +264,36 @@ typedef enum msp_isa
   MSP_ISA_430Xv2
 } msp_isa;
 
-struct mcu_type_s
-{
-  char *  name;
-  msp_isa isa;
-};
-
-static struct mcu_type_s mcu_types[] =
-{
-  {"msp430afe221", MSP_ISA_430},
-  {"msp430afe222", MSP_ISA_430},
-  {"msp430afe223", MSP_ISA_430},
-  {"msp430afe231", MSP_ISA_430},
-  {"msp430afe232", MSP_ISA_430},
-  {"msp430afe233", MSP_ISA_430},
-  {"msp430afe251", MSP_ISA_430},
-  {"msp430afe252", MSP_ISA_430},
-  {"msp430afe253", MSP_ISA_430},
-  {"msp430c091",   MSP_ISA_430},
-  {"msp430c092",   MSP_ISA_430},
-  {"msp430c111",   MSP_ISA_430},
-  {"msp430c1111",  MSP_ISA_430},
-  {"msp430c112",   MSP_ISA_430},
-  {"msp430c1121",  MSP_ISA_430},
-  {"msp430e112",   MSP_ISA_430},
-  {"msp430c1331", MSP_ISA_430},
-  {"msp430c1351", MSP_ISA_430},
-  {"msp430c311s", MSP_ISA_430},
-  {"msp430c312",  MSP_ISA_430},
-  {"msp430c313",  MSP_ISA_430},
-  {"msp430c314",  MSP_ISA_430},
-  {"msp430c315", MSP_ISA_430},
-  {"msp430c323", MSP_ISA_430},
-  {"msp430c325", MSP_ISA_430},
-  {"msp430c336", MSP_ISA_430},
-  {"msp430c337", MSP_ISA_430},
-  {"msp430c412", MSP_ISA_430},
-  {"msp430c413", MSP_ISA_430},
-  {"msp430e313", MSP_ISA_430},
-  {"msp430e315", MSP_ISA_430},
-  {"msp430e325", MSP_ISA_430},
-  {"msp430e337", MSP_ISA_430},
-  {"msp430f110", MSP_ISA_430},
-  {"msp430f1101", MSP_ISA_430},
-  {"msp430f1101a", MSP_ISA_430},
-  {"msp430f1111", MSP_ISA_430},
-  {"msp430f1111a", MSP_ISA_430},
-  {"msp430f112", MSP_ISA_430},
-  {"msp430f1121", MSP_ISA_430},
-  {"msp430f1121a", MSP_ISA_430},
-  {"msp430f1122", MSP_ISA_430},
-  {"msp430f1132", MSP_ISA_430},
-  {"msp430f122", MSP_ISA_430},
-  {"msp430f1222", MSP_ISA_430},
-  {"msp430f123", MSP_ISA_430},
-  {"msp430f1232", MSP_ISA_430},
-  {"msp430f133", MSP_ISA_430},
-  {"msp430f135", MSP_ISA_430},
-  {"msp430f147", MSP_ISA_430},
-  {"msp430f1471", MSP_ISA_430},
-  {"msp430f148", MSP_ISA_430},
-  {"msp430f1481", MSP_ISA_430},
-  {"msp430f149", MSP_ISA_430},
-  {"msp430f1491", MSP_ISA_430},
-  {"msp430f155", MSP_ISA_430},
-  {"msp430f156", MSP_ISA_430},
-  {"msp430f157", MSP_ISA_430},
-  {"msp430f1610", MSP_ISA_430},
-  {"msp430f1611", MSP_ISA_430},
-  {"msp430f1612", MSP_ISA_430},
-  {"msp430f167", MSP_ISA_430},
-  {"msp430f168", MSP_ISA_430},
-  {"msp430f169", MSP_ISA_430},
-  {"msp430f2001", MSP_ISA_430},
-  {"msp430f2002", MSP_ISA_430},
-  {"msp430f2003", MSP_ISA_430},
-  {"msp430f2011", MSP_ISA_430},
-  {"msp430f2012", MSP_ISA_430},
-  {"msp430f2013", MSP_ISA_430},
-  {"msp430f2101", MSP_ISA_430},
-  {"msp430f2111", MSP_ISA_430},
-  {"msp430f2112", MSP_ISA_430},
-  {"msp430f2121", MSP_ISA_430},
-  {"msp430f2122", MSP_ISA_430},
-  {"msp430f2131", MSP_ISA_430},
-  {"msp430f2132", MSP_ISA_430},
-  {"msp430f2232", MSP_ISA_430},
-  {"msp430f2234", MSP_ISA_430},
-  {"msp430f2252", MSP_ISA_430},
-  {"msp430f2254", MSP_ISA_430},
-  {"msp430f2272", MSP_ISA_430},
-  {"msp430f2274", MSP_ISA_430},
-  {"msp430f233", MSP_ISA_430},
-  {"msp430f2330", MSP_ISA_430},
-  {"msp430f235", MSP_ISA_430},
-  {"msp430f2350", MSP_ISA_430},
-  {"msp430f2370", MSP_ISA_430},
-  {"msp430f2410", MSP_ISA_430},
-  {"msp430f247", MSP_ISA_430},
-  {"msp430f2471", MSP_ISA_430},
-  {"msp430f248", MSP_ISA_430},
-  {"msp430f2481", MSP_ISA_430},
-  {"msp430f249", MSP_ISA_430},
-  {"msp430f2491", MSP_ISA_430},
-  {"msp430f412", MSP_ISA_430},
-  {"msp430f413", MSP_ISA_430},
-  {"msp430f4132", MSP_ISA_430},
-  {"msp430f415", MSP_ISA_430},
-  {"msp430f4152", MSP_ISA_430},
-  {"msp430f417", MSP_ISA_430},
-  {"msp430f423", MSP_ISA_430},
-  {"msp430f423a", MSP_ISA_430},
-  {"msp430f425",  MSP_ISA_430},
-  {"msp430f4250", MSP_ISA_430},
-  {"msp430f425a", MSP_ISA_430},
-  {"msp430f4260", MSP_ISA_430},
-  {"msp430f427",  MSP_ISA_430},
-  {"msp430f4270", MSP_ISA_430},
-  {"msp430f427a", MSP_ISA_430},
-  {"msp430f435", MSP_ISA_430},
-  {"msp430f4351", MSP_ISA_430},
-  {"msp430f436", MSP_ISA_430},
-  {"msp430f4361", MSP_ISA_430},
-  {"msp430f437", MSP_ISA_430},
-  {"msp430f4371", MSP_ISA_430},
-  {"msp430f438", MSP_ISA_430},
-  {"msp430f439", MSP_ISA_430},
-  {"msp430f447", MSP_ISA_430},
-  {"msp430f448", MSP_ISA_430},
-  {"msp430f4481", MSP_ISA_430},
-  {"msp430f449", MSP_ISA_430},
-  {"msp430f4491", MSP_ISA_430},
-  {"msp430f477", MSP_ISA_430},
-  {"msp430f478", MSP_ISA_430},
-  {"msp430f4783", MSP_ISA_430},
-  {"msp430f4784", MSP_ISA_430},
-  {"msp430f479", MSP_ISA_430},
-  {"msp430f4793", MSP_ISA_430},
-  {"msp430f4794", MSP_ISA_430},
-  {"msp430fe423", MSP_ISA_430},
-  {"msp430fe4232", MSP_ISA_430},
-  {"msp430fe423a", MSP_ISA_430},
-  {"msp430fe4242", MSP_ISA_430},
-  {"msp430fe425", MSP_ISA_430},
-  {"msp430fe4252", MSP_ISA_430},
-  {"msp430fe425a", MSP_ISA_430},
-  {"msp430fe427", MSP_ISA_430},
-  {"msp430fe4272", MSP_ISA_430},
-  {"msp430fe427a", MSP_ISA_430},
-  {"msp430fg4250", MSP_ISA_430},
-  {"msp430fg4260", MSP_ISA_430},
-  {"msp430fg4270", MSP_ISA_430},
-  {"msp430fg437", MSP_ISA_430},
-  {"msp430fg438", MSP_ISA_430},
-  {"msp430fg439", MSP_ISA_430},
-  {"msp430fg477", MSP_ISA_430},
-  {"msp430fg478", MSP_ISA_430},
-  {"msp430fg479", MSP_ISA_430},
-  {"msp430fw423", MSP_ISA_430},
-  {"msp430fw425", MSP_ISA_430},
-  {"msp430fw427", MSP_ISA_430},
-  {"msp430fw428", MSP_ISA_430},
-  {"msp430fw429", MSP_ISA_430},
-  {"msp430g2001", MSP_ISA_430},
-  {"msp430g2101", MSP_ISA_430},
-  {"msp430g2102", MSP_ISA_430},
-  {"msp430g2111", MSP_ISA_430},
-  {"msp430g2112", MSP_ISA_430},
-  {"msp430g2113", MSP_ISA_430},
-  {"msp430g2121", MSP_ISA_430},
-  {"msp430g2131", MSP_ISA_430},
-  {"msp430g2132", MSP_ISA_430},
-  {"msp430g2152", MSP_ISA_430},
-  {"msp430g2153", MSP_ISA_430},
-  {"msp430g2201", MSP_ISA_430},
-  {"msp430g2202", MSP_ISA_430},
-  {"msp430g2203", MSP_ISA_430},
-  {"msp430g2210", MSP_ISA_430},
-  {"msp430g2211", MSP_ISA_430},
-  {"msp430g2212", MSP_ISA_430},
-  {"msp430g2213", MSP_ISA_430},
-  {"msp430g2221", MSP_ISA_430},
-  {"msp430g2230", MSP_ISA_430},
-  {"msp430g2231", MSP_ISA_430},
-  {"msp430g2232", MSP_ISA_430},
-  {"msp430g2233", MSP_ISA_430},
-  {"msp430g2252", MSP_ISA_430},
-  {"msp430g2253", MSP_ISA_430},
-  {"msp430g2302", MSP_ISA_430},
-  {"msp430g2303", MSP_ISA_430},
-  {"msp430g2312", MSP_ISA_430},
-  {"msp430g2313", MSP_ISA_430},
-  {"msp430g2332", MSP_ISA_430},
-  {"msp430g2333", MSP_ISA_430},
-  {"msp430g2352", MSP_ISA_430},
-  {"msp430g2353", MSP_ISA_430},
-  {"msp430g2402", MSP_ISA_430},
-  {"msp430g2403", MSP_ISA_430},
-  {"msp430g2412", MSP_ISA_430},
-  {"msp430g2413", MSP_ISA_430},
-  {"msp430g2432", MSP_ISA_430},
-  {"msp430g2433", MSP_ISA_430},
-  {"msp430g2444", MSP_ISA_430},
-  {"msp430g2452", MSP_ISA_430},
-  {"msp430g2453", MSP_ISA_430},
-  {"msp430g2513", MSP_ISA_430},
-  {"msp430g2533", MSP_ISA_430},
-  {"msp430g2544", MSP_ISA_430},
-  {"msp430g2553", MSP_ISA_430},
-  {"msp430g2744", MSP_ISA_430},
-  {"msp430g2755", MSP_ISA_430},
-  {"msp430g2855", MSP_ISA_430},
-  {"msp430g2955", MSP_ISA_430},
-  {"msp430l092",  MSP_ISA_430},
-  {"msp430p112",  MSP_ISA_430},
-  {"msp430p313",  MSP_ISA_430},
-  {"msp430p315",  MSP_ISA_430},
-  {"msp430p315s", MSP_ISA_430},
-  {"msp430p325",  MSP_ISA_430},
-  {"msp430p337",  MSP_ISA_430},
-  {"msp430tch5e", MSP_ISA_430},
-
-  {"msp430cg4616", MSP_ISA_430X},
-  {"msp430cg4617", MSP_ISA_430X},
-  {"msp430cg4618", MSP_ISA_430X},
-  {"msp430cg4619", MSP_ISA_430X},
-  {"msp430f2416", MSP_ISA_430X},
-  {"msp430f2417", MSP_ISA_430X},
-  {"msp430f2418", MSP_ISA_430X},
-  {"msp430f2419", MSP_ISA_430X},
-  {"msp430f2616", MSP_ISA_430X},
-  {"msp430f2617", MSP_ISA_430X},
-  {"msp430f2618", MSP_ISA_430X},
-  {"msp430f2619", MSP_ISA_430X},
-  {"msp430f47126", MSP_ISA_430X},
-  {"msp430f47127", MSP_ISA_430X},
-  {"msp430f47163", MSP_ISA_430X},
-  {"msp430f47173", MSP_ISA_430X},
-  {"msp430f47183", MSP_ISA_430X},
-  {"msp430f47193", MSP_ISA_430X},
-  {"msp430f47166", MSP_ISA_430X},
-  {"msp430f47176", MSP_ISA_430X},
-  {"msp430f47186", MSP_ISA_430X},
-  {"msp430f47196", MSP_ISA_430X},
-  {"msp430f47167", MSP_ISA_430X},
-  {"msp430f47177", MSP_ISA_430X},
-  {"msp430f47187", MSP_ISA_430X},
-  {"msp430f47197", MSP_ISA_430X},
-  {"msp430f46161", MSP_ISA_430X},
-  {"msp430f46171", MSP_ISA_430X},
-  {"msp430f46181", MSP_ISA_430X},
-  {"msp430f46191", MSP_ISA_430X},
-  {"msp430f4616", MSP_ISA_430X},
-  {"msp430f4617", MSP_ISA_430X},
-  {"msp430f4618", MSP_ISA_430X},
-  {"msp430f4619", MSP_ISA_430X},
-  {"msp430fg4616", MSP_ISA_430X},
-  {"msp430fg4617", MSP_ISA_430X},
-  {"msp430fg4618", MSP_ISA_430X},
-  {"msp430fg4619", MSP_ISA_430X},
-
-  {"msp430f5418", MSP_ISA_430Xv2},
-  {"msp430f5419", MSP_ISA_430Xv2},
-  {"msp430f5435", MSP_ISA_430Xv2},
-  {"msp430f5436", MSP_ISA_430Xv2},
-  {"msp430f5437", MSP_ISA_430Xv2},
-  {"msp430f5438", MSP_ISA_430Xv2},
-  {"msp430f5418a", MSP_ISA_430Xv2},
-  {"msp430f5419a", MSP_ISA_430Xv2},
-  {"msp430f5435a", MSP_ISA_430Xv2},
-  {"msp430f5436a", MSP_ISA_430Xv2},
-  {"msp430f5437a", MSP_ISA_430Xv2},
-  {"msp430f5438a", MSP_ISA_430Xv2},
-  {"msp430f5212", MSP_ISA_430Xv2},
-  {"msp430f5213", MSP_ISA_430Xv2},
-  {"msp430f5214", MSP_ISA_430Xv2},
-  {"msp430f5217", MSP_ISA_430Xv2},
-  {"msp430f5218", MSP_ISA_430Xv2},
-  {"msp430f5219", MSP_ISA_430Xv2},
-  {"msp430f5222", MSP_ISA_430Xv2},
-  {"msp430f5223", MSP_ISA_430Xv2},
-  {"msp430f5224", MSP_ISA_430Xv2},
-  {"msp430f5227", MSP_ISA_430Xv2},
-  {"msp430f5228", MSP_ISA_430Xv2},
-  {"msp430f5229", MSP_ISA_430Xv2},
-  {"msp430f5304", MSP_ISA_430Xv2},
-  {"msp430f5308", MSP_ISA_430Xv2},
-  {"msp430f5309", MSP_ISA_430Xv2},
-  {"msp430f5310", MSP_ISA_430Xv2},
-  {"msp430f5340", MSP_ISA_430Xv2},
-  {"msp430f5341", MSP_ISA_430Xv2},
-  {"msp430f5342", MSP_ISA_430Xv2},
-  {"msp430f5324", MSP_ISA_430Xv2},
-  {"msp430f5325", MSP_ISA_430Xv2},
-  {"msp430f5326", MSP_ISA_430Xv2},
-  {"msp430f5327", MSP_ISA_430Xv2},
-  {"msp430f5328", MSP_ISA_430Xv2},
-  {"msp430f5329", MSP_ISA_430Xv2},
-  {"msp430f5500", MSP_ISA_430Xv2},
-  {"msp430f5501", MSP_ISA_430Xv2},
-  {"msp430f5502", MSP_ISA_430Xv2},
-  {"msp430f5503", MSP_ISA_430Xv2},
-  {"msp430f5504", MSP_ISA_430Xv2},
-  {"msp430f5505", MSP_ISA_430Xv2},
-  {"msp430f5506", MSP_ISA_430Xv2},
-  {"msp430f5507", MSP_ISA_430Xv2},
-  {"msp430f5508", MSP_ISA_430Xv2},
-  {"msp430f5509", MSP_ISA_430Xv2},
-  {"msp430f5510", MSP_ISA_430Xv2},
-  {"msp430f5513", MSP_ISA_430Xv2},
-  {"msp430f5514", MSP_ISA_430Xv2},
-  {"msp430f5515", MSP_ISA_430Xv2},
-  {"msp430f5517", MSP_ISA_430Xv2},
-  {"msp430f5519", MSP_ISA_430Xv2},
-  {"msp430f5521", MSP_ISA_430Xv2},
-  {"msp430f5522", MSP_ISA_430Xv2},
-  {"msp430f5524", MSP_ISA_430Xv2},
-  {"msp430f5525", MSP_ISA_430Xv2},
-  {"msp430f5526", MSP_ISA_430Xv2},
-  {"msp430f5527", MSP_ISA_430Xv2},
-  {"msp430f5528", MSP_ISA_430Xv2},
-  {"msp430f5529", MSP_ISA_430Xv2},
-  {"cc430f5133", MSP_ISA_430Xv2},
-  {"cc430f5135", MSP_ISA_430Xv2},
-  {"cc430f5137", MSP_ISA_430Xv2},
-  {"cc430f6125", MSP_ISA_430Xv2},
-  {"cc430f6126", MSP_ISA_430Xv2},
-  {"cc430f6127", MSP_ISA_430Xv2},
-  {"cc430f6135", MSP_ISA_430Xv2},
-  {"cc430f6137", MSP_ISA_430Xv2},
-  {"cc430f5123", MSP_ISA_430Xv2},
-  {"cc430f5125", MSP_ISA_430Xv2},
-  {"cc430f5143", MSP_ISA_430Xv2},
-  {"cc430f5145", MSP_ISA_430Xv2},
-  {"cc430f5147", MSP_ISA_430Xv2},
-  {"cc430f6143", MSP_ISA_430Xv2},
-  {"cc430f6145", MSP_ISA_430Xv2},
-  {"cc430f6147", MSP_ISA_430Xv2},
-  {"msp430f5333", MSP_ISA_430Xv2},
-  {"msp430f5335", MSP_ISA_430Xv2},
-  {"msp430f5336", MSP_ISA_430Xv2},
-  {"msp430f5338", MSP_ISA_430Xv2},
-  {"msp430f5630", MSP_ISA_430Xv2},
-  {"msp430f5631", MSP_ISA_430Xv2},
-  {"msp430f5632", MSP_ISA_430Xv2},
-  {"msp430f5633", MSP_ISA_430Xv2},
-  {"msp430f5634", MSP_ISA_430Xv2},
-  {"msp430f5635", MSP_ISA_430Xv2},
-  {"msp430f5636", MSP_ISA_430Xv2},
-  {"msp430f5637", MSP_ISA_430Xv2},
-  {"msp430f5638", MSP_ISA_430Xv2},
-  {"msp430f6433", MSP_ISA_430Xv2},
-  {"msp430f6435", MSP_ISA_430Xv2},
-  {"msp430f6436", MSP_ISA_430Xv2},
-  {"msp430f6438", MSP_ISA_430Xv2},
-  {"msp430f6630", MSP_ISA_430Xv2},
-  {"msp430f6631", MSP_ISA_430Xv2},
-  {"msp430f6632", MSP_ISA_430Xv2},
-  {"msp430f6633", MSP_ISA_430Xv2},
-  {"msp430f6634", MSP_ISA_430Xv2},
-  {"msp430f6635", MSP_ISA_430Xv2},
-  {"msp430f6636", MSP_ISA_430Xv2},
-  {"msp430f6637", MSP_ISA_430Xv2},
-  {"msp430f6638", MSP_ISA_430Xv2},
-  {"msp430f5358", MSP_ISA_430Xv2},
-  {"msp430f5359", MSP_ISA_430Xv2},
-  {"msp430f5658", MSP_ISA_430Xv2},
-  {"msp430f5659", MSP_ISA_430Xv2},
-  {"msp430f6458", MSP_ISA_430Xv2},
-  {"msp430f6459", MSP_ISA_430Xv2},
-  {"msp430f6658", MSP_ISA_430Xv2},
-  {"msp430f6659", MSP_ISA_430Xv2},
-  {"msp430f5131", MSP_ISA_430Xv2},
-  {"msp430f5151", MSP_ISA_430Xv2},
-  {"msp430f5171", MSP_ISA_430Xv2},
-  {"msp430f5132", MSP_ISA_430Xv2},
-  {"msp430f5152", MSP_ISA_430Xv2},
-  {"msp430f5172", MSP_ISA_430Xv2},
-  {"msp430f6720", MSP_ISA_430Xv2},
-  {"msp430f6721", MSP_ISA_430Xv2},
-  {"msp430f6723", MSP_ISA_430Xv2},
-  {"msp430f6724", MSP_ISA_430Xv2},
-  {"msp430f6725", MSP_ISA_430Xv2},
-  {"msp430f6726", MSP_ISA_430Xv2},
-  {"msp430f6730", MSP_ISA_430Xv2},
-  {"msp430f6731", MSP_ISA_430Xv2},
-  {"msp430f6733", MSP_ISA_430Xv2},
-  {"msp430f6734", MSP_ISA_430Xv2},
-  {"msp430f6735", MSP_ISA_430Xv2},
-  {"msp430f6736", MSP_ISA_430Xv2},
-  {"msp430f67451", MSP_ISA_430Xv2},
-  {"msp430f67651", MSP_ISA_430Xv2},
-  {"msp430f67751", MSP_ISA_430Xv2},
-  {"msp430f67461", MSP_ISA_430Xv2},
-  {"msp430f67661", MSP_ISA_430Xv2},
-  {"msp430f67761", MSP_ISA_430Xv2},
-  {"msp430f67471", MSP_ISA_430Xv2},
-  {"msp430f67671", MSP_ISA_430Xv2},
-  {"msp430f67771", MSP_ISA_430Xv2},
-  {"msp430f67481", MSP_ISA_430Xv2},
-  {"msp430f67681", MSP_ISA_430Xv2},
-  {"msp430f67781", MSP_ISA_430Xv2},
-  {"msp430f67491", MSP_ISA_430Xv2},
-  {"msp430f67691", MSP_ISA_430Xv2},
-  {"msp430f67791", MSP_ISA_430Xv2},
-  {"msp430f6745", MSP_ISA_430Xv2},
-  {"msp430f6765", MSP_ISA_430Xv2},
-  {"msp430f6775", MSP_ISA_430Xv2},
-  {"msp430f6746", MSP_ISA_430Xv2},
-  {"msp430f6766", MSP_ISA_430Xv2},
-  {"msp430f6776", MSP_ISA_430Xv2},
-  {"msp430f6747", MSP_ISA_430Xv2},
-  {"msp430f6767", MSP_ISA_430Xv2},
-  {"msp430f6777", MSP_ISA_430Xv2},
-  {"msp430f6748", MSP_ISA_430Xv2},
-  {"msp430f6768", MSP_ISA_430Xv2},
-  {"msp430f6778", MSP_ISA_430Xv2},
-  {"msp430f6749", MSP_ISA_430Xv2},
-  {"msp430f6769", MSP_ISA_430Xv2},
-  {"msp430f6779", MSP_ISA_430Xv2},
-  {"msp430fr5720", MSP_ISA_430Xv2},
-  {"msp430fr5721", MSP_ISA_430Xv2},
-  {"msp430fr5722", MSP_ISA_430Xv2},
-  {"msp430fr5723", MSP_ISA_430Xv2},
-  {"msp430fr5724", MSP_ISA_430Xv2},
-  {"msp430fr5725", MSP_ISA_430Xv2},
-  {"msp430fr5726", MSP_ISA_430Xv2},
-  {"msp430fr5727", MSP_ISA_430Xv2},
-  {"msp430fr5728", MSP_ISA_430Xv2},
-  {"msp430fr5729", MSP_ISA_430Xv2},
-  {"msp430fr5730", MSP_ISA_430Xv2},
-  {"msp430fr5731", MSP_ISA_430Xv2},
-  {"msp430fr5732", MSP_ISA_430Xv2},
-  {"msp430fr5733", MSP_ISA_430Xv2},
-  {"msp430fr5734", MSP_ISA_430Xv2},
-  {"msp430fr5735", MSP_ISA_430Xv2},
-  {"msp430fr5736", MSP_ISA_430Xv2},
-  {"msp430fr5737", MSP_ISA_430Xv2},
-  {"msp430fr5738", MSP_ISA_430Xv2},
-  {"msp430fr5739", MSP_ISA_430Xv2},
-  {"msp430bt5190", MSP_ISA_430Xv2},
-  {"msp430fr5949", MSP_ISA_430Xv2},
-  {"msp430fr5969", MSP_ISA_430Xv2},
-  {"msp430sl5438a", MSP_ISA_430Xv2},
-
-  /* Generic names.  */
-  {"msp430",    MSP_ISA_430},
-  {"msp430X",   MSP_ISA_430X},
-  {"msp430Xv2", MSP_ISA_430Xv2},
-    
-  {NULL, 0}
-};
-
-static struct mcu_type_s default_mcu   = { "msp430x11", MSP_ISA_430 };
-static struct mcu_type_s msp430x_mcu   = { "msp430x",   MSP_ISA_430X };
-static struct mcu_type_s msp430xv2_mcu = { "msp430xv2", MSP_ISA_430Xv2 };
-
-static struct mcu_type_s * msp430_mcu = & default_mcu;
+static enum msp_isa selected_isa = MSP_ISA_430Xv2;
 
 static inline bfd_boolean
 target_is_430x (void)
 {
-  return msp430_mcu->isa >= MSP_ISA_430X;
+  return selected_isa >= MSP_ISA_430X;
 }
 
 static inline bfd_boolean
 target_is_430xv2 (void)
 {
-  return msp430_mcu->isa == MSP_ISA_430Xv2;
+  return selected_isa == MSP_ISA_430Xv2;
 }
 
-/* Generate a 16-bit relocation.
-   For the 430X we generate a relocation without linkwer range checking
-   if the value is being used in an extended (ie 20-bit) instruction.
+/* Generate an absolute 16-bit relocation.
+   For the 430X we generate a relocation without linker range checking
+    if the value is being used in an extended (ie 20-bit) instruction,
+    otherwise if have a shifted expression we use a HI reloc.
    For the 430 we generate a relocation without assembler range checking
-   if we are handling an immediate value or a byte-width instruction.  */
+    if we are handling an immediate value or a byte-width instruction.  */
+
 #undef  CHECK_RELOC_MSP430
-#define CHECK_RELOC_MSP430                                  \
-  (target_is_430x ()                                        \
-   ? (extended_op ? BFD_RELOC_16 : BFD_RELOC_MSP430X_ABS16)  \
-   : ((imm_op || byte_op)                                   \
+#define CHECK_RELOC_MSP430(OP)                         \
+  (target_is_430x ()                                   \
+  ? (extended_op                                       \
+     ? BFD_RELOC_16                                    \
+     : ((OP).vshift == 1)                              \
+     ? BFD_RELOC_MSP430_ABS_HI16                       \
+     : BFD_RELOC_MSP430X_ABS16)                                \
+   : ((imm_op || byte_op)                              \
       ? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16))
 
 /* Generate a 16-bit pc-relative relocation.
@@ -1121,8 +671,14 @@ extract_word (char * from, char * to, int limit)
 #define OPTION_LARGE 'l'
 static bfd_boolean large_model = FALSE;
 #define OPTION_NO_INTR_NOPS 'N'
-static bfd_boolean gen_interrupt_nops = TRUE;
+#define OPTION_INTR_NOPS 'n'
+static bfd_boolean gen_interrupt_nops = FALSE;
+#define OPTION_WARN_INTR_NOPS 'y'
+#define OPTION_NO_WARN_INTR_NOPS 'Y'
+static bfd_boolean warn_interrupt_nops = TRUE;
 #define OPTION_MCPU 'c'
+#define OPTION_MOVE_DATA 'd'
+static bfd_boolean move_data = FALSE;
 
 static void
 msp430_set_arch (int option)
@@ -1136,65 +692,110 @@ msp430_set_arch (int option)
                     target_is_430x () ? bfd_mach_msp430x : bfd_mach_msp11);
 }
 
-static void
-show_mcu_list (FILE * stream)
+/* This is the full list of MCU names that are known to only
+   support the 430 ISA.  */
+static const char * msp430_mcu_names [] =
 {
-  int i;
-
-  fprintf (stream, _("Known MCU names:\n"));
-
-  for (i = 0; mcu_types[i].name; i++)
-    {
-      fprintf (stream, "%14.14s", mcu_types[i].name);
-      if ((i % 6) == 5)
-       fprintf (stream, "\n");
-    }
-
-  fprintf (stream, "\n");
-}
+"msp430afe221",        "msp430afe222", "msp430afe223", "msp430afe231", 
+"msp430afe232",        "msp430afe233", "msp430afe251", "msp430afe252", 
+"msp430afe253",        "msp430c091",   "msp430c092",   "msp430c111",   
+"msp430c1111", "msp430c112",   "msp430c1121",  "msp430c1331",  
+"msp430c1351", "msp430c311s",  "msp430c312",   "msp430c313",   
+"msp430c314",  "msp430c315",   "msp430c323",   "msp430c325",   
+"msp430c336",  "msp430c337",   "msp430c412",   "msp430c413",   
+"msp430e112",  "msp430e313",   "msp430e315",   "msp430e325",   
+"msp430e337",  "msp430f110",   "msp430f1101",  "msp430f1101a", 
+"msp430f1111", "msp430f1111a", "msp430f112",   "msp430f1121",  
+"msp430f1121a",        "msp430f1122",  "msp430f1132",  "msp430f122",   
+"msp430f1222", "msp430f123",   "msp430f1232",  "msp430f133",   
+"msp430f135",  "msp430f147",   "msp430f1471",  "msp430f148",   
+"msp430f1481", "msp430f149",   "msp430f1491",  "msp430f155",   
+"msp430f156",  "msp430f157",   "msp430f1610",  "msp430f1611",  
+"msp430f1612", "msp430f167",   "msp430f168",   "msp430f169",   
+"msp430f2001", "msp430f2002",  "msp430f2003",  "msp430f2011",  
+"msp430f2012", "msp430f2013",  "msp430f2101",  "msp430f2111",  
+"msp430f2112", "msp430f2121",  "msp430f2122",  "msp430f2131",  
+"msp430f2132", "msp430f2232",  "msp430f2234",  "msp430f2252",  
+"msp430f2254", "msp430f2272",  "msp430f2274",  "msp430f233",   
+"msp430f2330", "msp430f235",   "msp430f2350",  "msp430f2370",  
+"msp430f2410", "msp430f247",   "msp430f2471",  "msp430f248",   
+"msp430f2481", "msp430f249",   "msp430f2491",  "msp430f412",   
+"msp430f413",  "msp430f4132",  "msp430f415",   "msp430f4152",  
+"msp430f417",  "msp430f423",   "msp430f423a",  "msp430f425",   
+"msp430f4250", "msp430f425a",  "msp430f4260",  "msp430f427",   
+"msp430f4270", "msp430f427a",  "msp430f435",   "msp430f4351",  
+"msp430f436",  "msp430f4361",  "msp430f437",   "msp430f4371",  
+"msp430f438",  "msp430f439",   "msp430f447",   "msp430f448",   
+"msp430f4481", "msp430f449",   "msp430f4491",  "msp430f477",   
+"msp430f478",  "msp430f4783",  "msp430f4784",  "msp430f479",   
+"msp430f4793", "msp430f4794",  "msp430fe423",  "msp430fe4232", 
+"msp430fe423a",        "msp430fe4242", "msp430fe425",  "msp430fe4252", 
+"msp430fe425a",        "msp430fe427",  "msp430fe4272", "msp430fe427a", 
+"msp430fg4250",        "msp430fg4260", "msp430fg4270", "msp430fg437",  
+"msp430fg438", "msp430fg439",  "msp430fg477",  "msp430fg478",  
+"msp430fg479", "msp430fw423",  "msp430fw425",  "msp430fw427",  
+"msp430fw428", "msp430fw429",  "msp430g2001",  "msp430g2101",  
+"msp430g2102", "msp430g2111",  "msp430g2112",  "msp430g2113",  
+"msp430g2121", "msp430g2131",  "msp430g2132",  "msp430g2152",  
+"msp430g2153", "msp430g2201",  "msp430g2202",  "msp430g2203",  
+"msp430g2210", "msp430g2211",  "msp430g2212",  "msp430g2213",  
+"msp430g2221", "msp430g2230",  "msp430g2231",  "msp430g2232",  
+"msp430g2233", "msp430g2252",  "msp430g2253",  "msp430g2302",  
+"msp430g2303", "msp430g2312",  "msp430g2313",  "msp430g2332",  
+"msp430g2333", "msp430g2352",  "msp430g2353",  "msp430g2402",  
+"msp430g2403", "msp430g2412",  "msp430g2413",  "msp430g2432",  
+"msp430g2433", "msp430g2444",  "msp430g2452",  "msp430g2453",  
+"msp430g2513", "msp430g2533",  "msp430g2544",  "msp430g2553",  
+"msp430g2744", "msp430g2755",  "msp430g2855",  "msp430g2955",  
+"msp430i2020", "msp430i2021",  "msp430i2030",  "msp430i2031",  
+"msp430i2040", "msp430i2041",  "msp430l092",   "msp430p112",   
+"msp430p313",  "msp430p315",   "msp430p315s",  "msp430p325",   
+"msp430p337",  "msp430tch5e"
+};
 
 int
 md_parse_option (int c, char * arg)
 {
-  int i;
-
   switch (c)
     {
     case OPTION_MMCU:
       if (arg == NULL)
        as_fatal (_("MCU option requires a name\n"));
 
-      for (i = 0; mcu_types[i].name; ++i)
-       if (strcasecmp (mcu_types[i].name, arg) == 0)
-         break;
-
-      if (mcu_types[i].name == NULL)
+      if (strcasecmp ("msp430", arg) == 0)
+       selected_isa = MSP_ISA_430;
+      else if (strcasecmp ("msp430xv2", arg) == 0)
+       selected_isa = MSP_ISA_430Xv2;
+      else if (strcasecmp ("msp430x", arg) == 0)
+       selected_isa = MSP_ISA_430X;
+      else
        {
-         show_mcu_list (stderr);
-         as_fatal (_("unknown MCU: %s\n"), arg);
-       }
+         int i;
 
-      /* Allow switching to the same or a lesser architecture.  */
-      if (msp430_mcu == &default_mcu || msp430_mcu->isa >= mcu_types[i].isa)
-       msp430_mcu = mcu_types + i;
-      else
-       as_fatal (_("redefinition of mcu type '%s' to '%s'"),
-                 msp430_mcu->name, mcu_types[i].name);
+         for (i = sizeof msp430_mcu_names / sizeof msp430_mcu_names[0]; i--;)
+           if (strcasecmp (msp430_mcu_names[i], arg) == 0)
+             {
+               selected_isa = MSP_ISA_430;
+               break;
+           }
+       }
+      /* It is not an error if we do not match the MCU name.  */
       return 1;
 
     case OPTION_MCPU:
-      if (strcmp (arg, "430") == 0)
-       msp430_mcu = & default_mcu;
-      else if (strcmp (arg, "430x") == 0
-              || strcmp (arg, "430X") == 0)
-       msp430_mcu = & msp430x_mcu;
-      else if (strcasecmp (arg, "430xv2") == 0)
-       msp430_mcu = & msp430xv2_mcu;
+      if (strcmp (arg, "430") == 0
+         || strcasecmp (arg, "msp430") == 0)
+       selected_isa = MSP_ISA_430;
+      else if (strcasecmp (arg, "430x") == 0
+              || strcasecmp (arg, "msp430x") == 0)
+       selected_isa = MSP_ISA_430X;
+      else if (strcasecmp (arg, "430xv2") == 0
+              || strcasecmp (arg, "msp430xv2") == 0)
+       selected_isa = MSP_ISA_430Xv2;
       else
        as_fatal (_("unrecognised argument to -mcpu option '%s'"), arg);
-
       return 1;
-      
+
     case OPTION_RELAX:
       msp430_enable_relax = 1;
       return 1;
@@ -1210,20 +811,127 @@ md_parse_option (int c, char * arg)
     case OPTION_NO_INTR_NOPS:
       gen_interrupt_nops = FALSE;
       return 1;
+    case OPTION_INTR_NOPS:
+      gen_interrupt_nops = TRUE;
+      return 1;
+
+    case OPTION_WARN_INTR_NOPS:
+      warn_interrupt_nops = TRUE;
+      return 1;
+    case OPTION_NO_WARN_INTR_NOPS:
+      warn_interrupt_nops = FALSE;
+      return 1;
+
+    case OPTION_MOVE_DATA:
+      move_data = TRUE;
+      return 1;
     }
 
   return 0;
 }
 
+/* The intention here is to have the mere presence of these sections
+   cause the object to have a reference to a well-known symbol.  This
+   reference pulls in the bits of the runtime (crt0) that initialize
+   these sections.  Thus, for example, the startup code to call
+   memset() to initialize .bss will only be linked in when there is a
+   non-empty .bss section.  Otherwise, the call would exist but have a
+   zero length parameter, which is a waste of memory and cycles.
+
+   The code which initializes these sections should have a global
+   label for these symbols, and should be marked with KEEP() in the
+   linker script.  */
+
+static void
+msp430_make_init_symbols (const char * name)
+{
+  if (strncmp (name, ".bss", 4) == 0
+      || strncmp (name, ".gnu.linkonce.b.", 16) == 0)
+    (void) symbol_find_or_make ("__crt0_init_bss");
+
+  if (strncmp (name, ".data", 5) == 0
+      || strncmp (name, ".gnu.linkonce.d.", 16) == 0)
+    (void) symbol_find_or_make ("__crt0_movedata");
+
+  /* Note - data assigned to the .either.data section may end up being
+     placed in the .upper.data section if the .lower.data section is
+     full.  Hence the need to define the crt0 symbol.  */
+  if (strncmp (name, ".either.data", 12) == 0
+      || strncmp (name, ".upper.data", 11) == 0)
+    (void) symbol_find_or_make ("__crt0_move_highdata");
+
+  /* See note about .either.data above.  */
+  if (strncmp (name, ".upper.bss", 10) == 0
+      || strncmp (name, ".either.bss", 11) == 0)
+    (void) symbol_find_or_make ("__crt0_init_highbss");
+}
+
+static void
+msp430_section (int arg)
+{
+  char * saved_ilp = input_line_pointer;
+  char * name = obj_elf_section_name ();
+
+  msp430_make_init_symbols (name);
+    
+  input_line_pointer = saved_ilp;
+  obj_elf_section (arg);
+}
+
+void
+msp430_frob_section (asection *sec)
+{
+  const char *name = sec->name;
+
+  if (sec->size == 0)
+    return;
+
+  msp430_make_init_symbols (name);
+}
+
+static void
+msp430_lcomm (int ignore ATTRIBUTE_UNUSED)
+{
+  symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
+
+  if (symbolP)
+    symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
+  (void) symbol_find_or_make ("__crt0_init_bss");
+}
+
+static void
+msp430_comm (int needs_align)
+{
+  s_comm_internal (needs_align, elf_common_parse);
+  (void) symbol_find_or_make ("__crt0_init_bss");
+}
+
+static void
+msp430_refsym (int arg ATTRIBUTE_UNUSED)
+{
+  char sym_name[1024];
+  input_line_pointer = extract_word (input_line_pointer, sym_name, 1024);
+
+  (void) symbol_find_or_make (sym_name);
+}
+
 const pseudo_typeS md_pseudo_table[] =
 {
   {"arch", msp430_set_arch, OPTION_MMCU},
   {"cpu", msp430_set_arch, OPTION_MCPU},
   {"profiler", msp430_profiler, 0},
+  {"section", msp430_section, 0},
+  {"section.s", msp430_section, 0},
+  {"sect", msp430_section, 0},
+  {"sect.s", msp430_section, 0},
+  {"pushsection", msp430_section, 1},
+  {"refsym", msp430_refsym, 0},
+  {"comm", msp430_comm, 0},
+  {"lcomm", msp430_lcomm, 0},
   {NULL, NULL, 0}
 };
 
-const char *md_shortopts = "mm:,mP,mQ,ml,mN";
+const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY";
 
 struct option md_longopts[] =
 {
@@ -1233,6 +941,10 @@ struct option md_longopts[] =
   {"mQ", no_argument, NULL, OPTION_RELAX},
   {"ml", no_argument, NULL, OPTION_LARGE},
   {"mN", no_argument, NULL, OPTION_NO_INTR_NOPS},
+  {"mn", no_argument, NULL, OPTION_INTR_NOPS},
+  {"mY", no_argument, NULL, OPTION_NO_WARN_INTR_NOPS},
+  {"my", no_argument, NULL, OPTION_WARN_INTR_NOPS},
+  {"md", no_argument, NULL, OPTION_MOVE_DATA},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -1251,9 +963,15 @@ md_show_usage (FILE * stream)
   fprintf (stream,
           _("  -ml - enable large code model\n"));
   fprintf (stream,
-          _("  -mN - disable generation of NOP after changing interrupts\n"));
-
-  show_mcu_list (stream);
+          _("  -mN - do not insert NOPs after changing interrupts (default)\n"));
+  fprintf (stream,
+          _("  -mn - insert a NOP after changing interrupts\n"));
+  fprintf (stream,
+          _("  -mY - do not warn about missing NOPs after changing interrupts\n"));
+  fprintf (stream,
+          _("  -my - warn about missing NOPs after changing interrupts (default)\n"));
+  fprintf (stream,
+          _("  -md - Force copying of data from ROM to RAM at startup\n"));
 }
 
 symbolS *
@@ -1338,7 +1056,7 @@ static int
 msp430_srcoperand (struct msp430_operand_s * op,
                   char * l,
                   int bin,
-                  int * imm_op,
+                  bfd_boolean * imm_op,
                   bfd_boolean allow_20bit_values,
                   bfd_boolean constants_allowed)
 {
@@ -1358,7 +1076,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
         hhi(x) - x = (x >> 48) & 0xffff
         The value _MUST_ be constant expression: #hlo(1231231231).  */
 
-      *imm_op = 1;
+      *imm_op = TRUE;
 
       if (strncasecmp (h, "#llo(", 5) == 0)
        {
@@ -1393,9 +1111,10 @@ msp430_srcoperand (struct msp430_operand_s * op,
 
       op->reg = 0;             /* Reg PC.  */
       op->am = 3;
-      op->ol = 1;              /* Immediate  will follow an instruction.  */
+      op->ol = 1;              /* Immediate will follow an instruction.  */
       __tl = h + 1 + rval;
       op->mode = OP_EXP;
+      op->vshift = vshift;
 
       parse_exp (__tl, &(op->exp));
       if (op->exp.X_op == O_constant)
@@ -1411,6 +1130,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
            {
              x = (x >> 16) & 0xffff;
              op->exp.X_add_number = x;
+             op->vshift = 0;
            }
          else if (vshift > 1)
            {
@@ -1419,11 +1139,12 @@ msp430_srcoperand (struct msp430_operand_s * op,
              else
                op->exp.X_add_number = 0;       /* Nothing left.  */
              x = op->exp.X_add_number;
+             op->vshift = 0;
            }
 
          if (allow_20bit_values)
            {
-             if (op->exp.X_add_number > 0xfffff || op->exp.X_add_number < - (0x7ffff))
+             if (op->exp.X_add_number > 0xfffff || op->exp.X_add_number < -524288)
                {
                  as_bad (_("value 0x%x out of extended range."), x);
                  return 1;
@@ -1508,16 +1229,20 @@ msp430_srcoperand (struct msp430_operand_s * op,
        }
       else if (op->exp.X_op == O_symbol)
        {
+         if (vshift > 1)
+           as_bad (_("error: unsupported #foo() directive used on symbol"));
          op->mode = OP_EXP;
        }
       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;
+             op->vshift = 0;
            }
          else
            {
@@ -1591,6 +1316,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       __tl = h + 1;
       parse_exp (__tl, &(op->exp));
       op->mode = OP_EXP;
+      op->vshift = 0;
       if (op->exp.X_op == O_constant)
        {
          int x = op->exp.X_add_number;
@@ -1654,6 +1380,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
          as_bad (_("cannot use indirect addressing with the PC"));
          return 1;
        }
+
       return 0;
     }
 
@@ -1664,7 +1391,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       char *m = strrchr (l, ')');
       char *t;
 
-      *imm_op = 1;
+      *imm_op = TRUE;
 
       if (!h)
        break;
@@ -1697,6 +1424,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       __tl = l;
       *h = 0;
       op->mode = OP_EXP;
+      op->vshift = 0;
       parse_exp (__tl, &(op->exp));
       if (op->exp.X_op == O_constant)
        {
@@ -1758,6 +1486,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
       /* An expression starting with a minus sign is a constant, not an address.  */
       op->am = (*l == '-' ? 3 : 1);
       op->ol = 1;
+      op->vshift = 0;
       __tl = l;
       parse_exp (__tl, &(op->exp));
       return 0;
@@ -1792,6 +1521,7 @@ msp430_dstoperand (struct msp430_operand_s * op,
       op->mode = OP_EXP;
       op->am = 1;
       op->ol = 1;
+      op->vshift = 0;
       parse_exp (__tl, &(op->exp));
 
       if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
@@ -1812,7 +1542,6 @@ msp430_dstoperand (struct msp430_operand_s * op,
   return 0;
 }
 
-
 /* Attempt to encode a MOVA instruction with the given operands.
    Returns the length of the encoded instruction if successful
    or 0 upon failure.  If the encoding fails, an error message
@@ -2072,6 +1801,8 @@ try_encode_mova (bfd_boolean imm_op,
   return 0;
 }
 
+static bfd_boolean check_for_nop = FALSE;
+
 #define is_opcode(NAME) (strcmp (opcode->name, NAME) == 0)
 
 /* Parse instruction operands.
@@ -2088,7 +1819,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   struct msp430_operand_s op1, op2;
   int res = 0;
   static short ZEROS = 0;
-  int byte_op, imm_op;
+  bfd_boolean byte_op, imm_op;
   int op_length = 0;
   int fmt;
   int extended = 0x1800;
@@ -2097,6 +1828,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   const char * error_message;
   static signed int repeat_count = 0;
   bfd_boolean fix_emitted;
+  bfd_boolean nop_check_needed = FALSE;
 
   /* Opcode is the one from opcodes table
      line contains something like
@@ -2104,27 +1836,85 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
      or
      .b @r2+, 5(R1).  */
 
-  /* Check if byte or word operation.  */
-  if (*line == '.' && TOLOWER (*(line + 1)) == 'b')
+  byte_op = FALSE;
+  addr_op = FALSE;
+  if (*line == '.')
     {
-      bin |= BYTE_OPERATION;
-      byte_op = 1;
+      bfd_boolean check = FALSE;
+      ++ line;
+
+      switch (TOLOWER (* line))
+       {
+       case 'b':
+         /* Byte operation.  */
+         bin |= BYTE_OPERATION;
+         byte_op = TRUE;
+         check = TRUE;
+         break;
+
+       case 'a':
+         /* "Address" ops work on 20-bit values.  */
+         addr_op = TRUE;
+         bin |= BYTE_OPERATION;
+         check = TRUE;
+         break;
+
+       case 'w':
+         /* Word operation - this is the default.  */
+         check = TRUE;
+         break;
+
+       case 0:
+       case ' ':
+       case '\n':
+       case '\r':
+         as_warn (_("no size modifier after period, .w assumed"));
+         break;
+
+       default:
+         as_bad (_("unrecognised instruction size modifier .%c"),
+                  * line);
+         return 0;
+       }
+
+      if (check)
+       {
+         ++ line;
+
+       }
     }
-  else
-    byte_op = 0;
 
-  /* "Address" ops work on 20-bit values.  */
-  if (*line == '.' && TOLOWER (*(line + 1)) == 'a')
+  if (*line && ! ISSPACE (*line))
     {
-      addr_op = TRUE;
-      bin |= BYTE_OPERATION;
+      as_bad (_("junk found after instruction: %s.%s"),
+             opcode->name, line);
+      return 0;
     }
-  else
-    addr_op = FALSE;
 
-  /* skip .[aAbwBW].  */
-  while (! ISSPACE (*line) && *line)
-    line++;
+  /* Catch the case where the programmer has used a ".a" size modifier on an
+     instruction that does not support it.  Look for an alternative extended
+     instruction that has the same name without the period.  Eg: "add.a"
+     becomes "adda".  Although this not an officially supported way of
+     specifing instruction aliases other MSP430 assemblers allow it.  So we
+     support it for compatibility purposes.  */
+  if (addr_op && opcode->fmt >= 0)
+    {
+      char * old_name = opcode->name;
+      char real_name[32];
+
+      sprintf (real_name, "%sa", old_name);
+      opcode = hash_find (msp430_hash, real_name);
+      if (opcode == NULL)
+       {
+         as_bad (_("instruction %s.a does not exist"), old_name);
+         return 0;
+       }
+#if 0 /* Enable for debugging.  */
+      as_warn ("treating %s.a as %s", old_name, real_name);
+#endif
+      addr_op = FALSE;
+      bin = opcode->bin_opcode;
+    }
 
   if (opcode->fmt != -1
       && opcode->insn_opnumb
@@ -2140,7 +1930,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   memset (&op1, 0, sizeof (op1));
   memset (&op2, 0, sizeof (op2));
 
-  imm_op = 0;
+  imm_op = FALSE;
 
   if ((fmt = opcode->fmt) < 0)
     {
@@ -2171,12 +1961,40 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       repeat_count = 0;
     }
 
+  if (check_for_nop && is_opcode ("nop"))
+    check_for_nop = FALSE;
+
   switch (fmt)
     {
     case 0:                    /* Emulated.  */
       switch (opcode->insn_opnumb)
        {
        case 0:
+         if (is_opcode ("eint") || is_opcode ("dint"))
+           {
+             if (check_for_nop)
+               {
+                 if (warn_interrupt_nops)
+                   {
+                     if (gen_interrupt_nops)
+                       as_warn (_("NOP inserted between two instructions that change interrupt state"));
+                     else
+                       as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
+                   }
+
+                 if (gen_interrupt_nops)
+                   {
+                     /* Emit a NOP between interrupt enable/disable.
+                        See 1.3.4.1 of the MSP430x5xx User Guide.  */
+                     insn_length += 2;
+                     frag = frag_more (2);
+                     bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
+                   }
+               }
+
+             nop_check_needed = TRUE;
+           }
+
          /* Set/clear bits instructions.  */
          if (extended_op)
            {
@@ -2185,24 +2003,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
              /* Emit the extension word.  */
              insn_length += 2;
-             frag = frag_more (insn_length);
+             frag = frag_more (2);
              bfd_putl16 (extended, frag);
            }
 
          insn_length += 2;
-         frag = frag_more (insn_length);
+         frag = frag_more (2);
          bfd_putl16 ((bfd_vma) bin, frag);
-
-         if (gen_interrupt_nops
-             && target_is_430xv2 ()
-             && (is_opcode ("eint") || is_opcode ("dint")))
-           {
-             /* Emit a NOP following interrupt enable/disable.
-                See 1.3.4.1 of the MSP430x5xx User Guide.  */
-             insn_length += 2;
-             frag = frag_more (2);
-             bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-           }
          dwarf2_emit_insn (insn_length);
          break;
 
@@ -2213,11 +2020,39 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          if (res)
            break;
 
+         bin |= (op1.reg | (op1.am << 7));
+
+         if (is_opcode ("clr") && bin == 0x4302 /* CLR R2*/)
+           {
+             if (check_for_nop)
+               {
+                 if (warn_interrupt_nops)
+                   {
+                     if (gen_interrupt_nops)
+                       as_warn (_("NOP inserted between two instructions that change interrupt state"));
+                     else
+                       as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
+                   }
+
+                 if (gen_interrupt_nops)
+                   {
+                     /* Emit a NOP between interrupt enable/disable.
+                        See 1.3.4.1 of the MSP430x5xx User Guide.  */
+                     insn_length += 2;
+                     frag = frag_more (2);
+                     bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
+                   }
+               }
+
+             nop_check_needed = TRUE;
+           }
+
          /* Compute the entire instruction length, in bytes.  */
-         insn_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2);
-         frag = frag_more (insn_length);
+         op_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2);
+         insn_length += op_length;
+         frag = frag_more (op_length);
          where = frag - frag_now->fr_literal;
-         
+
          if (extended_op)
            {
              if (!addr_op)
@@ -2228,7 +2063,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                  as_bad (_("repeat instruction used with non-register mode instruction"));
                  extended &= ~ 0xf;
                }
-             
+
              if (op1.mode == OP_EXP)
                {
                  if (op1.exp.X_op == O_constant)
@@ -2241,14 +2076,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    fix_new_exp (frag_now, where, 6, &(op1.exp), FALSE,
                                 BFD_RELOC_MSP430X_PCR20_EXT_SRC);
                }
-         
+
              /* Emit the extension word.  */
              bfd_putl16 (extended, frag);
              frag += 2;
              where += 2;
            }
 
-         bin |= (op1.reg | (op1.am << 7));
          bfd_putl16 ((bfd_vma) bin, frag);
          frag += 2;
          where += 2;
@@ -2267,7 +2101,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op1.reg)
                        fix_new_exp (frag_now, where, 2,
-                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2275,18 +2109,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                }
            }
 
-         if (gen_interrupt_nops
-             && target_is_430xv2 ()
-             && is_opcode ("clr")
-             && bin == 0x4302 /* CLR R2*/)
-           {
-             /* Emit a NOP following interrupt enable/disable.
-                See 1.3.4.1 of the MSP430x5xx User Guide.  */
-             insn_length += 2;
-             frag = frag_more (2);
-             bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-           }
-
          dwarf2_emit_insn (insn_length);
          break;
 
@@ -2307,16 +2129,16 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
          if (target_is_430xv2 ()
              && op1.mode == OP_REG
-             && op1.reg == 0 
+             && op1.reg == 0
              && (is_opcode ("rlax")
                  || is_opcode ("rlcx")
                  || is_opcode ("rla")
                  || is_opcode ("rlc")))
            {
              as_bad (_("%s: attempt to rotate the PC register"), opcode->name);
-             return 0;
+             break;
            }
-         
+
          if (extended_op)
            {
              if (!addr_op)
@@ -2327,7 +2149,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                  as_bad (_("repeat instruction used with non-register mode instruction"));
                  extended &= ~ 0xf;
                }
-             
+
              if (op1.mode == OP_EXP)
                {
                  if (op1.exp.X_op == O_constant)
@@ -2381,7 +2203,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op1.reg || (op1.reg == 0 && op1.am == 3))     /* Not PC relative.  */
                        fix_new_exp (frag_now, where, 2,
-                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2405,7 +2227,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    {
                      if (op2.reg)      /* Not PC relative.  */
                        fix_new_exp (frag_now, where, 2,
-                                    &(op2.exp), FALSE, CHECK_RELOC_MSP430);
+                                    &(op2.exp), FALSE, CHECK_RELOC_MSP430 (op2));
                      else
                        fix_new_exp (frag_now, where, 2,
                                     &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2421,7 +2243,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          if (extended_op)
            {
              as_bad ("Internal error: state 0/3 not coded for extended instructions");
-             return 0;
+             break;
            }
 
          line = extract_operand (line, l1, sizeof (l1));
@@ -2429,8 +2251,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          if (res)
            break;
 
-         byte_op = 0;
-         imm_op = 0;
+         byte_op = FALSE;
+         imm_op = FALSE;
          bin |= ((op1.reg << 8) | (op1.am << 4));
          op_length = 2 + 2 * op1.ol;
          frag = frag_more (op_length);
@@ -2446,12 +2268,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              else
                {
                  where += 2;
-             
+
                  bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
 
                  if (op1.reg || (op1.reg == 0 && op1.am == 3))
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -2466,14 +2288,14 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          fix_emitted = FALSE;
 
          line = extract_operand (line, l1, sizeof (l1));
-         imm_op = 0;
+         imm_op = FALSE;
 
          res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op,
                                   extended_op, FALSE);
          if (res)
            break;
 
-         byte_op = 0;
+         byte_op = FALSE;
 
          op_length = 2 + 2 * op1.ol;
          frag = frag_more (op_length);
@@ -2517,7 +2339,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            bin |= 0x60 | op1.reg;
          else if (op1.am == 3)
            bin |= 0x70 | op1.reg;
-         
+
          bfd_putl16 ((bfd_vma) bin, frag);
 
          if (op1.mode == OP_EXP)
@@ -2525,7 +2347,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              if (op1.ol != 1)
                {
                  as_bad ("Internal error: unexpected CALLA instruction length: %d\n", op1.ol);
-                 return 0;
+                 break;
                }
 
              bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
@@ -2550,21 +2372,21 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            if (*l1 != '#')
              {
                as_bad (_("expected #n as first argument of %s"), opcode->name);
-               return 0;
+               break;
              }
            parse_exp (l1 + 1, &(op1.exp));
            if (op1.exp.X_op != O_constant)
              {
                as_bad (_("expected constant expression for first argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            if ((reg = check_reg (l2)) == -1)
              {
                as_bad (_("expected register as second argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            op_length = 2;
@@ -2582,17 +2404,17 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                if (reg - n + 1 < 0)
                  {
                    as_bad (_("Too many registers popped"));
-                   return 0;
+                   break;
                  }
 
-               /* CPU21 parts cannot use POPM to restore the SR register.  */
+               /* CPU21 errata: cannot use POPM to restore the SR register.  */
                if (target_is_430xv2 ()
                    && (reg - n + 1 < 3)
                    && reg >= 2
                    && is_opcode ("popm"))
                  {
                    as_bad (_("Cannot use POPM to restore the SR register"));
-                   return 0;
+                   break;
                  }
 
                bin |= (reg - n + 1);
@@ -2612,7 +2434,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            if (extended & 0xff)
              {
                as_bad (_("repeat count cannot be used with %s"), opcode->name);
-               return 0;
+               break;
              }
 
            line = extract_operand (line, l1, sizeof (l1));
@@ -2621,34 +2443,34 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            if (*l1 != '#')
              {
                as_bad (_("expected #n as first argument of %s"), opcode->name);
-               return 0;
+               break;
              }
            parse_exp (l1 + 1, &(op1.exp));
            if (op1.exp.X_op != O_constant)
              {
                as_bad (_("expected constant expression for first argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
            n = op1.exp.X_add_number;
            if (n > 4 || n < 1)
              {
                as_bad (_("expected first argument of %s to be in the range 1-4"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            if ((reg = check_reg (l2)) == -1)
              {
                as_bad (_("expected register as second argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            if (target_is_430xv2 () && reg == 0)
              {
                as_bad (_("%s: attempt to rotate the PC register"), opcode->name);
-               return 0;
+               break;
              }
 
            op_length = 2;
@@ -2674,7 +2496,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            if (extended & 0xff)
              {
                as_bad (_("repeat count cannot be used with %s"), opcode->name);
-               return 0;
+               break;
              }
 
            line = extract_operand (line, l1, sizeof (l1));
@@ -2682,13 +2504,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              {
                as_bad (_("expected register as argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            if (target_is_430xv2 () && reg == 0)
              {
                as_bad (_("%s: attempt to rotate the PC register"), opcode->name);
-               return 0;
+               break;
              }
 
            if (byte_op)
@@ -2719,7 +2541,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                where = frag - frag_now->fr_literal;
                bfd_putl16 ((bfd_vma) bin, frag);
                dwarf2_emit_insn (op_length);
-             }     
+             }
            break;
          }
 
@@ -2733,7 +2555,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            if (extended & 0xff)
              {
                as_bad (_("repeat count cannot be used with %s"), opcode->name);
-               return 0;
+               break;
              }
 
            line = extract_operand (line, l1, sizeof (l1));
@@ -2752,7 +2574,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                      {
                        as_bad (_("expected value of first argument of %s to fit into 20-bits"),
                                opcode->name);
-                       return 0;
+                       break;
                      }
 
                    bin |= ((n >> 16) & 0xf) << 8;
@@ -2771,7 +2593,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                  {
                    as_bad (_("expected register name or constant as first argument of %s"),
                            opcode->name);
-                   return 0;
+                   break;
                  }
 
                bin |= (n << 8) | (1 << 6);
@@ -2782,7 +2604,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              {
                as_bad (_("expected register as second argument of %s"),
                        opcode->name);
-               return 0;
+               break;
              }
 
            frag = frag_more (op_length);
@@ -2798,9 +2620,9 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            dwarf2_emit_insn (op_length);
            break;
          }
-         
+
        case 9: /* MOVA, BRA, RETA.  */
-         imm_op = 0;
+         imm_op = FALSE;
          bin = opcode->bin_opcode;
 
          if (is_opcode ("reta"))
@@ -2834,7 +2656,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                  res += msp430_dstoperand (&op2, l2, opcode->bin_opcode,
                                            extended_op, TRUE);
                }
-         
+
              if (res)
                break;  /* Error occurred.  All warnings were done before.  */
            }
@@ -2845,7 +2667,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                                            & error_message)) == 0)
            {
              as_bad (error_message, opcode->name);
-             return 0;
+             break;
            }
          dwarf2_emit_insn (op_length);
          break;
@@ -2859,13 +2681,13 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              if (op1.exp.X_op != O_constant)
                {
                  as_bad (_("expected constant value as argument to RPT"));
-                 return 0;
+                 break;
                }
              if (op1.exp.X_add_number < 1
                  || op1.exp.X_add_number > (1 << 4))
                {
                  as_bad (_("expected constant in the range 2..16"));
-                 return 0;
+                 break;
                }
 
              /* We silently accept and ignore a repeat count of 1.  */
@@ -2886,7 +2708,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              else
                {
                  as_bad (_("expected constant or register name as argument to RPT insn"));
-                 return 0;
+                 break;
                }
            }
          break;
@@ -2921,16 +2743,45 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            }
        }
 
+      bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
+
+      if (   (is_opcode ("bic") && bin == 0xc232)
+         || (is_opcode ("bis") && bin == 0xd232)
+         || (is_opcode ("mov") && op2.mode == OP_REG && op2.reg == 2))
+       {
+         if (check_for_nop)
+           {
+             if (warn_interrupt_nops)
+               {
+                 if (gen_interrupt_nops)
+                   as_warn (_("NOP inserted between two instructions that change interrupt state"));
+                 else
+                   as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
+               }
+
+             if (gen_interrupt_nops)
+               {
+                 /* Emit a NOP between interrupt enable/disable.
+                    See 1.3.4.1 of the MSP430x5xx User Guide.  */
+                 insn_length += 2;
+                 frag = frag_more (2);
+                 bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
+               }
+           }
+
+         nop_check_needed = TRUE;
+       }
+
       /* Compute the entire length of the instruction in bytes.  */
-      insn_length =
-       (extended_op ? 2 : 0)   /* The extension word.  */
+      op_length = (extended_op ? 2 : 0)        /* The extension word.  */
        + 2                     /* The opcode */
        + (2 * op1.ol)          /* The first operand. */
        + (2 * op2.ol);         /* The second operand.  */
 
-      frag = frag_more (insn_length);
+      insn_length += op_length;
+      frag = frag_more (op_length);
       where = frag - frag_now->fr_literal;
-      
+
       if (extended_op)
        {
          if (!addr_op)
@@ -2955,7 +2806,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                fix_new_exp (frag_now, where, 6, &(op1.exp), FALSE,
                             BFD_RELOC_MSP430X_PCR20_EXT_SRC);
            }
-         
+
          if (op2.mode == OP_EXP)
            {
              if (op2.exp.X_op == O_constant)
@@ -2965,7 +2816,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                fix_new_exp (frag_now, where, 8, &(op2.exp), FALSE,
                             op2.reg ? BFD_RELOC_MSP430X_ABS20_EXT_ODST
                             : BFD_RELOC_MSP430X_PCR20_EXT_ODST);
-           
+
              else
                fix_new_exp (frag_now, where, 6, &(op2.exp), FALSE,
                             op2.reg ? BFD_RELOC_MSP430X_ABS20_EXT_DST
@@ -2978,7 +2829,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          frag += 2;
        }
 
-      bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
       bfd_putl16 ((bfd_vma) bin, frag);
       where += 2;
       frag += 2;
@@ -2997,7 +2847,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -3022,7 +2872,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op2.reg)          /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                            &(op2.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op2.exp), FALSE, CHECK_RELOC_MSP430 (op2));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -3030,19 +2880,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            }
        }
 
-      if (gen_interrupt_nops
-         && target_is_430xv2 ()
-         && (   (is_opcode ("bic") && bin == 0xc232)
-             || (is_opcode ("bis") && bin == 0xd232)
-             || (is_opcode ("mov") && op2.mode == OP_REG && op2.reg == 2)))
-       {
-         /* Emit a NOP following interrupt enable/disable.
-            See 1.3.4.1 of the MSP430x5xx User Guide.  */
-         insn_length += 2;
-         frag = frag_more (2);
-         bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-       }
-
       dwarf2_emit_insn (insn_length);
       break;
 
@@ -3065,20 +2902,20 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
       if (target_is_430xv2 ()
          && op1.mode == OP_REG
-         && op1.reg == 0 
+         && op1.reg == 0
          && (is_opcode ("rrax")
              || is_opcode ("rrcx")
              || is_opcode ("rra")
              || is_opcode ("rrc")))
        {
          as_bad (_("%s: attempt to rotate the PC register"), opcode->name);
-         return 0;
+         break;
        }
-      
+
       insn_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2);
       frag = frag_more (insn_length);
       where = frag - frag_now->fr_literal;
-      
+
       if (extended_op)
        {
          if (is_opcode ("swpbx") || is_opcode ("sxtx"))
@@ -3091,7 +2928,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  as_bad (_("%s instruction does not accept a .b suffix"),
                          opcode->name);
-                 return 0;
+                 break;
                }
              else if (! addr_op)
                extended |= BYTE_OPERATION;
@@ -3109,7 +2946,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
            {
              if (op1.exp.X_op == O_constant)
                extended |= ((op1.exp.X_add_number >> 16) & 0xf) << 7;
-         
+
              else if (op1.reg || (op1.reg == 0 && op1.am == 3))        /* Not PC relative.  */
                fix_new_exp (frag_now, where, 6, &(op1.exp), FALSE,
                             BFD_RELOC_MSP430X_ABS20_EXT_SRC);
@@ -3117,7 +2954,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                fix_new_exp (frag_now, where, 6, &(op1.exp), FALSE,
                             BFD_RELOC_MSP430X_PCR20_EXT_SRC);
            }
-         
+
          /* Emit the extension word.  */
          bfd_putl16 (extended, frag);
          frag += 2;
@@ -3143,7 +2980,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                {
                  if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative.  */
                    fix_new_exp (frag_now, where, 2,
-                                &(op1.exp), FALSE, CHECK_RELOC_MSP430);
+                                &(op1.exp), FALSE, CHECK_RELOC_MSP430 (op1));
                  else
                    fix_new_exp (frag_now, where, 2,
                                 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
@@ -3337,6 +3174,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
     }
 
   input_line_pointer = line;
+  check_for_nop = nop_check_needed;
   return 0;
 }
 
@@ -3348,9 +3186,9 @@ md_assemble (char * str)
   unsigned int i = 0;
 
   str = skip_space (str);      /* Skip leading spaces.  */
-  str = extract_cmd (str, cmd, sizeof (cmd));
+  str = extract_cmd (str, cmd, sizeof (cmd) - 1);
 
-  while (cmd[i] && i < sizeof (cmd))
+  while (cmd[i])
     {
       char a = TOLOWER (cmd[i]);
       cmd[i] = a;
@@ -3480,12 +3318,12 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
 
   fixp->fx_no_overflow = 1;
 
-  /* If polymorphs are enabled and relax disabled. 
+  /* If polymorphs are enabled and relax disabled.
      do not kill any relocs and pass them to linker.  */
-  if (msp430_enable_polys 
+  if (msp430_enable_polys
       && !msp430_enable_relax)
     {
-      if (!fixp->fx_addsy || (fixp->fx_addsy 
+      if (!fixp->fx_addsy || (fixp->fx_addsy
          && S_GET_SEGMENT (fixp->fx_addsy) == absolute_section))
        fixp->fx_done = 1;      /* It is ok to kill 'abs' reloc.  */
       else
@@ -3542,6 +3380,12 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
          bfd_putl16 ((bfd_vma) value, where);
          break;
 
+       case BFD_RELOC_MSP430_ABS_HI16:
+         value >>= 16;
+         value &= 0xffff;      /* Get rid of extended sign.  */
+         bfd_putl16 ((bfd_vma) value, where);
+         break;
+         
        case BFD_RELOC_32:
          bfd_putl16 ((bfd_vma) value, where);
          break;
@@ -3554,13 +3398,13 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
        case BFD_RELOC_MSP430X_ABS20_EXT_SRC:
        case BFD_RELOC_MSP430X_PCR20_EXT_SRC:
          bfd_putl16 ((bfd_vma) (value & 0xffff), where + 4);
-         value >>= 16;   
+         value >>= 16;
          bfd_putl16 ((bfd_vma) (((value & 0xf) << 7) | insn), where);
          break;
 
        case BFD_RELOC_MSP430X_ABS20_ADR_SRC:
          bfd_putl16 ((bfd_vma) (value & 0xffff), where + 2);
-         value >>= 16;   
+         value >>= 16;
          bfd_putl16 ((bfd_vma) (((value & 0xf) << 8) | insn), where);
          break;
 
@@ -3594,7 +3438,7 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
          value >>= 16;
          bfd_putl16 ((bfd_vma) ((value & 0xf) | insn), where);
          break;
-         
+
        default:
          as_fatal (_("line %d: unknown relocation type: 0x%x"),
                    fixp->fx_line, fixp->fx_r_type);
@@ -3617,7 +3461,7 @@ S_IS_GAS_LOCAL (symbolS * s)
     return FALSE;
   name = S_GET_NAME (s);
   len = strlen (name) - 1;
-  
+
   return name[len] == 1 || name[len] == 2;
 }
 
@@ -3706,7 +3550,7 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
              *reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
            }
 
-         reloc->addend = fixp->fx_offset; 
+         reloc->addend = fixp->fx_offset;
          if (asec == absolute_section)
            {
              reloc->addend += S_GET_VALUE (fixp->fx_addsy);
@@ -4006,7 +3850,7 @@ msp430_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS * fragP,
          by setting 'aim' to quite high value.  */
       aim = 0x7fff;
     }
-  
+
   this_state = fragP->fr_subtype;
   start_type = this_type = table + this_state;
 
@@ -4056,7 +3900,7 @@ msp430_fix_adjustable (struct fix *fixp ATTRIBUTE_UNUSED)
   if (fixp->fx_addsy
       && ((S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE) == 0))
     return TRUE;
-          
+
   return FALSE;
 }
 
@@ -4065,6 +3909,9 @@ msp430_fix_adjustable (struct fix *fixp ATTRIBUTE_UNUSED)
 void
 msp430_md_end (void)
 {
+  if (check_for_nop == TRUE && warn_interrupt_nops)
+    as_warn ("assembly finished with the last instruction changing interrupt state - a NOP might be needed");
+
   bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_ISA,
                             target_is_430x () ? 2 : 1);
 
This page took 0.04611 seconds and 4 git commands to generate.