[msp430-gcc] Upgrade to the mspgcc uniarch LTS release

rspanton rspanton at fedoraproject.org
Wed Aug 15 14:16:20 UTC 2012


commit cd6ba65750d49d5639e2656a56efa96630ae5913
Author: Rob Spanton <rspanton at zepler.net>
Date:   Wed Aug 15 15:10:07 2012 +0100

    Upgrade to the mspgcc uniarch LTS release

 .gitignore                      |    1 +
 msp430-gcc-4.6.3-20120406.patch |12291 +++++++++++++++++++++++++++++++++++++++
 msp430-gcc.spec                 |   51 +-
 sources                         |    3 +-
 4 files changed, 12317 insertions(+), 29 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 16e8bd9..81cfdc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 gcc-core-3.2.3.tar.bz2
 mspgcc-gcc-3.3-20100805.tar.bz2
+/gcc-core-4.6.3.tar.bz2
diff --git a/msp430-gcc-4.6.3-20120406.patch b/msp430-gcc-4.6.3-20120406.patch
new file mode 100644
index 0000000..6dec1e2
--- /dev/null
+++ b/msp430-gcc-4.6.3-20120406.patch
@@ -0,0 +1,12291 @@
+Copyright 2000-2012 Free Software Foundation, Inc.
+
+The material in this patch is a derivative work of the gcc package,
+and is subject to licensing and copyright of its parent package.
+
+This patch adds/enhances support for the Texas Instruments MSP430 family of
+microcontrollers to GNU gcc.  The material incorporated is maintained
+in a git repository hosted at:
+
+  git://mspgcc.git.sourceforge.net/gitroot/mspgcc/gcc
+
+This patch incorporates changes between:
+  upstream/release/gcc-4.6.3 (dffc052d8762f398d8d0198accbcb12185b0610a)
+and
+  gcc-4_6/gcc-4.6.3 (d005eb492eb2e3c41d4f77ef22e8f91c1e0bf27c)
+
+To build, obtain the upstream release distribution from:
+  ftp://ftp.gnu.org/pub/gnu/gcc/gcc-4.6.3/gcc-4.6.3.tar.bz2
+
+Unpack the distribution, apply the patch, and build.  (Note: The example
+commands are in Bourne-shell syntax.)
+
+  tar xjf gcc-4.6.3.tar.bz2
+  ( cd gcc-4.6.3 ; patch -p1 < ../msp430-gcc-4.6.3-20120406.patch )
+  mkdir -p BUILD/gcc
+  cd BUILD/gcc
+  ../../gcc-4.6.3/configure \
+    --target=msp430 \
+    --enable-languages=c,c++ \
+    --prefix=/usr/local/msp430 \
+  2>&1 | tee co
+  make 2>&1 | tee mo
+  make install 2>&1 | tee moi
+
+For support please use the mspgcc-users mailing list.  You can subscribe at
+https://lists.sourceforge.net/lists/listinfo/mspgcc-users.  Once subscribed,
+you can post by email to mspgcc-users at lists.sourceforge.net.  To report
+bugs, please file a tracker ticket on SourceForge at
+https://sourceforge.net/tracker/?group_id=42303&atid=432701
+
+Log of relevant changes:
+32f42c9 [2012-04-06 11:08:42 -0500] Update DEV-PHASE for release
+e33bad7 [2012-04-06 08:36:12 -0500] Update for release
+80e4799 [2012-03-30 19:26:05 -0500] Update DEV-PHASE for release
+79a5b04 [2012-03-21 16:00:08 -0500] Add msp430 target support to GCC
+2cc7120 [2012-03-30 19:22:48 -0500] Revert "Add msp430 target support to GCC"
+6511e76 [2012-03-30 18:49:30 -0500] Update for release
+58b91df [2012-03-30 10:22:34 -0500] SF 3513285 add CPU/MPY defines to internal cpp set
+2eac54bc [2012-03-30 10:08:03 -0500] Provide __interrupt support independently from iomacros.h
+0fa909f [2012-03-23 08:30:38 -0500] Update for release
+5a3c262 [2012-03-22 15:22:49 -0500] msp430.md: fix operand 1 pattern for strlen
+fac40d9 [2012-03-22 14:45:35 -0500] Eliminate various compiler warnings
+75e6526 [2012-03-22 10:00:54 -0500] Update for release
+6ee7148 [2012-03-22 04:01:56 -0500] SF 3113886 Peripheral RAM block mapping
+ba7338c [2012-03-21 15:58:43 -0500] SF 3474171 support TI standard interrupt declaration
+57c0b69 [2012-03-11 13:12:37 -0500] Update DEV-PHASE for release
+d3f7972 [2012-03-11 13:09:56 -0500] Update for release
+8e6ca75 [2012-03-10 15:00:01 -0600] SF 3499699 Incorrect generated code returning from main
+b2ed137 [2012-03-07 13:33:04 -0600] SF 3420924 gdb can't find local variables in unoptimized main
+b96f163 [2012-03-07 11:14:52 -0600] SF 3498729 diagnose frame pointer corruption in task
+11f355e [2012-03-04 16:36:31 -0600] msp430-builtins: eliminate signed/unsigned comparison warning
+8f6a458 [2012-03-04 16:26:17 -0600] SF 3496195 possibly incorrect using of conditional branch
+adf92c7 [2012-03-04 14:07:16 -0600] Refine cc0 implementation
+ac421b7 [2012-02-24 14:28:04 -0600] Update DEV-PHASE for release
+dca4c73 [2012-02-24 04:33:56 -0600] Update for release
+d3a6ed9 [2012-02-23 17:06:37 -0600] SF 3486466 if mcu left off, unclear error msg
+b39ee97 [2012-02-23 16:37:08 -0600] SF 3486463 msp430 4.6.1 toolchain warns about .noinit
+473e1ea [2012-02-06 17:29:00 -0600] Use standard method of emitting labels
+59ded52 [2012-02-06 17:25:33 -0600] SF 3440809 -O2 conflicts with naked functions
+ff1697d [2012-02-06 17:13:16 -0600] Reorder return insns so default does not have extraneous tests
+d4c922c [2012-02-06 13:51:29 -0600] Revert "SF 3440809 -O2 conflicts with naked functions"
+6932fa0 [2012-01-25 13:37:08 -0600] Update DEV-PHASE for release
+b27610a [2012-01-25 13:35:56 -0600] Update for release
+51fd720 [2012-01-25 12:02:17 -0600] SF 3479668 msp430-libc ICE on 32-bit host
+161ca2e [2012-01-25 10:33:48 -0600] SF 3479660 delay_cycles(INT32_MAX) fails on 32-bit host
+e313f64 [2012-01-19 17:54:37 -0600] Update DEV-PHASE for release
+135695f [2011-10-30 11:49:46 -0500] Add msp430 target support to GCC
+ec1dfda [2011-10-30 11:48:55 -0500] Revert "Add msp430 target support to GCC"
+79181ea [2012-01-19 16:01:35 -0600] Update for release
+2da8f82 [2012-01-06 16:39:04 -0600] Reuse existing function to determine length of constant
+8196139 [2012-01-06 16:16:14 -0600] Accept length for tablejump
+ec86a20 [2012-01-06 11:46:06 -0600] Swap args when dest is indirect register
+3228dad [2012-01-06 10:29:39 -0600] Disable early-clobber constraints on multi-word operations
+f5bcb28 [2012-01-05 17:05:11 -0600] Update for release
+9e311cd [2012-01-05 14:35:56 -0600] Fix length for non-standard out-of-range branches
+64670b7 [2012-01-05 10:08:06 -0600] Update length adjustment for conditional jump, return, and basic operands
+707930d [2012-01-05 09:09:40 -0600] Correct setcc insn length; fix bit carry mode error
+ee4eccd [2012-01-04 21:45:47 -0600] Use local labels instead of byte offsets
+9acab17 [2012-01-04 21:13:28 -0600] Permit comparisons on stack pointer and pseudo registers
+ad2846a [2012-01-04 20:50:19 -0600] Restore SF 3296698 peephole optimization
+6f93e81 [2012-01-04 19:04:54 -0600] Another attempt to make bittest for bit extraction non-volatile
+b440bae [2012-01-04 18:16:09 -0600] Update CC status based on attribute effects
+295a3b1 [2011-10-31 11:29:56 -0500] Review and update all cc attr values
+6356b4d [2012-01-04 17:11:30 -0600] Avoid comparison change on symbol_ref operands
+b700ea0 [2011-10-30 12:59:24 -0500] Replace cbranch infrastructure
+44686c2 [2012-01-05 16:58:09 -0600] Restore peephole optimization for andm2
+172eabb [2011-10-26 10:01:56 -0500] Cull peepholes and sequelae
+234f8ae [2011-12-24 11:09:01 -0600] Update for release
+5e574ea [2011-12-23 16:46:35 -0600] SF 3461162 remove non-standard ABI from libgcc functions
+e6f2470 [2011-12-23 13:05:23 -0600] Replace div/mod library functions
+b1d9c36 [2011-12-23 11:54:42 -0600] Remove all div/mod/divmod traces in preparation for replacement
+4f0a4b1 [2011-12-21 17:45:55 -0600] Rework libcall multiply to conform to ABI
+8ae17f9 [2011-12-21 10:17:46 -0600] Remove unreferenced umulsi3hw
+83ced76 [2011-12-21 10:07:25 -0600] Remove cmpsf libfunc
+0e29d57 [2011-12-19 11:18:02 -0600] Update for release
+a6b5024 [2011-12-16 16:20:29 -0600] SF 3459792 64-bit division/remainder clobber frame pointer
+2ae67d6 [2011-12-16 16:02:45 -0600] SF 3461136 epilog popm insn corrupted
+55c7f4b [2011-12-13 20:31:50 -0600] SF 3459655 broken bitfield extraction
+a4eef8e [2011-12-09 07:59:37 -0600] Validate SF 3273856
+1f0ec33 [2011-12-05 08:55:43 -0600] Regenerate
+7bc944e [2011-09-22 09:22:25 -0500] SF 3412886 pre-patch pr50213/tree-optimization
+1e1a365 [2011-09-22 09:25:24 -0500] SF 3412439 address IRA issue in upstream pr50427/rtl-optimization
+35b555b [2011-01-18 13:13:21 -0600] Add %:include-noerr as spec function.
+aee9347 [2011-02-21 03:47:03 -0600] Anticipatory patch for PR middle-end/42722 (SF 3148801)
+2240a54 [2011-07-16 12:21:25 -0500] Add msp430 target support to GCC
+bee4f4d [2011-12-05 08:17:00 -0600] Update for release
+5d1b4b6 [2011-11-21 12:28:33 -0600] SF 3440809 -O2 conflicts with naked functions
+377b6c8 [2011-11-20 09:32:43 -0600] SF 3383371 add watchdog support intrinsics
+0798f01 [2011-11-18 20:30:49 -0600] Test for errors on use of -fpic/-fPIC
+21cfc98 [2011-11-05 09:31:47 -0500] SF 3433730 Bug when casting function parameters
+4f902d7 [2011-11-04 09:34:12 -0500] Update for release
+c0bfdb1 [2011-11-03 12:06:53 -0500] Rework shift to avoid techniques that inhibit optimizations
+21a606e [2011-10-31 16:01:56 -0500] Generalize bittest to support non-constant values
+6d2c0aa [2011-11-03 10:41:00 -0500] SF 3431602 Incorrect comparison to 32-bit literal
+408f228 [2011-10-30 08:59:10 -0500] Update for release
+27f8454 [2011-10-29 15:01:11 -0500] Simplify convoluted template output
+dd0075e [2011-10-26 13:09:04 -0500] Clean up print operand
+9a900b5 [2011-10-29 14:12:02 -0500] Remove unreachable code
+6bbfd3b [2011-10-25 17:31:58 -0500] SF 3428439 support source auto increment operands
+7aa61ac [2011-10-25 16:06:11 -0500] Remove definitions of unused constraints
+12ff090 [2011-10-25 12:04:50 -0500] Canonicalize placement of cc attr settings and post-comma asm spacing
+dc3b946 [2011-10-25 11:46:50 -0500] Replace gratuitously complex jump insn
+675176b [2011-10-24 14:42:05 -0500] Eliminate inconsistency between call/call_value
+613706b [2011-10-25 11:31:56 -0500] Clean up extract insns
+b152dad [2011-10-25 18:36:59 -0500] Restore lost mode on unspec
+440301c [2011-10-24 10:11:33 -0500] Update for release
+0a76b34 [2011-10-24 09:59:20 -0500] Clarify interface to msp430_expand_insn functions
+eca5c47 [2011-10-24 09:30:05 -0500] Run things through indent
+bba6b13 [2011-10-24 09:25:51 -0500] Remove unused file
+0be6fc8 [2011-10-24 09:00:52 -0500] Use prefered mechanism for identifying size optimization
+0ee4d4e [2011-10-23 14:52:17 -0500] Refine length correction for other unspecs
+0babd77 [2011-10-23 14:45:30 -0500] SF 3426564 signed bitfield extraction broken
+774f509 [2011-10-21 13:24:30 -0500] Fix insn models for rotate in from carry.
+117ac67 [2011-10-21 12:38:30 -0500] Remove unspec_volatile from insns that are correctly modeled without it
+27a2c6a [2011-10-21 12:13:01 -0500] Model effect of rotate insns on carry flag
+18ada90 [2011-10-21 10:56:18 -0500] Inhibit extv insns
+2fde3be [2011-10-21 07:59:11 -0500] Update for release
+ebe1165 [2011-10-20 20:37:05 -0500] Eliminate peepholes related to shift operations
+bdbcf3e [2011-10-20 16:46:40 -0500] Remove redundant quotes
+cdf919b [2011-10-20 16:24:23 -0500] Use REGNO_* for register number constants
+87d3f7e [2011-10-20 12:35:53 -0500] Use pushm/popm in libgcc functions
+14fadac [2011-10-20 12:22:33 -0500] SF 3426468 use pushm for si/di values on stack
+44ba82e [2011-10-20 11:53:22 -0500] SF 3237004 implement 430x pushm
+dfb2de2 [2011-10-18 20:13:21 -0500] Update for release
+e8294a4 [2011-10-16 10:25:48 -0500] SF 3423822 validate interrupt attribute parameter
+e6c4351 [2011-10-11 09:23:06 -0500] Update for release
+2a8a2c9 [2011-10-11 09:19:52 -0500] SF 3377789 Review ASSEMBLER_DIALECT
+47b1a52 [2011-10-11 09:15:16 -0500] SF 3377785 test default ASM_APP_{ON,OFF}
+a2096f6 [2011-10-08 09:35:12 -0500] SF 3416278 allow users to control __low_level_init()
+c404e6e [2011-10-07 10:33:35 -0500] SF 3417263 GDB wrong address for variables
+ad6bb37 [2011-09-22 11:21:37 -0500] Update for release
+4830af7 [2011-09-18 13:15:02 -0500] SF 3411254 add __swap_bytes intrinsic
+f60dcf8 [2011-09-18 12:08:16 -0500] SF 3411243 need get/set interrupt state intrinsics
+4214b9f [2011-08-30 13:06:33 -0500] Update for release
+6a654e0 [2011-08-30 12:23:26 -0500] SF 3399395 revisit no-volatile-workaround
+9fab0e5 [2011-08-30 09:37:26 -0500] SF 3400750 infomemnobits missing
+44b88a0 [2011-08-29 20:57:00 -0500] Verify self-modifying operations.
+556cbad [2011-08-29 17:15:49 -0500] Extend RMW peepholes to addition and subtraction
+b5b464f [2011-08-29 16:58:23 -0500] Fix regression assigning through constant cast as volatile pointer
+fc183b6 [2011-08-29 15:30:20 -0500] Fix remaining regressions in existing test suite
+45c1914 [2011-08-29 15:28:41 -0500] Fix VWA regression in builtins_sp.c.
+31dd799 [2011-08-29 15:17:54 -0500] Fix VWA regression in builtins_read_sr.c.
+307d7f5 [2011-08-29 15:00:00 -0500] Optimize nand on volatile memory
+f671271 [2011-08-29 14:40:22 -0500] Optimize nand from memory
+f3872bf [2011-08-29 14:15:39 -0500] Optimizations involving non-volatile and volatile memory
+c37b500 [2011-08-29 13:52:27 -0500] Optimizations involving only volatile memory
+6c89cb6 [2011-08-29 13:23:59 -0500] Combine bit operation peepholes with structural equivalence
+cb03664 [2011-08-29 13:03:36 -0500] Peephole optimizations supporting peripheral register AND, IOR, XOR, NAND*
+f35a949 [2011-08-29 11:16:49 -0500] Remove the volatile workaround
+a2f0e8f [2011-08-29 09:42:50 -0500] Avoid addition of nonexistent libg during static links using -g
+1cc49f3 [2011-08-23 20:07:50 -0500] Update for release
+904f407 [2011-08-23 18:21:52 -0500] SF 3397068 generalize noinit support
+227645b [2011-08-22 16:54:33 -0500] Eliminate easy_mul
+09e55aa [2011-08-22 16:51:49 -0500] SF 3192592 review cost expressions
+a7d4a15 [2011-08-20 20:21:02 -0500] Update for release
+129e28e [2011-08-20 19:53:15 -0500] SF 3237002 implement 430x multi-bit shift/rotate
+60b0556 [2011-08-20 18:46:06 -0500] Lift clrc out of loop for all lshr operations
+cd984c5 [2011-08-20 17:29:04 -0500] Refactor to decrease use of r_op
+c48bd09 [2011-08-20 10:21:03 -0500] Prepare for inline non-const shifts
+3aeae48 [2011-08-20 09:02:59 -0500] Avoid r_op for multi-word register shifts
+cbe5cb5 [2011-08-20 04:25:13 -0500] Optimize 8-bit shifts
+ac32b96 [2011-08-20 02:43:13 -0500] Eliminate redundant moves related to r_op
+a86a6f5 [2011-08-19 15:37:27 -0500] Avoid temporary registers where no optimization possible
+c80fb27 [2011-08-19 15:08:33 -0500] Rework to use temporary registers independently of subregs
+f2b650c [2011-08-19 10:26:45 -0500] Refactor NBITS-1 shifts to avoid excessive multi-word registers
+2f93714 [2011-08-19 10:26:11 -0500] Correct predicate on LHS of storeqi2
+5365c4a [2011-08-19 08:34:37 -0500] Use standard RTL for extension operation, rename for clarity
+0226d04 [2011-08-19 08:16:11 -0500] Define matching pair for QI val / full reg load and store
+20335d2 [2011-08-18 14:04:57 -0500] Implement 16-bit optimized shifts and piecewise sub-8bit shifts
+97fad8e [2011-08-18 14:04:25 -0500] Correct insn constraints
+3977c66 [2011-08-18 12:01:26 -0500] Add piecewise insn for logical right shift; correct shift cc clobbers
+c59d8cb [2011-08-18 11:17:56 -0500] Rework tradeoff between loop and inline to respect -Os vs -O
+2bd47e9 [2011-08-18 10:36:39 -0500] Restructure in preparation for word-based sub-8-bit rotates
+0914c4a [2011-08-17 20:28:06 -0500] Optimize shifts 32..47 bits
+2109c59 [2011-08-17 19:59:48 -0500] Refactor for clarity
+34751fa [2011-08-17 19:42:09 -0500] Optimize shifts of 48 or more bits
+e7fab1f [2011-08-17 19:25:01 -0500] Start move toward eliminating copy from src to dest
+4bb7e55 [2011-08-17 14:57:13 -0500] Clean up how shift types are identified
+aa91bd5 [2011-08-17 12:03:12 -0500] Add shift primitive ops, optimize shift of NBITS-1
+fed9c4a [2011-08-17 10:08:34 -0500] Invert so we can replace r_op as we refine the results
+622528d [2011-08-17 05:09:02 -0500] Use loops for constant shifts if unrolled will take more space
+927c7bb [2011-08-17 04:39:34 -0500] Eliminate bogus cost estimations for shift operations.
+60dbead [2011-08-17 04:29:58 -0500] Another stab at multi-position support.
+baf509d [2011-08-17 04:02:12 -0500] Fix rrum on CPUX hi.
+027f317 [2011-08-17 03:33:38 -0500] Gross generation of constant shift sequences.
+74449ed [2011-08-17 03:08:16 -0500] Cleanup: consistent use of constraint instead of matchdup
+ae4fe30 [2011-08-16 17:55:31 -0500] Fix ashrhi3_15 again
+6fd83e8 [2011-08-16 17:34:56 -0500] Recognize more (trivial) inline opportunities
+9e68677 [2011-08-16 17:06:19 -0500] Fix ashrhi3_15 clobber; emit inline single-insn HImode shifts
+8acad80 [2011-08-16 16:26:26 -0500] Correct format for rl* insns
+de793db [2011-08-16 16:14:44 -0500] Prepare for potential of expanding using template
+b1205bc [2011-08-16 13:30:17 -0500] Replace shift implementation with library calls
+42da5d9 [2011-08-16 03:50:31 -0500] Add optimized shift implementations
+b98a654 [2011-08-18 20:06:13 -0500] SF 3394176 unrecognizable insn error subtracting addresses
+1df1153 [2011-08-16 16:18:27 -0500] Correct first parameter to conditional generator
+61a7360 [2011-08-16 04:51:12 -0500] Eliminate compiler errors, detect unhandled cases
+626e547 [2011-08-16 02:48:31 -0500] Comment cleanup
+b886801 [2011-08-13 11:17:45 -0500] SF 3390964 broken optimization with emulated multiply libcalls
+2f5126f [2011-08-09 13:16:59 -0500] Update for release
+544b161 [2011-08-09 03:17:25 -0500] SF 3388064 __delay_cycles is limited to 65535
+62f859e [2011-08-08 12:29:09 -0500] Eliminate compiler warning
+8f9c203 [2011-08-06 07:44:58 -0500] Update for release
+af7ce10 [2011-08-05 18:15:43 -0500] SF 3191569 register use cleanup: tieable
+ff84717 [2011-08-05 17:15:46 -0500] SF 3195549 addc_zero/subc_zero inconsistency
+eec1581 [2011-08-05 17:07:54 -0500] SF 3273856 eliminate cse of constant zero
+2b00fae [2011-08-05 16:33:49 -0500] Eliminate compiler warnings and style errors
+23a6f17 [2011-08-05 16:24:23 -0500] Remove unused global costs function
+97268c5 [2011-08-05 09:21:26 -0500] Get rid of magic numbers
+dbd2219 [2011-08-05 08:32:31 -0500] Put function-local string constants into unique rodata where appropriate
+1cf2f35 [2011-08-03 04:29:35 -0500] Update for release
+e4f5384 [2011-08-02 16:34:25 -0500] SF 3384766 string constants misplaced in text section
+3f602e2 [2011-07-27 09:54:27 -0500] SF 3370978: ICE on shift with 32-bit count
+5454162 [2011-07-27 06:03:06 -0500] Avoid warning about undeclared diagnostic functions
+95e763b [2011-07-25 21:13:35 -0500] Review and update to 4.6.0 version of Chapter 17 (Target Macros)
+98f6c89 [2011-07-25 19:31:48 -0500] Run everything through indent
+db4a82e [2011-07-25 18:09:55 -0500] Change spelling of spec function
+38dde08 [2011-07-25 16:53:02 -0500] Avoid garbage collection of mpy rtx structures
+79787aa [2011-07-25 14:00:41 -0500] Remove non-standard movstrhi/clrstrhi
+9e2bf05 [2011-01-01 20:51:50 -0600] Rework how unwinding is done.
+f4a6bd4 [2011-07-25 12:03:54 -0500] Replace GET_ENVIRONMENT
+51fcf95 [2011-01-01 20:18:39 -0600] Update GNU garbage collector use.
+a322715 [2011-01-01 20:57:32 -0600] Eliminate declarations for option variables.
+26e94eb [2011-01-01 21:24:01 -0600] Generalize optimization-dependent option defaults.
+086f349 [2011-01-01 20:42:15 -0600] Replace OVERRIDE_OPTIONS with TARGET_OPTION_OVERRIDE.
+0f8c96c [2011-01-01 20:37:34 -0600] Remove RETURN_POPS_ARGS.
+95ffbd3 [2011-01-01 20:03:53 -0600] Eliminate ORDER_REGS_FOR_LOCAL_ALLOC and TARGET_REORDER.
+b3bc594 [2011-07-05 17:09:07 -0500] Update for release
+203cd7e [2011-07-05 17:03:47 -0500] SF 3354800 put back -mdisable-hwmul
+5a9eec4 [2011-07-05 16:42:49 -0500] SF 3354807 ICE with -mmpy=16 on 32-bit constant multiplies
+c17a05a [2011-07-05 16:08:47 -0500] Update for release
+356dce9 [2011-07-05 15:56:40 -0500] Fix illegal extraction of low part of constant multiplication operand
+29af6de [2011-07-05 15:19:06 -0500] Complete support for MPY32
+339ecc8 [2011-07-05 15:06:47 -0500] Tested hardware multiply for non-MPY32 support
+e018493 [2011-07-05 15:01:28 -0500] Tiny optimization in mulsidi3
+0808b4d [2011-07-05 14:59:27 -0500] Add library functions for widen-to-64 multiply
+a74eec7 [2011-07-05 14:33:06 -0500] Validate muldi3
+391b168 [2011-07-05 10:39:24 -0500] Use mode iterators for multiplication insns
+3fd730b [2011-07-05 10:03:32 -0500] Clean up multiplication
+f6048bb [2011-07-05 09:03:08 -0500] Use correct "can't happen" function
+5ceb03b [2011-07-05 07:21:04 -0500] Remove patterns from non-expanded RTL templates
+c8d5bff [2011-07-04 21:29:21 -0500] Avoid unnecessary sign extension on mulqihi operations
+c692ec0 [2011-07-04 21:24:19 -0500] Refine multiplier peripheral indicator values
+c979dee [2011-07-04 21:16:18 -0500] SF 3354053 remove -mforce-hwmul, -mdisable-hwmul
+c4cc7fd [2011-07-04 20:13:07 -0500] Fix indentation
+defe95e [2011-07-04 15:43:25 -0500] More syntax cleanup
+7ae064f [2011-07-04 15:38:45 -0500] Syntax cleanup
+c6f5686 [2011-07-04 14:57:11 -0500] SF 3317421 -Os generates unrecognized insn for multiply-by-constant
+e534b53 [2011-07-04 14:08:58 -0500] Run things through GNU indent again
+c6b9d85 [2011-07-04 13:44:11 -0500] Eliminate special insns for MPY peripheral access
+7301357 [2011-07-04 12:56:41 -0500] Rework multiply interrupt protection insns
+81c5841 [2011-07-04 07:30:03 -0500] pophi sr clobbers condition codes
+596fe75 [2011-07-04 08:02:06 -0500] Clean up msp430_init_once
+4f1b02a [2011-06-25 15:15:52 -0500] Remove distracting disabled code
+2b1e36a [2011-06-25 15:01:31 -0500] Reformat macros so they are readable
+0aa02ac [2011-06-25 15:00:52 -0500] Remove unreferenced multiply-related registers
+0b0cd25 [2011-06-25 13:43:53 -0500] Remove outdated push helper functions
+b680b48 [2011-06-25 13:20:43 -0500] SF 3317711 path to ldscripts broken if installation moved
+73007d8 [2011-06-25 11:07:53 -0500] Patch provided by submitter
+9f6f736 [2011-06-12 08:35:07 -0500] Update for release
+e0d67b8 [2011-06-12 08:33:32 -0500] SF 3313978 ICE (unrecognizable insn) related to rotate
+c67eb41 [2011-05-30 11:39:49 -0500] Update for release
+c5b4fc7 [2011-05-30 10:23:18 -0500] SF 3302511: ICE building newlib 1.19.0
+eb98053 [2011-05-15 15:36:20 -0500] Update for release
+a6911fa [2011-05-10 20:02:57 -0500] SF 300205 regression: sizeof(short) != 2
+7949660 [2011-05-03 06:15:17 -0500] SF 3296698: unoptimized code for bit field/union
+d372fa6 [2011-04-30 14:21:18 -0500] Use a less obscure RTL pattern for swpb
+7aceebf [2011-04-30 12:35:41 -0500] Remove repeated calculation in cost expression calculation
+6e3c8e9 [2011-04-24 04:32:16 -0500] SF 3291533 __cmpdi2 wrong redux
+f4dcf98 [2011-04-23 13:34:41 -0500] Lift out function that splits multiword operands
+bbb040e [2011-04-23 09:48:47 -0500] Simplify absm2
+2cf5283 [2011-04-23 09:48:24 -0500] Avoid mode-less constants as op0
+f3c5554 [2011-04-22 20:50:21 -0500] New solution to expansion of multi-word comparisons
+87310b1 [2011-04-22 17:36:53 -0500] Strip cbranchsi4 support
+e545f89 [2011-04-22 13:25:29 -0500] SF 3291533 __cmpdi2 wrong
+5111472 [2011-04-21 17:33:06 -0500] Refactor high/low part extraction
+d24a5af [2011-04-21 16:58:42 -0500] Consolidate cbranch-related functions
+c5cacde [2011-04-21 15:44:34 -0500] Inline the operation to use canonical MSP430 comparison operator
+138db44 [2011-04-21 15:33:24 -0500] Eliminate unreferenced functions
+74cc7c0 [2011-04-21 11:36:18 -0500] br is an emulated format II instruction
+629871e [2011-04-21 10:22:56 -0500] Update for release
+e3b4304 [2011-04-21 09:09:11 -0500] SF 3195322 remove profile options -mpgs, -mpgl, -mpgr
+378cb1e [2011-04-21 09:02:14 -0500] SF 3288916 dint builtin should emit noop
+6809b99 [2011-04-21 08:55:04 -0500] SF 3290923 sequence of calls can overrun stack
+e0cda89 [2011-04-19 16:04:42 -0500] Eliminate introduction of temporary
+c638954 [2011-04-19 15:11:38 -0500] Strip out unused code
+1ed8438 [2011-04-19 14:52:02 -0500] Remove useless TARGET_LEGITIMIZE_ADDRESS
+4f07ba8 [2011-04-19 14:30:54 -0500] Tighten up checks on base register validity
+731f995 [2011-04-19 13:27:14 -0500] Rework strlenhi
+1b0bb04 [2011-04-19 09:27:41 -0500] Review use of vwa predicates in new insn definitions
+1f5fd5c [2011-04-19 08:29:15 -0500] Rename predicates associated with volatile work-around
+212891e [2011-04-18 10:36:32 -0500] Implement xorm3
+5d19c1f [2011-04-18 10:09:09 -0500] Replace iorm3
+244b312 [2011-04-18 09:53:07 -0500] Implement andm3
+f9ff60d [2011-04-18 08:06:10 -0500] Move validated instructions up in file
+2a623d5 [2011-04-18 08:05:46 -0500] Mode-specific condition code iterator macro
+d832a5d [2011-04-16 21:32:00 -0500] Add unary output support (ones complement, neg expansion)
+b87855f [2011-04-16 21:16:19 -0500] Correct push/pop length calculations
+36f2fdf [2011-04-16 18:38:10 -0500] Eliminate compile-time warnings
+5b7f8b4 [2011-04-16 14:41:57 -0500] Use iterator to generate RMW insn patterns
+2ac17c0 [2011-04-16 13:47:25 -0500] Calculate default instr_mult from destination mode
+e08079c [2011-04-16 13:34:32 -0500] Normalize NAND and check resulting lengths
+214da4a [2011-04-16 12:55:38 -0500] Combine indirect_jump and verify length calculations
+7f4e613 [2011-04-16 12:19:05 -0500] Remove explicit_br
+5237148 [2011-04-16 11:59:03 -0500] Remove unused code
+f3f561b [2011-04-16 11:53:44 -0500] Disallow use of stack or pseudo-registers in non-HImode operations
+15a2411 [2011-04-16 11:49:05 -0500] SF 3288235 : clobber in non-move operations
+7101e2e [2011-04-16 09:30:11 -0500] Re-optimize frame register adjustments
+325baaa [2011-04-15 17:22:42 -0500] Clean up subm3
+823391e [2011-04-15 14:21:14 -0500] Remove old addm3 code
+a508e2a [2011-04-15 13:50:45 -0500] Use iterator to avoid duplicating CG plus-to-minus split
+549a067 [2011-04-15 13:44:39 -0500] Use split to detect negative CG matches
+9070d43 [2011-04-15 13:20:59 -0500] Update for lengths for addhi3
+11c06de [2011-04-15 12:48:49 -0500] Use iterator to define addm3 expansions
+43b08b3 [2011-04-15 12:32:26 -0500] Implement swpb as rotate:HI for better optimization
+b812758 [2011-04-15 04:02:06 -0500] Define SHIFT_COUNT_TRUNCATED
+e00e7f5 [2011-04-14 14:33:17 -0500] Reduce alternatives in multi-word push operations
+91c9f6d [2011-04-14 14:32:44 -0500] pop operands are indirect stack references with side effects
+c298a78 [2011-04-14 14:13:25 -0500] Normalize order of attributes
+d4afe8c [2011-04-14 13:47:58 -0500] Handle parallel patterns, adjust delay_cycles builtin
+c08216c [2011-04-14 13:18:45 -0500] Refine format/length/alternatives for builtins
+2e169bf [2011-04-14 13:04:28 -0500] Indirect register as destination requires offset word
+95e0c28 [2011-04-14 12:48:29 -0500] Make instruction length based on format, not specific insn
+32585d4 [2011-04-14 09:57:01 -0500] Step to refining instruction length calculations
+b0c3415 [2011-04-15 12:32:26 -0500] Implement swpb as rotate:HI for better optimization
+0e7b758 [2011-04-15 04:02:43 -0500] Add a delay_cycles where the constant is not compatible with CG
+d69a3cf [2011-04-15 16:01:51 -0500] Remove dead dummy updates
+4d8b01e [2011-04-15 15:50:28 -0500] Remove unnecessary arguments from msp430_cbranch
+be559d2 [2011-04-14 17:52:13 -0500] SF 3286842 Compiler stores r2 but does not restore it
+4092793 [2011-04-13 18:06:16 -0500] Avoid potentially too strict requirement on index expressions
+1a62597 [2011-04-13 18:03:58 -0500] Replace imprecisely named function with new version
+6078f25 [2011-04-13 17:55:02 -0500] Provide utility functions to characterize rtx addressing mode
+a661df5 [2011-04-13 17:31:25 -0500] Eliminate whines from callers using unsigned regnum expressions
+17641ef [2011-04-12 15:43:47 -0500] Update for release
+b4aa2cb [2011-04-12 14:43:03 -0500] SF 3207700 make watchdog optional
+a32ae89 [2011-04-12 11:14:12 -0500] SF 3237009 default task for main
+31da821 [2011-04-12 15:39:54 -0500] Correct mis-use of force_reg
+d5e6c6d [2011-04-11 13:53:14 -0500] Update for release
+512271a [2011-04-11 11:05:12 -0500] Correct another frame/stack misunderstanding
+7526887 [2011-04-11 09:18:25 -0500] Improve optimization of zero-extended byte values
+4a492a8 [2011-04-11 09:14:41 -0500] Remove extranous space from movhi2 template
+56556b7 [2011-04-10 21:31:41 -0500] Correct potential mis-assignment of registers
+b0cabfe [2011-04-10 21:25:31 -0500] Fix suboptimal register reloading
+703a8d0 [2011-04-10 21:19:16 -0500] Make internal functions/data static
+c40ae95 [2011-04-10 16:47:46 -0500] Avoid abort() in ASM_OUTPUT macros
+972c5d5 [2011-04-10 16:46:31 -0500] Use register as more evocative unspecv parameter
+2d5b4cd [2011-04-10 16:33:44 -0500] SF 3260589 change frame pointer semantics
+9924371 [2011-04-10 10:38:14 -0500] SF 3191622 register use cleanup: SMALL_REGISTER_CLASSES
+cc2a80e [2011-04-09 19:17:06 -0500] Become much more strict about register uses.
+cd59dd3 [2011-04-09 18:54:30 -0500] Revert SF 3188386
+263c35c [2011-04-09 15:03:48 -0500] Fix wrong operator
+2d28aa6c [2011-04-09 13:33:44 -0500] Get rid of unnecessary TFPR (alloca already handled)
+3065f10 [2011-04-09 10:47:42 -0500] Rework implementation of critical to avoid RETI
+6583166 [2011-04-09 10:16:15 -0500] Minor documentation cleanup
+927f4d3 [2011-04-08 21:27:25 -0500] SF 3261372: critical attribute incompatible with -g flag
+8cc29a6 [2011-04-08 09:38:52 -0500] SF 3191614: register use cleanup: old constraints
+c155abc [2011-04-08 08:26:05 -0500] Uniformly use pushm1 insns
+c04654b [2011-04-07 21:18:44 -0500] Fix problem with pseudo-register assignment
+0bd318a [2011-04-07 09:15:04 -0500] Handle SFmode in msp430_mov_noclobber
+764d7f5 [2011-04-05 13:47:30 -0500] Use utility function to create offset mem exprs
+507ebad [2011-04-05 13:11:42 -0500] Inhibit peephole code when no peepholes defined
+5f4f010 [2011-04-05 13:09:19 -0500] Storing into memory cannot clobber registers
+2fd1283 [2011-04-05 12:54:38 -0500] Handle interior clobbers
+b452d9c [2011-04-05 12:47:17 -0500] Implement alternative no-clobber solution
+632da2f [2011-04-05 10:09:12 -0500] Use mode iterators to reduce duplication in extend insns
+d8381a8 [2011-04-05 08:05:06 -0500] Use pushqi1 instead of relaxing constraint on push_operand
+7be7f29 [2011-04-05 07:20:57 -0500] Avoid corrupting registers in moves
+f53a4cd [2011-04-04 22:44:25 -0500] Correct constraint documentation; clobber regs in builtins
+2d8a38e [2011-04-04 22:37:04 -0500] Remove some magic numbers
+6b77e9a [2011-04-04 22:22:46 -0500] Use a move iterator to handle SF using SI at no extra charge
+07b1838 [2011-04-04 22:04:28 -0500] Remove unused code
+3fc7864 [2011-04-04 21:53:12 -0500] Add movdi code
+5a5e4bc [2011-04-04 21:41:19 -0500] Combine alternatives with same pattern and lengths
+cd5a82e [2011-04-04 21:27:11 -0500] Implement movsi
+7cbd810 [2011-04-04 15:24:18 -0500] Support offset for stack-relative pushes
+0071bac [2011-04-04 12:47:03 -0500] Add movhi*
+0b2ce1e [2011-04-04 12:46:19 -0500] Disable ADJUST_INSN_LENGTH
+1db0967 [2011-04-04 12:22:14 -0500] Incorporate pushqi into movqi handling.
+bca4d4e [2011-04-04 08:47:25 -0500] Validation of movqi
+e5ff982 [2011-04-04 08:58:41 -0500] Remove unreferenced sameoperand code (leftover pre extend rewrite)
+6ed2af5 [2011-04-04 08:17:28 -0500] Move all peephole definitions to separate file.
+77f1c6a [2011-04-03 17:43:29 -0500] Cleanup around extend insns
+df372c4 [2011-04-03 17:17:33 -0500] Implement zero_extendmn2 sharing extendmn2 code
+29099e7 [2011-04-03 16:28:48 -0500] Re-implement sign extension insns (extendmn2)
+8ce32c4 [2011-04-03 12:45:56 -0500] Avoid overwrite when r11:di is copied to r12:di
+f74872c [2011-03-31 15:07:36 -0500] SF 3264484: need naked with stack variables
+14f89fa [2011-03-31 14:14:36 -0500] Trivial cleanups
+9a3f541 [2011-03-31 09:38:35 -0500] Remove RTX_FRAME_RELATED_P from prologue insns not affecting frame
+ed80052 [2011-03-30 11:14:56 -0500] Verify critical attribute results in reti
+3c63c7f [2011-03-30 09:24:53 -0500] Remove unreferenced variable
+dcbe77e [2011-03-30 08:55:23 -0500] SF 3257192: obey noreturn
+a11a4b6 [2011-03-30 08:37:16 -0500] Convert saveprologue elimination to warning
+9982fac [2011-03-29 11:46:52 -0500] Remove debug messages
+0d370a4 [2011-03-29 10:50:28 -0500] Update for release
+a72612b [2011-03-29 10:49:11 -0500] SF 3257021, 3257192: function attribute rework
+3abb531 [2011-03-28 12:50:38 -0500] Run everything through indent again
+091b3d0 [2011-03-28 12:36:12 -0500] SF 3250899: error right shift 32-bit values
+64c6735 [2011-03-27 19:33:36 -0500] SF 3250605: error left shift 64-bit values
+5a0a5da [2011-03-27 18:58:59 -0500] SF 3250633: error right logical shift 64-bit values
+53cbbd9 [2011-03-26 12:43:06 -0500] Reformatting in shift code
+96ecb5a [2011-03-26 11:50:34 -0500] Remove uncalled statics, inline uniquely called statics
+d1dcc05 [2011-03-26 11:42:21 -0500] Remove length calculations in shift operations
+bb404e2 [2011-03-26 11:02:41 -0500] Clear out more bogus instruction length infrastructure
+4e598c6 [2011-03-25 14:07:41 -0500] Partial SF 3244669: remove hard-coded lengths from msp430_name_code
+5fef21d [2011-03-25 13:43:40 -0500] Remove patterns which use @Rn+ naturally.
+c1fbc59 [2011-03-25 12:54:35 -0500] Reduce visibility of utility functions.
+c42f445 [2011-03-25 12:47:22 -0500] Correct instruction lengths for set expressions in builtins.
+3d2dd01 [2011-03-25 11:50:40 -0500] Consistent placement of unspec_volatile on set patterns.
+a059b93 [2011-03-25 11:50:34 -0500] Eliminate build warnings from use of HOST_WIDE_INT in printf formats
+6b16b08 [2011-03-26 07:48:23 -0500] Update version for next release
+238764f [2011-03-25 22:00:19 -0500] Fix delay_cycles on CPUXV2
+a454332 [2011-03-25 00:36:23 -0500] SF 3237005: add __delay_cycles intrinsic
+660b860 [2011-03-24 13:25:27 -0500] Fix varargs problem on 64-bit hosts.
+c3279c7 [2011-03-22 17:44:06 -0500] Update version for next release
+0820353 [2011-03-22 15:25:24 -0500] Remove problematic and unuseful example
+fd873cf [2011-03-22 10:34:07 -0500] Rename builtin for consistency
+eea6dd2 [2011-03-21 12:18:51 -0500] Clean up interrupt attribute parameter processing
+a0beb09 [2011-03-21 11:34:46 -0500] Clean up prototypes/public functions
+0875583 [2011-03-21 11:12:57 -0500] Improve validation of naked/task attributes.
+1e086ab [2011-03-21 10:19:17 -0500] Check for incompatibility among attribute declarations
+240b794 [2011-03-20 15:30:08 -0500] Replace code that detected empty epilogue
+6fe5e6c [2011-03-20 14:20:59 -0500] Use flags to specify frame prologue/epilogue actions
+3e9047c [2011-03-20 13:05:45 -0500] Disable saveprologue
+a65f990 [2011-03-20 11:56:58 -0500] Remove unused references to instruction address data
+2dbd885 [2011-03-20 11:46:25 -0500] Clean up stack alignment and adjustment for frame size
+3a69c2f [2011-03-20 11:16:20 -0500] Regression test for saveprologue.
+8973349 [2011-03-20 10:28:23 -0500] Calculate frame-saved register set in one place.
+f917da2 [2011-03-19 14:22:36 -0500] Use attribute trees instead of booleans to record function attributes
+ac08763 [2011-03-19 11:00:10 -0500] Make machine_status the ultimate source of function attributes.
+cdadcad [2011-03-19 10:44:36 -0500] Remove sibcall-related code.
+a5a0f44 [2011-03-19 09:43:11 -0500] Avoid marking interrupt functions as used until is_interrupt validated.
+70197bb [2011-03-19 09:27:31 -0500] Attribute cleanup: consistent format for warning messages
+105eb82 [2011-03-19 08:24:40 -0500] Run through indent
+cd4f3b6 [2011-03-19 08:19:36 -0500] Inline once-called, remove never-called frame handler functions
+96d200c [2011-03-16 12:27:20 -0500] Collect function attribute analysis into one place.
+cfbbf71 [2011-03-16 10:19:49 -0500] Remove unreferenced reserve attribute
+b950248 [2011-03-15 15:25:22 -0500] SF 3214051: validate is_leaf workaround
+8cdad9e [2011-03-14 20:47:40 -0500] Rename function to reflect what it does
+c657168 [2011-03-14 20:39:28 -0500] Remove -mendup-at and -minit-stack
+c0d0094 [2011-03-15 13:53:42 -0500] Remove calculation of function prologue/epilogue size.
+ddae3bc [2011-03-14 19:35:40 -0500] Remove .L__FrameSize/.L__FrameOffset
+f1f180b [2011-03-15 13:44:02 -0500] Remove GCC_VERSION_INT.
+33a486a [2011-03-14 19:24:32 -0500] SF 3195317: clean up -maccumulate-outgoing-args
+dfdf943 [2011-03-14 13:04:51 -0500] SF 3193396: fix uniarch ctors/dtors
+4b859f0 [2011-03-12 15:34:40 -0600] SF 3207046: get rid of jump to main
+b00681e [2011-03-12 15:21:44 -0600] Recognize that stack pointer may be a 20-bit pointer (not an unsigned int)
+04b7030 [2011-03-12 14:48:26 -0600] Correct support for named sections
+7856ccc [2011-03-12 11:56:08 -0600] SF 3207853: bad constant extraction on 64-bit systems
+b4fa76e [2011-03-11 17:40:27 -0600] Mark frame-related instructions
+b984f27 [2011-03-11 15:26:59 -0600] Inline the inline functions (not shared, no reason to put in separate file)
+e640bc6 [2011-03-11 15:24:47 -0600] Baby step: remove unused garbage from framehelpers.inl
+935d403 [2011-03-11 14:29:23 -0600] SF 3195323: remove -mrtl
+1294c59 [2011-03-11 12:08:51 -0600] Unit tests validating SF 3104943
+85bd56d [2011-03-11 11:40:16 -0600] SF 3206654: provide facility to identify mspgcc version
+39596e3 [2011-03-11 10:15:12 -0600] Implement __builtin_{read,write}_stack_pointer
+f02889e [2011-03-11 10:05:57 -0600] Implement __bis_status_register
+1dfce7c [2011-03-11 09:59:10 -0600] Implement __bic_status_register
+34c43ae [2011-03-11 09:47:08 -0600] Implement __write_status_register
+4d3889b [2011-03-11 09:24:09 -0600] Stub status-register builtins; implement read
+e5a7012 [2011-03-11 08:46:24 -0600] SF 3195325: remove -mdeb
+7cd7646 [2011-03-11 08:36:42 -0600] SF 3195329: remove -mIAR
+5a9c069 [2011-03-06 20:38:53 -0600] SF 3201686: gcc optimizes away static isr
+53eb3ab [2011-03-06 20:18:23 -0600] SF 3198920: bi*_sr_irq incorrect
+a026cc3 [2011-03-05 14:34:35 -0600] SF 3198924: get_frame_address wrong
+ff69c66 [2011-03-05 13:45:44 -0600] Test builtins for return address and frame address.
+537f549 [2011-03-03 15:55:14 -0600] Rework intrinsics that require frame pointers.
+aafe5cc [2011-03-03 12:44:05 -0600] Cleanup/consistency in nop/eint/dint
+a5a6811 [2011-03-03 12:31:04 -0600] Clean up bi*_sr_irq builtins.
+4af5a14 [2011-03-02 13:39:37 -0600] Add built-ins for nop, eint, dint
+1cad52d [2011-03-02 13:19:54 -0600] Unit test for get_frame_address
+5e8a925 [2011-03-02 13:19:33 -0600] Refine parameter to builtins
+df9cf2a [2011-03-02 09:46:35 -0600] Tests for bi[cs]_sr_irq intrinsics
+32a021d [2011-03-01 10:18:06 -0600] Generate preprocessor symbols for cpu, mpy, and ivcnt values.
+6371377 [2011-02-28 17:20:04 -0600] Clean up built-in declarations.
+5813cf3 [2011-02-28 16:49:53 -0600] Remove more magic numbers
+67fae96 [2011-02-28 16:31:36 -0600] Clean up built-in RTX expressions.
+9d18745 [2011-02-28 16:17:00 -0600] Replace magic numbers with constants from md file
+8102441 [2011-02-28 15:54:04 -0600] Eliminate magic numbers for unspec indices
+7d5c8f8 [2011-02-27 13:13:11 -0600] Make everything just depend on cpu/mpy/ivcnt
+2ce5df8 [2011-02-27 12:53:39 -0600] Enable calculation of proper multilib directory.
+81f6003 [2011-02-27 11:50:39 -0600] Correct various problems with multilib specification
+9096dee [2011-02-27 10:32:54 -0600] Basic multilib support.
+6e41a2b [2011-02-27 09:19:26 -0600] Sort target hooks by manual section
+727739a [2011-02-26 13:29:45 -0600] Remove all the declarations by moving the reference to follow the definition
+4abff5d [2011-02-26 13:11:55 -0600] Do not presume that c++ is the same as c
+600cad3 [2011-02-26 13:11:37 -0600] Put more things back where they belong.
+bd7b5e8 [2011-02-26 13:02:02 -0600] Remove more unreferenced stuff; keep in the one legitimate one
+f7a48de [2011-02-26 12:57:52 -0600] Replace unnecessary global macro
+c23994a [2011-02-26 12:51:19 -0600] Put things where they belong
+8f4fefa [2011-02-26 12:18:10 -0600] Go back and do the first subsections of Target Macros
+cb4494f [2011-02-26 12:02:29 -0600] Move private macro to implementation file; remove outdated comments
+30404eb [2011-02-26 11:59:28 -0600] Complete target macros.
+8f0e198 [2011-02-26 11:36:50 -0600] Debugging info.
+8d1c576 [2011-02-26 11:25:47 -0600] Complete Assembler Format
+909929d [2011-02-26 11:18:14 -0600] Instruction output
+4bde3c0 [2011-02-26 11:03:54 -0600] Macros for initialization
+7332c83 [2011-02-26 11:00:51 -0600] Initialization
+6ff0a5d [2011-02-26 11:00:43 -0600] Correct function name; add documentation removed from libgcc.S
+4b07834 [2011-02-26 11:00:16 -0600] Remove material now located in crt0.S
+f601076 [2011-02-25 16:04:32 -0600] Data and label output
+4bc8c86 [2011-02-25 15:20:25 -0600] Reverse incorrect code standard change.
+3be4849 [2011-02-25 15:10:18 -0600] Move hook to msp430.c; do 17.21.2 Data Output
+405c77e [2011-02-25 14:56:42 -0600] Remove outdated/unreferenced asm_output_* functions
+b1f3392 [2011-02-25 14:40:03 -0600] Sections
+257efb3 [2011-02-25 14:19:26 -0600] Costs and scheduling
+c9f5a9d [2011-02-25 13:58:35 -0600] Condition codes.
+7a283c2 [2011-02-25 13:37:54 -0600] Run things through indent again
+e45d06f [2011-02-25 13:33:00 -0600] Replace GO_IF_LEGITIMATE_ADDRESS with target hook
+213ce55 [2011-02-25 13:20:44 -0600] Cleanup varargs, trampolines, library calls, addressing modes
+d32099b [2011-02-25 10:14:15 -0600] Minor cleanup
+d93445d [2011-02-25 09:33:21 -0600] Complete review of msp430.h for 17.10 Stack and Calling
+c801827 [2011-02-25 09:19:37 -0600] 17.10.7 Register Arguments
+6555205 [2011-02-25 08:55:15 -0600] 17.10.6 Stack Arguments
+1f2ccd3 [2011-02-25 08:45:07 -0600] Stack/call up to 17.10.6
+cd569f1 [2011-02-24 15:31:31 -0600] Review 17.8 and 17.9 (register classes and outdated constraints)
+ef9e05c [2011-02-24 14:38:22 -0600] Review 17.7 Registers
+c3beb73 [2011-02-24 13:31:06 -0600] Clean up section 17.6 Layout of Source Language Data Types
+99fc7e4 [2011-02-24 13:08:51 -0600] Review and cleanup storage-related target data
+acfd4e4 [2011-02-24 12:14:53 -0600] Consistent names for macros related to register returns
+3adeb1d [2011-02-21 12:23:03 -0600] Convert LIBCALL_VALUE to target hook.
+a98a5e7 [2011-02-21 12:07:03 -0600] SF 3188386: inefficient struct return convention
+46f8277 [2011-02-21 11:52:13 -0600] Convert FUNCTION_VALUE to target hook
+7689eb5 [2011-02-21 10:58:45 -0600] Remove STRUCT_VALUE macro.
+94fccc8 [2011-02-21 10:55:06 -0600] Convert RETURN_IN_MEMORY to target hook
+feee18d [2011-02-21 10:54:24 -0600] Correct target macro selection
+d230668 [2011-02-10 09:04:44 -0600] Remove multilib and default mcu
+7d72ab9 [2011-02-07 09:59:05 -0600] Emit cpu and mpy in generated assembly source
+634cd52 [2011-02-24 11:52:32 -0600] Reduce check to accommodate gcc 4.5 limitation.
+669ba0c [2011-02-21 03:46:48 -0600] Test case for PR middle-end/42722 (SF 3148801)
+d6772e6 [2011-02-20 12:18:35 -0600] Test case for SF 3177314
+951a044 [2011-02-20 11:39:38 -0600] Test case for SF 3112089
+78fbbf0 [2011-02-19 16:14:12 -0600] Infrastructure for dejagnu autotests.
+ebd6be7 [2011-02-24 09:47:54 -0600] Remove hard-coded MCU-specific information from msp430 port.
+a13c84e [2011-01-01 19:51:09 -0600] Decouple front-end dependencies from target.
+b2accf6 [2011-01-01 15:10:24 -0600] Update trampoline interface to current GCC implementation.
+de467e5 [2011-01-01 14:46:49 -0600] Remove CAN_ELIMINATE.
+50fd87a [2011-01-01 14:39:16 -0600] Update frame pointer support to current GCC implementation.
+63cb597 [2011-01-01 14:25:04 -0600] Update for cond-optab branch.
+2354f1f [2011-01-01 13:46:09 -0600] Remove poisoned LEGITIMIZE_ADDRESS.
+6cf95dd [2011-01-01 13:41:09 -0600] Correct placement of GC marker
+03a9106 [2011-01-01 12:22:52 -0600] Avoid reference to uninitialized operands.
+36b4cae [2011-01-01 12:21:13 -0600] Fix mis-use of MEM_VOLATILE_P.
+4c59517 [2010-12-31 18:43:31 -0600] Run through indent again
+cba5a77 [2010-11-14 10:11:57 -0600] SF 3109143: Support value-line MSP430G22x1 devices
+5092e93 [2010-08-29 13:10:46 -0500] SF 3055519: add support for 55xx chips
+526fee6 [2010-08-29 10:45:10 -0500] Provide machine mode for certain constant integer operands.
+7401fc6 [2010-08-29 10:22:54 -0500] SF 3055171: ICE in trunc_int_for_mode
+d7d7602 [2010-11-19 14:50:58 -0600] SF 3112089: improper elimination of condition code set
+1b0f6ad [2010-11-06 14:58:21 -0500] SF 3090574: -fPIC silently won't work
+d89c540 [2010-08-15 08:58:26 -0500] Correct function prototype
+735355e [2010-08-14 21:57:21 -0500] Down to one last warning that I plan to ignore for now
+d2104bf [2010-08-14 21:45:10 -0500] C++ comments, format spec, const and signed qualifiers
+4b508e3 [2010-08-14 21:36:00 -0500] Remove invalid comma, fix function declarations
+acc8075 [2010-08-14 21:23:20 -0500] Eliminate warnings about C++ comments, mixed code/decl, unused variable
+d0d36e1 [2010-08-14 21:12:01 -0500] Run through indent again
+03bff4b [2010-08-14 21:11:32 -0500] Remove old-style definitions
+136e923 [2010-08-14 20:36:44 -0500] Remove PARAMS wrappers, re-run indent.
+3785875 [2010-08-14 20:27:26 -0500] Run everything through GNU indent version 2.2.10.
+7ba79e4 [2010-07-16 19:00:47 -0500] Merge branch 'msp430' into dev/4.4.4
+95b0112 [2010-07-16 18:11:23 -0500] Avoid dereferencing SET_SRC if instruction is not SET.
+8288f6e [2010-05-27 14:19:20 -0500] Correct chip name
+9da84ee [2010-05-20 19:17:08 +0000] Add file missed in commit 133
+1b52f5f [2010-05-20 19:04:47 +0000] Revise generic categorization to match binutils and support new architectures.
+2de401c [2010-02-15 21:26:05 -0700] Revise generic categorization to match binutils and support new architectures.
+f7a3ca5 [2010-02-09 21:58:10 +0000] Integrated cc430 patches
+4681bf9 [2010-02-03 09:53:20 +0000] Fixed incorrect stack allocation in main()
+8efbb4c [2010-01-24 17:23:32 +0000] Improved MinGW compatibility
+ed54f2c [2010-01-14 13:09:59 +0000] Fixed 'critical' and 'reentrant' attributes.
+0cbc9ff [2010-01-14 11:58:49 +0000] Added patch for gcc 4.4.2 fixing incorrect structure pushing Fixed incorrect "call offset(sp)" instruction generation and simulation Fixed incorrect prologue generation for function with stack frame pointer caused by stack arguments and without local variables
+b596201 [2009-12-23 14:37:11 +0000] Fixed frame structure generation
+14dc41f [2009-12-19 11:07:46 +0000] Fixed the cc1 crash when a "push SP" instruction was generated. Eliminated the need to use R5 as an argument pointer. Added experimental support for -maccumulate-outgoing-args
+fb8c53c [2009-11-21 19:30:36 +0000] Added full support for DWARF2 frame info and epilogue-based unwinder.
+2d439aa [2009-11-21 14:57:38 +0000] Upgraded prologue/epilogue generation to INSN-level interface. Added support for DWARF2 frame unwind info generation.
+df2957c [2009-11-03 15:21:55 +0000] Fixed ret/reti bug
+a0c7049 [2009-11-03 12:45:40 +0000] git-svn-id: http://mspgcc4.svn.sourceforge.net/svnroot/mspgcc4@25 9c79f009-54bf-40f1-a1dd-edde5f34ab85
+716d2c5 [2009-10-25 12:24:55 +0000] Temporary disabled incomplete DWARF2 unwind info generation
+710a650 [2009-10-24 20:56:37 +0000] git-svn-id: http://mspgcc4.svn.sourceforge.net/svnroot/mspgcc4@16 9c79f009-54bf-40f1-a1dd-edde5f34ab85
+236305a [2009-10-24 20:41:22 +0000] Added unwind info generation flag
+f948168 [2009-10-24 19:14:13 +0000] Added full support for GDB 6.8 and 7.0 Added support for GCC 4.4.2
+e72d34a [2009-10-01 10:49:22 +0000] Updated copyright notes
+d730759 [2009-09-08 14:21:29 +0000] Initial version
+
+diff --git gcc-4.6.3.orig/configure gcc-4.6.3/configure
+index 6be5e9d..fefe43a 100755
+--- gcc-4.6.3.orig/configure
++++ gcc-4.6.3/configure
+@@ -3467,6 +3467,9 @@ case "${target}" in
+   mn10300-*-*)
+     noconfigdirs="$noconfigdirs ${libgcj}"
+     ;;
++  msp430-*-*)
++    noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj} target-libssp"
++    ;;
+   mt-*-*)
+     noconfigdirs="$noconfigdirs sim"
+     ;;
+diff --git gcc-4.6.3.orig/configure.ac gcc-4.6.3/configure.ac
+index ba6d84d..56d8506 100644
+--- gcc-4.6.3.orig/configure.ac
++++ gcc-4.6.3/configure.ac
+@@ -913,6 +913,9 @@ case "${target}" in
+   mn10300-*-*)
+     noconfigdirs="$noconfigdirs ${libgcj}"
+     ;;
++  msp430-*-*)
++    noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj} target-libssp"
++    ;;
+   mt-*-*)
+     noconfigdirs="$noconfigdirs sim"
+     ;;
+diff --git gcc-4.6.3.orig/gcc/DEV-PHASE gcc-4.6.3/gcc/DEV-PHASE
+index e69de29..f914eb5 100644
+--- gcc-4.6.3.orig/gcc/DEV-PHASE
++++ gcc-4.6.3/gcc/DEV-PHASE
+@@ -0,0 +1 @@
++mspgcc LTS 20120406 unpatched
+diff --git gcc-4.6.3.orig/gcc/config.gcc gcc-4.6.3/gcc/config.gcc
+index 39d9a19..714612d 100644
+--- gcc-4.6.3.orig/gcc/config.gcc
++++ gcc-4.6.3/gcc/config.gcc
+@@ -930,6 +930,12 @@ avr-*-*)
+ 	extra_gcc_objs="driver-avr.o avr-devices.o"
+ 	extra_objs="avr-devices.o"
+ 	;;
++msp430-*-*)
++	tm_file="msp430/msp430.h dbxelf.h"
++	c_target_objs="msp430-c.o"
++	cxx_target_objs="msp430-c.o"
++	extra_objs="msp430-builtins.o msp430-function.o"
++	;;
+ bfin*-elf*)
+ 	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h"
+ 	tmake_file=bfin/t-bfin-elf
+diff --git gcc-4.6.3.orig/gcc/config/msp430/constraints.md gcc-4.6.3/gcc/config/msp430/constraints.md
+new file mode 100644
+index 0000000..4eab121
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/constraints.md
+@@ -0,0 +1,81 @@
++;; -*- Mode: Scheme -*-
++;; Constraint definitions for Texas Instruments MSP430.
++;; Copyright (C) 2011 Free Software Foundation, Inc.
++;;
++;; This file is part of GCC.
++;;
++;; GCC 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, or (at your option)
++;; any later version.
++;;
++;; GCC 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 GCC; see the file COPYING3.  If not see
++;; <http://www.gnu.org/licenses/>.
++
++;;; Available letters:
++;;;    ABCD  GHIJKL  O          Z
++;;;    abcdef h jkl    q  t v x  
++;;; (nb: generic used are EFVXgimnoprs)
++
++;; Note that the hard frame pointer is also a general register.
++
++(define_register_constraint "z" "PC_REG"
++  "Program counter r0")
++
++(define_register_constraint "y" "SP_REG"
++  "Stack pointer r1")
++
++(define_register_constraint "Y" "GENERAL_SP_REGS"
++  "Union of r (GENERAL), y (SP)")
++
++(define_register_constraint "w" "SR_REG"
++  "Status register r2")
++
++(define_register_constraint "W" "GENERAL_SR_REGS"
++  "Union of r (GENERAL), w (SR)")
++
++(define_register_constraint "u" "FIXED_PSEUDO_REGS"
++  "Fixed pseudo-register (argp, soft fp)")
++
++(define_register_constraint "U" "FIXED_PSEUDO_GENERAL_SP_REGS"
++  "Union of u (FIXED PSEUDO), r (GENERAL), y (SP)")
++
++(define_constraint "R"
++  "Indirect register @rN (general or stack pointer)"
++  (match_test "msp430_indirect_register_operand (op)"))
++
++(define_constraint "S"
++  "Indirect stack pointer @r2"
++  (match_test "msp430_indirect_register_operand (op) && REGNO (XEXP (op, 0)) == STACK_POINTER_REGNUM"))
++
++(define_constraint "T"
++  "Indexed stack pointer X(r2)"
++  (match_test "msp430_indexed_register_operand (op) && REGNO (XEXP (XEXP (op, 0), 0)) == STACK_POINTER_REGNUM"))
++
++(define_constraint "M"
++  "CPUX and integer constant suitable for multi-position shift operations"
++  (and (match_code "const_int")
++       (match_test "msp430_cpu & MSP430_CPU_MSP430X && MSP430_CPUX_MULTISHIFT_COUNT_P(ival)")))
++
++(define_constraint "Q"
++  "Post-increment memory reference"
++  (and (match_code "mem")
++       (match_code "post_inc" "0")
++       (match_code "reg" "00")))
++
++(define_constraint "N"
++  "General purpose register number as integer constant "
++  (and (match_code "const_int")
++       (match_test "(MSP430_MIN_GENERAL_REGNUM <= ival) && (ival <= MSP430_MAX_GENERAL_REGNUM)")))
++
++(define_constraint "P"
++  "Integer constant supported by constant generator registers"
++  (and (match_code "const_int")
++       (match_test "(ival == -1 || ival == 0 || ival == 1 || ival == 2 || ival == 4 || ival == 8)")))
++
+diff --git gcc-4.6.3.orig/gcc/config/msp430/crt0.S gcc-4.6.3/gcc/config/msp430/crt0.S
+new file mode 100644
+index 0000000..112ef09
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/crt0.S
+@@ -0,0 +1,336 @@
++/*  -*- Mode: Asm -*-  */
++#if WITH_DISABLE_WDT
++#define WDTIMER_KICK
++#else /* WITH_DISABLE_WDT */
++#define WDTIMER_KICK \
++	mov	&__wdt_clear_value, &__WDTCTL
++#endif /* WITH_DISABLE_WDT */
++/******* CRT support functions *********/
++
++/* The following sections are arranged in exactly this order by the loader,
++ * right before the text region.
++	;; .init0 (_reset_vector__: Start here after reset)
++	;; .init1 (User definable)
++	;; .init2 (__init_stack: Initialize stack)
++	;; .init3 (__low_level_init: Initialize hardware; user definable)
++	;; .init4 (__do_copy_data; __do_clear_bss: Copy data to .data, clear bss)
++	;; .init5 (User definable)
++	;; .init6 (__do_global_ctors: C++ constructors)
++	;; .init7 (User definable)
++	;; .init8 (User definable)
++	;; .init9 (main)
++	;; .fini9 (__stop_progExec__: Falls into here after main(). User definable)
++	;; .fini8 (User definable)
++	;; .fini7 (User definable)
++	;; .fini6 (C++ destructors)
++	;; .fini5 (User definable)
++	;; .fini4 (User definable)
++	;; .fini3 (User definable)
++	;; .fini2 (User definable)
++	;; .fini1 (User definable)
++	;; .fini0 (_endless_loop__: Infinite loop after program termination)
++
++NOTE: If you override any of the startup functions, ensure you put the
++	replacement in the correct section.
++*/
++
++#if defined(L_reset_vector__)
++/*****************************************************************
++ * Program starts here.
++ *   overwriting this label in the user program
++ *   causes removing all startup code except __do_global_ctors
++ *****************************************************************/
++	.section .init0, "ax", @progbits
++
++	.global	_reset_vector__
++	.weak   _reset_vector__
++
++	.func   _reset_vector__
++
++	;; .init0 (Start here after reset)
++_reset_vector__:
++
++	;; .init1 (Initialize watchdog support)
++	.global __watchdog_support
++	;; .init2 (Initialize stack)
++	.global	__init_stack
++	;; .init3 (Initialize hardware: user definable)
++	.global	__low_level_init
++	;; .init4 (Copy data to .data, clear bss)
++	.global __do_copy_data
++	.global __do_clear_bss
++	;; .init5 (User definable)
++	;; .init6 (C++ constructors)
++	/* .global __do_global_ctors ; Do not reference unless ctors exist */
++	;; .init7 (User definable)
++	;; .init8 (User definable)
++	;; .init9 (Main routine)
++	
++	;; compiler places the main routine in .init9 unless it is "hosted"
++	
++	;; .fini9 (__stop_progExec__: Falls into here after .init9. User definable)
++	.global __stop_progExec__
++	;; .fini8 (User definable)
++	;; .fini7 (User definable)
++	;; .fini6 (C++ destructors)
++	/* .global __do_global_dtors ; Do not reference unless dtors exist */
++	;; .fini5 (User definable)
++	;; .fini4 (User definable)
++	;; .fini3 (User definable)
++	;; .fini2 (User definable)
++	;; .fini1 (User definable)
++	;; .fini0 (_endless_loop__: Infinite loop after program termination)
++	.global _endless_loop__
++
++	.endfunc
++#endif  /* defined(L_reset_vector__) */
++	
++#if defined(L__watchdog_support)
++/*****************************************************************
++ * Initialize watchdog support
++ * Depending on variant selected, watchdog is disabled or its restart
++ * value is loaded into __wdt_clear_value for use throughout execution
++ *****************************************************************/
++	.section .init1, "ax", @progbits
++
++	.global	__watchdog_support
++	.weak   __watchdog_support
++
++	.func   __watchdog_support
++
++__watchdog_support:
++#if WITH_DISABLE_WDT
++	mov     #0x5a80, &__WDTCTL
++#else /* WITH_DISABLE_WDT */
++	mov.b	&__WDTCTL, r5
++	bis	#0x5a08, r5
++	mov	r5, &__wdt_clear_value
++#endif /* WITH_DISABLE_WDT */
++	.endfunc
++	
++#if ! WITH_DISABLE_WDT
++        .section        .noinit.crt0,"aw", at nobits
++        .p2align 1,0
++        .type   __wdt_clear_value, at object
++        .size   __wdt_clear_value,2
++	.global	__wdt_clear_value
++__wdt_clear_value:
++        .skip 2,0
++#endif /* WITH_DISABLE_WDT */
++
++#endif
++
++#if defined(L__init_stack)
++/*****************************************************************
++ * Set stack pointer
++ * can be overwriten
++    stack can be initialized in main() prologue,
++    but setting stack pointer here allows to call subroutines 
++    from startup code and call constructors of statically allocated C++ objects.
++    Stack pointer will have the same value entering main() as here,
++    so -mno-stack-init can be used to reduce code size.
++    initial stack value can be set in ld script as __stack symbol 
++    (end of RAM by default), or via -defsym __stack=<address> ld option
++    or via -Wl,defsym,__stack=<address> gcc option, or by redefining
++    __init_stack function as follows:
++
++#if defined (__cplusplus)
++extern "C" 
++endif
++__attribute__((__naked__)) __attribute__((section(".init2"))) void __init_stack()
++{
++    asm volatile("\tmov\t#stack_addr, r1\n");
++}
++
++ *****************************************************************/
++	.section .init2, "ax", @progbits
++
++	.global	__init_stack
++	.weak   __init_stack
++
++	.func   __init_stack
++
++__init_stack:
++	mov     #__stack, r1
++
++	.endfunc
++#endif
++
++#if defined(L__low_level_init)
++/*****************************************************************
++ * Initialize peripherals
++ * Available for user override
++ *****************************************************************/
++	.section .init3, "ax", @progbits
++
++	.global	__low_level_init
++	.weak   __low_level_init
++
++	.func   __low_level_init
++
++__low_level_init:
++	.endfunc
++#endif
++
++#if defined(L_copy_data)
++/*****************************************************************
++ * Initialize data: copy data 
++ * from __data_load_start ( = _etext) to __data_start
++ * can be overwriten
++ *****************************************************************/
++	.section .init4, "ax", @progbits
++
++	.global __do_copy_data
++	.weak   __do_copy_data
++
++	.func   __do_copy_data
++
++__do_copy_data:
++	mov     #__data_size, r15
++	tst     r15
++	jz      .L__copy_data_end
++.L__copy_data_loop:
++	WDTIMER_KICK
++	decd    r15
++	mov.w   __data_load_start(r15), __data_start(r15)    ; data section is word-aligned, so word transfer is acceptable
++	jne     .L__copy_data_loop
++.L__copy_data_end:
++
++	.endfunc
++#endif /* defined(L_copy_data) */
++    
++#if defined(L_clear_bss)
++/*****************************************************************
++ * Initialize data: clear .bss
++ * can be overwriten
++ *****************************************************************/
++	.section .init4, "ax", @progbits
++
++	.global __do_clear_bss
++	.weak   __do_clear_bss
++
++	.func   __do_clear_bss
++
++__do_clear_bss:
++	mov     #__bss_size, r15
++	tst     r15
++	jz      .L__clear_bss_end
++.L__clear_bss_loop:
++	WDTIMER_KICK
++	dec     r15
++	clr.b   __bss_start(r15)
++	jne     .L__clear_bss_loop
++.L__clear_bss_end:
++
++	.endfunc
++#endif  /* defined(L_clear_bss) */
++
++#if defined(L__stop_progExec__)
++/*****************************************************************
++ * Execute after main returns
++ * Default implementation does nothing
++ *****************************************************************/
++	.section .fini9, "ax", @progbits
++	.global __stop_progExec__
++	.weak	__stop_progExec__
++
++	.func  __stop_progExec__
++__stop_progExec__:
++	.endfunc
++	
++#endif
++
++#if defined(L_endless_loop__)
++/*****************************************************************
++ * Placed at end of CRT code unless overridden
++ * Default implementation loops entering LPM4, leaving GIE unchanged
++ *****************************************************************/
++	.section .fini0, "ax", @progbits
++
++	.global _endless_loop__
++	.weak	_endless_loop__
++	.func   _endless_loop__
++
++_endless_loop__:
++	bis	#0xf0, r2
++	jmp  _endless_loop__
++
++	.endfunc
++
++#endif  /* defined(L_endless_loop__) */
++    
++#if defined(L_ctors430)
++/*****************************************************************
++ * Call constructor functions.
++ *
++ * No reference to this should be generated unless a function pointer
++ * is added to the .ctors section.  This means that the code will
++ * be absent from the executable unless at least one pointer is
++ * present, which also means we don't have to check for an empty
++ * function list.
++ *****************************************************************/
++	.section .init6, "ax", @progbits
++	.global __do_global_ctors
++	.weak   __do_global_ctors
++    
++	.func   __do_global_ctors
++
++__do_global_ctors:
++	mov     #__ctors_start, r11
++	mov     #__ctors_end,   r10
++.L__ctors_loop:
++	WDTIMER_KICK
++	call	@r11+	; call constructor
++	cmp     r10, r11
++	jne     .L__ctors_loop
++
++	.endfunc
++#endif
++    
++#if defined(L_dtors430)
++/*****************************************************************
++ * Call destructor functions.
++ *
++ * No reference to this should be generated unless a function pointer
++ * is added to the .dtors section.  This means that the code will
++ * be absent from the executable unless at least one pointer is
++ * present, which also means we don't have to check for an empty
++ * function list.
++ *****************************************************************/
++	.section .fini6,"ax", at progbits
++	.global __do_global_dtors
++	.weak   __do_global_dtors
++    
++	.func   __do_global_dtors
++
++__do_global_dtors:
++	mov     #__dtors_start, r11
++	mov     #__dtors_end, r10
++.L__dtors_loop:
++	WDTIMER_KICK
++	call    @r11+
++	cmp     r10, r11
++	jne     .L__dtors_loop
++
++	.endfunc
++#endif
++
++#if defined(L_unexpected_)
++
++/*****************************************************************
++ * unexpected interrupt vector handler
++ * can be overwriten by user function with the same name:
++ *   void _unexpected_ __attribute__((interrupt)) { }
++ *
++ *****************************************************************/
++
++	.section .text.crt0, "ax", @progbits
++
++	.global	_unexpected_
++        .weak   _unexpected_
++
++        .p2align 1,0
++_unexpected_:
++        reti
++	
++#endif
+diff --git gcc-4.6.3.orig/gcc/config/msp430/crt0ivtbl.S gcc-4.6.3/gcc/config/msp430/crt0ivtbl.S
+new file mode 100644
+index 0000000..696f6aa
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/crt0ivtbl.S
+@@ -0,0 +1,102 @@
++/*  -*- Mode: Asm -*-  */
++
++	.section .text.crt0, "ax", @progbits
++	
++/***************************************************************
++ *	Interrupt Vectors:
++ *	WARNING!!! All vectors must be defined here!!!
++ *	User may not define its interrupt service routines!
++ ***************************************************************/
++	
++.macro  INITIALIZE_ISR_SLOT sn
++        .weak   __isr_\sn
++        .equ    __isr_\sn, __br_unexpected_
++        .word   __isr_\sn
++.endm
++
++.macro	DEFINE_IVTABLE _n
++	.global	__ivtbl_\_n
++	.type	__ivtbl_\_n, @object
++	.size	__ivtbl_\_n, 2*\_n
++__ivtbl_\_n:
++.endm	
++
++.text
++        .p2align 1,0
++__br_unexpected_:
++        br     #_unexpected_
++
++	.global	_unexpected_
++	.global	_reset_vector__
++        .section .vectors, "ax", @progbits
++	
++DEFINE_IVTABLE INTERRUPT_VECTOR_COUNT
++	
++	INITIALIZE_ISR_SLOT 0
++	INITIALIZE_ISR_SLOT 1
++	INITIALIZE_ISR_SLOT 2
++	INITIALIZE_ISR_SLOT 3
++	INITIALIZE_ISR_SLOT 4
++	INITIALIZE_ISR_SLOT 5
++	INITIALIZE_ISR_SLOT 6
++	INITIALIZE_ISR_SLOT 7
++	INITIALIZE_ISR_SLOT 8
++	INITIALIZE_ISR_SLOT 9
++	INITIALIZE_ISR_SLOT 10
++	INITIALIZE_ISR_SLOT 11
++	INITIALIZE_ISR_SLOT 12
++	INITIALIZE_ISR_SLOT 13
++	INITIALIZE_ISR_SLOT 14
++#if 16 < INTERRUPT_VECTOR_COUNT
++	INITIALIZE_ISR_SLOT 15
++	INITIALIZE_ISR_SLOT 16
++	INITIALIZE_ISR_SLOT 17
++	INITIALIZE_ISR_SLOT 18
++	INITIALIZE_ISR_SLOT 19
++	INITIALIZE_ISR_SLOT 20
++	INITIALIZE_ISR_SLOT 21
++	INITIALIZE_ISR_SLOT 22
++	INITIALIZE_ISR_SLOT 23
++	INITIALIZE_ISR_SLOT 24
++	INITIALIZE_ISR_SLOT 25
++	INITIALIZE_ISR_SLOT 26
++	INITIALIZE_ISR_SLOT 27
++	INITIALIZE_ISR_SLOT 28
++	INITIALIZE_ISR_SLOT 29
++	INITIALIZE_ISR_SLOT 30
++#endif /* 16 < INTERRUPT_VECTOR_COUNT */
++#if 32 < INTERRUPT_VECTOR_COUNT
++	INITIALIZE_ISR_SLOT 31
++	INITIALIZE_ISR_SLOT 32
++	INITIALIZE_ISR_SLOT 33
++	INITIALIZE_ISR_SLOT 34
++	INITIALIZE_ISR_SLOT 35
++	INITIALIZE_ISR_SLOT 36
++	INITIALIZE_ISR_SLOT 37
++	INITIALIZE_ISR_SLOT 38
++	INITIALIZE_ISR_SLOT 39
++	INITIALIZE_ISR_SLOT 40
++	INITIALIZE_ISR_SLOT 41
++	INITIALIZE_ISR_SLOT 42
++	INITIALIZE_ISR_SLOT 43
++	INITIALIZE_ISR_SLOT 44
++	INITIALIZE_ISR_SLOT 45
++	INITIALIZE_ISR_SLOT 46
++	INITIALIZE_ISR_SLOT 47
++	INITIALIZE_ISR_SLOT 48
++	INITIALIZE_ISR_SLOT 49
++	INITIALIZE_ISR_SLOT 50
++	INITIALIZE_ISR_SLOT 51
++	INITIALIZE_ISR_SLOT 52
++	INITIALIZE_ISR_SLOT 53
++	INITIALIZE_ISR_SLOT 54
++	INITIALIZE_ISR_SLOT 55
++	INITIALIZE_ISR_SLOT 56
++	INITIALIZE_ISR_SLOT 57
++	INITIALIZE_ISR_SLOT 58
++	INITIALIZE_ISR_SLOT 59
++	INITIALIZE_ISR_SLOT 60
++	INITIALIZE_ISR_SLOT 61
++	INITIALIZE_ISR_SLOT 62
++#endif /* 32 < INTERRUPT_VECTOR_COUNT */
++        .word _reset_vector__
+diff --git gcc-4.6.3.orig/gcc/config/msp430/libgcc.S gcc-4.6.3/gcc/config/msp430/libgcc.S
+new file mode 100644
+index 0000000..8d7bc44
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/libgcc.S
+@@ -0,0 +1,1489 @@
++/*  -*- Mode: Asm -*-  */
++
++/* Routines with __ext_ are extensions that differ from the
++ * similarly-named libgcc standard routine in either name or calling
++ * convention.
++ * 
++ * Routines with __xabi_ use an extended ABI where some input and
++ * output parameters are passed in registers that are normally
++ * reserved for caller-saved.  These routines are still responsible
++ * for preserving the values in any register that is not used for
++ * either an input or an output of the function.  __xabi_ routines are
++ * implicitly __ext_ routines. */
++
++
++/* Flag in __MSP430_CPU__ denoting CPUX instructions available */
++#define MSP430_CPU_MSP430X 0x0002
++
++/* Offset from r1 to first word of stack-pushed arguments. */
++#define	ARGP_OFFSET	2	
++
++	.section .text.libgcc, "ax", @progbits
++
++#if defined (L_cmpsi2)
++	
++	.global	__cmpsi2
++	.func	__cmpsi2
++__cmpsi2:
++	sub	r12, r14
++	subc	r13, r15
++	jge	.L_ge
++	mov	#0, r15		; a < b return 0
++	ret
++	
++.L_ge:
++	bis	r14, r15
++	tst	r15
++	jz	.L_eq
++
++	mov	#2, r15		; a > b return 2
++	ret
++.L_eq:
++	mov	#1, r15		; a == b return 1
++	ret
++.endfunc
++#endif
++
++#if defined (L_ucmpsi2)
++	
++	.global	__ucmpsi2
++	.func	__ucmpsi2
++__ucmpsi2:
++	sub	r12, r14
++	subc	r13, r15
++	jhs	.L_ge
++	mov	#0, r15		; a < b return 0
++	ret
++	
++.L_ge:
++	bis	r14, r15
++	tst	r15
++	jz	.L_eq
++
++	mov	#2, r15		; a > b return 2
++	ret
++.L_eq:
++	mov	#1, r15		; a == b return 1
++	ret
++.endfunc
++#endif
++
++#if defined (L_cmpdi2)
++	.global	__cmpdi2
++	.func	__cmpdi2
++__cmpdi2:
++	sub	ARGP_OFFSET(r1), r12
++	subc	2+ARGP_OFFSET(r1), r13
++	subc	4+ARGP_OFFSET(r1), r14
++	subc	6+ARGP_OFFSET(r1), r15
++	jge	.L_ge
++	mov	#0, r15		; a < b return 0
++	ret
++	
++.L_ge:
++	bis	r12, r15
++	bis	r13, r15
++	bis	r14, r15
++	tst	r15
++	jz	.L_eq
++
++	mov	#2, r15		; a > b return 2
++	ret
++.L_eq:
++	mov	#1, r15		; a == b return 1
++	ret
++.endfunc
++#endif
++
++#if defined (L_ucmpdi2)
++	
++	.global	__ucmpdi2
++	.func	__ucmpdi2
++__ucmpdi2:
++	sub	ARGP_OFFSET(r1), r12
++	subc	2+ARGP_OFFSET(r1), r13
++	subc	4+ARGP_OFFSET(r1), r14
++	subc	6+ARGP_OFFSET(r1), r15
++	jhs	.L_ge
++	mov	#0, r15		; a < b return 0
++	ret
++	
++.L_ge:
++	bis	r12, r15
++	bis	r13, r15
++	bis	r14, r15
++	tst	r15
++	jz	.L_eq
++
++	mov	#2, r15		; a > b return 2
++	ret
++.L_eq:
++	mov	#1, r15		; a == b return 1
++	ret
++.endfunc
++#endif
++
++
++/*******************************************************
++               Multiplication  8 x 8
++*******************************************************/
++#if defined (L_mulqi3)
++	.global	__mulqi3
++	.func	__mulqi3
++__mulqi3:
++	mov.b	r15, r13
++	clr	r15
++1:	tst.b	r14
++	jz	3f
++	rrc.b	r13
++	jnc	2f
++	add.b	r14, r15
++2:	rla.b	r14
++	tst.b	r13
++	jne	1b
++3:	ret
++	.endfunc
++#endif 	/* defined (L_mulqi3) */
++
++
++#if defined (L_mulqihi3)
++	.global	__mulqihi3
++	.func	__mulqihi3
++__mulqihi3:
++	sxt	r14
++	sxt	r15
++	br	#__mulhi3
++.endfunc
++#endif /* defined (L_mulqihi3) */
++
++#if defined (L_umulqihi3)
++	.global	__umulqihi3
++	.func	__umulqihi3
++__umulqihi3:
++	mov.b	r14, r14
++	mov.b	r15, r15
++	br	#__mulhi3
++	.endfunc
++#endif /* defined (L_umulqihi3) */
++
++/*******************************************************
++               Multiplication  16 x 16
++*******************************************************/
++#if defined (L_mulhi3)
++	.global	__mulhi3
++	.func	__mulhi3
++__mulhi3:
++	mov	r15, r13
++	clr	r15
++1:	tst	r14
++	jz	3f
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r13
++#else /* CPUX */
++	clrc
++	rrc	r13
++#endif /* CPUX */
++	jnc	2f
++	add	r14, r15
++2:	rla	r14
++	tst     r13
++	jne	1b
++3:	ret
++	.endfunc
++#endif /* defined (L_mulhi3) */
++
++#if defined (L_mulhisi3)
++	.global	__mulhisi3
++	.func	__mulhisi3
++__mulhisi3:
++	mov	r14, r12
++	mov	r15, r14
++	clr	r15
++	tst	r14
++	jge	1f
++	mov	#-1, r15
++1:	clr	r13
++	tst	r12
++	jge	2f
++	mov	#-1, r13
++2:	br	#__mulsi3
++	.endfunc
++#endif /* defined (L_mulhisi3) */
++
++#if defined (L_umulhisi3)
++	.global	__umulhisi3
++	.func	__umulhisi3
++__umulhisi3:
++	mov	r14, r12
++	mov	r15, r14
++	clr	r13
++	clr	r15
++	br	#__mulsi3
++	.endfunc
++#endif /* defined (L_umulhisi3) */
++
++#if defined (L_mulsi3)
++/*******************************************************
++               Multiplication  32 x 32
++*******************************************************/
++	.global	__mulsi3
++	.func	__mulsi3
++
++__mulsi3:
++	push	r11
++	push	r10
++	clr	r11
++	clr	r10
++	jmp	3f
++1:	; b >>= 1
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r13
++#else /* CPUX */
++	clrc
++	rrc	r13
++#endif /* CPUX */
++	rrc 	r12
++	jnc	2f
++	add	r14, r10	; res = res + a
++	addc	r15, r11
++2:	rla	r14
++	rlc	r15		; a <<= 1
++3:	tst	r12		; stop if b zero
++	jnz	1b
++	tst	r13
++	jnz	1b
++	mov	r10, r14
++	mov	r11, r15
++	pop	r10
++	pop	r11
++	ret
++	.endfunc
++
++#endif
++	
++#if defined (L_mulsidi3)
++	.global	__mulsidi3
++	.func	__mulsidi3
++
++__mulsidi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#8, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++	push	r7
++	push	r6
++	push	r5
++	push	r4
++#endif /* CPUX */
++
++	mov	r12, r8
++	mov	r13, r9
++	mov	#0, r10
++	tst	r9
++	jge	1f
++	mov	#-1, r10
++1:	mov	r10, r11
++	mov	r14, r12
++	mov	r15, r13
++	mov	#0, r14
++	tst	r13
++	jge	2f
++	mov	#-1, r14
++2:	mov	r14, r15
++	call	#__xabi_muldi3
++
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#8, r11
++#else /* CPUX */
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++	.endfunc
++#endif
++	
++#if defined (L_umulsidi3)
++	.global	__umulsidi3
++	.func	__umulsidi3
++
++__umulsidi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#8, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++	push	r7
++	push	r6
++	push	r5
++	push	r4
++#endif /* CPUX */
++
++	mov	r12, r8
++	mov	r13, r9
++	mov	#0, r10
++	mov	#0, r11
++	mov	r14, r12
++	mov	r15, r13
++	mov	#0, r14
++	mov	#0, r15
++	
++	call	#__xabi_muldi3
++
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#8, r11
++#else /* CPUX */
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++	.endfunc
++
++#endif
++
++#if defined (L_muldi3)
++/*******************************************************
++               Multiplication 64 x 64
++*******************************************************/
++	
++	.global	__muldi3
++	.func	__muldi3
++
++__muldi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#8, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++	push	r7
++	push	r6
++	push	r5
++	push	r4
++#endif /* CPUX */
++	
++	mov	16+ARGP_OFFSET(r1), r8 ; load b
++	mov	2+16+ARGP_OFFSET(r1), r9
++	mov	4+16+ARGP_OFFSET(r1), r10
++	mov	6+16+ARGP_OFFSET(r1), r11
++	call	#__xabi_muldi3
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#8, r11
++#else /* CPUX */
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++	.endfunc
++	
++	.global	__xabi_muldi3
++	.func	__xabi_muldi3
++__xabi_muldi3:
++	clr	r4		; clear result
++	clr	r5
++	clr	r6
++	clr	r7
++	jmp	3f
++1:	; b >>= 1
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r11
++#else /* CPUX */
++	clrc
++	rrc	r11
++#endif /* CPUX */
++	rrc 	r10
++	rrc 	r9
++	rrc 	r8
++	jnc	2f
++	add	r12, r4	; res = res + a
++	addc	r13, r5
++	addc	r14, r6
++	addc	r15, r7
++2:	rla	r12		; a <<= 1
++	rlc	r13
++	rlc	r14
++	rlc	r15
++3:	tst	r8		; stop if b zero
++	jnz	1b
++	tst	r9
++	jnz	1b
++	tst	r10
++	jnz	1b
++	tst	r11
++	jnz	1b
++	mov	r4, r12
++	mov	r5, r13
++	mov	r6, r14
++	mov	r7, r15
++
++	ret
++#endif
++	
++/* Unsigned division uses a non-performing restoring division
++ * algorithm.  Signed division uses the same routine after converting
++ * numerator and divisor if negative, then adjusts the sign of the
++ * remainder to match the origin sign of the numerator, and negates
++ * the quotient if exactly one of the numerator and divisor was
++ * negative.
++ *
++ * The extension routines that do the real work place the return
++ * values under the assumption that the quotient is the most used
++ * value.  This way the library routines for __divm3 can often alias
++ * directly to the extension routine. */
++
++#if defined (L_udivmod8)
++	
++	.global	__udivqi3
++	.type	__udivqi3, @function
++	.global	__ext_udivmod8
++	.func	__ext_udivmod8
++__ext_udivmod8:
++__udivqi3:
++	;; r15 = N in ; Q out
++	;; r14 = D in ; A = R out
++	;; r13 = M
++	;; r12 = count
++	mov.b	#8, r12		; set count
++	mov.b	r14, r13	; M := D
++	clr	r14		; A := 0
++1:	rla.b	r15		; left shift Q ...
++	rlc.b	r14		; ... into left shift A
++	cmp.b	r13, r14	; M > A?
++	jlo	2f		; yes, skip adjustment
++	sub.b	r13, r14	; no, A := A - M
++	bis.b	#1, r15		; set Qi
++2:	dec	r12
++	jnz	1b
++	ret
++	.endfunc
++
++	.global	__umodqi3
++	.type	__umodqi3, @function
++__umodqi3:
++	call	#__ext_udivmod8
++	mov	r14, r15
++	ret
++	
++#endif /* _udivmod8 */	
++
++#if defined (L_divmod8)
++
++	.global	__divqi3
++	.type	__divqi3, @function
++	.global	__ext_divmod8
++	.func	__ext_divmod8
++__ext_divmod8:
++__divqi3:
++	;; r15 = N in ; Q out
++	;; r14 = D in ; R out
++	;; r13 = work, bit 0x02 to invert R, bit 0x01 to invert Q
++	clr	r13
++	tst.b	r15		; invert N?
++	jge	1f
++	mov	#3, r13
++	inv.b	r15
++	inc.b	r15
++1:	tst.b	r14		; invert D?
++	jge	2f
++	xor.b	#1, r13
++	inv.b	r14
++	inc.b	r14
++2:	push	r13		; save flags
++	call	#__ext_udivmod8 ; unsigned divmod
++	pop	r13		;restore flags
++	bit.b	#2, r13		; neg rem?
++	jz	3f
++	inv.b	r14
++	inc.b	r14
++3:	bit.b	#1, r13		; neg quot?
++	jz	4f
++	inv.b	r15
++	inc.b	r15
++4:	ret
++	.endfunc
++
++	.global	__modqi3
++	.type	__modqi3, @function
++__modqi3:
++	call	#__ext_divmod8
++	mov	r14, r15
++	ret
++
++#endif /* _divmod8 */	
++
++#if defined (L_udivmod16)
++	
++	.global	__udivhi3
++	.type	__udivhi3, @function
++	.global	__ext_udivmod16
++	.func	__ext_udivmod16
++__ext_udivmod16:
++__udivhi3:
++	;; r15 = N in ; Q out
++	;; r14 = D in ; A = R out
++	;; r13 = M
++	;; r12 = count
++	mov.b	#16, r12	; set count
++	mov	r14, r13	; M := D
++	clr	r14		; A := 0
++1:	rla	r15		; left shift Q ...
++	rlc	r14		; ... into left shift A
++	cmp	r13, r14	; M < A?
++	jlo	2f		; yes, skip adjustment
++	sub	r13, r14	; no, A := A - M
++	bis	#1, r15		; set Qi
++2:	dec	r12
++	jnz	1b
++	ret
++	.endfunc
++
++	.global	__umodhi3
++	.type	__umodhi3, @function
++__umodhi3:
++	call	#__ext_udivmod16
++	mov	r14, r15
++	ret
++	
++#endif /* _udivmod16 */	
++
++#if defined (L_divmod16)
++
++	.global	__divhi3
++	.type	__divhi3, @function
++	.global	__ext_divmod16
++	.func	__ext_divmod16
++__ext_divmod16:
++__divhi3:
++	;; r15 = N in ; Q out
++	;; r14 = D in ; R out
++	;; r13 = work, bit 0x02 to invert R, bit 0x01 to invert Q
++	clr	r13
++	tst	r15		; invert N?
++	jge	1f
++	mov	#3, r13
++	inv	r15
++	inc	r15
++1:	tst	r14		; invert D?
++	jge	2f
++	xor.b	#1, r13
++	inv	r14
++	inc	r14
++2:	push	r13		; save flags
++	call	#__ext_udivmod16 ; unsigned divmod
++	pop	r13		; restore flags
++	bit.b	#2, r13		; neg rem?
++	jz	3f
++	inv	r14
++	inc	r14
++3:	bit.b	#1, r13		; neg quot?
++	jz	4f
++	inv	r15
++	inc	r15
++4:	ret
++	.endfunc
++
++	.global	__modhi3
++	.type	__modhi3, @function
++__modhi3:
++	call	#__ext_divmod16
++	mov	r14, r15
++	ret
++
++#endif /* _divmod16 */	
++
++#if defined (L_udivmod32)
++	
++	.global	__udivsi3
++	.type	__udivsi3, @function
++	.global	__ext_udivmod32
++	.func	__ext_udivmod32
++	
++__ext_udivmod32:
++__udivsi3:
++	;; r14:r15 = N in ; Q out
++	;; r12:r13 = D in ; A = R out
++	;; r10:r11 = M
++	;; r9 = count
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#3, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++#endif /* CPUX */
++	mov.b	#32, r9		; set count
++	mov	r12, r10	; M := D
++	mov	r13, r11
++	clr	r12		; A := 0
++	clr	r13
++1:	rla	r14		; left shift Q ...
++	rlc	r15
++	rlc	r12		; ... into left shift A
++	rlc	r13
++	cmp	r11, r13	; M > A?
++	jlo	3f		; yes at high word, skip adjustment
++	jne	2f		; no, need adjustment
++	cmp	r10, r12	; high word M = A; low word M < A?
++	jlo	3f		; yes, skip adjustment
++2:	sub	r10, r12	; no, A := A - M
++	subc	r11, r13
++	bis	#1, r14		; set Qi
++3:	dec	r9
++	jnz	1b
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#3, r11
++#else /* CPUX */
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++	.endfunc
++
++	.global	__umodsi3
++	.type	__umodsi3, @function
++__umodsi3:
++	call	#__ext_udivmod32
++	mov	r12, r14
++	mov	r13, r15
++	ret
++	
++#endif /* _udivmod32 */	
++	
++#if defined (L_divmod32)
++
++	.global	__divsi3
++	.type	__divsi3, @function
++	.global	__ext_divmod32
++	.func	__ext_divmod32
++	
++__ext_divmod32:
++__divsi3:
++	;; r14:r15 = N in ; Q out
++	;; r12:r13 = D in ; R out
++	;; r11 = work, bit 0x02 to invert R, bit 0x01 to invert Q
++	push	r11
++	clr	r11
++	tst	r15		; invert N?
++	jge	1f
++	mov	#3, r11
++	inv	r14
++	inv	r15
++	inc	r14
++	adc	r15
++1:	tst	r13		; invert D?
++	jge	2f
++	xor.b	#1, r11
++	inv	r12
++	inv	r13
++	inc	r12
++	adc	r13
++2:	call	#__ext_udivmod32 ; unsigned divmod
++	bit.b	#2, r11		; neg rem?
++	jz	3f
++	inv	r12
++	inv	r13
++	inc	r12
++	adc	r13
++3:	bit.b	#1, r11		; neg quot?
++	jz	4f
++	inv	r14
++	inv	r15
++	inc	r14
++	adc	r15
++4:	pop	r11
++	ret
++	.endfunc
++
++	.global	__modsi3
++	.type	__modsi3, @function
++__modsi3:
++	call	#__ext_divmod32
++	mov	r12, r14
++	mov	r13, r15
++	ret
++
++#endif /* _divmod32 */	
++
++#if defined (L_udivmod64)
++	
++	.global	__xabi_udivmod64
++	.func	__xabi_udivmod64
++__xabi_udivmod64:
++	;; r12:r15 = N in ; Q out
++	;; r8:r11 = D in ; A = R out
++	;; r4:r7 = M
++	;; @r1 = count
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#4, r7
++#else /* CPUX */
++	push	r7
++	push	r6
++	push	r5
++	push	r4
++#endif /* CPUX */
++	push	#64
++	mov	r8, r4		; M := D
++	mov	r9, r5
++	mov	r10, r6
++	mov	r11, r7
++	clr	r8		; A := 0
++	clr	r9
++	clr	r10
++	clr	r11
++1:	rla	r12		; left shift Q ...
++	rlc	r13
++	rlc	r14
++	rlc	r15
++	rlc	r8		; ... into left shift A
++	rlc	r9
++	rlc	r10
++	rlc	r11
++	cmp	r7, r11		; M > A?
++	jlo	3f		; yes at hhi word, skip adjustment
++	jne	2f		; no, need adjustment
++	cmp	r6, r10		; hhi word M = A; hlo word M < A?
++	jlo	3f		; yes, skip adjustment
++	jne	2f		; no, need adjustment
++	cmp	r5, r9		; hlo word M = A; lhi word M < A?
++	jlo	3f		; yes, skip adjustment
++	jne	2f		; no, need adjustment
++	cmp	r4, r8		; lhi word M = A; llo word M < A?
++	jlo	3f		; yes, skip adjustment
++2:	sub	r4, r8		; no, A := A - M
++	subc	r5, r9
++	subc	r6, r10
++	subc	r7, r11
++	bis	#1, r12		; set Qi
++3:	dec	@r1
++	jnz	1b
++	add	#2, r1
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#4, r7
++#else /* CPUX */
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++#endif /* CPUX */
++	ret
++	.endfunc
++	
++	.global	__udivdi3
++	.type	__udivdi3, @function
++__udivdi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#4, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++#endif /* CPUX */
++	mov	8+ARGP_OFFSET(r1), r8
++	mov	2+8+ARGP_OFFSET(r1), r9
++	mov	4+8+ARGP_OFFSET(r1), r10
++	mov	6+8+ARGP_OFFSET(r1), r11
++	
++	call	#__xabi_udivmod64
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#4, r11
++#else /* CPUX */
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++	
++	.global	__umoddi3
++	.type	__umoddi3, @function
++__umoddi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#4, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++#endif /* CPUX */
++	mov	8+ARGP_OFFSET(r1), r8
++	mov	2+8+ARGP_OFFSET(r1), r9
++	mov	4+8+ARGP_OFFSET(r1), r10
++	mov	6+8+ARGP_OFFSET(r1), r11
++	
++	call	#__xabi_udivmod64
++	mov	r8, r12
++	mov	r9, r13
++	mov	r10, r14
++	mov	r11, r15
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#4, r11
++#else /* CPUX */
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++
++	.global	__udivmoddi4
++	.func	__udivmoddi4
++__udivmoddi4:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#5, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++	push	r7
++#endif /* CPUX */
++	mov	10+ARGP_OFFSET(r1), r8
++	mov	2+10+ARGP_OFFSET(r1), r9
++	mov	4+10+ARGP_OFFSET(r1), r10
++	mov	6+10+ARGP_OFFSET(r1), r11
++	
++	call	#__xabi_udivmod64
++
++	mov	8+10+ARGP_OFFSET(r1), r7
++	mov	r8, @r7
++	mov	r9, 2(r7)
++	mov	r10, 4(r7)
++	mov	r11, 6(r7)
++
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#5, r11
++#else /* CPUX */
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++
++#endif /* _udivmod64 */	
++
++#if defined (L_divmod64)
++
++	.global	__xabi_divmod64
++	.func	__xabi_divmod64
++	
++__xabi_divmod64:
++	;; r12:r15 = N in ; Q out
++	;; r8:r11 = D in ;R out
++	;; r7 = work, bit 0x02 to invert R, bit 0x01 to invert Q
++	push	r7
++	clr	r7
++	tst	r15		; invert N?
++	jge	1f
++	mov	#3, r7
++	inv	r12
++	inv	r13
++	inv	r14
++	inv	r15
++	inc	r12
++	adc	r13
++	adc	r14
++	adc	r15
++1:	tst	r11		; invert D?
++	jge	2f
++	xor.b	#1, r7
++	inv	r8
++	inv	r9
++	inv	r10
++	inv	r11
++	inc	r8
++	adc	r9
++	adc	r10
++	adc	r11
++2:	call	#__xabi_udivmod64 ; unsigned divmod
++	bit.b	#2, r7		; neg rem?
++	jz	3f
++	inv	r8
++	inv	r9
++	inv	r10
++	inv	r11
++	inc	r8
++	adc	r9
++	adc	r10
++	adc	r11
++3:	bit.b	#1, r7		; neg quot?
++	jz	4f
++	inv	r12
++	inv	r13
++	inv	r14
++	inv	r15
++	inc	r12
++	adc	r13
++	adc	r14
++	adc	r15
++4:	pop	r7
++	ret
++	.endfunc
++
++	.global	__divdi3
++	.type	__divdi3, @function
++__divdi3:	
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#4, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++#endif /* CPUX */
++	mov	8+ARGP_OFFSET(r1), r8
++	mov	2+8+ARGP_OFFSET(r1), r9
++	mov	4+8+ARGP_OFFSET(r1), r10
++	mov	6+8+ARGP_OFFSET(r1), r11
++	
++	call	#__xabi_divmod64
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#4, r11
++#else /* CPUX */
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++
++	.global	__moddi3
++	.type	__moddi3, @function
++__moddi3:
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	pushm	#4, r11
++#else /* CPUX */
++	push	r11
++	push	r10
++	push	r9
++	push	r8
++#endif /* CPUX */
++	mov	8+ARGP_OFFSET(r1), r8
++	mov	2+8+ARGP_OFFSET(r1), r9
++	mov	4+8+ARGP_OFFSET(r1), r10
++	mov	6+8+ARGP_OFFSET(r1), r11
++	
++	call	#__xabi_divmod64
++	mov	r8, r12
++	mov	r9, r13
++	mov	r10, r14
++	mov	r11, r15
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	popm	#4, r11
++#else /* CPUX */
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++#endif /* CPUX */
++	ret
++
++#endif /* _divmod64 */	
++
++/********* PROLOGE / EPILOGUE aux routines ******************/
++#if defined (L__prologue_saver)
++	.global __prologue_saver
++	.func	__prologue_saver
++__prologue_saver:
++	mov	r4, 0(r1)
++	mov	r5, 2(r1)
++	mov	r6, 4(r1)
++	mov	r7, 6(r1)
++	mov	r8, 8(r1)
++	mov	r9, 10(r1)
++	mov	r10, 12(r1)
++	mov	r11, 14(r1)
++	br	r12	; now jump to the function body
++.endfunc
++
++#endif
++
++
++#if defined (L__epilogue_restorer)
++	.global __epilogue_restorer
++	.func	__epilogue_restorer
++__epilogue_restorer:
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++	ret
++.endfunc
++
++#endif
++
++
++#if defined (L__epilogue_restorer_intr)
++	.global __epilogue_restorer_intr
++	.func	__epilogue_restorer_intr
++__epilogue_restorer_intr:
++	pop	r4
++	pop	r5
++	pop	r6
++	pop	r7
++	pop	r8
++	pop	r9
++	pop	r10
++	pop	r11
++	pop	r12
++	pop	r13
++	pop	r14
++	pop	r15
++	reti
++.endfunc
++
++#endif
++
++/*
++ ******************
++ * Shift operations 
++ ******************
++ */
++
++#if defined(L_ashlqi3)
++; clobber r14, return r15 
++	.global	__ashlqi3
++	.type	__ashlqi3, at function
++__ashlqi3:
++	and.b	#7, r14
++	jz	1f
++2:	rla.b	r15
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_ashlqi3 */
++
++#if defined(L_ashrqi3)
++; clobber r14, return r15 
++	.global	__ashrqi3
++	.type	__ashrqi3, at function
++__ashrqi3:
++	and.b	#7, r14
++	jz	1f
++2:	rra.b	r15
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_ashrqi3 */
++
++#if defined(L_lshrqi3)
++; clobber r14, return r15 
++	.global	__lshrqi3
++	.type	__lshrqi3, at function
++__lshrqi3:
++	and.b	#7, r14
++	jz	1f
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	and.b	#-1, r15
++2:	rrum	#1, r15
++#else /* CPUX */
++2:	clrc
++	rrc.b	r15
++#endif /* CPUX */
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_lshrqi3 */
++
++#if defined(L_ashlhi3)
++; clobber r14, return r15 
++	.global	__ashlhi3
++	.type	__ashlhi3, at function
++__ashlhi3:
++	and.b	#0x0f, r14
++	jz	1f
++	cmp.b	#8, r14
++	jlo	2f
++	and.b	#-1, r15
++	swpb	r15
++	sub.b	#8, r14
++	jz	1f
++2:	rla	r15
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_ashlhi3 */
++
++#if defined(L_ashrhi3)
++; clobber r14, return r15 
++	.global	__ashrhi3
++	.type	__ashrhi3, at function
++__ashrhi3:
++	and.b	#0x0f, r14
++	jz	1f
++	cmp.b	#8, r14
++	jlo	2f
++	swpb	r15
++	sxt	r15
++	sub.b	#8, r14
++	jz	1f
++2:	rra	r15
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_ashrhi3 */
++
++#if defined(L_lshrhi3)
++; clobber r14, return r15 
++	.global	__lshrhi3
++	.type	__lshrhi3, at function
++__lshrhi3:
++	and.b	#0x0f, r14
++	jz	1f
++	cmp.b	#8, r14
++	jlo	2f
++	swpb	r15
++	and.b	#-1, r15
++	sub.b	#8, r14
++	jz	1f
++2:	
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r15
++#else /* CPUX */
++	clrc
++	rrc	r15
++#endif /* CPUX */
++	dec.b	r14
++	jnz	2b
++1:	ret
++#endif /* L_lshrhi3 */
++
++#if defined(L_ashlsi3)
++; clobber r13, return r14+r15 
++	.global	__ashlsi3
++	.type	__ashlsi3, at function
++__ashlsi3:
++	and.b	#0x1f, r13
++	jz	1f
++	;; Move whole words, if appropriate
++	cmp.b	#16, r13
++	jlo	3f
++	mov	r14, r15
++	mov	r13, r14
++	sub.b	#16, r14
++	call	#__ashlhi3
++	clr	r14
++	jmp	1f
++3:	cmp.b	#8, r13
++	jlo	2f
++	xor.b	r14, r15
++	xor	r14, r15
++	swpb	r15
++	and.b	#-1, r14
++	swpb	r14
++	sub.b	#8, r13
++	jz	1f
++2:	rla	r14
++	rlc	r15
++	dec.b	r13
++	jnz	2b
++1:	ret
++#endif /* L_ashlsi3 */
++
++#if defined(L_ashrsi3)
++; clobber r12+r13, return r14+r15 
++	.global	__ashrsi3
++	.type	__ashrsi3, at function
++__ashrsi3:
++	and.b	#0x1f, r13
++	jz	1f
++	;; Move whole words, if appropriate
++	cmp.b	#16, r13
++	jlo	3f
++	clr	r12		; r12 is sign extension word, unmodified by __ashrhi3
++	tst	r15
++	jge	4f
++	mov	#-1, r12
++4:	mov	r13, r14
++	sub.b	#16, r14
++	call	#__ashrhi3
++	mov	r15, r14
++	mov	r12, r15
++	jmp	1f
++3:	cmp.b	#8, r13
++	jlo	2f
++	swpb	r14
++	swpb	r15
++	xor.b	r15, r14
++	xor	r15, r14
++	sxt	r15
++	sub.b	#8, r13
++	jz	1f
++2:	rra	r15
++	rrc	r14
++	dec.b	r13
++	jnz	2b
++1:	ret
++#endif /* L_ashrsi3 */
++
++#if defined(L_lshrhi3)
++; clobber r13, return r14+r15 
++	.global	__lshrsi3
++	.type	__lshrsi3, at function
++__lshrsi3:
++	and.b	#0x1f, r13
++	jz	1f
++	;; Move whole words, if appropriate
++	cmp.b	#16, r13
++	jlo	3f
++	mov	r13, r14
++	sub.b	#16, r14
++	call	#__lshrhi3
++	mov	r15, r14
++	clr	r15
++	jmp	1f
++3:	cmp.b	#8, r13
++	jlo	2f
++	swpb	r14
++	swpb	r15
++	xor.b	r15, r14
++	xor	r15, r14
++	and.b	#-1, r15
++	sub.b	#8, r13
++	jz	1f
++2:	
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r15
++#else /* CPUX */
++	clrc
++	rrc	r15
++#endif /* CPUX */
++	rrc	r14
++	dec.b	r13
++	jnz	2b
++1:	ret
++#endif /* L_lshrsi3 */
++
++#if defined(L_ashldi3)
++; clobber r11, return r12-r15  
++	.global	__ashldi3
++	.type	__ashldi3, at function
++__ashldi3:
++	push	r11
++	mov.b	2+ARGP_OFFSET(r1), r11
++	and.b	#0x3f, r11
++	jz	1f
++	cmp	#48, r11
++	jlo	3f
++	mov	r12, r15
++	mov	r11, r14
++	sub.b	#48, r14
++	call	#__ashlhi3
++	clr	r12
++	clr	r13
++	clr	r14
++	jmp	1f
++3:	cmp	#32, r11
++	jlo	4f
++	mov	r13, r15
++	mov	r12, r14
++	mov	r11, r13
++	sub.b	#32, r13
++	call	#__ashlsi3
++	clr	r12
++	clr	r13
++	jmp	1f
++4:	cmp	#16, r11
++	jlo	5f
++	mov	r14, r15
++	mov	r13, r14
++	mov	r12, r13
++	clr	r12
++	jz	1f
++	sub	#16, r11
++5:	cmp.b	#8, r11
++	jlo	2f
++	xor.b	r14, r15
++	xor	r14, r15
++	swpb	r15
++	xor.b	r13, r14
++	xor	r13, r14
++	swpb	r14
++	xor.b	r12, r13
++	xor	r12, r13
++	swpb	r13
++	and.b	#-1, r12
++	swpb	r12
++	sub.b	#8, r11
++	jz	1f
++2:	rla	r12
++	rlc	r13
++	rlc	r14
++	rlc	r15
++	dec.b	r11
++	jnz	2b
++1:	pop	r11
++	ret
++#endif /* L_ashldi3 */
++
++#if defined(L_ashrdi3)
++; clobber r11, return r12-r15  
++	.global	__ashrdi3
++	.type	__ashrdi3, at function
++__ashrdi3:
++	push	r11
++	mov.b	2+ARGP_OFFSET(r1), r11
++	and.b	#0x3f, r11
++	jz	1f
++	cmp	#48, r11
++	jlo	4f
++	clr	r13		; r13 is sign extension word, unmodified by __ashrhi3
++	tst	r15
++	jge	3f
++	mov	#-1, r13
++3:	mov	r11, r14
++	sub.b	#48, r14
++	call	#__ashrhi3
++	mov	r15, r12
++	mov	r13, r14
++	mov	r13, r15
++	jmp	1f
++4:	cmp	#32, r11
++	jlo	6f
++	push	r10		; r12+r13 clobbered by __ashrsi3
++	clr	r10
++	tst	r15
++	jge	5f
++	mov	#-1, r10
++5:	mov	r11, r13
++	sub	#32, r13
++	call	#__ashrsi3
++	mov	r14, r12
++	mov	r15, r13
++	mov	r10, r14
++	mov	r10, r15
++	pop	r10
++	jmp	1f
++6:	cmp	#16, r11
++	jlo	8f
++	mov	r13, r12
++	mov	r14, r13
++	mov	r15, r14
++	clr	r15
++	tst	r14
++	jge	7f
++	mov	#-1, r15
++7:	sub	#16, r11
++	jz	1f
++8:	cmp	#8, r11
++	jlo	2f
++	swpb	r12
++	swpb	r13
++	xor.b	r13, r12
++	xor	r13, r12
++	swpb	r14
++	xor.b	r14, r13
++	xor	r14, r13
++	swpb	r15
++	xor.b	r15, r14
++	xor	r15, r14
++	sxt	r15
++	sub.b	#8, r11
++	jz	1f
++2:	rra	r15
++	rrc	r14
++	rrc	r13
++	rrc	r12
++	dec.b	r11
++	jnz	2b
++1:	pop	r11
++	ret
++#endif /* L_ashrdi3 */
++
++#if defined(L_lshrdi3)
++; clobber r11, return r12-r15  
++	.global	__lshrdi3
++	.type	__lshrdi3, at function
++__lshrdi3:
++	push	r11
++	mov.b	2+ARGP_OFFSET(r1), r11
++	and.b	#0x3f, r11
++	jz	1f
++	cmp	#48, r11
++	jlo	3f
++	mov	r11, r14
++	sub.b	#48, r14
++	call	#__lshrhi3
++	mov	r15, r12
++	clr	r13
++	clr	r14
++	clr	r15
++	jmp	1f
++3:	cmp	#32, r11
++	jlo	4f
++	mov	r11, r13
++	sub	#32, r13
++	call	#__lshrsi3
++	mov	r14, r12
++	mov	r15, r13
++	clr	r14
++	clr	r15
++	jmp	1f
++4:	cmp	#16, r11
++	jlo	5f
++	mov	r13, r12
++	mov	r14, r13
++	mov	r15, r14
++	clr	r15
++	sub	#16, r11
++	jz	1f
++5:	cmp	#8, r11
++	jlo	2f
++	swpb	r12
++	swpb	r13
++	xor.b	r13, r12
++	xor	r13, r12
++	swpb	r14
++	xor.b	r14, r13
++	xor	r14, r13
++	swpb	r15
++	xor.b	r15, r14
++	xor	r15, r14
++	and.b	#-1, r15
++	sub.b	#8, r11
++	jz	1f
++2:	
++#if __MSP430_CPU__ & MSP430_CPU_MSP430X
++	rrum	#1, r15
++#else /* CPUX */
++	clrc
++	rrc	r15
++#endif /* CPUX */
++	rrc	r14
++	rrc	r13
++	rrc	r12
++	dec.b	r11
++	jnz	2b
++1:	pop	r11
++	ret
++#endif /* L_lshldi3 */
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430-builtins.c gcc-4.6.3/gcc/config/msp430/msp430-builtins.c
+new file mode 100644
+index 0000000..ca76762
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430-builtins.c
+@@ -0,0 +1,444 @@
++/* This work is partially financed by the European Commission under the
++* Framework 6 Information Society Technologies Project
++* "Wirelessly Accessible Sensor Populations (WASP)".
++*/
++
++/*
++GCC 4.x port by Ivan Shcherbakov <mspgcc at sysprogs.org>
++*/
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "insn-attr.h"
++#include "flags.h"
++#include "reload.h"
++#include "tree.h"
++#include "output.h"
++#include "expr.h"
++#include "toplev.h"
++#include "obstack.h"
++#include "function.h"
++#include "recog.h"
++#include "tm_p.h"
++#include "target.h"
++#include "target-def.h"
++#include "insn-codes.h"
++#include "ggc.h"
++#include "langhooks.h"
++#include "rtl-error.h"
++
++/* The following functions are defined in this file and used by msp430.c */
++void msp430_init_builtins (void);
++rtx msp430_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
++
++enum msp430_builtins
++{
++  MSP430_BUILTIN_NOP,
++  MSP430_BUILTIN_DINT,
++  MSP430_BUILTIN_EINT,
++  MSP430_BUILTIN_READ_STATUS_REGISTER,
++  MSP430_BUILTIN_WRITE_STATUS_REGISTER,
++  MSP430_BUILTIN_BIC_STATUS_REGISTER,
++  MSP430_BUILTIN_BIS_STATUS_REGISTER,
++  MSP430_BUILTIN_BIC_SR_IRQ,
++  MSP430_BUILTIN_BIS_SR_IRQ,
++  MSP430_BUILTIN_READ_STACK_POINTER,
++  MSP430_BUILTIN_WRITE_STACK_POINTER,
++  MSP430_BUILTIN_DELAY_CYCLES,
++  MSP430_BUILTIN_GET_INTERRUPT_STATE,
++  MSP430_BUILTIN_SET_INTERRUPT_STATE,
++  MSP430_BUILTIN_SWAP_BYTES,
++  MSP430_BUILTIN_GET_WATCHDOG_CLEAR_VALUE,
++  MSP430_BUILTIN_SET_WATCHDOG_CLEAR_VALUE,
++  MSP430_BUILTIN_WATCHDOG_CLEAR,
++  MSP430_BUILTIN_last_enum
++};
++
++void
++msp430_init_builtins (void)
++{
++  add_builtin_function ("__nop",
++			build_function_type_list (void_type_node, NULL_TREE),
++			MSP430_BUILTIN_NOP, BUILT_IN_MD, NULL, NULL_TREE);
++  add_builtin_function ("__dint",
++			build_function_type_list (void_type_node, NULL_TREE),
++			MSP430_BUILTIN_DINT, BUILT_IN_MD, NULL, NULL_TREE);
++  add_builtin_function ("__eint",
++			build_function_type_list (void_type_node, NULL_TREE),
++			MSP430_BUILTIN_EINT, BUILT_IN_MD, NULL, NULL_TREE);
++  add_builtin_function ("__read_status_register",
++			build_function_type_list (unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_READ_STATUS_REGISTER, BUILT_IN_MD,
++			NULL, NULL_TREE);
++  add_builtin_function ("__get_interrupt_state",
++			build_function_type_list (unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_GET_INTERRUPT_STATE, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__write_status_register",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_WRITE_STATUS_REGISTER, BUILT_IN_MD,
++			NULL, NULL_TREE);
++  add_builtin_function ("__bic_status_register",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_BIC_STATUS_REGISTER, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__bis_status_register",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_BIS_STATUS_REGISTER, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__set_interrupt_state",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_SET_INTERRUPT_STATE, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__bic_status_register_on_exit",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_BIC_SR_IRQ, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__bis_status_register_on_exit",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_BIS_SR_IRQ, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__read_stack_pointer",
++			build_function_type_list (ptr_type_node, NULL_TREE),
++			MSP430_BUILTIN_READ_STACK_POINTER, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__write_stack_pointer",
++			build_function_type_list (void_type_node,
++						  ptr_type_node, NULL_TREE),
++			MSP430_BUILTIN_WRITE_STACK_POINTER, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__delay_cycles",
++			build_function_type_list (void_type_node,
++						  long_unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__swap_bytes",
++			build_function_type_list (unsigned_type_node,
++						  unsigned_type_node,
++						  NULL_TREE),
++			MSP430_BUILTIN_SWAP_BYTES, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__get_watchdog_clear_value",
++			build_function_type_list (unsigned_type_node, NULL_TREE),
++			MSP430_BUILTIN_GET_WATCHDOG_CLEAR_VALUE, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__set_watchdog_clear_value",
++			build_function_type_list (void_type_node,
++						  unsigned_type_node, NULL_TREE),
++			MSP430_BUILTIN_SET_WATCHDOG_CLEAR_VALUE, BUILT_IN_MD, NULL,
++			NULL_TREE);
++  add_builtin_function ("__watchdog_clear",
++			build_function_type_list (void_type_node, NULL_TREE),
++			MSP430_BUILTIN_WATCHDOG_CLEAR, BUILT_IN_MD, NULL, NULL_TREE);
++}
++
++rtx
++msp430_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
++		       rtx subtarget ATTRIBUTE_UNUSED,
++		       enum machine_mode mode ATTRIBUTE_UNUSED,
++		       int ignore ATTRIBUTE_UNUSED)
++{
++  rtx arg = 0;
++  rtx retval = 0;
++  rtx deref_stack_sr = 0;
++  rtx insn = 0;
++  bool need_insn = true;
++  tree fndecl;
++  enum msp430_builtins builtin_code;
++  struct machine_function *mfp = cfun->machine;
++
++  fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
++  builtin_code = (enum msp430_builtins) DECL_FUNCTION_CODE (fndecl);
++
++  if (builtin_code == MSP430_BUILTIN_BIC_SR_IRQ
++      || builtin_code == MSP430_BUILTIN_BIS_SR_IRQ)
++    {
++      if (mfp->interrupt == NULL_TREE)
++	error
++	  ("__bi%c_status_register_on_exit invalid outside of function with interrupt attribute",
++	   (builtin_code == MSP430_BUILTIN_BIC_SR_IRQ) ? 'c' : 's');
++      /* If we used hard_frame_pointer_rtx here, which would be right,
++         we'd end up setting frame_pointer_required even if it isn't.
++         So use arg_pointer_rtx offset by the two words pushed by the
++         interrupt. */
++      deref_stack_sr =
++	gen_rtx_MEM (Pmode,
++		     plus_constant (arg_pointer_rtx, -2 * UNITS_PER_WORD));
++    }
++
++  switch (builtin_code)
++    {
++    default:
++      break;
++    case MSP430_BUILTIN_NOP:
++      insn = gen_nop ();
++      break;
++    case MSP430_BUILTIN_DINT:
++      emit_insn (gen_dint ());
++      insn = gen_nop ();
++      break;
++    case MSP430_BUILTIN_EINT:
++      insn = gen_eint ();
++      break;
++    case MSP430_BUILTIN_READ_STATUS_REGISTER:
++      retval = gen_reg_rtx (HImode);
++      insn = gen_read_status_register (retval);
++      break;
++    case MSP430_BUILTIN_WRITE_STATUS_REGISTER:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_write_status_register (arg);
++      break;
++    case MSP430_BUILTIN_GET_INTERRUPT_STATE:
++      retval = gen_reg_rtx (HImode);
++      insn = gen_get_interrupt_state (retval);
++      break;
++    case MSP430_BUILTIN_BIC_STATUS_REGISTER:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_bic_status_register (arg);
++      break;
++    case MSP430_BUILTIN_BIS_STATUS_REGISTER:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_bis_status_register (arg);
++      break;
++    case MSP430_BUILTIN_SET_INTERRUPT_STATE:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_set_interrupt_state (arg);
++      break;
++    case MSP430_BUILTIN_BIC_SR_IRQ:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_bic_status_register_on_exit (deref_stack_sr, arg);
++      break;
++    case MSP430_BUILTIN_BIS_SR_IRQ:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_bis_status_register_on_exit (deref_stack_sr, arg);
++      break;
++    case MSP430_BUILTIN_READ_STACK_POINTER:
++      retval = gen_reg_rtx (HImode);
++      insn = gen_read_stack_pointer (retval);
++      break;
++    case MSP430_BUILTIN_WRITE_STACK_POINTER:
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      insn = gen_write_stack_pointer (arg);
++      break;
++    case MSP430_BUILTIN_GET_WATCHDOG_CLEAR_VALUE:
++      retval = gen_reg_rtx (HImode);
++      if (msp430_disable_watchdog)
++	insn = gen_movhi (retval, constm1_rtx);
++      else
++	insn = gen_get_watchdog_clear_value (retval);
++      break;
++    case MSP430_BUILTIN_SET_WATCHDOG_CLEAR_VALUE:
++      if (msp430_disable_watchdog)
++	need_insn = false;
++      else
++	{
++	  arg =
++	    expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++			 EXPAND_NORMAL);
++	  insn = gen_set_watchdog_clear_value (arg);
++	}
++      break;
++    case MSP430_BUILTIN_WATCHDOG_CLEAR:
++      if (msp430_disable_watchdog)
++	need_insn = false;
++      else
++	insn = gen_watchdog_clear ();
++      break;
++    case MSP430_BUILTIN_DELAY_CYCLES:
++      {
++	tree cycles_arg = CALL_EXPR_ARG (exp, 0);
++	const enum machine_mode itercnt_mode = HImode;
++	const HOST_WIDE_INT itercnt_max =
++	  (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (itercnt_mode);
++	const int decr_cycles = 1;
++	const int jump_cycles = 2;
++	const int iter_overhead_cycles = decr_cycles + jump_cycles;
++	const int iter0_cycles = iter_overhead_cycles;
++	const int cg_init_cycles = 1;
++	const int noncg_init_cycles = 2;
++	const HOST_WIDE_INT iter1_cycles =
++	  itercnt_max * iter0_cycles + iter_overhead_cycles;
++	HOST_WIDE_INT cycles;
++	rtx iterreg0 = NULL_RTX;
++
++	need_insn = false;
++	if (!cst_and_fits_in_hwi (cycles_arg)
++	    || (0 > ((cycles = int_cst_value (cycles_arg)))))
++	  {
++	    error
++	      ("__delay_cycles argument must be non-negative integer constant");
++	    break;
++	  }
++	while (0 < cycles)
++	  {
++	    HOST_WIDE_INT itercnt1 = 0;
++	    HOST_WIDE_INT itercnt0;
++
++	    if (cycles >= iter_overhead_cycles)
++	      itercnt1 = (cycles - iter_overhead_cycles) / iter1_cycles;
++	    if (itercnt1 > 0)
++	      itercnt0 =
++		(cycles - itercnt1 * iter1_cycles -
++		 iter_overhead_cycles) / iter0_cycles;
++	    else
++	      itercnt0 = cycles / iter0_cycles;
++	    if (itercnt0 > itercnt_max)
++	      {
++		itercnt0 -= itercnt_max;
++		++itercnt1;
++	      }
++	    else if ((itercnt1 > 0) && (itercnt0 == 0))
++	      {
++		itercnt1 -= 1;
++		itercnt0 += itercnt_max;
++	      }
++	    gcc_assert (0 <= itercnt0 && itercnt0 <= itercnt_max);
++	    if (itercnt0 > 0)
++	      {
++		while (1)
++		  {
++		    unsigned HOST_WIDE_INT loop_cycles;
++		    int cycles_in_init;
++
++		    cycles_in_init =
++		      MSP430_CG_INT_P (trunc_int_for_mode
++				       (itercnt0,
++					itercnt_mode)) ? cg_init_cycles :
++		      noncg_init_cycles;
++		    loop_cycles = itercnt0 * iter0_cycles;
++		    if (itercnt1 > 0)
++		      {
++			loop_cycles +=
++			  itercnt1 * iter1_cycles + iter_overhead_cycles;
++			cycles_in_init +=
++			  MSP430_CG_INT_P (trunc_int_for_mode
++					   (1 + itercnt1,
++					    itercnt_mode)) ? cg_init_cycles :
++			  noncg_init_cycles;
++		      }
++		    if (loop_cycles + cycles_in_init <= (unsigned HOST_WIDE_INT) cycles)
++		      break;
++
++		    --itercnt0;
++		    if (itercnt0 == 0 && itercnt1 > 0)
++		      {
++			itercnt0 += itercnt_max;
++			--itercnt1;
++		      }
++		  }
++		if (itercnt0 > 0)
++		  {
++		    rtx loop_label = gen_label_rtx ();
++		    rtx loop_test;
++		    rtx iterreg1 = NULL_RTX;
++
++		    if (itercnt1 > 0)
++		      iterreg1 = gen_reg_rtx (itercnt_mode);
++		    if (iterreg0 == NULL_RTX)
++		      iterreg0 = gen_reg_rtx (itercnt_mode);
++
++		    if (iterreg1 != NULL_RTX)
++		      {
++			emit_insn (gen_delay_cycles_init
++				   (iterreg1,
++				    gen_int_mode (1 + itercnt1,
++						  itercnt_mode)));
++			cycles -=
++			  MSP430_CG_INT_P (trunc_int_for_mode
++					   (1 + itercnt1,
++					    itercnt_mode)) ? cg_init_cycles :
++			  noncg_init_cycles;
++		      }
++
++		    emit_insn (gen_delay_cycles_init
++			       (iterreg0,
++				gen_int_mode (itercnt0, itercnt_mode)));
++		    cycles -=
++		      MSP430_CG_INT_P (trunc_int_for_mode
++				       (itercnt0,
++					itercnt_mode)) ? cg_init_cycles :
++		      noncg_init_cycles;
++
++		    emit_label (loop_label);
++		    emit_insn (gen_delay_cycles_decr (iterreg0));
++		    loop_test = gen_rtx_NE (itercnt_mode, iterreg0, const0_rtx);
++		    gcc_assert (HImode == itercnt_mode);
++		    emit_jump_insn (gen_cbranchhi4 (loop_test, iterreg0, const0_rtx, loop_label));
++		    cycles -= itercnt0 * iter0_cycles;
++		    if (iterreg1 != NULL_RTX)
++		      {
++			emit_insn (gen_delay_cycles_decr (iterreg1));
++			loop_test = gen_rtx_NE (itercnt_mode, iterreg1, const0_rtx);
++			emit_jump_insn (gen_cbranchhi4 (loop_test, iterreg1, const0_rtx, loop_label));
++			cycles -=
++			  itercnt1 * iter1_cycles + iter_overhead_cycles;
++		      }
++		    /* In the areas between single (max 196608) and
++		     * double (min 196619) loops, the remainder may
++		     * warrant another single loop instead of a
++		     * sequence of nine nops. */
++		    gcc_assert (0 <= cycles);
++		    continue;
++		  }
++	      }
++	    while (cycles--)
++	      emit_insn (gen_nop ());
++	    break;
++	  }
++	break;
++      }
++    case MSP430_BUILTIN_SWAP_BYTES:
++      retval = gen_reg_rtx (HImode);
++      arg =
++	expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, VOIDmode,
++		     EXPAND_NORMAL);
++      emit_move_insn (retval, arg);
++      insn = gen_bswaphi1 (retval);
++      break;
++    }
++
++  if (insn)
++    emit_insn (insn);
++  else if (need_insn)
++    error ("Unhandled built-in function `%s'",
++	   IDENTIFIER_POINTER (DECL_NAME (fndecl)));
++
++  return retval;
++}
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430-c.c gcc-4.6.3/gcc/config/msp430/msp430-c.c
+new file mode 100644
+index 0000000..1c023c8
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430-c.c
+@@ -0,0 +1,62 @@
++/* C-family support for MSP430 back end.
++   
++Copyright (C) 2012 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC 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, or (at your option) any later
++version.
++
++GCC 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 GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tree.h"
++#include "tm.h"
++#include "tm_p.h"
++#include "target.h"
++#include "output.h"
++#include "c-family/c-common.h"
++#include "c-family/c-pragma.h"
++#include "intl.h"
++#include "diagnostic.h"
++
++#define GCC_BAD(gmsgid) \
++  do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
++#define GCC_BAD2(gmsgid, arg) \
++  do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
++
++void
++msp430_pr_vector (cpp_reader * reader ATTRIBUTE_UNUSED)
++{
++  enum cpp_ttype token;
++  bool need_close_paren = false;
++  tree x;
++  tree t;
++
++  if (pragma_lex (&t) != CPP_EQ)
++    GCC_BAD ("missing %<=%> after %<#pragma vector%> - ignored");
++  token = pragma_lex (&t);
++  if (token == CPP_OPEN_PAREN)
++    {
++      token = pragma_lex (&t);
++      need_close_paren = true;
++    }
++  if (token != CPP_NUMBER)
++    GCC_BAD ("malformed %<#pragma vector%> - ignored");
++  if (TREE_CODE (t) != INTEGER_CST)
++    GCC_BAD ("invalid constant in %<#pragma vector%> - ignored");
++  if (need_close_paren && pragma_lex (&x) != CPP_CLOSE_PAREN)
++    GCC_BAD ("malformed %<#pragma vector%> - ignored");
++  msp430_vector_offset_tree = t;
++}
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430-function.c gcc-4.6.3/gcc/config/msp430/msp430-function.c
+new file mode 100644
+index 0000000..684fd2a
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430-function.c
+@@ -0,0 +1,772 @@
++/* This work is partially financed by the European Commission under the
++* Framework 6 Information Society Technologies Project
++* "Wirelessly Accessible Sensor Populations (WASP)".
++*/
++
++/*
++GCC 4.x port by Ivan Shcherbakov <mspgcc at sysprogs.org>
++*/
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "insn-attr.h"
++#include "flags.h"
++#include "reload.h"
++#include "tree.h"
++#include "output.h"
++#include "expr.h"
++#include "toplev.h"
++#include "obstack.h"
++#include "function.h"
++#include "recog.h"
++#include "tm_p.h"
++#include "target.h"
++#include "target-def.h"
++#include "insn-codes.h"
++#include "ggc.h"
++#include "langhooks.h"
++#include "df.h"
++#include "intl.h"
++#include "rtl-error.h"
++
++#define STACK_ALIGN_SIZE(_v) (~1 & ((_v)+1))
++
++/* registers used for incoming funct arguments */
++static char arg_register_used[16];
++
++#define FIRST_CUM_REG 16
++static CUMULATIVE_ARGS *cum_incoming = 0;
++
++static int msp430_num_arg_regs (enum machine_mode mode, tree type);
++
++static const char *S_signal = "signal";
++static const char *S_interrupt = "interrupt";
++static const char *S_naked = "naked";
++static const char *S_task = "task";
++static const char *S_wakeup = "wakeup";
++static const char *S_critical = "critical";
++static const char *S_reentrant = "reentrant";
++static const char *S_saveprologue = "saveprologue";
++static const char *S_noint_hwmul = "noint_hwmul";
++static const char *S_hosted = "hosted";
++
++void msp430_function_end_prologue (FILE * file);
++void msp430_function_begin_epilogue (FILE * file);
++
++static inline void
++warn_attribute_requires (tree decl, const char *a1, const char *a2)
++{
++  warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
++	      _("%qs attribute ignored (requires %qs)"), a1, a2);
++}
++
++static inline void
++warn_attribute_incompatible (tree decl, const char *a1, const char *a2)
++{
++  warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
++	      _("%qs attribute ignored (incompatible with %qs)"), a1, a2);
++}
++
++GTY(()) tree msp430_vector_offset_tree;
++
++void
++msp430_set_current_function (tree decl)
++{
++  struct machine_function *mfp;
++  tree attributes;
++  tree naked;
++  tree interrupt;
++  tree task;
++  tree saveprologue;
++  tree noint_hwmul;
++  tree critical;
++  tree reentrant;
++  tree wakeup;
++  tree signal;
++  tree hosted;
++
++  if ((decl == NULL_TREE) || (!cfun) || (!cfun->machine)
++      || cfun->machine->initialized)
++    return;
++  gcc_assert ((cfun->decl == NULL_TREE) || (cfun->decl == decl));
++  attributes = DECL_ATTRIBUTES (decl);
++
++  mfp = cfun->machine;
++  signal = lookup_attribute (S_signal, attributes);
++  interrupt = lookup_attribute (S_interrupt, attributes);
++  naked = lookup_attribute (S_naked, attributes);
++  task = lookup_attribute (S_task, attributes);
++  wakeup = lookup_attribute (S_wakeup, attributes);
++  critical = lookup_attribute (S_critical, attributes);
++  reentrant = lookup_attribute (S_reentrant, attributes);
++  saveprologue = lookup_attribute (S_saveprologue, attributes);
++  noint_hwmul = lookup_attribute (S_noint_hwmul, attributes);
++  hosted = lookup_attribute (S_hosted, attributes);
++
++  /* Validate attribute parameters */
++  if (interrupt)
++    {
++      tree ia_args = TREE_VALUE (interrupt);
++      int vector_offset = -1;
++      tree t0;
++
++      t0 = msp430_vector_offset_tree;
++      msp430_vector_offset_tree = NULL_TREE;
++
++      /* New style no argument means unvectored ISR.  Old-style used
++       * 255 as the vector offset for this. */
++      if (NULL_TREE != ia_args)
++	{
++	  gcc_assert (TREE_CODE (ia_args) == TREE_LIST);
++	  t0 = TREE_VALUE (ia_args);
++	  gcc_assert (NULL_TREE == TREE_CHAIN (ia_args));
++	}
++      if (NULL_TREE != t0)
++	{
++	  if (TREE_CODE (t0) == INTEGER_CST)
++	    {
++	      vector_offset = TREE_INT_CST_LOW (t0);
++	      if (255 == vector_offset)
++		vector_offset = -1;
++	      else if ((0 > vector_offset) || (vector_offset & 1))
++		{
++		  error_at (DECL_SOURCE_LOCATION (decl),
++			    _("interrupt vector offset %d"
++			      " must be even and non-negative"),
++			    vector_offset);
++		  vector_offset = 0;
++		}
++	    }
++	  else if (TREE_CODE (t0) == IDENTIFIER_NODE)
++	    {
++	      error_at (DECL_SOURCE_LOCATION (decl),
++			_("interrupt vector offset %qE"
++			  " is not an integer constant"), t0);
++	      vector_offset = 0;
++	    }
++	  else
++	    {
++	      error_at (DECL_SOURCE_LOCATION (decl),
++			_
++			("interrupt vector offset must be an even non-negative integer constant"));
++	      vector_offset = 0;
++	    }
++	}
++      mfp->vector_offset = vector_offset;
++    }
++
++
++  /* check attribute compatibility */
++#define REJECT_INCOMPATIBLE(_a1,_a2) do {			\
++    if ((_a1) && (_a2))						\
++      {								\
++	warn_attribute_incompatible (decl, S_##_a1, S_##_a2);	\
++	_a1 = NULL_TREE;					\
++      }								\
++  } while (0)
++#define REJECT_REQUIRES(_a1,_a2) do {				\
++    if ((_a1) && !(_a2))					\
++      {								\
++	warn_attribute_requires (decl, S_##_a1, S_##_a2);	\
++	_a1 = NULL_TREE;					\
++      }								\
++  } while (0)
++
++  /* incompatible hosted && noreturn */
++  if (hosted && TREE_THIS_VOLATILE (decl))
++    {
++      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
++		  _("%qs ignored on noreturn function"), S_hosted);
++      hosted = NULL_TREE;
++    }
++
++  /* interrupt > critical > reentrant */
++  REJECT_INCOMPATIBLE (reentrant, critical);
++  REJECT_INCOMPATIBLE (reentrant, interrupt);
++  REJECT_INCOMPATIBLE (critical, interrupt);
++
++  /* Ignore signal/wakeup on non-interrupt */
++  REJECT_REQUIRES (signal, interrupt);
++  REJECT_REQUIRES (wakeup, interrupt);
++
++  /* task > naked > saveprologue (or its successor) */
++  if (saveprologue)
++    {
++      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
++		  _("saveprologue no longer supported"));
++      saveprologue = NULL_TREE;
++    }
++  REJECT_INCOMPATIBLE (saveprologue, naked);
++  REJECT_INCOMPATIBLE (saveprologue, task);
++  REJECT_INCOMPATIBLE (naked, task);
++
++  /* Legacy ignore reentrant/critical on naked (but we allow them on
++   * task) */
++  REJECT_INCOMPATIBLE (reentrant, naked);
++  REJECT_INCOMPATIBLE (critical, naked);
++
++#undef REJECT_REQUIRES
++#undef REJECT_INCOMPATIBLE
++
++  /* Update declaration based on validated attributes */
++  if (interrupt)
++    {
++      /* Ensure code is not eliminated due to it (apparently) not
++       * being called. */
++      TREE_USED (decl) = 1;
++      DECL_PRESERVE_P (decl) = 1;
++    }
++
++  /* Set frame flags.  NB: allocate_frame will be cleared in the
++   * prologue if the frame size is zero. */
++  mfp->frame_flags |= MSP430_FF_preserve_registers | MSP430_FF_allocate_frame;
++  if (critical)
++    mfp->frame_flags |=
++      MSP430_FF_prologue_push_sr | MSP430_FF_epilogue_pop_sr;
++  if (interrupt)
++    mfp->frame_flags |= MSP430_FF_use_reti;
++  if (signal)
++    mfp->frame_flags |= MSP430_FF_prologue_eint;
++  if (critical || reentrant)
++    mfp->frame_flags |= MSP430_FF_prologue_dint;
++  if (reentrant)
++    mfp->frame_flags |= MSP430_FF_epilogue_eint;
++  if (wakeup)
++    mfp->frame_flags |= MSP430_FF_epilogue_exit_lpm;
++  if (TREE_THIS_VOLATILE (decl))
++    mfp->frame_flags |= MSP430_FF_inhibit_return;
++  if (MAIN_NAME_P (DECL_NAME (decl)) && !hosted)
++    {
++      static const char S_init9[] = ".init9";
++
++      mfp->frame_flags |= MSP430_FF_treat_as_main;
++      if (DECL_SECTION_NAME (decl) == NULL_TREE)
++	DECL_SECTION_NAME (decl) = build_string (sizeof (S_init9), S_init9);
++    }
++  if (naked || task || (MSP430_FF_treat_as_main & mfp->frame_flags))
++    {
++      mfp->frame_flags &= ~MSP430_FF_preserve_registers;
++      if (naked)
++	mfp->frame_flags &= ~MSP430_FF_allocate_frame;
++      mfp->frame_flags |= MSP430_FF_inhibit_return;
++    }
++  if (hosted)
++    mfp->frame_flags &= ~MSP430_FF_inhibit_return;
++
++  mfp->signal = signal;
++  mfp->interrupt = interrupt;
++  mfp->naked = naked;
++  mfp->task = task;
++  mfp->wakeup = wakeup;
++  mfp->critical = critical;
++  mfp->reentrant = reentrant;
++  mfp->saveprologue = saveprologue;
++  mfp->noint_hwmul = noint_hwmul;
++  mfp->initialized = true;
++}
++
++int
++msp430_epilogue_uses (int regno ATTRIBUTE_UNUSED)
++{
++  if (reload_completed
++      && cfun->machine && (cfun->machine->interrupt || cfun->machine->signal))
++    return 1;
++  return 0;
++}
++
++static rtx
++return_addr_pointer (void)
++{
++  int adjustment = 0;
++
++  if (cfun->machine->interrupt)
++    adjustment += UNITS_PER_WORD;
++  cfun->machine->frame_pointer_required = true;
++  return plus_constant (hard_frame_pointer_rtx, adjustment);
++}
++
++rtx
++msp430_return_addr_rtx (int count, rtx frameaddr ATTRIBUTE_UNUSED)
++{
++  if (0 == count)
++    return gen_rtx_MEM (Pmode, return_addr_pointer ());
++  return NULL_RTX;
++}
++
++/* Determine which registers need to be saved on the frame so they're
++ * restored for the caller.  Returns the number of such registers;
++ * optionally sets a mask identifying the registers.
++ *
++ * A register must be preserved for the caller if it is not a
++ * call-used register or if this is an interrupt routine.  The current
++ * function must perform such preservation if that register is live in
++ * this function.
++ *
++ * Non-leaf interrupt routines must save registers that they are
++ * allowed to use but don't. */
++static int
++compute_savable_registers (unsigned int *maskp)
++{
++  int mask;
++  int count = 0;
++  int reg;
++  bool is_isr = cfun->machine->interrupt != NULL_TREE;
++
++  mask = 0;
++  for (reg = 4; reg < 16; ++reg)
++    if ((df_regs_ever_live_p (reg) && (!call_used_regs[reg] || is_isr))
++	|| (is_isr && !current_function_is_leaf && call_used_regs[reg]))
++      {
++	mask |= (1 << reg);
++	++count;
++      }
++  if (maskp)
++    *maskp = mask;
++  return count;
++}
++
++/* Determine whether a particular register was saved in the frame */
++#define is_savable_register(REGNO) (cfun->machine->saved_regs_mask & (1 << (REGNO)))
++
++/* Generate and return an instruction that adjusts the register by a
++ * constant value. */
++static rtx
++gen_adjust_register (rtx reg_rtx, int offset)
++{
++  gcc_assert (0 != offset);
++  if (MSP430_CG_INT_P (-offset) && !MSP430_CG_INT_P (offset))
++    return gen_subhi3 (reg_rtx, reg_rtx, gen_int_mode (-offset, HImode));
++  return gen_addhi3 (reg_rtx, reg_rtx, gen_int_mode (offset, HImode));
++}
++
++static rtx
++emit_prolog_pushm (int regno, int numregs)
++{
++  rtx note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (1 + numregs));
++  rtx insn;
++  int i;
++
++  insn = gen_rtx_SET (HImode, stack_pointer_rtx,
++		      plus_constant (stack_pointer_rtx,
++				     -UNITS_PER_WORD * numregs));
++  RTX_FRAME_RELATED_P (insn) = 1;
++  XVECEXP (note, 0, 0) = insn;
++
++  for (i = 0; i < numregs; ++i)
++    {
++      rtx spr;
++      spr = gen_rtx_MEM (HImode,
++			 plus_constant (stack_pointer_rtx,
++					UNITS_PER_WORD * (numregs - i - 1)));
++      insn = gen_rtx_SET (HImode, spr, gen_rtx_REG (HImode, regno - i));
++      RTX_FRAME_RELATED_P (insn) = 1;
++      XVECEXP (note, 0, 1 + i) = insn;
++    }
++
++  insn =
++    emit_insn (gen_pushmhi2 (GEN_INT (numregs), GEN_INT (regno)));
++  RTX_FRAME_RELATED_P (insn) = 1;
++  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
++  return insn;
++}
++
++void
++msp430_expand_prologue (void)
++{
++  int i;
++  struct machine_function *mfp = cfun->machine;
++  rtx insn;			/* Last generated instruction */
++  rtx need_nop_insn = NULL_RTX;
++
++  mfp->saved_regs_count = compute_savable_registers (&mfp->saved_regs_mask);
++  if (0 == mfp->saved_regs_count)
++    mfp->frame_flags &= ~MSP430_FF_preserve_registers;
++  mfp->frame_size = STACK_ALIGN_SIZE (get_frame_size ());
++
++  /* Warn if we need a frame but have been told not to provide one. */
++  if ((0 < mfp->frame_size) && !(mfp->frame_flags & MSP430_FF_allocate_frame))
++    {
++      warning_at (DECL_SOURCE_LOCATION (cfun->decl), OPT_Wattributes,
++		  _
++		  ("function requires %u bytes for stack storage but frame allocation inhibited by %qs"),
++		  mfp->frame_size, S_naked);
++      mfp->frame_size = 0;
++    }
++  if (0 == mfp->frame_size)
++    mfp->frame_flags &= ~MSP430_FF_allocate_frame;
++
++  if (MSP430_FF_prologue_push_sr & mfp->frame_flags)
++    {
++      insn =
++	emit_insn (gen_pushhi1
++		   (gen_rtx_REG (HImode, STATUS_REGISTER_REGNUM)));
++      RTX_FRAME_RELATED_P (insn) = 1;
++    }
++
++  if (MSP430_FF_prologue_dint & mfp->frame_flags)
++    {
++      need_nop_insn = insn = emit_insn (gen_dint ());
++    }
++
++  if (MSP430_FF_preserve_registers & mfp->frame_flags)
++    {
++      for (i = MSP430_MAX_GENERAL_REGNUM; i >= MSP430_MIN_GENERAL_REGNUM; --i)
++	if (is_savable_register (i))
++	  {
++	    if (MSP430_CPU_MSP430X <= msp430_cpu)
++	      {
++		int n = 1;
++
++		while ((i - n) >= MSP430_MIN_GENERAL_REGNUM
++		       && is_savable_register (i - n))
++		  ++n;
++		if (1 < n)
++		  {
++		    insn = emit_prolog_pushm (i, n);
++		    i = i - n + 1;
++		    continue;
++		  }
++	      }
++	    insn = emit_insn (gen_pushhi1 (gen_rtx_REG (HImode, i)));
++	    RTX_FRAME_RELATED_P (insn) = 1;
++	  }
++    }
++
++  if (frame_pointer_needed)
++    {
++      int fp_hfp_offset;
++
++      if (!(MSP430_FF_preserve_registers & mfp->frame_flags)
++	  && !(MSP430_FF_treat_as_main & mfp->frame_flags))
++	warning_at (DECL_SOURCE_LOCATION (cfun->decl), OPT_Wattributes,
++		    _("frame allocation destroys caller register due to %qs"),
++		    S_task);
++
++      fp_hfp_offset =
++	msp430_initial_elimination_offset (FRAME_POINTER_REGNUM,
++					   HARD_FRAME_POINTER_REGNUM);
++      fp_hfp_offset += mfp->frame_size;
++
++      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
++      RTX_FRAME_RELATED_P (insn) = 1;
++      if (0 != fp_hfp_offset)
++	{
++	  insn =
++	    emit_insn (gen_adjust_register
++		       (hard_frame_pointer_rtx, -fp_hfp_offset));
++	  RTX_FRAME_RELATED_P (insn) = 1;
++	}
++    }
++
++  if (MSP430_FF_allocate_frame & mfp->frame_flags)
++    {
++      insn =
++	emit_insn (gen_adjust_register (stack_pointer_rtx, -mfp->frame_size));
++      RTX_FRAME_RELATED_P (insn) = 1;
++    }
++
++  if (MSP430_FF_prologue_eint & mfp->frame_flags)
++    {
++      insn = emit_insn (gen_eint ());
++    }
++
++  /* Ensure dint is followed by something before we hit the
++   * uninterruptible code */
++  if (need_nop_insn != NULL_RTX && need_nop_insn == get_last_insn ())
++    {
++      insn = emit_insn (gen_nop ());
++    }
++
++  /* If the epilogue will reduce to a single instruction, we can
++   * enable the return pattern now so gen_return at the end of basic
++   * blocks avoids a jump. */
++  if (!(mfp->frame_flags & (MSP430_FF_inhibit_return
++			    | MSP430_FF_epilogue_dint
++			    | MSP430_FF_allocate_frame
++			    | MSP430_FF_preserve_registers
++			    | MSP430_FF_epilogue_pop_sr
++			    | MSP430_FF_epilogue_exit_lpm
++			    | MSP430_FF_epilogue_eint)))
++    mfp->frame_flags |= MSP430_FF_ready_for_return;
++
++  mfp->inhibited_return_label = NULL;
++  if (mfp->frame_flags & MSP430_FF_inhibit_return)
++    {
++      static int const_labelno;
++      char tmp_label[100];
++
++      ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LIRD", const_labelno);
++      const_labelno++;
++      mfp->inhibited_return_label = ggc_strdup (tmp_label);
++    }
++}
++
++
++/* Output function epilogue */
++
++void
++msp430_expand_epilogue (void)
++{
++  int i;
++  struct machine_function *mfp = cfun->machine;
++  rtx insn;
++  rtx need_nop_insn = NULL_RTX;
++
++  /* Obey noreturn.  Can't just exit */
++  if (TREE_THIS_VOLATILE (current_function_decl))
++    goto epilogue_done;
++
++  if (MSP430_FF_epilogue_dint & mfp->frame_flags)
++    need_nop_insn = insn = emit_insn (gen_dint ());
++
++  if (MSP430_FF_allocate_frame & mfp->frame_flags)
++    insn =
++      emit_insn (gen_adjust_register (stack_pointer_rtx, mfp->frame_size));
++
++  if (MSP430_FF_preserve_registers & mfp->frame_flags)
++    {
++      for (i = MSP430_MIN_GENERAL_REGNUM; i <= MSP430_MAX_GENERAL_REGNUM; i++)
++	if (is_savable_register (i))
++	  {
++	    if (MSP430_CPU_MSP430X <= msp430_cpu)
++	      {
++		int n = 1;
++
++		while ((i + n) <= MSP430_MAX_GENERAL_REGNUM
++		       && is_savable_register (i + n))
++		  ++n;
++		if (1 < n)
++		  {
++		    i = i + n - 1;
++		    insn = emit_insn (gen_popmhi2 (GEN_INT (n), GEN_INT (i)));
++		    continue;
++		  }
++	      }
++	    insn = emit_insn (gen_pophi1 (gen_rtx_REG (HImode, i)));
++	  }
++    }
++
++  if (MSP430_FF_epilogue_pop_sr & mfp->frame_flags)
++    insn =
++      emit_insn (gen_pophi1 (gen_rtx_REG (HImode, STATUS_REGISTER_REGNUM)));
++
++  if (MSP430_FF_epilogue_exit_lpm & mfp->frame_flags)
++    insn =
++      emit_insn (gen_bic_status_register_on_exit
++		 (gen_rtx_MEM (Pmode, stack_pointer_rtx),
++		  gen_int_mode (0xf0, HImode)));
++
++  if (MSP430_FF_epilogue_eint & mfp->frame_flags)
++    insn = emit_insn (gen_eint ());
++
++epilogue_done:
++
++  /* NB: if naked, this does not emit any code, but we have to invoke
++   * gen_return() at least once or sanity checks in the shared code
++   * fail. */
++  mfp->frame_flags |= MSP430_FF_ready_for_return;
++  emit_jump_insn (gen_return ());
++
++  /* Ensure dint is followed by something before we hit the
++   * uninterruptible code.  (Test will only pass if
++   * inhibit_return.)  */
++  if (need_nop_insn != NULL_RTX && need_nop_insn == get_last_insn ())
++    insn = emit_insn (gen_nop ());
++}
++
++void
++msp430_output_addr_vec_elt (FILE * stream, int value)
++{
++  fprintf (stream, "\t.word	.L%d\n", value);
++}
++
++/* Controls whether a function argument is passed
++in a register, and which register. */
++rtx
++msp430_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type,
++		     int named ATTRIBUTE_UNUSED)
++{
++  int regs = msp430_num_arg_regs (mode, type);
++
++  if (cum->nregs && regs <= cum->nregs)
++    {
++      int regnum = cum->regno - regs;
++
++      if (cum == cum_incoming)
++	{
++	  arg_register_used[regnum] = 1;
++	  if (regs >= 2)
++	    arg_register_used[regnum + 1] = 1;
++	  if (regs >= 3)
++	    arg_register_used[regnum + 2] = 1;
++	  if (regs >= 4)
++	    arg_register_used[regnum + 3] = 1;
++	}
++
++      return gen_rtx_REG (mode, regnum);
++    }
++  return NULL_RTX;
++}
++
++/* the same in scope of the cum.args., buf usefull for a
++function call */
++void
++msp430_init_cumulative_incoming_args (CUMULATIVE_ARGS * cum, tree fntype,
++				      rtx libname)
++{
++  int i;
++  cum->nregs = 4;
++  cum->regno = FIRST_CUM_REG;
++  if (!libname)
++    {
++      int stdarg = (TYPE_ARG_TYPES (fntype) != 0
++		    && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
++			!= void_type_node));
++      if (stdarg)
++	cum->nregs = 0;
++    }
++
++  for (i = 0; i < 16; i++)
++    arg_register_used[i] = 0;
++
++  cum_incoming = cum;
++}
++
++/* Initializing the variable cum for the state at the beginning
++of the argument list.  */
++void
++msp430_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, rtx libname,
++			     tree fndecl ATTRIBUTE_UNUSED)
++{
++  cum->nregs = 4;
++  cum->regno = FIRST_CUM_REG;
++  if (!libname)
++    {
++      int stdarg = (TYPE_ARG_TYPES (fntype) != 0
++		    && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
++			!= void_type_node));
++      if (stdarg)
++	cum->nregs = 0;
++    }
++}
++
++
++/* Update the summarizer variable CUM to advance past an argument
++in the argument list.  */
++void
++msp430_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
++			     tree type, int named ATTRIBUTE_UNUSED)
++{
++  int regs = msp430_num_arg_regs (mode, type);
++
++  cum->nregs -= regs;
++  cum->regno -= regs;
++
++  if (cum->nregs <= 0)
++    {
++      cum->nregs = 0;
++      cum->regno = FIRST_CUM_REG;
++    }
++}
++
++/* Returns the number of registers to allocate for a function argument.  */
++static int
++msp430_num_arg_regs (enum machine_mode mode, tree type)
++{
++  int size;
++
++  if (mode == BLKmode)
++    size = int_size_in_bytes (type);
++  else
++    size = GET_MODE_SIZE (mode);
++
++  if (size < UNITS_PER_WORD)
++    size = UNITS_PER_WORD;
++
++  /* we do not care if argument is passed in odd register
++     so, do not align the size ...
++     BUT!!! even char argument passed in 16 bit register
++     so, align the size */
++  return STACK_ALIGN_SIZE (size) / UNITS_PER_WORD;
++}
++
++int
++msp430_initial_elimination_offset (int from, int to)
++{
++  const struct machine_function *mfp = cfun->machine;
++  int offset_words = 0;
++  int offset_bytes = 0;
++
++  switch (from)
++    {
++    case ARG_POINTER_REGNUM:
++      if (mfp->interrupt)
++	offset_words += 2;
++      else
++	offset_bytes += GET_MODE_SIZE (Pmode);
++      switch (to)
++	{
++	case HARD_FRAME_POINTER_REGNUM:
++	  break;
++	case STACK_POINTER_REGNUM:
++	  if (MSP430_FF_prologue_push_sr & mfp->frame_flags)
++	    ++offset_words;
++	  offset_words += compute_savable_registers (0);
++	  offset_bytes += get_frame_size ();
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++      break;
++    case FRAME_POINTER_REGNUM:
++      switch (to)
++	{
++	case STACK_POINTER_REGNUM:
++	  break;
++	case HARD_FRAME_POINTER_REGNUM:
++	  if (MSP430_FF_prologue_push_sr & mfp->frame_flags)
++	    ++offset_words;
++	  offset_words += compute_savable_registers (0);
++	  offset_bytes += get_frame_size ();
++	  offset_words = -offset_words;
++	  offset_bytes = -offset_bytes;
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++      break;
++    default:
++      gcc_unreachable ();
++    }
++  offset_bytes += UNITS_PER_WORD * offset_words;
++  return STACK_ALIGN_SIZE (offset_bytes);
++}
++
++int
++msp430_cfa_frame_base_offset (const_tree decl)
++{
++  int offset = 0;
++  struct machine_function *mfp = DECL_STRUCT_FUNCTION (decl)->machine;
++
++  if (mfp->interrupt)
++    {
++      /* If Pmode is 32-bits, default is right; otherwise need to
++       * adjust for intervening status register */
++      if (UNITS_PER_WORD == INCOMING_FRAME_SP_OFFSET)
++	offset -= UNITS_PER_WORD;
++    }
++
++  /* Main routine entered via fall-through; no return address */
++  if (mfp->frame_flags & MSP430_FF_treat_as_main)
++    offset -= INCOMING_FRAME_SP_OFFSET;
++
++  return offset;
++}
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430-gcc.c gcc-4.6.3/gcc/config/msp430/msp430-gcc.c
+new file mode 100644
+index 0000000..dece83d
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430-gcc.c
+@@ -0,0 +1,123 @@
++#include "config.h"
++#include "system.h"
++#include "prefix.h"
++#include "defaults.h"
++
++extern const char *msp430_mcucpp (int argc, const char **argv);
++
++extern const char *msp430_mculdscriptpaths (int argc, const char **argv);
++
++/* Return a new string -D__(toupper(mcu))__ */
++static const char *
++gen_cpp (const char *mcu)
++{
++  static const char prefix[] = "-D__";
++  static const char suffix[] = "__";
++  size_t len;
++  char *result;
++  char *ep;
++  const char *cp;
++
++  len = (sizeof (prefix) - 1) + strlen (mcu) + sizeof (suffix);
++  result = XNEWVAR (char, len);
++  ep = result;
++  strcpy (ep, prefix);
++  ep += sizeof (prefix) - 1;
++  cp = mcu;
++  while (*cp)
++    {
++      *ep++ = TOUPPER (*cp);
++      ++cp;
++    }
++  *ep = 0;
++  strcat (result, suffix);
++  return result;
++}
++
++const char *
++msp430_mcucpp (int argc, const char **argv)
++{
++  const char *mcu;
++  const char *defs;
++  const char *p;
++#if 0
++  fprintf (stderr, "%d args: ", argc);
++  for (len = 0; len < argc; ++len)
++    fprintf (stderr, "'%s' ", argv[len]);
++  fprintf (stderr, "\n");
++#endif
++
++  if (0 == argc)
++    return NULL;
++  mcu = argv[argc - 1];
++  defs = gen_cpp (mcu);
++  p = strchr (mcu, '_');
++  if (NULL != p)
++    {
++      char *base_mcu = xstrndup (mcu, p - mcu);
++      defs = concat (gen_cpp (base_mcu), " ", defs, NULL);
++      free (base_mcu);
++    }
++  return defs;
++}
++
++#ifndef DIR_UP
++#define DIR_UP ".."
++#endif /* DIR_UP */
++
++/* Join additional directory components to a separator-terminated path
++   to create a new separator-terminated path. */
++static const char *
++dir_join (const char *path, ...)
++{
++  static const char dir_sep[] = { DIR_SEPARATOR, 0 };
++  const char *rv = path;
++  const char *elt;
++  va_list ap;
++
++  va_start (ap, path);
++  while (1)
++    {
++      elt = va_arg (ap, const char *);
++      if (NULL == elt)
++	break;
++      rv = concat (rv, elt, dir_sep, NULL);
++    }
++  va_end (ap);
++  return rv;
++}
++
++static const char *
++gen_ldscriptpath (const char *mcu, const char *suffix)
++{
++  const char *gcc_exec_prefix;
++
++  gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
++  if (!gcc_exec_prefix)
++    gcc_exec_prefix = STANDARD_EXEC_PREFIX;
++
++  return update_path (dir_join (gcc_exec_prefix, DIR_UP, DIR_UP,
++				DEFAULT_TARGET_MACHINE, "lib",
++				"ldscripts", mcu, suffix, NULL), "BINUTILS");
++}
++
++const char *
++msp430_mculdscriptpaths (int argc, const char **argv)
++{
++  const char *mcu;
++  const char *paths = "";
++  const char *p;
++
++  if (0 == argc)
++    return 0;
++
++  mcu = argv[argc - 1];
++  p = strchr (mcu, '_');
++  if (NULL != p)
++    {
++      mcu = xstrndup (mcu, p - mcu);
++      paths = concat (paths, "-L ", gen_ldscriptpath (mcu, p + 1), NULL);
++    }
++  paths = concat (paths, " -L ", gen_ldscriptpath (mcu, NULL), NULL);
++  return paths;
++}
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430-protos.h gcc-4.6.3/gcc/config/msp430/msp430-protos.h
+new file mode 100644
+index 0000000..ce687a6
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430-protos.h
+@@ -0,0 +1,121 @@
++/* Prototypes for exported functions defined in msp430.c
++   
++   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
++   Contributed by Dmitry Diky <diwil at mail.ru>
++
++   This file is part of GNU CC.
++
++   GNU CC is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2, or (at your option)
++   any later version.
++
++   GNU CC 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 GNU CC; see the file COPYING.  If not, write to
++   the Free Software Foundation, 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++
++extern void gas_output_limited_string (FILE * file, const char *str);
++extern void gas_output_ascii (FILE * file, const char *str, size_t length);
++
++int msp430_regno_ok_for_base_p (int reg, int strict);
++
++int msp430_adjust_insn_length (rtx insn, int length);
++
++#ifdef HAVE_MACHINE_MODES
++extern int msp430_hard_regno_mode_ok (int regno, enum machine_mode mode);
++#endif
++
++extern int msp430_initial_elimination_offset (int, int);
++
++#ifdef TREE_CODE
++void msp430_asm_declare_function_name (FILE *, const char *, tree);
++unsigned int msp430_section_type_flags (tree DECL, const char *NAME,
++					int RELOC);
++
++#ifdef RTX_CODE			/* inside TREE_CODE */
++extern rtx msp430_function_arg (CUMULATIVE_ARGS * cum,
++				enum machine_mode mode, tree type, int named);
++extern void msp430_init_cumulative_args (CUMULATIVE_ARGS * cum,
++					 tree fntype, rtx libname,
++					 tree fndecl);
++extern void msp430_init_cumulative_incoming_args (CUMULATIVE_ARGS * cum,
++						  tree fntype, rtx libname);
++extern rtx msp430_function_incoming_arg (CUMULATIVE_ARGS * cum,
++					 enum machine_mode mode, tree type,
++					 int named);
++
++
++
++#endif /* RTX_CODE inside TREE_CODE */
++
++#ifdef HAVE_MACHINE_MODES	/* inside TREE_CODE */
++extern void msp430_function_arg_advance (CUMULATIVE_ARGS * cum,
++					 enum machine_mode mode, tree type,
++					 int named);
++#endif /* HAVE_MACHINE_MODES inside TREE_CODE */
++#endif /* TREE_CODE */
++
++#ifdef RTX_CODE
++
++int msp430_extract_multiword_operand (enum machine_mode innermode, rtx op,
++				      rtx * parts);
++
++const char *msp430_output_template (enum machine_mode mode,
++				    int src_operand,
++				    const char *init_op,
++				    const char *next_op,
++				    const char *prefix);
++const char * msp430_output_reverse_template (enum machine_mode mode,
++					     int src_operand,
++					     const char *init_op,
++					     const char *next_op,
++					     const char *prefix);
++
++const char *msp430_mov_noclobber (rtx operands[]);
++
++enum reg_class msp430_regno_reg_class (int);
++
++int msp430_extend_matches (const_rtx, const_rtx);
++void msp430_expand_signextend (rtx operands[]);
++void msp430_expand_zeroextend (rtx operands[]);
++
++int msp430_expand_extract (rtx operands[], bool signed_p);
++
++extern void msp430_notice_update_cc (rtx body, rtx insn);
++extern void msp430_output_addr_vec_elt (FILE * stream, int value);
++
++extern void msp430_print_operand (FILE * file, rtx x, int code);
++
++extern int msp430_jump_dist (rtx x, rtx insn);
++
++extern void msp430_expand_mul (rtx[], int);
++extern void msp430_expand_ashl (rtx[]);
++extern void msp430_expand_ashr (rtx[]);
++extern void msp430_expand_lshr (rtx[]);
++
++extern void msp430_expand_cbranch (rtx[]);
++extern const char* msp430_output_branchcc (rtx, rtx[]);
++
++extern void msp430_expand_prologue (void);
++extern void msp430_expand_epilogue (void);
++extern void msp430_set_current_function (tree);
++extern int msp430_epilogue_uses (int regno);
++
++bool msp430_inhibited_return_fallthru_p (rtx insn);
++
++#endif /* RTX_CODE */
++
++extern void msp430_pr_vector (struct cpp_reader *);
++#ifdef TREE_CODE
++extern GTY(()) tree msp430_vector_offset_tree;
++#endif /* TREE_CODE */
++
++extern rtx msp430_return_addr_rtx (int, rtx);
++extern int msp430_cfa_frame_base_offset (const_tree decl);
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430.c gcc-4.6.3/gcc/config/msp430/msp430.c
+new file mode 100644
+index 0000000..2defd6c
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430.c
+@@ -0,0 +1,3071 @@
++/* TODO
++ * cost speed attribute
++ */
++/* This work is partially financed by the European Commission under the
++* Framework 6 Information Society Technologies Project
++* "Wirelessly Accessible Sensor Populations (WASP)".
++*/
++
++/*
++	GCC 4.x port by Ivan Shcherbakov <mspgcc at sysprogs.org>
++*/
++
++/* Subroutines for insn-output.c for Texas Instruments MSP430 MCU
++Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++Contributed by Dmitry Diky <diwil at mail.ru>
++
++This file is part of GNU CC. 
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC 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 GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "insn-attr.h"
++#include "flags.h"
++#include "reload.h"
++#include "tree.h"
++#include "output.h"
++#include "expr.h"
++#include "toplev.h"
++#include "obstack.h"
++#include "function.h"
++#include "optabs.h"
++#include "recog.h"
++#include "tm_p.h"
++#include "target.h"
++#include "target-def.h"
++#include "insn-codes.h"
++#include "ggc.h"
++#include "langhooks.h"
++#include "df.h"
++#include "intl.h"
++#include "diagnostic.h"
++
++/* Number of consecutive registers available for returning values from
++ * a function.  These start with MSP430_RETURN_REGISTER_BASE and grow
++ * "down". */
++#define RETURN_REGISTERS_AVAILABLE 4
++
++msp430_cpu_e msp430_cpu = MSP430_CPU_MSP430;
++msp430_mpy_e msp430_mpy = MSP430_MPY_NONE;
++int msp430_ivcnt = 16;
++
++int msp430_case_values_threshold = 30000;
++int msp430_has_hwmul = 0;
++
++/* Defined in msp430-builtins.c */
++void msp430_init_builtins (void);
++rtx msp430_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
++
++static struct machine_function *
++msp430_init_machine_status (void)
++{
++  return ggc_alloc_cleared_machine_function ();
++}
++
++static GTY(()) rtx mpy_b_rtx;
++static GTY(()) rtx mpys_b_rtx;
++static GTY(()) rtx op2_b_rtx;
++static GTY(()) rtx reslo_b_rtx;
++static GTY(()) rtx mpy_rtx;
++static GTY(()) rtx mpys_rtx;
++static GTY(()) rtx op2_rtx;
++static GTY(()) rtx reslo_rtx;
++static GTY(()) rtx reshi_rtx;
++static GTY(()) rtx mpy32l_rtx;
++static GTY(()) rtx mpy32h_rtx;
++static GTY(()) rtx mpys32l_rtx;
++static GTY(()) rtx mpys32h_rtx;
++static GTY(()) rtx op2l_rtx;
++static GTY(()) rtx op2h_rtx;
++static GTY(()) rtx res0_rtx;
++static GTY(()) rtx res1_rtx;
++static GTY(()) rtx res2_rtx;
++static GTY(()) rtx res3_rtx;
++
++static GTY(()) rtx libsym_mulqi3;
++static GTY(()) rtx libsym_mulqihi3;
++static GTY(()) rtx libsym_umulqihi3;
++static GTY(()) rtx libsym_mulhi3;
++static GTY(()) rtx libsym_mulhisi3;
++static GTY(()) rtx libsym_umulhisi3;
++static GTY(()) rtx libsym_mulsi3;
++static GTY(()) rtx libsym_mulsidi3;
++static GTY(()) rtx libsym_umulsidi3;
++static GTY(()) rtx libsym_muldi3;
++
++static GTY(()) rtx libsym_ashlqi3;
++static GTY(()) rtx libsym_ashrqi3;
++static GTY(()) rtx libsym_lshrqi3;
++static GTY(()) rtx libsym_ashlhi3;
++static GTY(()) rtx libsym_ashrhi3;
++static GTY(()) rtx libsym_lshrhi3;
++static GTY(()) rtx libsym_ashlsi3;
++static GTY(()) rtx libsym_ashrsi3;
++static GTY(()) rtx libsym_lshrsi3;
++static GTY(()) rtx libsym_ashldi3;
++static GTY(()) rtx libsym_ashrdi3;
++static GTY(()) rtx libsym_lshrdi3;
++
++static rtx
++gen_rtx_HWREG (enum machine_mode mode, const char *name)
++{
++  rtx ret = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (mode, name));
++  MEM_VOLATILE_P (ret) = 1;
++  return ret;
++}
++
++static void
++msp430_init_once (void)
++{
++  init_machine_status = msp430_init_machine_status;
++
++  if (msp430_mpy & MSP430_MPY_TYPE_16)
++    {
++      mpy_b_rtx = gen_rtx_HWREG (QImode, "__MPY");
++      mpys_b_rtx = gen_rtx_HWREG (QImode, "__MPYS");
++      op2_b_rtx = gen_rtx_HWREG (QImode, "__OP2");
++      reslo_b_rtx = gen_rtx_HWREG (QImode, "__RESLO");
++      mpy_rtx = gen_rtx_HWREG (HImode, "__MPY");
++      mpys_rtx = gen_rtx_HWREG (HImode, "__MPYS");
++      op2_rtx = gen_rtx_HWREG (HImode, "__OP2");
++      reslo_rtx = gen_rtx_HWREG (HImode, "__RESLO");
++      reshi_rtx = gen_rtx_HWREG (HImode, "__RESHI");
++    }
++  if (msp430_mpy & MSP430_MPY_TYPE_32)
++    {
++      mpy32l_rtx = gen_rtx_HWREG (HImode, "__MPY32L");
++      mpy32h_rtx = gen_rtx_HWREG (HImode, "__MPY32H");
++      mpys32l_rtx = gen_rtx_HWREG (HImode, "__MPYS32L");
++      mpys32h_rtx = gen_rtx_HWREG (HImode, "__MPYS32H");
++      op2l_rtx = gen_rtx_HWREG (HImode, "__OP2L");
++      op2h_rtx = gen_rtx_HWREG (HImode, "__OP2H");
++      res0_rtx = gen_rtx_HWREG (HImode, "__RES0");
++      res1_rtx = gen_rtx_HWREG (HImode, "__RES1");
++      res2_rtx = gen_rtx_HWREG (HImode, "__RES2");
++      res3_rtx = gen_rtx_HWREG (HImode, "__RES3");
++    }
++  return;
++}
++
++/****** ATTRIBUTES *************************************/
++
++/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
++struct attribute_spec.handler.  */
++static tree
++handle_fndecl_attribute (tree * pnode, tree name,
++			 tree args ATTRIBUTE_UNUSED,
++			 int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
++{
++  if (TREE_CODE (*pnode) != FUNCTION_DECL)
++    {
++      warning (OPT_Wattributes, "%qE attribute ignored", name);
++      *no_add_attrs = true;
++    }
++  return NULL_TREE;
++}
++
++
++const struct attribute_spec msp430_attribute_table[] = {
++  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++  {"signal", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"interrupt", 0, 1, true, false, false, handle_fndecl_attribute},
++  {"naked", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"task", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"wakeup", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"critical", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"reentrant", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"saveprologue", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"noint_hwmul", 0, 0, true, false, false, handle_fndecl_attribute},
++  {"hosted", 0, 0, true, false, false, handle_fndecl_attribute},
++  {NULL, 0, 0, false, false, false, NULL}
++};
++
++int
++msp430_current_function_noint_hwmul_function_p (void)
++{
++  return TARGET_NOINT_HWMUL || (cfun && cfun->machine
++				&& cfun->machine->initialized
++				&& cfun->machine->noint_hwmul != NULL_TREE);
++}
++
++unsigned int
++msp430_section_type_flags (tree decl, const char *name, int reloc)
++{
++  unsigned int flags = default_section_type_flags (decl, name, reloc);
++  const char *suffix = strrchr (name, '.');
++
++  if (!strcmp (name, ".noinit")
++      || !strcmp (name, ".infomemnobits")
++      || (suffix && 0 == strcmp (suffix, ".bss")))
++    {
++      if (!strcmp (name, ".infomemnobits"))
++	warning_at (DECL_SOURCE_LOCATION (decl), 0,
++		    _(".infomemnobits is deprecated; use .infomem.bss"));
++      if (!decl
++	  || (TREE_CODE (decl) == VAR_DECL
++	      && DECL_INITIAL (decl) == NULL_TREE))
++	flags |= SECTION_BSS;	/* @nobits */
++      else
++	warning_at (DECL_SOURCE_LOCATION (decl), 0,
++		    "only uninitialized variables can be placed in a .bss section");
++    }
++  return flags;
++}
++
++struct tag_value_pair_t
++{
++  const char *tag;
++  unsigned long value;
++};
++
++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}
++};
++
++static const struct tag_value_pair_t *
++find_pair_by_tag (const char *tag, const struct tag_value_pair_t *map)
++{
++  while (map->tag)
++    {
++      if (0 == strcmp (tag, map->tag))
++	return map;
++      ++map;
++    }
++  return 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;
++}
++
++static void
++msp430_option_override (void)
++{
++  const struct tag_value_pair_t *mp;
++
++  if (flag_pic)
++    error ("PIC not supported on msp430");
++
++  if (msp430_mcu_name)
++    {
++      char * up = strchr(msp430_mcu_name, '_');
++      if (NULL != up)
++	*up = 0;
++    }
++
++  if (msp430_opt_cpu)
++    {
++      mp = find_pair_by_tag (msp430_opt_cpu, cpu_tag_value_map);
++      if (!mp)
++	{
++	  error (_("mcpu %s not recognized"), msp430_opt_cpu);
++	  return;
++	}
++      msp430_cpu = (msp430_cpu_e) mp->value;
++    }
++
++  if (msp430_opt_mpy)
++    {
++      mp = find_pair_by_tag (msp430_opt_mpy, mpy_tag_value_map);
++      if (!mp)
++	{
++	  error (_("mmpy %s not recognized"), msp430_opt_mpy);
++	  return;
++	}
++      msp430_mpy = (msp430_mpy_e) mp->value;
++    }
++
++  if (msp430_opt_ivcnt)
++    {
++      char *ep;
++      msp430_ivcnt = strtol (msp430_opt_ivcnt, &ep, 0);
++      if (*msp430_opt_ivcnt && *ep)
++	{
++	  error (_("ivcnt %s must be integer"), msp430_opt_ivcnt);
++	  gcc_unreachable ();
++	  return;
++	}
++      if ((16 != msp430_ivcnt) && (32 != msp430_ivcnt)
++	  && (64 != msp430_ivcnt))
++	{
++	  error (_("ivcnt %s must be 16, 32, or 64"), msp430_opt_ivcnt);
++	  gcc_unreachable ();
++	  return;
++	}
++    }
++
++  if (TARGET_NVWA)
++    warning (OPT_Wdeprecated, _("-mno-volatile-workaround ignored"));
++
++  if (TARGET_NO_HWMUL)
++    {
++      warning (OPT_Wdeprecated, "-mdisable-hwmul deprecated, use -mmpy=none");
++      msp430_mpy = MSP430_MPY_NONE;
++    }
++  msp430_has_hwmul = ! !(msp430_mpy & MSP430_MPY_TYPE_ANY);
++
++  msp430_case_values_threshold = 8;	/* ? or there is a better value ? */
++
++  flag_defer_pop = 0;
++
++  msp430_init_once ();
++}
++
++/* Return in memory unless size is determined to be no greater than
++ * eight bytes. */
++static bool
++msp430_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
++{
++  if (TYPE_MODE (type) == BLKmode)
++    {
++      HOST_WIDE_INT size = int_size_in_bytes (type);
++      return (size == -1
++	      || size > (RETURN_REGISTERS_AVAILABLE * UNITS_PER_WORD));
++    }
++  return false;
++}
++
++static int reg_class_tab[FIRST_VIRTUAL_REGISTER] = {
++  PC_REG, SP_REG, SR_REG, CG2_REG,	/* fixed registers */
++  FP_REG,			/* maybe fixed reg */
++  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,	/* unassigned registers r5 - r15 */
++  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
++  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
++  SOFT_ARGP_REG, SOFT_FP_REG,	/* fixed pseudo registers */
++};
++
++int
++msp430_regno_ok_for_base_p (int reg, int strict)
++{
++  if (strict && reg >= FIRST_PSEUDO_REGISTER && reg_renumber)
++    reg = reg_renumber[reg];
++  if (reg < 0)
++    return 0;
++  if (!strict && reg > MSP430_MAX_GENERAL_REGNUM)
++    return 1;
++  return reg == STACK_POINTER_REGNUM || MSP430_GENERAL_REGISTER_NUM_P (reg);
++}
++
++enum reg_class
++msp430_regno_reg_class (int r)
++{
++  if (r < (int) (sizeof (reg_class_tab) / sizeof (reg_class_tab[0])))
++    return (enum reg_class) reg_class_tab[r];
++
++  return NO_REGS;
++}
++
++void
++msp430_asm_declare_function_name (FILE * file, const char *name, tree decl)
++{
++  struct machine_function *mfp = cfun->machine;
++  bool is_isr = NULL_TREE != mfp->interrupt;
++  int vector = -1;
++
++  if (is_isr && (0 <= mfp->vector_offset))
++    {
++      vector = mfp->vector_offset / 2;
++      if (0 < msp430_ivcnt && (vector >= msp430_ivcnt))
++	{
++	  error_at (DECL_SOURCE_LOCATION (decl),
++		    _
++		    ("interrupt vector %d is beyond end of MCU vector table"),
++		    vector);
++	  vector = -1;
++	  is_isr = false;
++	}
++    }
++
++  fprintf (file, "%s", TYPE_ASM_OP);
++  assemble_name (file, name);
++  putc (',', file);
++  fprintf (file, TYPE_OPERAND_FMT, "function");
++  putc ('\n', file);
++  fprintf (file, "/***********************\n");
++  if (!is_isr)
++    fprintf (file, " * Function `");
++  else if (0 > vector)
++    fprintf (file, " * Interrupt Sub-Routine `");
++  else
++    fprintf (file, " * Interrupt Vector %d Service Routine `", vector);
++  assemble_name (file, name);
++  fprintf (file, "' %s\n ***********************/\n",
++	   (cfun->machine->critical != NULL_TREE)
++	   ? "(OS critical)"
++	   : (cfun->machine->reentrant != NULL_TREE) ? "(reentrant)" : "");
++  ASM_OUTPUT_LABEL (file, name);
++  if (0 <= vector)
++    {
++      char isrname[32];
++      snprintf (isrname, sizeof (isrname), "__isr_%u", vector);
++      fprintf (file, ".global\t%s\n", isrname);
++      fprintf (file, "%s:\n", isrname);
++    }
++
++}
++
++static bool
++msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
++			     rtx x, bool strict)
++{
++  switch (GET_CODE (x))
++    {
++    case REG:
++      return msp430_regno_ok_for_base_p (REGNO (x), strict);
++    case PLUS:
++      return REG_P (XEXP (x, 0))
++	&& msp430_legitimate_address_p (mode, XEXP (x, 0), strict)
++	&& CONSTANT_P (XEXP (x, 1));
++    default:
++      return CONSTANT_P (x);
++    }
++  gcc_unreachable ();
++}
++
++static const char *trim_array[] = { "llo", "lhi", "hlo", "hhi" };
++
++static void
++print_sub_operand (FILE * file, rtx x, int code)
++{
++
++  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
++    output_addr_const (file, x);
++  else if (GET_CODE (x) == CONST)
++    print_sub_operand (file, XEXP (x, 0), code);
++  else if (GET_CODE (x) == PLUS)
++    {
++      print_sub_operand (file, XEXP (x, 0), code);
++      fprintf (file, "+");
++      print_sub_operand (file, XEXP (x, 1), code);
++    }
++  else if (GET_CODE (x) == CONST_INT)
++    fprintf (file, "%ld", INTVAL (x));
++  else
++    gcc_unreachable ();
++}
++
++void
++msp430_print_operand (FILE * file, rtx x, int code)
++{
++  int shift = 0;
++
++  if (code >= 'A' && code <= 'D')
++    shift = code - 'A';
++  else if (code != 0 && code != 'S')
++    gcc_unreachable ();
++
++  if (REG_P (x))
++    fprintf (file, reg_names[REGNO (x) + shift]);
++  else if (GET_CODE (x) == CONST_INT)
++    {
++      HOST_WIDE_INT intval = INTVAL (x);
++
++      /* For improved ASM readability, omit #llo(const) for small constants */
++      if (!shift && !(intval & ~0xFFFF))
++	fprintf (file, "#%d", (int) intval);
++      else
++	fprintf (file, "#%s(%ld)", trim_array[shift], intval);
++    }
++  else if (GET_CODE (x) == MEM)
++    {
++      rtx addr = XEXP (x, 0);
++
++      if (GET_CODE (addr) == POST_INC)
++	fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
++      else if (GET_CODE (addr) == REG)
++	{			/* for X(Rn) */
++	  int regno = REGNO (addr);
++	  const char* regname = reg_names[regno];
++	  
++	  if (code == 'S' && regno == STACK_POINTER_REGNUM)
++	    fprintf (file, "%d(%s)", UNITS_PER_WORD, regname);
++	  else if (shift)
++	    fprintf (file, "%d(%s)", shift * UNITS_PER_WORD, regname);
++	  else
++	    fprintf (file, "@%s", regname);
++	}
++      else if (GET_CODE (addr) == SYMBOL_REF)
++	{
++	  fprintf (file, "&");
++	  output_addr_const (file, addr);
++	  if (shift)
++	    fprintf (file, "+%d", shift * UNITS_PER_WORD);
++	}
++      else if (GET_CODE (addr) == CONST || GET_CODE (addr) == CONST_INT)
++	{
++	  fputc ('&', file);
++	  output_addr_const (file, addr);
++	  if (shift)
++	    fprintf (file, "+%d", shift * UNITS_PER_WORD);
++	}
++      else if (GET_CODE (addr) == PLUS)
++	{
++	  rtx base = XEXP (addr, 0);
++	  rtx offset = XEXP (addr, 1);
++	  int regno = REGNO (base);
++	  const char* regname = reg_names[regno];
++
++	  gcc_assert (REG_P (base));
++	  print_sub_operand (file, offset, code);
++	  if (code == 'S' && regno == STACK_POINTER_REGNUM)
++	    fprintf (file, "+%d(%s)", UNITS_PER_WORD, regname);
++	  else
++	    {
++	      if (shift)
++		fprintf (file, "+%d", shift * UNITS_PER_WORD);
++	      fprintf (file, "(%s)", regname);
++	    }
++	}
++      else
++	gcc_unreachable ();
++    }
++  else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST)
++    {
++      fprintf (file, "#");
++      output_addr_const (file, x);
++      if (shift)
++	fprintf (file, "+%d", shift * UNITS_PER_WORD);
++    }
++  else if (GET_CODE (x) == CODE_LABEL)
++    output_addr_const (file, x);
++  else if (GET_CODE (x) == CONST_DOUBLE)
++    {
++      if (GET_MODE (x) == VOIDmode)	/* FIXME: may be long long?? */
++	{
++	  if (shift < 2)
++	    fprintf (file, "#%s(%ld)", trim_array[shift],
++		     CONST_DOUBLE_LOW (x));
++	  else
++	    fprintf (file, "#%s(%ld)", trim_array[shift - 2],
++		     CONST_DOUBLE_HIGH (x));
++	}
++      else if (GET_MODE (x) == SFmode || GET_MODE (x) == SImode)
++	{
++	  long val;
++	  REAL_VALUE_TYPE rv;
++	  REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
++	  REAL_VALUE_TO_TARGET_SINGLE (rv, val);
++	  asm_fprintf (file, "#%s(0x%lx)", trim_array[shift], val);
++	}
++      else
++	gcc_unreachable ();
++    }
++  else
++    gcc_unreachable ();
++}
++
++/* Convert an operand that requires multiple words into a sequence of
++   word-sized operands comprising its elements, from least significant
++   to most significant.  Returns the number of word elements
++   extracted. */
++int
++msp430_extract_multiword_operand (enum machine_mode innermode, rtx op,
++				  rtx * parts)
++{
++  int words;
++  rtx last_insn = get_last_insn ();
++  int i;
++
++  if (VOIDmode == innermode)
++    innermode = GET_MODE (op);
++  words = GET_MODE_SIZE (innermode) / UNITS_PER_WORD;
++  if (1 >= words)
++    {
++      parts[0] = op;
++      words = 1;
++    }
++  else
++    for (i = 0; i < words; ++i)
++      {
++	parts[i] =
++	  simplify_gen_subreg (HImode, op, innermode, i * UNITS_PER_WORD);
++	gcc_assert (parts[i]);
++	if (MEM_P (parts[i]))
++	  {
++	    parts[i] = validize_mem (parts[i]);
++	    gcc_assert (parts[i]);
++	  }
++      }
++  gcc_assert (last_insn == get_last_insn ());
++  return words;
++}
++
++
++/* Generate the appropriate template for a read-modify-write operation
++ * in MODE, using the SRC_OPERAND as the operand index for a binary
++ * pattern, with the least significant word generated using INIT_OP
++ * and any higher words are generated using NEXT_OP (which defaults to
++ * INIT_OP if NULL).  If SRC_OPERAND is 0, a unary pattern is used. */
++static const char *
++output_template (enum machine_mode mode,
++		 int src_operand, bool reversep,
++		 const char *init_op, const char *next_op,
++		 const char *prefix)
++{
++  char buffer[1024];
++  int offset = 0;
++
++  if (!next_op)
++    next_op = init_op;
++  buffer[offset] = 0;
++  if (prefix)
++    offset += snprintf (buffer, sizeof (buffer) - offset,
++			"%s\n\t", prefix);
++  switch (mode)
++    {
++    case QImode:
++      if (0 < src_operand)
++	offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			    "%s.b\t%%%d, %%0", init_op, src_operand);
++      else
++	offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			    "%s.b\t%%0", init_op);
++      break;
++    case HImode:
++      if (0 < src_operand)
++	offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			    "%s\t%%%d, %%0", init_op, src_operand);
++      else
++	offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			    "%s\t%%0", init_op);
++      break;
++    case SImode:
++    case SFmode:
++      if (0 < src_operand)
++	{
++	  const char* format = reversep
++	    ? "%s\t%%B%d, %%B0\n\t"
++	      "%s\t%%A%d, %%A0"
++	    : "%s\t%%A%d, %%A0\n\t"
++	      "%s\t%%B%d, %%B0";
++
++	  offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			      format, init_op, src_operand, next_op, src_operand);
++	}
++      else
++	{
++	  const char* format = reversep
++	    ? "%s\t%%B0\n\t" "%s\t%%A0"
++	    : "%s\t%%A0\n\t" "%s\t%%B0";
++	  offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			      format, init_op, next_op);
++	}
++      break;
++    case DImode:
++      if (0 < src_operand)
++	{
++	  const char* format = reversep
++	    ? "%s\t%%D%d, %%D0\n\t"
++	      "%s\t%%C%d, %%C0\n\t"
++	      "%s\t%%B%d, %%B0\n\t"
++	      "%s\t%%A%d, %%A0"
++	    : "%s\t%%A%d, %%A0\n\t"
++	      "%s\t%%B%d, %%B0\n\t"
++	      "%s\t%%C%d, %%C0\n\t"
++ 	      "%s\t%%D%d, %%D0";
++
++	  offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			      format,
++			      init_op, src_operand,
++			      next_op, src_operand,
++			      next_op, src_operand, next_op, src_operand);
++	}
++      else
++	{
++	  const char* format = reversep
++	    ? "%s\t%%D0\n\t"
++	      "%s\t%%C0\n\t"
++	      "%s\t%%B0\n\t"
++	      "%s\t%%A0"
++	    : "%s\t%%A0\n\t"
++	      "%s\t%%B0\n\t"
++	      "%s\t%%C0\n\t"
++	      "%s\t%%D0";
++	  offset += snprintf (buffer + offset, sizeof (buffer) - offset,
++			      format, init_op, next_op, next_op, next_op);
++	}
++      break;
++    default:
++      gcc_unreachable ();
++    }
++  return ggc_strdup (buffer);
++}
++
++/* Generate the appropriate template for a read-modify-write operation
++ * in MODE, using the SRC_OPERAND as the operand index for a binary
++ * pattern, with the least significant word generated using INIT_OP
++ * and any higher words are generated using NEXT_OP (which defaults to
++ * INIT_OP if NULL).  If SRC_OPERAND is 0, a unary pattern is used. */
++const char *
++msp430_output_template (enum machine_mode mode,
++			int src_operand,
++			const char *init_op, const char *next_op,
++			const char *prefix)
++{
++  return output_template (mode, src_operand, 0, init_op, next_op, prefix);
++}
++
++const char *
++msp430_output_reverse_template (enum machine_mode mode,
++				int src_operand,
++				const char *init_op, const char *next_op,
++				const char *prefix)
++{
++  return output_template (mode, src_operand, 1, init_op, next_op, prefix);
++}
++
++
++/* Return an instruction template that performs the move without
++   clobbering registers used in the input. */
++const char *
++msp430_mov_noclobber (rtx operands[])
++{
++  static const char si_fwdtempl[] = "mov\t%A1, %A0\n\tmov\t%B1, %B0";
++  static const char si_revtempl[] = "mov\t%B1, %B0\n\tmov\t%A1, %A0";
++  static const char di_fwdtempl[] =
++    "mov\t%A1, %A0\n\tmov\t%B1, %B0\n\tmov\t%C1, %C0\n\tmov\t%D1, %D0";
++  static const char di_revtempl[] =
++    "mov\t%D1, %D0\n\tmov\t%C1, %C0\n\tmov\t%B1, %B0\n\tmov\t%A1, %A0";
++  static const char di_xBtempl[] =
++    "mov\t%A1, %A0\n\tmov\t%C1, %C0\n\tmov\t%D1, %D0\n\tmov\t%B1, %B0";
++  static const char di_xCtempl[] =
++    "mov\t%A1, %A0\n\tmov\t%B1, %B0\n\tmov\t%D1, %D0\n\tmov\t%C1, %C0";
++
++  const char *fwdtempl;
++  const char *revtempl;
++  int dst_regno;
++  int dst_end_regno;
++  int index_reg;
++
++  switch (GET_MODE (operands[0]))
++    {
++    case SFmode:
++    case SImode:
++      fwdtempl = si_fwdtempl;
++      revtempl = si_revtempl;
++      break;
++    case DImode:
++      fwdtempl = di_fwdtempl;
++      revtempl = di_revtempl;
++      break;
++    default:
++      debug_rtx (operands[0]);
++      gcc_unreachable ();
++    }
++
++  if (!REG_P (operands[0])
++      || safe_from_earlyclobber (operands[1], operands[0]))
++    return fwdtempl;
++
++  if (REG_P (operands[1]))
++    return REGNO (operands[0]) > REGNO (operands[1]) ? revtempl : fwdtempl;
++
++  gcc_assert (MEM_P (operands[1]));
++  dst_regno = REGNO (operands[0]);
++  dst_end_regno = END_REGNO (operands[0]);
++  for (index_reg = dst_regno; index_reg < dst_end_regno; ++index_reg)
++    if (reg_mentioned_p (gen_rtx_REG (VOIDmode, index_reg), operands[1]))
++      break;
++  if (index_reg == dst_regno)
++    return revtempl;
++  if (index_reg + 1 == dst_end_regno)
++    return fwdtempl;
++  if (index_reg == dst_regno + 1)
++    return di_xBtempl;
++  if (index_reg == dst_regno + 2)
++    return di_xCtempl;
++
++  gcc_unreachable ();
++}
++
++/* Conservative guess whether jump is going to be in range.  If false
++   positive, assembler or linker will reject.  If false negative, code
++   will be larger than necessary.  Err on the side of working code.
++   
++   Note that the distance is in units (bytes), not words; the
++   underlying instruction supports -1024 to 1022 as it stores the
++   offset in words as a signed 10-bit value. */
++#define MSP430_JUMP_IN_RANGE(_d) (-500 <= (_d) && (_d) <= 500)
++
++/* Offset from insn to dest in bytes.  If addresses are not known,
++   returns a value known to be considered "out of range" for a
++   conditional jump. */
++int
++msp430_jump_dist (rtx dest, rtx insn)
++{
++  int dest_addr;
++  int cur_addr;
++
++  if (!insn_addresses_)
++    return 1026;
++
++  dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (dest) == LABEL_REF
++					? XEXP (dest, 0) : dest));
++  cur_addr = INSN_ADDRESSES (INSN_UID (insn));
++  return dest_addr - cur_addr;
++}
++
++
++static rtx
++msp430_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
++{
++  int words;
++
++  words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++  if (words > RETURN_REGISTERS_AVAILABLE)
++    internal_error ("Too many words (%d) for libcall register return", words);
++  return gen_rtx_REG (mode, (MSP430_RETURN_REGISTER_BASE + 1 - words));
++}
++
++static rtx
++msp430_function_value (const_tree type,
++		       const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
++		       bool outgoing ATTRIBUTE_UNUSED)
++{
++  unsigned HOST_WIDE_INT bytes;
++  int words;
++  enum machine_mode tmpmode;
++
++  if (TYPE_MODE (type) != BLKmode)
++    return msp430_libcall_value (TYPE_MODE (type), 0);
++
++  /* Although we return reg:BLK, explow.c:hard_function_value will
++     override this to be an integral mode, and we have to round the
++     size up so the return register is compatible. */
++  bytes = int_size_in_bytes (type);
++  tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
++  while ((tmpmode != VOIDmode) && (GET_MODE_SIZE (tmpmode) < bytes))
++    tmpmode = GET_MODE_WIDER_MODE (tmpmode);
++  gcc_assert (tmpmode != VOIDmode);
++  words = (GET_MODE_SIZE (tmpmode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++  if (words > RETURN_REGISTERS_AVAILABLE)
++    internal_error ("Too many words (%d) for block register return", words);
++
++  return gen_rtx_REG (BLKmode, (MSP430_RETURN_REGISTER_BASE + 1 - words));
++}
++
++/* 1 if REGNO is a general register or the stack pointer */
++int
++msp430_general_or_stack_reg (int regno)
++{
++  return MSP430_GENERAL_REGISTER_NUM_P (regno)
++    || STACK_POINTER_REGNUM == regno;
++}
++
++/* 1 if X is a memory reference through a register suitable for
++   indirect referencing: @rN. */
++int
++msp430_indirect_register_operand (rtx x)
++{
++  if (!MEM_P (x))
++    return 0;
++  x = XEXP (x, 0);
++  if (!REG_P (x))
++    return 0;
++  return msp430_general_or_stack_reg (REGNO (x));
++}
++
++/* 1 if X is a indexed memory reference: X(rN). */
++int
++msp430_indexed_register_operand (rtx x)
++{
++  if (!MEM_P (x))
++    return 0;
++  x = XEXP (x, 0);
++  if (GET_CODE (x) != PLUS)
++    return 0;
++  /* Left addend (Rn) must be an indexing register, but assume that
++     the assembler will be able to create a constant out of whatever
++     the right addend (X) is. */
++  return msp430_general_or_stack_reg (REGNO (XEXP (x, 0)));
++}
++
++/* The routine used to output NUL terminated strings.  We use a special
++version of this for most svr4 targets because doing so makes the
++generated assembly code more compact (and thus faster to assemble)
++as well as more readable, especially for targets like the i386
++(where the only alternative is to output character sequences as
++comma separated lists of numbers).   */
++
++#define ESCAPES \
++"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
++\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
++\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
++\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
++\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
++\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
++\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
++\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
++/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
++   ASM_OUTPUT_LIMITED_STRING macros.  Each byte in the table
++   corresponds to a particular byte value [0..255].  For any
++   given byte value, if the value in the corresponding table
++   position is zero, the given character can be output directly.
++   If the table value is 1, the byte must be output as a \ooo
++   octal escape.  If the tables value is anything else, then the
++   byte value should be output as a \ followed by the value
++   in the table.  Note that we can use standard UN*X escape
++   sequences for many control characters, but we don't use
++   \a to represent BEL because some svr4 assemblers (e.g. on
++   the i386) don't know about that.  Also, we don't use \v
++   since some versions of gas, such as 2.2 did not accept it.  */
++
++void
++gas_output_limited_string (FILE * file, const char *str)
++{
++  const unsigned char *_limited_str = (const unsigned char *) str;
++  unsigned ch;
++  fputs ("\t.string\t\"", file);
++  for (; (ch = *_limited_str); _limited_str++)
++    {
++      int escape;
++      switch (escape = ESCAPES[ch])
++	{
++	case 0:
++	  putc (ch, file);
++	  break;
++	case 1:
++	  fprintf (file, "\\%03o", ch);
++	  break;
++	default:
++	  putc ('\\', file);
++	  putc (escape, file);
++	  break;
++	}
++    }
++  fprintf (file, "\"\n");
++}
++
++/* The routine used to output sequences of byte values.  We use a special
++version of this for most svr4 targets because doing so makes the
++generated assembly code more compact (and thus faster to assemble)
++as well as more readable.  Note that if we find subparts of the
++character sequence which end with NUL (and which are shorter than
++STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
++
++#define STRING_LIMIT	((unsigned) 64)
++
++void
++gas_output_ascii (FILE * file, const char *str, size_t length)
++{
++  const unsigned char *_ascii_bytes = (const unsigned char *) str;
++  const unsigned char *limit = _ascii_bytes + length;
++  unsigned bytes_in_chunk = 0;
++  for (; _ascii_bytes < limit; _ascii_bytes++)
++    {
++      const unsigned char *p;
++      if (bytes_in_chunk >= 60)
++	{
++	  fprintf (file, "\"\n");
++	  bytes_in_chunk = 0;
++	}
++      for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
++	continue;
++      if (p < limit && (p - _ascii_bytes) <= (signed) STRING_LIMIT)
++	{
++	  if (bytes_in_chunk > 0)
++	    {
++	      fprintf (file, "\"\n");
++	      bytes_in_chunk = 0;
++	    }
++	  gas_output_limited_string (file, (const char *) _ascii_bytes);
++	  _ascii_bytes = p;
++	}
++      else
++	{
++	  int escape;
++	  unsigned ch;
++	  if (bytes_in_chunk == 0)
++	    fprintf (file, "\t.ascii\t\"");
++	  switch (escape = ESCAPES[ch = *_ascii_bytes])
++	    {
++	    case 0:
++	      putc (ch, file);
++	      bytes_in_chunk++;
++	      break;
++	    case 1:
++	      fprintf (file, "\\%03o", ch);
++	      bytes_in_chunk += 4;
++	      break;
++	    default:
++	      putc ('\\', file);
++	      putc (escape, file);
++	      bytes_in_chunk += 2;
++	      break;
++	    }
++	}
++    }
++  if (bytes_in_chunk > 0)
++    fprintf (file, "\"\n");
++}
++
++
++static section *
++msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
++{
++  /* For now, the only thing we override is const strings.  In the
++   * future we might be looking at near/far attributes. */
++  if (TREE_CODE (decl) == STRING_CST)
++    return default_function_rodata_section (current_function_decl);
++  return default_select_section (decl, reloc, align);
++}
++
++/* Outputs to the stdio stream FILE some
++appropriate text to go at the start of an assembler file.  */
++
++static void
++msp430_file_start (void)
++{
++  FILE *file = asm_out_file;
++  const struct tag_value_pair_t *mp;
++
++  output_file_directive (file, main_input_filename);
++  if (msp430_mcu_name)
++    fprintf (file, "\t.arch %s\n", msp430_mcu_name);
++  mp = find_pair_by_value (msp430_cpu, cpu_tag_value_map);
++  if (mp)
++    fprintf (file, "\t.cpu %s\n", mp->tag);
++  mp = find_pair_by_value (msp430_mpy, mpy_tag_value_map);
++  if (mp)
++    fprintf (file, "\t.mpy %s\n", mp->tag);
++  fprintf (file, "\n");
++}
++
++int
++msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
++			   enum machine_mode mode ATTRIBUTE_UNUSED)
++{
++  return 1;
++}
++
++static bool
++msp430_frame_pointer_required (void)
++{
++  return cfun->machine->frame_pointer_required;
++}
++
++static bool
++msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED, const int to_reg)
++{
++  if (frame_pointer_needed)
++    return to_reg == HARD_FRAME_POINTER_REGNUM;
++  return true;
++}
++
++/* Adjustment to overall insn length if the given integer value is the
++   source for an operation in the given value.  Assumption is that the
++   operation consists of a single MSP430 instruction repeated once for
++   each word in mode. */
++static int
++length_adjustment_for_int (HOST_WIDE_INT ival, enum machine_mode mode)
++{
++  HOST_WIDE_INT i;
++  int adjustment = 0;
++
++  switch (mode)
++    {
++    case DImode:
++#if HOST_BITS_PER_WIDE_INT > 32
++      i = trunc_int_for_mode (0xFFFF & (ival >> 48), HImode);
++      if (MSP430_CG_INT_P (i))
++	adjustment -= UNITS_PER_WORD;
++      i = trunc_int_for_mode (0xFFFF & (ival >> 32), HImode);
++      if (MSP430_CG_INT_P (i))
++	adjustment -= UNITS_PER_WORD;
++#endif /* HOST_BITS_PER_WIDE_INT */
++      /* FALLTHRU */
++    case SImode:
++    case SFmode:
++      i = trunc_int_for_mode (0xFFFF & (ival >> 16), HImode);
++      if (MSP430_CG_INT_P (i))
++	adjustment -= UNITS_PER_WORD;
++      /* FALLTHRU */
++    case HImode:
++    case QImode:
++      i = trunc_int_for_mode (0xFFFF & (ival >> 0), HImode);
++      if (MSP430_CG_INT_P (i))
++	adjustment -= UNITS_PER_WORD;
++      break;
++    default:
++      break;
++    }
++  return adjustment;
++}
++
++/* Adjustment to instruction length if the given op is an immediate
++   value source for an operation in the given mode. */
++static int
++length_adjustment_for_immediate (rtx op, enum machine_mode mode)
++{
++  int adjustment = 0;
++  HOST_WIDE_INT ival;
++
++  switch (GET_CODE (op))
++    {
++    case CONST_INT:
++      ival = INTVAL (op);
++#if HOST_BITS_PER_WIDE_INT <= 32
++      if (DImode == mode)
++	adjustment -= 2 * UNITS_PER_WORD;
++#endif /* HOST_BITS_PER_WIDE_INT */
++      break;
++    case CONST_DOUBLE:
++#if HOST_BITS_PER_WIDE_INT <= 32
++      if (4 < GET_MODE_SIZE (mode))
++	adjustment +=
++	  length_adjustment_for_int (CONST_DOUBLE_HIGH (op), mode);
++#endif /* HOST_BITS_PER_WIDE_INT */
++      ival = CONST_DOUBLE_LOW (op);
++      break;
++    case SYMBOL_REF:
++    case LABEL_REF:
++    case CONST:
++      return 0;
++    default:
++      gcc_unreachable ();
++    }
++  adjustment += length_adjustment_for_int (ival, mode);
++  return adjustment;
++}
++
++/* Return the length adjusted for the effects of pattern in the
++   context of insn. */
++static int
++adjust_pattern_length (rtx insn, rtx pattern, int len)
++{
++#if TRACE_INSN_LENGTH
++  int ilen = len;
++#endif
++
++  switch (GET_CODE (pattern))
++    {
++    case SET:
++      {
++	bool skip_adjustment = false;
++	enum rtx_code src_code;
++	bool output_uses_S;
++	rtx src = SET_SRC (pattern);
++	rtx src0;
++	rtx dst = SET_DEST (pattern);
++	enum machine_mode mode = GET_MODE (dst);
++	enum attr_instr_format format = get_attr_instr_format (insn);
++
++	if (INSTR_FORMAT_UNDEF == format)
++	  break;
++
++	output_uses_S = push_operand (dst, mode);
++	src_code = GET_CODE (src);
++	switch (src_code)
++	  {
++	  case UNSPEC:
++	    switch (XINT (src, 1))
++	      {
++	      case UNSPEC_PUSH_MULTI:
++	      case UNSPEC_POP_MULTI:
++		src = gen_rtx_REG (HImode, INTVAL (XVECEXP (src, 0, 1)));
++		break;
++	      default:
++#if CHECK_INSN_LENGTH
++		fprintf (stderr, "Unrecognized unspec code %d in source",
++			 XINT (src, 1));
++		debug_rtx (src);
++#endif /* CHECK_INSN_LENGTH */
++		break;
++	      case UNSPEC_BITTEST_FOR_CARRY:
++		{
++		  gcc_assert (dst == cc0_rtx || CCmode == GET_MODE (dst));
++		  dst = XVECEXP (src, 0, 0);
++		  src = XVECEXP (src, 0, 1);
++		  break;
++		}
++	      }
++	    break;
++	  case UNSPEC_VOLATILE:
++	    switch (XINT (src, 1))
++	      {
++	      case UNSPECV_GET_WATCHDOG_CLEAR_VALUE:
++		len += UNITS_PER_WORD;
++		src = XVECEXP (src, 0, 0);
++		break;
++	      default:
++		src = XVECEXP (src, 0, 0);
++		break;
++	      }
++	    break;
++	  case NOT:
++	  case SIGN_EXTEND:
++	  case ZERO_EXTEND:
++	  case BSWAP:
++	    src = XEXP (src, 0);
++	    break;
++	  case AND:		/* includes NAND */
++	  case IOR:
++	  case XOR:
++	  case PLUS:
++	  case MINUS:
++	  case ASHIFT:
++	    src0 = XEXP (src, 0);
++	    if (GET_CODE (src0) == UNSPEC_VOLATILE)
++	      src0 = XVECEXP (src0, 0, 0);
++	    if (rtx_equal_p (dst, src0))
++	      src = XEXP (src, 1);
++	    else
++	      {
++		gcc_assert (rtx_equal_p (dst, XEXP (src, 1)));
++		src = src0;
++	      }
++	    if (src_code == AND && GET_CODE (src) == NOT)
++	      src = XEXP (src, 0);
++	    break;
++	  case CALL:
++	    src = XEXP (src, 0);
++	    gcc_assert (MEM == GET_CODE (src));
++	    src = XEXP (src, 0);
++	    output_uses_S = true;
++	    break;
++	  case COMPARE:
++	    gcc_assert (dst == cc0_rtx);
++	    src0 = XEXP (src, 0);
++	    if (GET_CODE (src0) == AND)
++	      {
++		gcc_assert (rtx_equal_p (XEXP (src, 1), const0_rtx));
++		src = src0;
++	      }
++	    dst = XEXP (src, 0);
++	    src = XEXP (src, 1);
++	    break;
++	  case IF_THEN_ELSE:
++	    {
++	      static const int condjmp_insn_len = UNITS_PER_WORD;
++	      static const int jmp_insn_len = UNITS_PER_WORD;
++	      static const int offset_len = UNITS_PER_WORD; /* @todo A20 */
++	      rtx cmp = XEXP (src, 0);
++	      rtx if_loc = XEXP (src, 1);
++	      rtx else_loc = XEXP (src, 2);
++	      int dist = msp430_jump_dist (if_loc, insn);
++	      bool in_range = MSP430_JUMP_IN_RANGE (dist);
++
++	      gcc_assert (XEXP (cmp, 0) == cc0_rtx);
++	      gcc_assert (XEXP (cmp, 1) == const0_rtx);
++	      gcc_assert (else_loc == pc_rtx);
++	      switch (GET_CODE (cmp))
++		{
++		case LE:
++		case GT:
++		case LEU:
++		case GTU:
++		  /* Simulate unsupported comparisons with an extra local jump */
++		  len += condjmp_insn_len;
++		  /* FALLTHRU */
++		case EQ:
++		case NE:
++		case LT:
++		case GE:
++		case LTU:
++		case GEU:
++		  /* Out of range will jump around an added br insn
++		     plus immediate offset (@todo A20 update) */
++		  if (! in_range)
++		    len += jmp_insn_len + offset_len;
++		  break;
++		default:
++		  gcc_unreachable ();
++		}
++	      skip_adjustment = true;
++	    }
++	    break;
++	  case RETURN:
++	    skip_adjustment = true;
++	    break;
++	  case CONST_INT:
++	  case MEM:
++	  case REG:
++	    break;
++	  default:
++#if CHECK_INSN_LENGTH
++	    fprintf (stderr, "Unrecognized source code %d (%s) in pattern ",
++		     src_code, rtx_name[src_code]);
++	    debug_rtx (pattern);
++#endif /* CHECK_INSN_LENGTH */
++	    break;
++	  }
++	if (skip_adjustment)
++	  break;
++	
++	mode = GET_MODE (dst);
++
++	switch (format)
++	  {
++	  case INSTR_FORMAT_EMU1DD:
++	    src = dst;
++	    format = INSTR_FORMAT_FMT1;
++	    break;
++	  case INSTR_FORMAT_FMT1:
++	  case INSTR_FORMAT_FMT2:
++	  case INSTR_FORMAT_FMT2S:
++	  case INSTR_FORMAT_CONDJMP:
++	    break;
++	  default:
++	    gcc_unreachable ();
++	  }
++
++
++	if (immediate_operand (src, VOIDmode))
++	  len += length_adjustment_for_immediate (src, mode);
++	else if (register_operand (src, VOIDmode))
++	  len -= UNITS_PER_WORD * get_attr_instr_mult (insn);
++	else if (format == INSTR_FORMAT_FMT1 || format == INSTR_FORMAT_FMT2S)
++	  {
++	    if (pop_operand (src, VOIDmode))	/* or other auto-increment indirect */
++	      len -= UNITS_PER_WORD * get_attr_instr_mult (insn);
++	    else if (msp430_indirect_register_operand (src))
++	      {
++		if (!(format == INSTR_FORMAT_FMT2S
++		      && output_uses_S
++		      && REGNO (XEXP (src, 0)) == STACK_POINTER_REGNUM))
++		  len -= UNITS_PER_WORD;
++	      }
++	  }
++	else
++	  {
++	    /* indexed and symbolic accounted for in default length. */
++#if CHECK_INSN_LENGTH
++	    fprintf (stderr, "Unhandled src ");
++	    debug_rtx (src);
++#endif /* CHECK_INSN_LENGTH */
++	  }
++	switch (format)
++	  {
++	  case INSTR_FORMAT_FMT1:
++	    if (register_operand (dst, mode) || PC == GET_CODE (dst))
++	      len -= UNITS_PER_WORD * get_attr_instr_mult (insn);
++	    break;
++	  case INSTR_FORMAT_FMT2:
++	  case INSTR_FORMAT_FMT2S:
++	  case INSTR_FORMAT_CONDJMP:
++	    break;
++	  default:
++	    gcc_unreachable ();
++	  }
++	break;
++      }
++    case PARALLEL:
++    case SEQUENCE:
++      {
++	int i;
++	for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
++	  len = adjust_pattern_length (insn, XVECEXP (pattern, 0, i), len);
++	break;
++      }
++    case USE:
++      break;
++    case CALL:
++      {
++	rtx src = XEXP (pattern, 0);
++	gcc_assert (MEM == GET_CODE (src));
++	src = XEXP (src, 0);
++	if (immediate_operand (src, VOIDmode))
++	  len += length_adjustment_for_immediate (src, HImode);
++	else if (register_operand (src, VOIDmode))
++	  len -= UNITS_PER_WORD;
++	else if (msp430_indirect_register_operand (src))
++	  {
++	    if (REGNO (XEXP (src, 0)) != STACK_POINTER_REGNUM)
++	      len -= UNITS_PER_WORD;
++	  }
++	break;
++      }
++    case RETURN:
++    case UNSPEC_VOLATILE:
++    case CLOBBER:
++    case ASM_INPUT:
++    case ASM_OPERANDS:
++    case ADDR_VEC:
++    default:
++#if CHECK_INSN_LENGTH
++      fprintf (stderr, "Unhandled insn code %d %s\n", GET_CODE (pattern),
++	       rtx_name[GET_CODE (pattern)]);
++#endif /* CHECK_INSN_LENGTH */
++      break;
++    }
++
++#if TRACE_INSN_LENGTH
++  fprintf (stderr, "insn len %d to %d format %d ", ilen, len,
++	   get_attr_instr_format (insn));
++  debug_rtx (insn);
++#endif /* TRACE_INSN_LENGTH */
++  return len;
++}
++
++int
++msp430_adjust_insn_length (rtx insn, int len)
++{
++  return adjust_pattern_length (insn, PATTERN (insn), len);
++}
++
++/* Return 1 if X and Y are the same for a sign or zero extension,
++   i.e. register or memory reference match except in mode. */
++int
++msp430_extend_matches (const_rtx x, const_rtx y)
++{
++  int rc = rtx_equal_p (x, y);
++  if (rc)
++    return rc;
++  if (GET_CODE (x) == REG && GET_CODE (y) == SUBREG && SUBREG_BYTE (y) == 0)
++    return rtx_equal_p (x, SUBREG_REG (y));
++  if (GET_CODE (x) != GET_CODE (y))
++    return 0;
++  if (GET_CODE (x) == REG)
++    return REGNO (x) == REGNO (y);
++  if (GET_CODE (x) == MEM)
++    return (mpys_rtx == x && mpys_b_rtx == y)
++      || (op2_rtx == x && op2_b_rtx == y)
++      || rtx_equal_p (XEXP (x, 0), XEXP (y, 0));
++  if (GET_CODE (x) == SUBREG)
++    return SUBREG_BYTE (x) == SUBREG_BYTE (y)
++      && rtx_equal_p (SUBREG_REG (x), SUBREG_REG (y));
++  return 0;
++}
++
++/* x is the destination of an extend operation where the source is of
++   the given mode.  Obtain a compatible reference to the low part of
++   the destination so we can copy the source into it. */
++static rtx
++msp430_extend_force_to_mode (rtx x, enum machine_mode mode)
++{
++  switch (GET_CODE (x))
++    {
++    case REG:
++      return gen_lowpart (mode, x);
++    case MEM:
++      return adjust_address (x, mode, 0);
++      break;
++    case SUBREG:
++      return simplify_rtx (gen_lowpart_SUBREG (mode, x));
++    default:
++      break;
++    }
++  gcc_unreachable ();
++}
++
++/* Expand all {,zero_}extendmn2 instructions. */
++static void
++msp430_expand_extend (rtx operands[], bool signed_p)
++{
++  rtx dst_lo = NULL_RTX;	/* hi, or lowpart (hi, si) */
++  rtx dst_hi = NULL_RTX;	/* highpart (hi, si) or highpart (hi, lowpart (si, di)) */
++  rtx dst_llo = NULL_RTX;	/* lowpart (hi, lowpart (si, di)) */
++  rtx dst_lhi = NULL_RTX;	/* highpart (hi, lowpart (si, di)) */
++  rtx dst_hlo = NULL_RTX;	/* lowpart (hi, highpart (si, di)) */
++  rtx dst_hhi = NULL_RTX;	/* highpart (hi, highpart (si, di)) */
++  rtx extended_value;
++  bool need_copy;
++
++  switch (GET_MODE (operands[0]))
++    {
++    case HImode:
++      dst_lo = operands[0];
++      break;
++    case SImode:
++      dst_lo = gen_lowpart (HImode, operands[0]);
++      dst_hi = gen_highpart (HImode, operands[0]);
++      break;
++    case DImode:
++      if (REG_P (operands[0]))
++	{
++	  dst_llo = gen_rtx_SUBREG (HImode, operands[0], 0);
++	  dst_lhi = gen_rtx_SUBREG (HImode, operands[0], UNITS_PER_WORD);
++	  dst_hlo = gen_rtx_SUBREG (HImode, operands[0], 2 * UNITS_PER_WORD);
++	  dst_hhi = gen_rtx_SUBREG (HImode, operands[0], 3 * UNITS_PER_WORD);
++	}
++      else if (MEM_P (operands[0]))
++	{
++	  dst_llo = adjust_address (operands[0], HImode, 0);
++	  dst_lhi = adjust_address (dst_llo, HImode, UNITS_PER_WORD);
++	  dst_hlo = adjust_address (dst_lhi, HImode, UNITS_PER_WORD);
++	  dst_hhi = adjust_address (dst_hlo, HImode, UNITS_PER_WORD);
++	}
++      else
++	{
++	  debug_rtx (operands[0]);
++	  gcc_unreachable ();
++	}
++      dst_lo = dst_llo;
++      dst_hi = dst_lhi;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++  extended_value = signed_p ? NULL_RTX : GEN_INT (0);
++  need_copy = !msp430_extend_matches (operands[0], operands[1]);
++  if (QImode == GET_MODE (operands[1]))
++    {
++      rtx dst_qi = msp430_extend_force_to_mode (dst_lo, QImode);
++
++      if (!signed_p && GET_MODE (operands[0]) == HImode
++	  && operands[0] == op2_rtx)
++	{
++	  emit_insn (gen_andhi3 (dst_lo, dst_lo, GEN_INT (0xff00)));
++	  return;
++	}
++      if (need_copy)
++	{
++	  if (!signed_p && register_operand (dst_lo, HImode))
++	    emit_insn (gen_loadqi2 (dst_lo, operands[1]));
++	  else
++	    emit_move_insn (dst_qi, operands[1]);
++	}
++      if (signed_p)
++	{
++	  emit_insn (gen_extend8bithi1 (dst_lo));
++	  if (dst_hi)
++	    {
++	      extended_value = copy_to_reg (dst_lo);
++	      emit_insn (gen_bswaphi1 (extended_value));
++	      emit_insn (gen_extend8bithi1 (extended_value));
++	    }
++	}
++      else
++	{
++	  if (memory_operand (operands[0], GET_MODE (operands[0])))
++	    emit_move_insn (gen_highpart (QImode, dst_lo), extended_value);
++	  else if (!need_copy)
++	    emit_insn (gen_andhi3 (dst_lo, dst_lo, GEN_INT (0xff)));
++	}
++    }
++  else if (HImode == GET_MODE (operands[1]))
++    {
++      if (need_copy)
++	emit_move_insn (dst_lo, operands[1]);
++      if (signed_p)
++	{
++	  extended_value = gen_reg_rtx (HImode);
++	  emit_insn (gen_ashrhi3 (extended_value, dst_lo, 
++				  GEN_INT (GET_MODE_BITSIZE (HImode) - 1)));
++	}
++    }
++  else if (SImode == GET_MODE (operands[1]))
++    {
++      if (need_copy)
++	emit_move_insn (gen_lowpart (SImode, operands[0]), operands[1]);
++      if (signed_p)
++	{
++	  extended_value = gen_reg_rtx (HImode);
++	  emit_insn (gen_ashrhi3 (extended_value, dst_hi, 
++				  GEN_INT (GET_MODE_BITSIZE (HImode) - 1)));
++	}
++      dst_hi = NULL_RTX;
++    }
++  else
++    gcc_unreachable ();
++  if (dst_hi)
++    emit_move_insn (dst_hi, extended_value);
++  if (dst_hlo)
++    {
++      emit_move_insn (dst_hlo, extended_value);
++      emit_move_insn (dst_hhi, extended_value);
++    }
++}
++
++/***** SIGN EXTEND *********/
++
++/* Expand all (signed) extendmn2 instructions.  Return 1 if all
++   necessary instructions have been emited; returns 0 to fall through
++   and generate extendqihi2_match. */
++void
++msp430_expand_signextend (rtx operands[])
++{
++  msp430_expand_extend (operands, true);
++}
++
++/**** ZERO EXTEND *****/
++
++/* Expand all zero_extendmn2 instructions. */
++void
++msp430_expand_zeroextend (rtx operands[])
++{
++  msp430_expand_extend (operands, false);
++}
++
++int
++msp430_expand_extract (rtx operands[], bool signed_p)
++{
++  rtx dst = operands[0];
++  rtx bits = operands[1];
++  rtx width = operands[2];
++  rtx start = operands[3];
++  HOST_WIDE_INT mask;
++
++  if (!CONST_INT_P (width) || !CONST_INT_P (start))
++    return 0;
++  if (1 != INTVAL (width))
++    return 0;
++  if (signed_p)
++    return 0;
++  mask = (HOST_WIDE_INT)1 << INTVAL (start);
++  if (trunc_int_for_mode (mask, GET_MODE (bits)) != mask)
++    return 0;
++  gcc_assert (HImode == GET_MODE (dst));
++  if (GET_MODE (bits) == QImode)
++    emit_insn (gen_bittestforcarryqi2 (bits, GEN_INT (mask)));
++  else
++    {
++      gcc_assert (HImode == GET_MODE (bits));
++      emit_insn (gen_bittestforcarryhi2 (bits, GEN_INT (mask)));
++    }
++  emit_move_insn (dst, const0_rtx);
++  emit_insn (gen_rlchi1 (dst));
++  return 1;
++}
++
++static int
++mpy_for_hardware_multiply (enum machine_mode result_mode,
++			   enum machine_mode operand_mode)
++{
++  bool widen;
++  int required_mpy = 0;
++
++  if (VOIDmode == operand_mode)
++    operand_mode = result_mode;
++  widen = (operand_mode != result_mode);
++  switch (result_mode)
++    {
++    case QImode:
++      required_mpy = MSP430_MPY_TYPE_16;
++      break;
++    case HImode:
++      required_mpy = MSP430_MPY_TYPE_16;
++      break;
++    case SImode:
++      required_mpy = widen ? MSP430_MPY_TYPE_16 : MSP430_MPY_TYPE_32;
++      break;
++    case DImode:
++      required_mpy = widen ? MSP430_MPY_TYPE_32 : MSP430_MPY_NONE;
++      break;
++    default:
++      required_mpy = MSP430_MPY_NONE;
++      break;
++    }
++  return required_mpy;
++}
++
++void
++msp430_expand_mul (rtx operands[], int signed_mul)
++{
++  rtx m_mpy;
++  rtx m_op2;
++  rtx m_reslo;
++  int required_mpy;
++  bool widen;
++  enum machine_mode op0mode = GET_MODE (operands[0]);
++  enum machine_mode op1mode = GET_MODE (operands[1]);
++  enum machine_mode op2mode = GET_MODE (operands[2]);
++
++  gcc_assert ((op1mode == op2mode) || CONST_INT_P (operands[2]));
++  op2mode = op1mode;
++  widen = (op0mode == GET_MODE_WIDER_MODE (op1mode));
++  gcc_assert (widen || op0mode == op1mode);
++
++  required_mpy = mpy_for_hardware_multiply (op0mode, op1mode);
++
++  if (!(msp430_mpy & required_mpy))
++    {
++      rtx libsym = NULL_RTX;
++
++      switch (op0mode)
++	{
++	case QImode:
++	  libsym = libsym_mulqi3;
++	  break;
++	case HImode:
++	  if (widen)
++	    libsym = (signed_mul ? libsym_mulqihi3 : libsym_umulqihi3);
++	  else
++	    libsym = libsym_mulhi3;
++	  break;
++	case SImode:
++	  if (widen)
++	    libsym = (signed_mul ? libsym_mulhisi3 : libsym_umulhisi3);
++	  else
++	    libsym = libsym_mulsi3;
++	  break;
++	case DImode:
++	  if (widen)
++	    libsym = (signed_mul ? libsym_mulsidi3 : libsym_umulsidi3);
++	  else
++	    libsym = libsym_muldi3;
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++
++      emit_library_call_value (libsym, operands[0], LCT_CONST,
++			       op0mode, 2,
++			       operands[1], op1mode,
++			       operands[2], op1mode);
++      return;
++    }
++
++  if (!MSP430_NOINT_HWMUL)
++    emit_insn (gen_mpy_inhibit_intr ());
++
++  if (MSP430_MPY_TYPE_16 == required_mpy)
++    {
++      m_mpy = signed_mul ? mpys_rtx : mpy_rtx;
++      m_op2 = op2_rtx;
++      m_reslo = reslo_rtx;
++      if (op0mode == QImode)
++	m_reslo = reslo_b_rtx;
++      if (op1mode == QImode)
++	m_mpy = signed_mul ? mpys_b_rtx : mpy_b_rtx;
++      if (op2mode == QImode)
++	m_op2 = op2_b_rtx;
++
++      emit_move_insn (m_mpy, operands[1]);
++      if (op1mode == QImode && signed_mul
++	  && !(msp430_mpy & MSP430_MPY_HAS_SE))
++	{
++	  gcc_assert (m_mpy == mpys_b_rtx);
++	  emit_insn (gen_extendqihi2 (mpys_rtx, m_mpy));
++	}
++      emit_move_insn (m_op2, operands[2]);
++      if (op2mode == QImode && signed_mul
++	  && !(msp430_mpy & MSP430_MPY_HAS_SE))
++	emit_insn (gen_extendqihi2 (op2_rtx, m_op2));
++
++      switch (op0mode)
++	{
++	case QImode:
++	case HImode:
++	  emit_move_insn (operands[0], m_reslo);
++	  break;
++	case SImode:
++	  emit_move_insn (gen_lowpart (HImode, operands[0]), reslo_rtx);
++	  emit_move_insn (gen_highpart (HImode, operands[0]), reshi_rtx);
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++    }
++  else
++    {
++      gcc_assert (SImode == op1mode);
++      emit_move_insn (signed_mul ? mpys32l_rtx : mpy32l_rtx,
++		      gen_lowpart (HImode, operands[1]));
++      emit_move_insn (signed_mul ? mpys32h_rtx : mpy32h_rtx,
++		      gen_highpart (HImode, operands[1]));
++      if (CONST_INT_P (operands[2]))
++	{
++	  HOST_WIDE_INT iv = INTVAL (operands[2]);
++	  emit_move_insn (op2l_rtx,
++			  GEN_INT (trunc_int_for_mode
++				   (iv & ((1 << BITS_PER_WORD) - 1),
++				    HImode)));
++	  emit_move_insn (op2h_rtx,
++			  GEN_INT (trunc_int_for_mode
++				   (iv >> BITS_PER_WORD, HImode)));
++	}
++      else
++	{
++	  gcc_assert (SImode == op2mode);
++	  emit_move_insn (op2l_rtx, gen_lowpart (HImode, operands[2]));
++	  emit_move_insn (op2h_rtx, gen_highpart (HImode, operands[2]));
++	}
++      switch (op0mode)
++	{
++	case SImode:
++	  emit_move_insn (gen_lowpart (HImode, operands[0]), reslo_rtx);
++	  emit_move_insn (gen_highpart (HImode, operands[0]), reshi_rtx);
++	  break;
++	case DImode:
++	  {
++	    rtx dst_llo = NULL_RTX;	/* lowpart (hi, lowpart (si, di)) */
++	    rtx dst_lhi = NULL_RTX;	/* highpart (hi, lowpart (si, di)) */
++	    rtx dst_hlo = NULL_RTX;	/* lowpart (hi, highpart (si, di)) */
++	    rtx dst_hhi = NULL_RTX;	/* highpart (hi, highpart (si, di)) */
++
++	    if (REG_P (operands[0]))
++	      {
++		dst_llo = gen_rtx_SUBREG (HImode, operands[0], 0);
++		dst_lhi =
++		  gen_rtx_SUBREG (HImode, operands[0], UNITS_PER_WORD);
++		dst_hlo =
++		  gen_rtx_SUBREG (HImode, operands[0], 2 * UNITS_PER_WORD);
++		dst_hhi =
++		  gen_rtx_SUBREG (HImode, operands[0], 3 * UNITS_PER_WORD);
++	      }
++	    else if (MEM_P (operands[0]))
++	      {
++		dst_llo = adjust_address (operands[0], HImode, 0);
++		dst_lhi = adjust_address (dst_llo, HImode, UNITS_PER_WORD);
++		dst_hlo = adjust_address (dst_lhi, HImode, UNITS_PER_WORD);
++		dst_hhi = adjust_address (dst_hlo, HImode, UNITS_PER_WORD);
++	      }
++	    else
++	      gcc_unreachable ();
++
++	    emit_move_insn (dst_llo, res0_rtx);
++	    emit_move_insn (dst_lhi, res1_rtx);
++	    emit_move_insn (dst_hlo, res2_rtx);
++	    emit_move_insn (dst_hhi, res3_rtx);
++	    break;
++	  }
++	default:
++	  gcc_unreachable ();
++	}
++    }
++
++  if (!MSP430_NOINT_HWMUL)
++    emit_insn (gen_mpy_restore_intr ());
++}
++
++enum shift_type_e
++{
++  ST_INVALID,
++  ST_ashl,
++  ST_ashr,
++  ST_lshr,
++  ST_lshr_first,
++  ST_lshr_next
++};
++
++/* Shift types: (arith << 1) | left */
++
++#define ST_IS_ARITH(_st) (ST_ashl == (_st) || ST_ashr == (_st))
++#define ST_IS_LEFT(_st) (ST_ashl == (_st))
++
++static void
++msp430_expand_libcall_shift (rtx operands[], enum shift_type_e shift_type)
++{
++  enum machine_mode op0mode = GET_MODE (operands[0]);
++  bool arith_shift = ST_IS_ARITH (shift_type);
++  bool left_shift = ST_IS_LEFT (shift_type);
++  rtx libsym;
++
++  gcc_assert (CONST_INT_P (operands[2]) || QImode == GET_MODE (operands[2]));
++  gcc_assert (GET_MODE (operands[1]) == op0mode);
++  switch (op0mode)
++    {
++    case QImode:
++      if (arith_shift)
++	libsym = (left_shift ? libsym_ashlqi3 : libsym_ashrqi3);
++      else
++	libsym = libsym_lshrqi3;
++      break;
++    case HImode:
++      if (arith_shift)
++	libsym = (left_shift ? libsym_ashlhi3 : libsym_ashrhi3);
++      else
++	libsym = libsym_lshrhi3;
++      break;
++    case SImode:
++      if (arith_shift)
++	libsym = (left_shift ? libsym_ashlsi3 : libsym_ashrsi3);
++      else
++	libsym = libsym_lshrsi3;
++      break;
++    case DImode:
++      if (arith_shift)
++	libsym = (left_shift ? libsym_ashldi3 : libsym_ashrdi3);
++      else
++	libsym = libsym_lshrdi3;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++  emit_library_call_value (libsym,
++			   operands[0], LCT_CONST,
++			   op0mode, 2,
++			   operands[1], GET_MODE (operands[0]),
++			   operands[2], QImode);
++}
++
++static void
++expand_shift_bitsizem1 (rtx r_dst, rtx r_src, enum shift_type_e shift_type)
++{
++  enum machine_mode opmode = GET_MODE (r_dst);
++  rtx parts[4];
++  rtx r_hi;
++  rtx r_fill;
++  rtx r_qi = 0;
++  int pres;
++  int pmax;
++  int nparts = msp430_extract_multiword_operand (opmode, r_src, parts);
++
++  /* The only time it's worth considering doing this operation in
++   * memory is if src==dst and src is memory and it's an ashl or lshr
++   * on QImode or HImode, at which point we save one word of ROM. */
++  gcc_assert (0 < nparts);
++  pmax = nparts - 1;
++  pres = ST_IS_LEFT (shift_type) ? pmax : 0;
++  r_hi = gen_reg_rtx (HImode);
++  if (QImode == opmode)
++    {
++      emit_insn (gen_loadqi2 (r_hi, parts[pmax - pres]));
++      r_qi = gen_lowpart (QImode, r_hi);
++    }
++  else
++    emit_move_insn (r_hi, parts[pmax - pres]);
++
++  r_fill = const0_rtx;
++  if (ST_ashl == shift_type)
++    {
++      emit_insn (gen_rrahi1 (r_hi));
++      emit_move_insn (r_hi, const0_rtx);
++      if (QImode == opmode)
++	emit_insn (gen_rrcqi1 (r_qi));
++      else
++	emit_insn (gen_rrchi1 (r_hi));
++    }
++  else if (ST_ashr == shift_type)
++    {
++      if (QImode == opmode)
++	{
++	  emit_insn (gen_extend8bithi1 (r_hi));
++	  emit_insn (gen_bswaphi1 (r_hi));
++	}
++      else
++	{
++	  emit_insn (gen_bswaphi1 (r_hi));
++	  emit_insn (gen_extend8bithi1 (r_hi));
++	  emit_insn (gen_bswaphi1 (r_hi));
++	  emit_insn (gen_extend8bithi1 (r_hi));
++	}
++      r_fill = r_hi;
++    }
++  else
++    {
++      gcc_assert (ST_lshr == shift_type);
++      if (QImode == opmode)
++	emit_insn (gen_rlaqi1 (r_qi));
++      else
++	emit_insn (gen_rlahi1 (r_hi));
++      emit_move_insn (r_hi, const0_rtx);
++      emit_insn (gen_rlchi1 (r_hi));
++    }
++
++  if (QImode == opmode)
++    emit_insn (gen_storeqi2 (r_dst, r_hi));
++  else
++    {
++      int pi;
++
++      nparts = msp430_extract_multiword_operand (opmode, r_dst, parts);
++      for (pi = 0; pi < nparts; ++pi)
++	emit_move_insn (parts[pi], (pres == pi) ? r_hi : r_fill);
++    }
++}
++
++static void msp430_expand_shift (rtx operands[], enum shift_type_e shift_type);
++
++static void
++expand_unary_shift (rtx op, int count, enum shift_type_e shift_type)
++{
++  rtx operands[3];
++
++  operands[0] = op;
++  operands[1] = op;
++  operands[2] = GEN_INT (count);
++  msp430_expand_shift (operands, shift_type);
++}
++
++static const int shift_loop_overhead_words = 5;	/* push?, mov[2?], decr, jne, pop? */
++
++static void
++msp430_expand_shift (rtx operands[], enum shift_type_e shift_type)
++{
++  rtx r_src = operands[1];
++  rtx r_dst = operands[0];
++  enum machine_mode opmode = GET_MODE (r_dst);
++  bool arith_shift = ST_IS_ARITH (shift_type);
++  bool left_shift = ST_IS_LEFT (shift_type);
++  int count;
++  rtx src_parts[4];
++  rtx op_parts[4];
++  bool op_is_mem;
++  bool use_dst_as_op;
++  bool need_op_init;
++  bool need_op_store;
++  int pi;
++  int pmin;
++  int pmax;
++  int nparts;
++
++  if (CONST_INT_P (operands[2]))
++    {
++      count = INTVAL (operands[2]) % GET_MODE_BITSIZE (opmode);
++      operands[2] = GEN_INT (count);
++    }
++  else
++    count = -1;
++
++  gcc_assert (GET_MODE (r_src) == GET_MODE (r_dst));
++
++  /* If effective shift is zero, do nothing */
++  if (0 == count)
++    {
++      if (!rtx_equal_p (r_dst, r_src))
++	emit_move_insn (r_dst, r_src);
++      return;
++    }
++
++  if (count == GET_MODE_BITSIZE (opmode) - 1)
++    {
++      expand_shift_bitsizem1 (r_dst, r_src, shift_type);
++      return;
++    }
++
++  if (msp430_enable_libcall_shift)
++    {
++      bool use_libcall = false;
++
++      /* inline loops are smaller than the overhead of setting up for
++       * a library call plus the size of the library routine itself.
++       * Assuming that non-constant shifts are rare, prefer libcalls
++       * for non-constant shifts unless optimizing for size. */
++      if (!optimize_function_for_size_p (cfun) && QImode != opmode
++	  && 0 > count)
++	use_libcall = true;
++
++      if (use_libcall)
++	{
++	  msp430_expand_libcall_shift (operands, shift_type);
++	  return;
++	}
++    }
++
++  /* Canonicalize the count, or note that it's determined at runtime */
++  op_is_mem = false;
++  need_op_store = need_op_init = true;
++  if (rtx_equal_p (r_src, r_dst) && !register_operand (r_dst, VOIDmode))
++    {
++      /* Potentially decide to put op in memory. */
++    }
++
++  nparts = msp430_extract_multiword_operand (opmode, r_src, src_parts);
++  pmin = 0;
++  pmax = nparts - 1;
++
++  memset (op_parts, 0, sizeof (op_parts));
++
++  use_dst_as_op = false;
++  if (op_is_mem)
++    use_dst_as_op = true;
++  else if (QImode == opmode)
++    {
++      op_parts[pmin] = gen_reg_rtx (HImode);
++      emit_insn (gen_loadqi2 (op_parts[pmin], src_parts[pmin]));
++      if (ST_ashr == shift_type)
++	emit_insn (gen_extend8bithi1 (op_parts[pmin]));
++      need_op_init = false;
++    }
++  else if ((count < BITS_PER_WORD) && register_operand (r_dst, VOIDmode))
++    use_dst_as_op = true;
++
++  if (use_dst_as_op)
++    {
++      if (!rtx_equal_p (r_dst, r_src))
++	emit_move_insn (r_dst, r_src);
++      msp430_extract_multiword_operand (opmode, r_dst, op_parts);
++      need_op_store = need_op_init = false;
++    }
++  else if (!op_parts[0])
++    {
++      for (pi = 0; pi < nparts; ++pi)
++	op_parts[pi] = gen_reg_rtx (HImode);
++    }
++
++  if (count >= 48)
++    {
++      rtx newop = NULL_RTX;
++      gcc_assert (4 == nparts);
++      gcc_assert (need_op_init);
++      if (ST_IS_LEFT (shift_type))
++	{
++	  emit_move_insn (op_parts[3], src_parts[0]);
++	  emit_move_insn (op_parts[2], const0_rtx);
++	  emit_move_insn (op_parts[1], const0_rtx);
++	  emit_move_insn (op_parts[0], const0_rtx);
++	  newop = op_parts[3];
++	}
++      else
++	{
++	  emit_move_insn (op_parts[0], src_parts[3]);
++	  if (ST_IS_ARITH (shift_type))
++	    emit_insn (gen_ashrhi_15 (op_parts[3], op_parts[0]));
++	  else
++	    emit_move_insn (op_parts[3], const0_rtx);
++	  emit_move_insn (op_parts[2], op_parts[3]);
++	  emit_move_insn (op_parts[1], op_parts[3]);
++	  newop = op_parts[0];
++	}
++      need_op_init = false;
++      count -= 48;
++      if (0 < count)
++	{
++	  expand_unary_shift (newop, count, shift_type);
++	  count = 0;
++	}
++      goto done_op;
++    }
++
++  if (count >= 32)
++    {
++      int base;
++      rtx r_fill = const0_rtx;
++      rtx newop = gen_reg_rtx (SImode);
++
++      gcc_assert (4 == nparts);
++      if (ST_IS_LEFT (shift_type))
++	{
++	  emit_move_insn (gen_lowpart (HImode, newop), src_parts[0]);
++	  emit_move_insn (gen_highpart (HImode, newop), src_parts[1]);
++	  base = 2;
++	}
++      else
++	{
++	  emit_move_insn (gen_lowpart (HImode, newop), src_parts[2]);
++	  emit_move_insn (gen_highpart (HImode, newop), src_parts[3]);
++	  base = 0;
++	  if (ST_IS_ARITH (shift_type))
++	    {
++	      r_fill = gen_reg_rtx (HImode);
++	      emit_insn (gen_ashrhi_15 (r_fill, src_parts[3]));
++	    }
++	}
++      count -= 32;
++      if (0 < count)
++	{
++	  expand_unary_shift (newop, count, shift_type);
++	  count = 0;
++	}
++      emit_move_insn (op_parts[base], gen_lowpart (HImode, newop));
++      emit_move_insn (op_parts[base + 1], gen_highpart (HImode, newop));
++      emit_move_insn (op_parts[2 - base], r_fill);
++      emit_move_insn (op_parts[2 - base + 1], r_fill);
++      need_op_init = false;
++      goto done_op;
++    }
++
++  if (count >= 16)
++    {
++      gcc_assert (need_op_init);
++      if (ST_IS_LEFT (shift_type))
++	{
++	  for (pi = pmax; pmin < pi; --pi)
++	    emit_move_insn (op_parts[pi], src_parts[pi - 1]);
++	  emit_move_insn (op_parts[pmin], const0_rtx);
++	  ++pmin;
++	}
++      else
++	{
++	  for (pi = pmin; pi < pmax; ++pi)
++	    emit_move_insn (op_parts[pi], src_parts[pi + 1]);
++	  if (ST_IS_ARITH (shift_type))
++	    emit_insn (gen_ashrhi_15 (op_parts[pmax], src_parts[pmax]));
++	  else
++	    emit_move_insn (op_parts[pmax], const0_rtx);
++	  --pmax;
++	}
++      need_op_init = false;
++      count -= 16;
++    }
++
++  if (count >= 8)
++    {
++      if (need_op_init)
++	{
++	  for (pi = pmin; pi <= pmax; ++pi)
++	    emit_move_insn (op_parts[pi], src_parts[pi]);
++	  need_op_init = false;
++	}
++
++      if (ST_IS_LEFT (shift_type))
++	{
++	  for (pi = pmax; pmin < pi; --pi)
++	    emit_insn (gen_mwshl8xor (op_parts[pi], op_parts[pi - 1]));
++	  emit_insn (gen_loadqi2
++		     (op_parts[pmin], gen_lowpart (QImode, op_parts[pmin])));
++	  emit_insn (gen_bswaphi1 (op_parts[pmin]));
++	}
++      else
++	{
++	  emit_insn (gen_bswaphi1 (op_parts[pmin]));
++	  for (pi = pmin; pi < pmax; ++pi)
++	    emit_insn (gen_mwshr8xor (op_parts[pi], op_parts[pi + 1]));
++	  if (ST_ashr == shift_type)
++	    emit_insn (gen_extend8bithi1 (op_parts[pmax]));
++	  else
++	    emit_insn (gen_loadqi2
++		       (op_parts[pmax],
++			gen_lowpart (QImode, op_parts[pmax])));
++	}
++      count -= 8;
++    }
++
++  if (need_op_init)
++    for (pi = 0; pi < nparts; ++pi)
++      emit_move_insn (op_parts[pi], src_parts[pi]);
++
++  if (0 < count && msp430_cpu & MSP430_CPU_MSP430X && !op_is_mem && 1 == nparts)
++    {
++      rtx (*gen_shift_m) (rtx, rtx, rtx);
++
++      gen_shift_m = left_shift ? gen_ashlhi_m : (arith_shift ? gen_ashrhi_m : gen_lshrhi_m);
++      while (count >= MSP430_CPUX_MULTISHIFT_MAX)
++	{
++	  emit_insn (gen_shift_m
++		     (op_parts[pmin], op_parts[pmin],
++		      GEN_INT (MSP430_CPUX_MULTISHIFT_MAX)));
++	  count -= MSP430_CPUX_MULTISHIFT_MAX;
++	}
++      if (count)
++	{
++	  emit_insn (gen_shift_m
++		     (op_parts[pmin], op_parts[pmin], GEN_INT (count)));
++	  count -= count;
++	}
++    }
++
++done_op:
++  if (need_op_store)
++    {
++      if (QImode == opmode && HImode == GET_MODE (op_parts[0]))
++	emit_insn (gen_storeqi2 (r_dst, op_parts[0]));
++      else
++	{
++	  rtx dst_parts[4];
++	  msp430_extract_multiword_operand (opmode, r_dst, dst_parts);
++	  for (pi = 0; pi < nparts; ++pi)
++	    emit_move_insn (dst_parts[pi], op_parts[pi]);
++	}
++    }
++
++  if (0 != count)
++    {
++      rtx (*gen_shift_1) (rtx);
++      rtx r_cnt = NULL_RTX;
++      rtx l_top = NULL_RTX;
++      rtx l_bottom = NULL_RTX;
++      rtx t_ne = NULL_RTX;
++      rtx t_eq = NULL_RTX;
++      bool use_loop;
++
++      switch (opmode)
++	{
++	case QImode:
++	  gen_shift_1 =
++	    left_shift ? gen_ashlqi_1 : (arith_shift ? gen_ashrqi_1 :
++					 gen_lshrqi_1);
++	  break;
++	case HImode:
++	  gen_shift_1 =
++	    left_shift ? gen_ashlhi_1 : (arith_shift ? gen_ashrhi_1 :
++					 gen_lshrhi_1);
++	  break;
++	case SImode:
++	  gen_shift_1 =
++	    left_shift ? gen_ashlsi_1 : (arith_shift ? gen_ashrsi_1 :
++					 gen_lshrsi_1);
++	  break;
++	case DImode:
++	  gen_shift_1 =
++	    left_shift ? gen_ashldi_1 : (arith_shift ? gen_ashrdi_1 :
++					 gen_lshrdi_1);
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++
++      if (0 > count)
++	use_loop = true;
++      else
++	{
++	  int shift_1_words;
++	  int inline_words;
++	  int loop_words;
++
++	  /* Warning: gcc without -Os will unroll loops up to eight
++	   * times, so since we know the count will never exceed 7
++	   * this doesn't really do much good. */
++	  shift_1_words =
++	    (GET_MODE_SIZE (opmode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++	  inline_words = count * shift_1_words;
++	  loop_words = shift_loop_overhead_words + shift_1_words;
++	  use_loop =
++	    inline_words >=
++	    (optimize_function_for_size_p (cfun) ? 1 : 4) * loop_words;
++	}
++
++      if (use_loop)
++	{
++	  r_cnt = gen_reg_rtx (QImode);
++	  l_top = gen_label_rtx ();
++	  t_ne = gen_rtx_NE (QImode, r_cnt, const0_rtx);
++
++	  if (0 < count)
++	    emit_move_insn (r_cnt, GEN_INT (count));
++	  else
++	    {
++	      l_bottom = gen_label_rtx ();
++	      t_eq = gen_rtx_EQ (QImode, r_cnt, const0_rtx);
++	      emit_move_insn (r_cnt, operands[2]);
++	      emit_insn (gen_andqi3
++			 (r_cnt, r_cnt,
++			  GEN_INT (GET_MODE_BITSIZE (GET_MODE (r_dst)) - 1)));
++	      emit_jump_insn (gen_cbranchqi4
++			      (t_eq, r_cnt, const0_rtx, l_bottom));
++	    }
++	  emit_label (l_top);
++	  count = 1;
++	}
++
++      while (count--)
++	emit_insn (gen_shift_1 (r_dst));
++
++      if (l_top)
++	{
++	  emit_move_insn (r_cnt, plus_constant (r_cnt, -1));
++	  emit_jump_insn (gen_cbranchqi4 (t_ne, r_cnt, const0_rtx, l_top));
++	  if (l_bottom)
++	    emit_label (l_bottom);
++	}
++    }
++
++  return;
++}
++
++void
++msp430_expand_ashl (rtx operands[])
++{
++  msp430_expand_shift (operands, ST_ashl);
++}
++
++void
++msp430_expand_ashr (rtx operands[])
++{
++  msp430_expand_shift (operands, ST_ashr);
++}
++
++void
++msp430_expand_lshr (rtx operands[])
++{
++  msp430_expand_shift (operands, ST_lshr);
++}
++
++void
++msp430_notice_update_cc (rtx exp ATTRIBUTE_UNUSED, rtx insn)
++{
++  rtx set = single_set (insn);
++  rtx src;
++  enum attr_cc cc = get_attr_cc (insn);
++
++  switch (cc)
++    {
++    case CC_UNDEF:
++    default:
++      gcc_unreachable ();
++    case CC_NONE:
++      if (set)
++	{
++	  if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
++	    cc_status.value1 = NULL_RTX;
++	  if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
++	    cc_status.value2 = NULL_RTX;
++	}
++      return;
++    case CC_CLOBBER:
++      CC_STATUS_INIT;
++      break;
++    case CC_N:
++    case CC_NZ:
++    case CC_NZC:
++    case CC_VNZC:
++    case CC_EXPLICIT:
++      CC_STATUS_INIT;
++      gcc_assert (set);
++      switch (cc)
++	{
++	case CC_N:
++	  cc_status.flags |= CC_CLOBBER_V | CC_CLOBBER_Z | CC_CLOBBER_C;
++	  break;
++	case CC_NZ:
++	  cc_status.flags |= CC_CLOBBER_V | CC_CLOBBER_C;
++	  break;
++	case CC_NZC:
++	  cc_status.flags |= CC_NO_OVERFLOW;
++	  break;
++	case CC_EXPLICIT:
++	  cc_status.flags |= CC_EXPLICIT_COMPARE;
++	  break;
++	default:
++	  break;
++	}
++
++      if (rtx_equal_p (cc0_rtx, SET_DEST (set)))
++	{
++	  src = SET_SRC (set);
++	  gcc_assert (COMPARE == GET_CODE (src));
++	  cc_status.value1 = src;
++	  if (XEXP (src, 1) == const0_rtx)
++	    cc_status.value2 = XEXP (src, 0);
++	}
++      else
++	{
++	  cc_status.value1 = SET_DEST (set);
++	  if (!side_effects_p (SET_SRC (set)))
++	    cc_status.value2 = SET_SRC (set);
++	}
++      break;
++    }
++  return;
++}
++
++static void
++expand_cbranch (enum rtx_code code,
++		rtx op0,
++		rtx op1,
++		rtx loc)
++{
++  rtx cmp;
++  enum machine_mode mode;
++  bool ps0;
++  bool ps1;
++
++  /* If dest prefers source addressing, and source doesn't, swap
++     them */
++  ps0 = CONSTANT_P (op0) || (MEM_P (op0) && REG_P (XEXP (op0, 0)));
++  ps1 = CONSTANT_P (op1) || (MEM_P (op1) && REG_P (XEXP (op1, 0)));
++  if (ps0 && !ps1)
++    {
++      rtx tmp = op0;
++      op0 = op1;
++      op1 = tmp;
++      code = swap_condition (code);
++    }
++  if (GT == code || GTU == code || LE == code || LEU == code)
++    {
++      if (CONSTANT_P (op1))
++	{
++	  if (GET_CODE (op1) == CONST_INT)
++	    {
++	      HOST_WIDE_INT new_bound = 1 + INTVAL (op1);
++	      HOST_WIDE_INT new_bound_trunc;
++
++	      new_bound_trunc = trunc_int_for_mode (new_bound, GET_MODE (op0));
++	      if ((new_bound == new_bound_trunc)
++		  && ((0 != new_bound)
++		      || (code != GTU && code != LEU)))
++		{
++		  op1 = GEN_INT (new_bound);
++		  switch (code)
++		    {
++		    case GT:
++		      code = GE;
++		      break;
++		    case LE:
++		      code = LT;
++		      break;
++		    case GTU:
++		      code = GEU;
++		      break;
++		    case LEU:
++		      code = LTU;
++		      break;
++		    default:
++		      gcc_unreachable ();
++		    }
++		}
++	    }
++	}
++      else
++	{
++	  rtx tmp = op0;
++	  op0 = op1;
++	  op1 = tmp;
++	  code = swap_condition (code);
++	}
++    }
++
++  mode = GET_MODE (op0);
++
++  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
++  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
++    {
++      enum rtx_code rcode = reverse_condition (code);
++      rtx fail = gen_label_rtx ();
++      rtx parts0[4];
++      rtx parts1[4];
++      int words;
++      int w;
++
++      words = msp430_extract_multiword_operand (mode, op0, parts0);
++      msp430_extract_multiword_operand (mode, op1, parts1);
++      switch (code)
++	{
++	case EQ:
++	  for (w = 0; w < words - 1; ++w)
++	    expand_cbranch (rcode, parts0[w], parts1[w], fail);
++	  expand_cbranch (code, parts0[w], parts1[w], loc);
++	  emit_label (fail);
++	  break;
++	case NE:
++	  for (w = 0; w < words; ++w)
++	    expand_cbranch (code, parts0[w], parts1[w], loc);
++	  break;
++	case LT:
++	case LTU:
++	case GT:
++	case GTU:
++	  for (w = words - 1; w > 0; --w)
++	    {
++	      expand_cbranch (code, parts0[w], parts1[w], loc);
++	      expand_cbranch (NE, parts0[w], parts1[w], fail);
++	      code = unsigned_condition (code);
++	    }
++	  expand_cbranch (code, parts0[0], parts1[0], loc);
++	  emit_label (fail);
++	  break;
++	case LE:
++	case LEU:
++	case GE:
++	case GEU:
++	  for (w = words - 1; w > 0; --w)
++	    {
++	      expand_cbranch (rcode, parts0[w], parts1[w], fail);
++	      expand_cbranch (rcode, parts1[w], parts0[w], loc);
++	      rcode = unsigned_condition (rcode);
++	    }
++	  expand_cbranch (unsigned_condition (code), parts0[0],
++			  parts1[0], loc);
++	  emit_label (fail);
++	  break;
++
++	default:
++	  gcc_unreachable ();
++	}
++      return;
++    }
++  if (QImode == mode)
++    emit_insn (gen_setccqi2 (op0, op1));
++  else
++    {
++      gcc_assert (HImode == mode);
++      emit_insn (gen_setcchi2 (op0, op1));
++    }
++  cmp = gen_rtx_fmt_ee (code, CCmode, cc0_rtx, const0_rtx);
++  emit_jump_insn (gen_branchcc (loc, cmp));
++}
++
++void
++msp430_expand_cbranch (rtx operands[])
++{
++  enum rtx_code code = GET_CODE (operands[0]);
++  rtx op0 = operands[1];
++  rtx op1 = operands[2];
++  rtx loc = operands[3];
++
++  gcc_assert (rtx_equal_p (XEXP (operands[0], 0), op0));
++  gcc_assert (rtx_equal_p (XEXP (operands[0], 1), op1));
++  expand_cbranch (code, op0, op1, loc);
++}
++
++
++const char*
++msp430_output_branchcc (rtx insn, rtx operands[])
++{
++  rtx loc = operands[0];
++  enum rtx_code cmp = GET_CODE (operands[1]);
++  int dist = msp430_jump_dist (loc, insn);
++  int in_range = MSP430_JUMP_IN_RANGE (dist);
++
++  /* If optimization deleted a test instruction that ensured SR.V has
++     the correct value for a jl/jge opcode, force the instruction to
++     be emitted. */
++  if ((cmp == LT || cmp == GE || cmp == LE || cmp == GT)
++      && (!(cc_status.flags & (CC_EXPLICIT_COMPARE | CC_NO_OVERFLOW))))
++    return 0;
++
++  /* NB: Update the IF_THEN_ELSE block in adjust_pattern_length if
++     this changes. */
++  switch (cmp)
++    {
++    case EQ:
++      return in_range ? "jeq\t%0" : "jne\t1f\n\tbr\t#%0\n1:\n";
++    case NE:
++      return in_range ? "jne\t%0" : "jeq\t1f\n\tbr\t#%0\n1:\n";
++    case LT:
++      return in_range ? "jl\t%0" : "jge\t1f\n\tbr\t#%0\n1:\n";
++    case GE:
++      return in_range ? "jge\t%0" : "jl\t1f\n\tbr\t#%0\n1:\n";
++    case LTU:
++      return in_range ? "jlo\t%0" : "jhs\t1f\n\tbr\t#%0\n1:\n";
++    case GEU:
++      return in_range ? "jhs\t%0" : "jlo\t1f\n\tbr\t#%0\n1:\n";
++    case LE:
++      return in_range ? "jeq\t%0\n\tjl\t%0" : "jeq\t1f\n\tjge\t2f\n1:\tbr\t#%0\n2:\n";
++    case GT:
++      return in_range ? "jeq\t1f\n\tjge\t%0\n1:\n" : "jeq\t2f\n\tjl\t2f\n1:\tbr\t#%0\n2:\n";
++    case LEU:
++      return in_range ? "jeq\t%0\n\tjlo\t%0" : "jeq\t1f\n\tjhs\t2f\n1:\tbr\t#%0\n2:\n";
++    case GTU:
++      return in_range ? "jeq\t1f\n\tjhs\t%0\n1:\n" : "jeq\t2f\n\tjlo\t2f\n1:\tbr\t#%0\n2:\n";
++    default:
++      break;
++    }
++  gcc_unreachable ();
++  return 0;
++}
++
++static void
++msp430_asm_function_epilogue (FILE *file,
++			      HOST_WIDE_INT size ATTRIBUTE_UNUSED)
++{
++  struct machine_function *mfp = cfun->machine;
++  if (mfp->inhibited_return_label != NULL)
++    ASM_OUTPUT_LABEL(file, mfp->inhibited_return_label);
++}
++
++static void
++msp430_asm_trampoline_template (FILE * fd)
++{
++  fprintf (fd, "; TRAMPOLINE HERE\n"
++	   "; move context (either r1 or r4) to r6\n"
++	   "; call function (0xf0f0 will be changed)\n");
++  fprintf (fd, "\tmov	#0xf0f0, r6\n");
++  fprintf (fd, "\tbr	#0xf0f0\n");
++  fprintf (fd, "; END OF TRAMPOLINE\n\n");
++}
++
++static void
++msp430_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
++{
++  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
++  emit_move_insn (gen_rtx_MEM (HImode, plus_constant (m_tramp, 2)),
++		  static_chain);
++  emit_move_insn (gen_rtx_MEM (HImode, plus_constant (m_tramp, 6)), fnaddr);
++}
++
++static void
++msp430_init_libfuncs (void)
++{
++  libsym_mulqi3 = init_one_libfunc ("__mulqi3");
++  set_optab_libfunc (smul_optab, QImode, "__mulqi3");
++
++  libsym_mulqihi3 = init_one_libfunc ("__mulqihi3");
++  set_optab_libfunc (smul_widen_optab, HImode, "__mulqihi3");
++  libsym_umulqihi3 = init_one_libfunc ("__umulqihi3");
++  set_optab_libfunc (umul_widen_optab, HImode, "__umulqihi3");
++  libsym_mulhi3 = init_one_libfunc ("__mulhi3");
++  set_optab_libfunc (smul_optab, HImode, "__mulhi3");
++
++  libsym_mulhisi3 = init_one_libfunc ("__mulhisi3");
++  set_optab_libfunc (smul_widen_optab, SImode, "__mulhisi3");
++  libsym_umulhisi3 = init_one_libfunc ("__umulhisi3");
++  set_optab_libfunc (umul_widen_optab, SImode, "__umulhisi3");
++  libsym_mulsi3 = init_one_libfunc ("__mulsi3");
++  set_optab_libfunc (smul_optab, SImode, "__mulsi3");
++
++  libsym_mulsidi3 = init_one_libfunc ("__mulsidi3");
++  set_optab_libfunc (smul_widen_optab, DImode, "__mulsidi3");
++  libsym_umulsidi3 = init_one_libfunc ("__umulsidi3");
++  set_optab_libfunc (umul_widen_optab, DImode, "__umulsidi3");
++  libsym_muldi3 = init_one_libfunc ("__muldi3");
++  set_optab_libfunc (smul_optab, DImode, "__muldi3");
++
++  /* libcalls used for all divide and remainder operations */
++  set_optab_libfunc (sdiv_optab, QImode, "__divqi3");
++  set_optab_libfunc (sdiv_optab, HImode, "__divhi3");
++  set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
++  set_optab_libfunc (sdiv_optab, DImode, "__divdi3");
++  set_optab_libfunc (udiv_optab, QImode, "__udivqi3");
++  set_optab_libfunc (udiv_optab, HImode, "__udivhi3");
++  set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
++  set_optab_libfunc (udiv_optab, DImode, "__udivdi3");
++  set_optab_libfunc (smod_optab, QImode, "__modqi3");
++  set_optab_libfunc (smod_optab, HImode, "__modhi3");
++  set_optab_libfunc (smod_optab, SImode, "__modsi3");
++  set_optab_libfunc (smod_optab, DImode, "__moddi3");
++  set_optab_libfunc (umod_optab, QImode, "__umodqi3");
++  set_optab_libfunc (umod_optab, HImode, "__umodhi3");
++  set_optab_libfunc (umod_optab, SImode, "__umodsi3");
++  set_optab_libfunc (umod_optab, DImode, "__umoddi3");
++
++  libsym_ashlqi3 = init_one_libfunc ("__ashlqi3");
++  set_optab_libfunc (ashl_optab, QImode, "__ashlqi3");
++  libsym_ashrqi3 = init_one_libfunc ("__ashrqi3");
++  set_optab_libfunc (ashr_optab, QImode, "__ashrqi3");
++  libsym_lshrqi3 = init_one_libfunc ("__lshrqi3");
++  set_optab_libfunc (lshr_optab, QImode, "__lshrqi3");
++  libsym_ashlhi3 = init_one_libfunc ("__ashlhi3");
++  set_optab_libfunc (ashl_optab, HImode, "__ashlhi3");
++  libsym_ashrhi3 = init_one_libfunc ("__ashrhi3");
++  set_optab_libfunc (ashr_optab, HImode, "__ashrhi3");
++  libsym_lshrhi3 = init_one_libfunc ("__lshrhi3");
++  set_optab_libfunc (lshr_optab, HImode, "__lshrhi3");
++  libsym_ashlsi3 = init_one_libfunc ("__ashlsi3");
++  set_optab_libfunc (ashl_optab, SImode, "__ashlsi3");
++  libsym_ashrsi3 = init_one_libfunc ("__ashrsi3");
++  set_optab_libfunc (ashr_optab, SImode, "__ashrsi3");
++  libsym_lshrsi3 = init_one_libfunc ("__lshrsi3");
++  set_optab_libfunc (lshr_optab, SImode, "__lshrsi3");
++  libsym_ashldi3 = init_one_libfunc ("__ashldi3");
++  set_optab_libfunc (ashl_optab, DImode, "__ashldi3");
++  libsym_ashrdi3 = init_one_libfunc ("__ashrdi3");
++  set_optab_libfunc (ashr_optab, DImode, "__ashrdi3");
++  libsym_lshrdi3 = init_one_libfunc ("__lshrdi3");
++  set_optab_libfunc (lshr_optab, DImode, "__lshrdi3");
++
++}
++
++/* ---------------------------------------------------------------------------------------------------------------------------------------------- */
++
++static bool
++msp430_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
++		 int *total, bool speed)
++{
++  enum machine_mode mode = GET_MODE (x);
++  int words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++  bool is_430x = msp430_cpu & MSP430_CPU_MSP430X;
++  bool rv;
++
++  rv = true;
++  switch (code)
++    {
++    case CONST_INT:
++      {
++	int cwords = words * UNITS_PER_WORD;
++	cwords -= length_adjustment_for_int (INTVAL (x), mode);
++	*total = cwords;
++	break;
++      }
++    case SYMBOL_REF:
++      *total = COSTS_N_INSNS (words);
++      break;
++    case ASHIFT:
++    case ASHIFTRT:
++    case LSHIFTRT:
++      {
++	rtx r_count = XEXP (x, 1);
++	int count;
++
++	if (CONST_INT_P (r_count))
++	  count = INTVAL (r_count) & (GET_MODE_BITSIZE (mode) - 1);
++	else
++	  count = -1;
++
++	if (msp430_enable_libcall_shift && speed && QImode != mode
++	    && 0 > count)
++	  break;
++
++	if (0 > count)
++	  {
++	    *total =
++	      COSTS_N_INSNS (shift_loop_overhead_words +
++			     words * (1 << GET_MODE_SIZE (mode)));
++	    break;
++	  }
++
++	*total = 0;
++	while (0 < count)
++	  {
++	    if (GET_MODE_BITSIZE (mode) - 1 == count)
++	      {
++		*total += COSTS_N_INSNS (2);
++		break;
++	      }
++	    if (count >= 48)
++	      {
++		*total += words * COSTS_N_INSNS (1);
++		count -= 48;
++		words = 1;
++		continue;
++	      }
++	    if (count >= 32)
++	      {
++		*total += words * COSTS_N_INSNS (1);
++		count -= 32;
++		words = 2;
++		continue;
++	      }
++	    if (count >= 16)
++	      {
++		*total += words * COSTS_N_INSNS (1);
++		count -= 16;
++	      }
++	    if (count >= 8)
++	      {
++		*total +=
++		  3 * (words - 1) * COSTS_N_INSNS (1) + COSTS_N_INSNS (2);
++		count -= 8;
++	      }
++	    if (is_430x && HImode == mode
++		&& MSP430_CPUX_MULTISHIFT_COUNT_P (count))
++	      {
++		while (0 < count)
++		  {
++		    *total += COSTS_N_INSNS (speed ? count - 1 : 1);
++		    count -= MSP430_CPUX_MULTISHIFT_MAX;
++		  }
++		count = 0;
++	      }
++	    *total += count * words * COSTS_N_INSNS (1);
++	    break;
++	  }
++	break;
++      }
++
++    case MULT:
++      {
++	rtx r_op2 = XEXP (x, 1);
++	if (msp430_mpy & mpy_for_hardware_multiply (mode, GET_MODE (r_op2)))
++	  break;
++	*total = words * COSTS_N_INSNS (10);
++	if (speed)
++	  {
++	    int mf = GET_MODE_BITSIZE (mode);
++
++	    if (CONST_INT_P (r_op2))
++	      {
++		HOST_WIDE_INT ival =
++		  trunc_int_for_mode (INTVAL (r_op2), mode);
++		mf = 0;
++		while (ival)
++		  {
++		    ++mf;
++		    ival = (unsigned HOST_WIDE_INT) ival >> 2;
++		  }
++	      }
++	    *total *= mf;
++	  }
++	break;
++      }
++    case DIV:
++    case UDIV:
++    case MOD:
++    case UMOD:
++      *total = words * COSTS_N_INSNS (20);
++      if (speed)
++	*total *= GET_MODE_BITSIZE (mode);
++      break;
++    default:
++      *total *= words;
++      rv = false;
++      break;
++    }
++
++  return rv;
++}
++
++static int
++msp430_address_cost (rtx x, bool speed)
++{
++  /* Nothing special now; at some point auto increment/decrement might
++   * affect this. */
++  return rtx_cost (x, MEM, speed);
++}
++
++/* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
++static const struct default_options msp430_option_optimization_table[] = {
++  {OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1},
++  {OPT_LEVELS_NONE, 0, NULL, 0}
++};
++
++static void
++msp430_globalize_label (FILE * stream, const char *name)
++{
++  if (*name == '*' || *name == '@')
++    name++;
++  if (*name >= '0' && *name <= '9')
++    return;
++  fputs (".global\t", stream);
++  assemble_name (stream, name);
++  putc ('\n', stream);
++}
++
++bool
++msp430_inhibited_return_fallthru_p (rtx insn)
++{
++  struct machine_function *mfp;
++  
++  gcc_assert(cfun);
++  mfp = cfun->machine;
++  gcc_assert(mfp);
++  gcc_assert(mfp->frame_flags & MSP430_FF_ready_for_return);
++  gcc_assert(mfp->frame_flags & MSP430_FF_inhibit_return);
++
++  insn = next_nonnote_insn (insn);
++  gcc_assert (insn && BARRIER_P (insn));
++  insn = next_nonnote_insn (insn);
++  if (NULL_RTX == insn)
++    return true;
++  gcc_assert (LABEL_P (insn));
++  return false;
++}
++
++static bool
++msp430_cannot_modify_jumps_p (void)
++{
++  if (reload_completed && cfun && cfun->machine)
++    return !!(cfun->machine->frame_flags & MSP430_FF_inhibit_return);
++  return false;
++}
++
++/* 17.2 Driver -- no hooks */
++/* 17.3 Run-time Target */
++#undef TARGET_OPTION_OPTIMIZATION_TABLE
++#define TARGET_OPTION_OPTIMIZATION_TABLE msp430_option_optimization_table
++
++/* 17.4 Per-Function Data -- no hooks*/
++/* 17.5: Storage Layout */
++
++/* 17.6 Type Layout */
++/* SF 3191528: TARGET_DEFAULT_SHORT_ENUMS */
++
++/* 17.7 Registers */
++
++/* 17.8 Register Classes */
++/* TODO TARGET_IRA_COVER_CLASSES seems important */
++
++/* 17.9 Old Constraints */
++
++/* 17.10 Stack and Calling */
++/* 17.10.5 Elimination */
++#undef TARGET_FRAME_POINTER_REQUIRED
++#define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
++#undef TARGET_CAN_ELIMINATE
++#define TARGET_CAN_ELIMINATE msp430_can_eliminate
++/* 17.10.8 Scalar Return */
++#undef TARGET_FUNCTION_VALUE
++#define TARGET_FUNCTION_VALUE msp430_function_value
++#undef TARGET_LIBCALL_VALUE
++#define TARGET_LIBCALL_VALUE msp430_libcall_value
++/* 17.19.9 Aggregate Return */
++#undef TARGET_RETURN_IN_MEMORY
++#define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
++/* 17.10.11 Function Entry */
++#undef TARGET_ASM_FUNCTION_EPILOGUE
++#define TARGET_ASM_FUNCTION_EPILOGUE msp430_asm_function_epilogue
++/* 17.10.13 Tail Calls */
++
++/* 17.11 Varargs */
++
++/* 17.12 Trampolines */
++#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
++#define TARGET_ASM_TRAMPOLINE_TEMPLATE msp430_asm_trampoline_template
++#undef TARGET_TRAMPOLINE_INIT
++#define TARGET_TRAMPOLINE_INIT msp430_trampoline_init
++
++/* 17.13 Library Calls */
++#undef TARGET_INIT_LIBFUNCS
++#define TARGET_INIT_LIBFUNCS msp430_init_libfuncs
++
++/* 17.14 Addressing Modes */
++#undef TARGET_LEGITIMATE_ADDRESS_P
++#define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
++
++/* 17.15 Anchored Addresses */
++
++/* 17.16 Condition Code */
++
++/* 17.17 Costs */
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS msp430_rtx_cost
++#undef TARGET_ADDRESS_COST
++#define TARGET_ADDRESS_COST msp430_address_cost
++
++/* 17.18 Scheduling */
++
++/* 17.19 Sections */
++#undef TARGET_ASM_SELECT_SECTION
++#define TARGET_ASM_SELECT_SECTION msp430_select_section
++
++/* 17.20 PIC -- not supported */
++
++/* 17.21 Assembler Format */
++/* 17.21.1 File Framework */
++#undef TARGET_ASM_FILE_START
++#define TARGET_ASM_FILE_START msp430_file_start
++#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
++#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
++/* TARGET_ASM_NAMED_SECTION is defined in msp430.h */
++#undef 	TARGET_SECTION_TYPE_FLAGS
++#define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
++/* 17.21.2 Data Output */
++/* TODO: Verify these */
++#undef TARGET_ASM_ALIGNED_HI_OP
++#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
++/* 17.21.4 Label Output */
++#undef TARGET_ASM_GLOBALIZE_LABEL
++#define TARGET_ASM_GLOBALIZE_LABEL msp430_globalize_label
++/* 17.21.9 Assembler Commands for Exception Regions */
++#undef TARGET_EXCEPT_UNWIND_INFO
++#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
++
++/* 17.25 Target Attributes */
++#undef 	TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
++#undef TARGET_OPTION_OVERRIDE
++#define TARGET_OPTION_OVERRIDE msp430_option_override
++
++/* 17.26 Emulated TLS */
++/* 17.27 MIPS Coprocessors -- not relevant */
++/* 17.28 PCH Target */
++/* 17.29 C++ ABI */
++/* 17.30 Named Address Spaces */
++
++/* 17.31 Misc */
++#undef TARGET_INIT_BUILTINS
++#define TARGET_INIT_BUILTINS msp430_init_builtins
++#undef TARGET_EXPAND_BUILTIN
++#define TARGET_EXPAND_BUILTIN msp430_expand_builtin
++#undef TARGET_SET_CURRENT_FUNCTION
++#define TARGET_SET_CURRENT_FUNCTION msp430_set_current_function
++#undef TARGET_CANNOT_MODIFY_JUMPS_P
++#define TARGET_CANNOT_MODIFY_JUMPS_P msp430_cannot_modify_jumps_p
++
++/* 17.1 Target Structure */
++struct gcc_target targetm = TARGET_INITIALIZER;
++
++#include "gt-msp430.h"
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430.h gcc-4.6.3/gcc/config/msp430/msp430.h
+new file mode 100644
+index 0000000..79ee686
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430.h
+@@ -0,0 +1,826 @@
++/* This work is partially financed by the European Commission under the
++ * Framework 6 Information Society Technologies Project
++ * "Wirelessly Accessible Sensor Populations (WASP)".
++ */
++
++/* Definitions of target machine for GNU compiler,
++   for Texas Instruments MSP430 microcontrollers.
++   Copyright (C) 2001-2009 Free Software Foundation, Inc.
++   Contributed by Dmitry Diky <diwil at mail.ru>
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC 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 GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++/* The GCC internals manual (http://gcc.gnu.org/onlinedocs/gccint, but
++ * only if you're working on the trunk) defines the current standard
++ * back-end expectations.  See Chapter 17 "Target Macros".
++ *
++ * Target macros and hooks should not be defined if the default
++ * behavior is correct for the platform.  To make it clear that the
++ * maintainer is aware of the macro and has verified it, it may be
++ * defined to be its default in a comment with a prefix DEFAULT: to
++ * make it clear this is a comment, not droppings from disabled code
++ * (see, for example, PTR_DIFF_TYPE below).
++ */
++
++/** Update this on each release */
++#define MSP430_MSPGCC_VERSION 20120406
++
++/** 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_TYPE_16 = 0x0010,
++  MSP430_MPY_TYPE_32 = 0x0020,
++  MSP430_MPY_TYPE_ANY = 0x0030,
++  MSP430_MPY_HAS_SE = 0x0001,
++  MSP430_MPY_HAS_DW = 0x0002,
++  MSP430_MPY_16 = MSP430_MPY_TYPE_16,
++  MSP430_MPY_16SE = MSP430_MPY_16 | MSP430_MPY_HAS_SE,
++  MSP430_MPY_32 = MSP430_MPY_TYPE_16 | MSP430_MPY_TYPE_32 | MSP430_MPY_HAS_SE,
++  MSP430_MPY_32DW = MSP430_MPY_32 | MSP430_MPY_HAS_DW
++} msp430_mpy_e;
++
++extern msp430_cpu_e msp430_cpu;
++extern msp430_mpy_e msp430_mpy;
++extern int msp430_ivcnt;
++extern int msp430_has_hwmul;
++
++#define MSP430_HAS_HWMUL_INTERNAL (msp430_has_hwmul)
++
++int msp430_current_function_noint_hwmul_function_p (void);
++#define MSP430_NOINT_HWMUL (msp430_current_function_noint_hwmul_function_p())
++
++/* 1 if the integral value can be produced by the MSP430 CG registers */
++#define MSP430_CG_INT_P(VALUE)	\
++  ((-1 == (VALUE))		\
++   || (0 == (VALUE))		\
++   || (1 == (VALUE))		\
++   || (2 == (VALUE))		\
++   || (4 == (VALUE))		\
++   || (8 == (VALUE)))
++
++/* Maximum number of positions a single CPUX multi-position shift
++ * operation can take. */
++#define MSP430_CPUX_MULTISHIFT_MAX 4
++
++/* 1 if the integral value can be the shift count in a CPUX
++ * multi-position shift operation. */
++#define MSP430_CPUX_MULTISHIFT_COUNT_P(VALUE) \
++  (1 <= (VALUE) && (VALUE) <= MSP430_CPUX_MULTISHIFT_MAX)
++
++/* 16.19.5 Insn Lengths */
++#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
++  (LENGTH = msp430_adjust_insn_length (INSN, LENGTH))
++
++/* 17.1 Target Structure -- defined in msp430.c */
++
++/* 17.2 Driver */
++/* On startup read the spec file that translates known MCUs into
++ * device-specific flags (note: this is an msp430 extension to the
++ * upstream driver).  Also normalize any legacy mcu descriptions,
++ * then ensure we have -mcpu and -mmpy configurations derived from
++ * the mcu. */
++#define DRIVER_SELF_SPECS \
++  "%:include-noerr(msp430mcu.spec)" \
++  " %(msp430_cpu)" \
++  " %(msp430_mpy)" \
++  " %(msp430_ivcnt)"
++/* Accept -posix; invoke a special function to
++ * rote-translate -mmcu options into preprocessor definition
++ * options.  */
++#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %:msp430_mcucpp(%{mmcu=*:%*})"
++/* Provide device-specific -mivcnt, -mcpu, -mmpy options. */
++#define CC1_SPEC "%{profile:-p} %{mcpu=*} %{mmpy=*} %{mivcnt=*}"
++/* TODO: legacy value */
++#define CC1PLUS_SPEC "-fno-rtti -fno-exceptions"
++/* Pass MCU-related options to the assembler. */
++#define ASM_SPEC "%{mcpu=*} %{mmcu=*}"
++/* Do not add -lg when linking statically */
++#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
++/* Use the msp430 linker emulation */
++#define LINK_SPEC "-m msp430"
++/* Select the corresponding interrupt vector initializer based on
++ * mivcnt. */
++#define STARTFILE_SPEC				\
++  "%{mivcnt=16:crt0ivtbl16%O%s} "		\
++  "%{mivcnt=32:crt0ivtbl32%O%s} "		\
++  "%{mivcnt=64:crt0ivtbl64%O%s}"
++#define ENDFILE_SPEC \
++  "%{mno-disable-watchdog|!mdisable-watchdog:-lcrt0; :-lcrt0dwdt}"
++extern const char *msp430_mcucpp (int argc, const char **argv);
++extern const char *msp430_mculdscriptpaths (int argc, const char **argv);
++#define EXTRA_SPEC_FUNCTIONS				\
++  { "msp430_mcucpp", msp430_mcucpp },			\
++  { "msp430_mculdscriptpaths", msp430_mculdscriptpaths },
++#define EXTRA_SPECS							\
++  { "msp430_cpu", "%{!mcpu=*:%{mcpu=430}}" },				\
++  { "msp430_mpy", "%{!mmpy=*:%{mmpy=none}}" },				\
++  { "msp430_ivcnt", "%{!mivcnt=*:%{mivcnt=16}}" },
++/* Override this.  The value is essentially the default from gcc.c,
++ * but we need to be able to define a default linker script derived
++ * from the -mmcu parameter, and it has to be at the end; it doesn't
++ * work when placed after the emulation in LINK_SPEC.  */
++#define LINK_COMMAND_SPEC "\
++%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
++    %(linker) \
++    %{"PLUGIN_COND": \
++    -plugin %(linker_plugin_file) \
++    -plugin-opt=%(lto_wrapper) \
++    -plugin-opt=-fresolution=%u.res \
++    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
++    }"PLUGIN_COND_CLOSE" \
++    %{flto|flto=*:%<fcompare-debug*} \
++    %{flto} %{flto=*} %l " LINK_PIE_SPEC \
++   "%X %{o*} %{e*} %{N} %{n} %{r}\
++    %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
++    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
++    %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
++    %(mflib) " STACK_SPLIT_SPEC "\
++    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
++    %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
++    %{!nostdlib:%{!nostartfiles:%E}} %{T*} \
++    %{mmcu=*:%:msp430_mculdscriptpaths(%{mmcu=*:%*})} \
++    }}}}}}"
++#define MULTILIB_DEFAULTS { "mcpu=430", "mmpy=none" }
++
++/* 17.3 Run-time Target */
++#define MSP430_BUILTIN_DEFINE(_m) do {				\
++  snprintf(defstr, sizeof(defstr), "__" #_m "__=%d", _m);	\
++  builtin_define(defstr);					\
++} while (0)
++
++#define TARGET_CPU_CPP_BUILTINS()					\
++  do {									\
++    char defstr[64];							\
++    builtin_define_std ("MSP430");					\
++    if(msp430_has_hwmul)						\
++      builtin_define ("MSP430_HAS_HWMUL");				\
++    else								\
++      builtin_define ("MSP430_NO_HWMUL");				\
++    if (MSP430_CPU_MSP430X <= msp430_cpu)				\
++      {									\
++	snprintf(defstr, sizeof (defstr), "__MSP430X__=%d", msp430_cpu); \
++	builtin_define (defstr);					\
++      }									\
++    snprintf (defstr, sizeof (defstr), "__MSPGCC__=%d", MSP430_MSPGCC_VERSION); \
++    builtin_define (defstr);						\
++    MSP430_BUILTIN_DEFINE(MSP430_CPU_MSP430);				\
++    MSP430_BUILTIN_DEFINE(MSP430_CPU_MSP430X);				\
++    MSP430_BUILTIN_DEFINE(MSP430_CPU_MSP430XV2);			\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_NONE);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_TYPE_16);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_TYPE_32);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_TYPE_ANY);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_HAS_SE);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_HAS_DW);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_16);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_16SE);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_32);				\
++    MSP430_BUILTIN_DEFINE(MSP430_MPY_32DW);				\
++    snprintf (defstr, sizeof (defstr), "__MSP430_CPU__=%d", msp430_cpu); \
++    builtin_define (defstr);						\
++    if (MSP430_MPY_NONE != msp430_mpy)					\
++      {									\
++	snprintf (defstr, sizeof (defstr), "__MSP430_MPY__=%d", msp430_mpy); \
++	builtin_define (defstr);					\
++	if (msp430_mpy & MSP430_MPY_TYPE_16)				\
++	  {								\
++	    snprintf (defstr, sizeof (defstr), "__MSP430_MPY16__=%d", msp430_mpy); \
++	    builtin_define (defstr);					\
++	  }								\
++	if (msp430_mpy & MSP430_MPY_TYPE_32)				\
++	  {								\
++	    snprintf (defstr, sizeof (defstr), "__MSP430_MPY32__=%d", msp430_mpy); \
++	    builtin_define (defstr);					\
++	  }								\
++      }									\
++    snprintf (defstr, sizeof (defstr), "__MSP430_IVCNT__=%d", msp430_ivcnt); \
++    builtin_define (defstr);						\
++    builtin_define ("__interrupt=__attribute__((__interrupt__))");	\
++  } while (0)
++/* TODO: TARGET_HANDLE_OPTION ? */
++#define TARGET_VERSION fprintf (stderr, " (TI MSP430)");
++
++/* 17.4 Per-Function Data -- not used*/
++
++/* 17.5: Storage Layout */
++#define BITS_BIG_ENDIAN 0
++#define BYTES_BIG_ENDIAN 0
++#define WORDS_BIG_ENDIAN 0
++#define UNITS_PER_WORD 2
++#define POINTER_SIZE BITS_PER_WORD
++/* TODO: POINTERS_EXTEND_UNSIGNED for A20 support */
++#define PARM_BOUNDARY BITS_PER_WORD
++#define STACK_BOUNDARY PARM_BOUNDARY
++#define FUNCTION_BOUNDARY BITS_PER_WORD
++#define BIGGEST_ALIGNMENT BITS_PER_WORD
++#define MINIMUM_ATOMIC_ALIGNMENT BITS_PER_UNIT
++#define EMPTY_FIELD_BOUNDARY BITS_PER_WORD
++#define STRUCTURE_SIZE_BOUNDARY BITS_PER_WORD
++#define STRICT_ALIGNMENT 1
++/* DEFAULT: #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode) */
++
++/* 17.6 Type Layout */
++#define SHORT_TYPE_SIZE 16
++#define LONG_TYPE_SIZE 32
++#define LONG_LONG_TYPE_SIZE 64
++#define FLOAT_TYPE_SIZE 32
++#define DOUBLE_TYPE_SIZE FLOAT_TYPE_SIZE
++#define LONG_DOUBLE_TYPE_SIZE FLOAT_TYPE_SIZE
++#define DEFAULT_SIGNED_CHAR 1
++#define SIZE_TYPE "unsigned int"
++/* DEFAULT: #define PTRDIFF_TYPE "long int */
++
++/* 17.7 Registers */
++#define MSP430_CG1_REGNUM 2
++#define MSP430_CG2_REGNUM 3
++#define MSP430_MIN_GENERAL_REGNUM 4
++#define MSP430_MAX_GENERAL_REGNUM 15
++#define MSP430_MAX_HARD_REGNUM 15
++#define MSP430_RETURN_REGISTER_BASE 15
++#define MSP430_ARG_REGISTER_BASE 15
++#define MSP430_ARG_REGISTER_COUNT 4
++/* 1 if REG is a valid register number (not a fixed pseudo-reg) */
++#define MSP430_HARD_REGISTER_NUM_P(REGNO) \
++  ((unsigned int)(REGNO) <= MSP430_MAX_HARD_REGNUM)
++/* 1 if REG is a general register */
++#define MSP430_GENERAL_REGISTER_NUM_P(REGNO) \
++  (MSP430_MIN_GENERAL_REGNUM <= (REGNO) \
++   && (REGNO) <= MSP430_MAX_GENERAL_REGNUM)
++
++/* 17.7.1 Basic Characteristics of Registers */
++#define FIRST_PSEUDO_REGISTER 18
++#define FIXED_REGISTERS {							\
++    1,		/* r0 : Program Counter (PC) */					\
++    1,		/* r1 : Stack Pointer (SP) */					\
++    1,		/* r2 : Status Register (SR); Constant Generator (CG1) */	\
++    1,		/* r3 : Constant Generator (CG2) */				\
++    0, 0, 0, 0, /* r4-r7 */							\
++    0, 0, 0, 0, /* r8-r11 */							\
++    0, 0, 0, 0, /* r12-r15 */							\
++    1,		/* r16 (PSEUDO) : Argument Pointer */				\
++    1,		/* r17 (PSEUDO) : Frame Pointer */				\
++    }
++#define CALL_USED_REGISTERS {				\
++    1, 1, 1, 1,	/* r0-r3: fixed registers */		\
++    0, 0, 0, 0,	/* r4-r7 : callee saved */		\
++    0, 0, 0, 0,	/* r8-r11 : callee saved */		\
++    1, 1, 1, 1,	/* r12-r15 : parameter registers */	\
++    1, 1,	/* r16-r17 : fixed pseudo register */	\
++    }
++#define PC_REGNUM 0
++
++/* 17.7.2 Order of Allocation of Registers */
++/* TODO: SF 3191557 */
++#define REG_ALLOC_ORDER { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }
++
++/* 17.7.3 How Values Fit in Registers */
++#define HARD_REGNO_NREGS(REGNO, MODE)					\
++  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
++#define HARD_REGNO_MODE_OK(REGNO, MODE)					\
++  MSP430_HARD_REGISTER_NUM_P((REGNO) + HARD_REGNO_NREGS (REGNO, MODE) - 1)
++#define MODES_TIEABLE_P(MODE1, MODE2)			\
++  (GET_MODE_SIZE (MODE1) == GET_MODE_SIZE (MODE2)	\
++   || (GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD		\
++       && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD))
++
++/* 17.8 Register Classes */
++int msp430_general_or_stack_reg (int regno);
++int msp430_indirect_register_operand (rtx x);
++int msp430_indexed_register_operand (rtx x);
++
++enum reg_class
++{
++  NO_REGS,
++  PC_REG,			/* r0 (PC) */
++  SP_REG,			/* r1 (SP) */
++  SR_REG,			/* r2 (SR) */
++  CG1_REG,			/* r2 (CG1) */
++  CG2_REG,			/* r3 (CG2) */
++  CG_REGS,			/* r2,r3 */
++  FP_REG,			/* r4 (HARD_FRAME_POINTER) */
++  GENERAL_REGS,			/* r4-r15 */
++  GENERAL_SP_REGS,		/* r1,r4-r15 */
++  GENERAL_SR_REGS,		/* r2,r4-r15 */
++  POINTER_REGS,			/* r1,r4-r15 */
++  SOFT_ARGP_REG,		/* r16 (ARG_POINTER) */
++  SOFT_FP_REG,			/* r17 (FRAME_POINTER) */
++  FIXED_PSEUDO_REGS,		/* r16- */
++  FIXED_PSEUDO_GENERAL_REGS,	/* r4-r15,r16- */
++  FIXED_PSEUDO_GENERAL_SP_REGS,	/* r1,r4-r15,r16- */
++  ALL_REGS,
++  LIM_REG_CLASSES
++};
++#define N_REG_CLASSES (int) LIM_REG_CLASSES
++#define REG_CLASS_NAMES {		\
++		"NO_REGS",		\
++		"PC_REG",		\
++		"SP_REG",		\
++		"SR_REG",		\
++		"CG1_REG",		\
++		"CG2_REG",		\
++		"CG_REGS",		\
++		"FP_REG",		\
++		"GENERAL_REGS",		\
++		"GENERAL_SP_REGS",	\
++		"GENERAL_SR_REGS",	\
++		"POINTER_REGS",		\
++		"SOFT_ARGP_REG",	\
++		"SOFT_FP_REG",		\
++		"FIXED_PSEUDO_REGS",	\
++		"FIXED_PSEUDO_GENERAL_REGS",	\
++		"FIXED_PSEUDO_GENERAL_SP_REGS",	\
++		"ALL_REGS" 		\
++}
++#define REG_CLASS_CONTENTS {			\
++  {0x00000000ul},	/* NO_REGS */		\
++  {0x00000001ul},	/* PC_REG */		\
++  {0x00000002ul},	/* SP_REG */		\
++  {0x00000004ul},	/* SR_REG */		\
++  {0x00000004ul},	/* CG1_REG */		\
++  {0x00000008ul},	/* CG2_REG */		\
++  {0x0000000cul},	/* CG_REGS */		\
++  {0x00000010ul},	/* FP_REG */		\
++  {0x0000fff0ul},	/* GENERAL_REGS */      \
++  {0x0000fff2ul},	/* GENERAL_SP_REGS */   \
++  {0x0000fff4ul},	/* GENERAL_SR_REGS */   \
++  {0x0000fff2ul},	/* POINTER_REGS */      \
++  {0x00010000ul},	/* SOFT_ARGP_REG */     \
++  {0x00020000ul},	/* SOFT_FP_REG */	\
++  {0x00030000ul},	/* FIXED_PSEUDO_REGS */ \
++  {0x0003fff0ul},	/* FIXED_PSEUDO_GENERAL_REGS */	\
++  {0x0003fff2ul},	/* FIXED_PSEUDO_GENERAL_SP_REGS */ \
++  {0x0003fffful}	/* ALL_REGS */		\
++}
++#define REGNO_REG_CLASS(REGNO) msp430_regno_reg_class (REGNO)
++#define BASE_REG_CLASS POINTER_REGS
++#define INDEX_REG_CLASS NO_REGS
++#define REGNO_OK_FOR_BASE_STRICT_P(NUM) msp430_regno_ok_for_base_p(NUM, 1)
++#define REGNO_OK_FOR_BASE_NONSTRICT_P(NUM) msp430_regno_ok_for_base_p(NUM, 0)
++#ifdef REG_OK_STRICT
++#define REGNO_OK_FOR_BASE_P(NUM) REGNO_OK_FOR_BASE_STRICT_P(NUM)
++#else
++#define REGNO_OK_FOR_BASE_P(NUM) REGNO_OK_FOR_BASE_NONSTRICT_P(NUM)
++#endif
++#define REGNO_OK_FOR_INDEX_P(NUM) 0
++#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
++#define CLASS_MAX_NREGS(CLASS, MODE) HARD_REGNO_NREGS(_unreferenced, MODE)
++
++/* 17.9 Old Constraints */
++
++/* 17.10 Stack and Calling */
++/* 17.10.1 Frame Layout */
++#define STACK_GROWS_DOWNWARD
++#define STARTING_FRAME_OFFSET 0
++#define FIRST_PARM_OFFSET(FUNDECL) 0
++#define INCOMING_RETURN_ADDR_RTX gen_rtx_MEM (Pmode, stack_pointer_rtx)
++#define INCOMING_FRAME_SP_OFFSET GET_MODE_SIZE (Pmode)
++#define CFA_FRAME_BASE_OFFSET(FUNDECL) msp430_cfa_frame_base_offset (FUNDECL)
++#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) msp430_return_addr_rtx (COUNT, FRAMEADDR)
++/* 17.10.2 Exception Handling */
++/* 17.10.3 Stack Checking */
++/* 17.10.4 Frame Registers */
++#define STACK_POINTER_REGNUM 1
++#define STATUS_REGISTER_REGNUM 2
++#define HARD_FRAME_POINTER_REGNUM 4
++#define STATIC_CHAIN_REGNUM 6
++#define ARG_POINTER_REGNUM 16
++#define FRAME_POINTER_REGNUM 17
++/* 17.10.5 Elimination */
++#define ELIMINABLE_REGS {				\
++    {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},		\
++    {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},	\
++    {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},	\
++    {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},	\
++}
++#define INITIAL_ELIMINATION_OFFSET(FROM_REG, TO_REG, OFFSET_VAR) \
++  OFFSET_VAR = msp430_initial_elimination_offset (FROM_REG, TO_REG)
++/* 17.10.6 Stack Arguments */
++/* NB Default ACCUMULATE_OUTGOING_ARGS is 0, so default PUSH_ARGS is 1 */
++#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 1) & ~1)
++/* 17.10.7 Register Arguments */
++struct msp430_cumulative_args
++{
++  int nregs;			/* # registers available for passing */
++  int regno;			/* next available register number */
++};
++#define CUMULATIVE_ARGS struct msp430_cumulative_args
++#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
++  (msp430_function_arg (&(CUM), MODE, TYPE, NAMED))
++#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS ) \
++  msp430_init_cumulative_args (&(CUM), FNTYPE, LIBNAME, FNDECL)
++#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
++  msp430_init_cumulative_incoming_args (&(CUM), FNTYPE, LIBNAME)
++#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
++  msp430_function_arg_advance (&CUM, MODE, TYPE, NAMED)
++#define FUNCTION_ARG_REGNO_P(R) \
++  (R >= (MSP430_ARG_REGISTER_BASE - MSP430_ARG_REGISTER_COUNT + 1) \
++   && R <= MSP430_ARG_REGISTER_BASE)
++/* 17.10.8 Scalar Return */
++/* TODO: Replace with target function */
++#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == MSP430_RETURN_REGISTER_BASE)
++/* 17.10.9 Aggregate Return */
++#define DEFAULT_PCC_STRUCT_RETURN 0
++/* 17.10.10 Caller Saves */
++/* 17.10.11 Function Entry */
++#define EPILOGUE_USES(REGNO) msp430_epilogue_uses(REGNO)
++/* 17.10.12 Profiling */
++#define FUNCTION_PROFILER(FILE, LABELNO)  \
++  fprintf (FILE, "/* profiler %d */", LABELNO)
++/* 17.10.13 Tail Calls */
++/* 17.10.14 Stack Smashing Protection */
++
++/* 17.11 Varargs (no macros relevant) */
++
++/* 17.12 Trampolines */
++#define TRAMPOLINE_SIZE 8
++#define TRAMPOLINE_ALIGNMENT BITS_PER_WORD
++
++/* 17.13 Library Calls */
++#define TARGET_LIB_INT_CMP_BIASED true
++
++/* 17.14 Addressing Modes */
++#define HAVE_POST_INCREMENT 1
++#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X) && GET_CODE (X) != CONST_DOUBLE)
++#define MAX_REGS_PER_ADDRESS 1
++#define LEGITIMATE_CONSTANT_P(X) 1
++
++/* 17.15 Anchored Addresses */
++
++/* 17.16 Condition Code */
++#define NOTICE_UPDATE_CC(EXP, INSN) msp430_notice_update_cc (EXP, INSN)
++
++/* Extend conditions.h to explicitly note cases where the carry flag
++   is invalid; these mostly are rotate-through-carry, and
++   multi-instruction operations on 32- or 64-bit values.  (Note that
++   the standard CC_NO_OVERFLOW is being used to refer to SR.V being
++   reset.) */
++#define CC_CLOBBER_C 0x1000
++
++/* Extend conditions.h to explicitly note cases where the zero flag is
++   invalid; these mostly are multi-instruction operations on 32- or
++   64-bit values. */
++#define CC_CLOBBER_Z 0x2000
++
++/* Extend conditions.h to explicitly note cases where the overflow
++   flag is invalid. */
++#define CC_CLOBBER_V 0x4000
++
++/* Extend conditions.h to note when the comparison was actually
++   output. */
++#define CC_EXPLICIT_COMPARE 0x8000
++
++/* 17.17 Costs */
++#define REGISTER_MOVE_COST(MODE, FROM, TO) ((MODE)==QImode ? 1 :	\
++					    (MODE)==HImode ? 1 :	\
++					    (MODE)==SImode ? 2 :	\
++					    (MODE)==SFmode ? 2 : 4)
++/* TODO: SF 3192592 */
++#define MEMORY_MOVE_COST(MODE, CLASS, IN) ((MODE)==QImode ? 2 :		\
++					   (MODE)==HImode ? 2 :		\
++					   (MODE)==SImode ? 4 :		\
++					   (MODE)==SFmode ? 4 : 8)
++/* TODO: SF 3192592 */
++#define BRANCH_COST(SPEED_P, PREDICTABLE_P) 0
++/* TODO: SF 3192592 */
++#define SLOW_BYTE_ACCESS 0
++#define NO_FUNCTION_CSE
++
++/* 17.18 Scheduling */
++
++/* 17.19 Sections */
++/* See also 17.21.6 for CTORS/DTORS */
++#define TEXT_SECTION_ASM_OP "\t.text"
++#define DATA_SECTION_ASM_OP "\t.data"
++#define BSS_SECTION_ASM_OP "\t.section\t.bss"
++#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
++
++/* 17.20 PIC */
++/* Not supported on this platform at this time */
++
++/* 17.21 Assembler Format */
++/* 17.21.1 File Framework */
++#define ASM_COMMENT_START " ; "
++#define ASM_APP_ON "#APP\n"
++#define ASM_APP_OFF "#NOAPP\n"
++/* Define this hook here so TARGET_HAVE_NAMED_SECTIONS is defaulted to
++ * true in c-common.c */
++#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
++/* 17.21.2 Data Output */
++#define ASM_OUTPUT_ASCII(FILE, P, SIZE) gas_output_ascii (FILE, P, SIZE)
++/* TODO: this is probably a misinterpretation of "logical line separator" */
++#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n')
++/* 17.21.3 Uninitialized Data */
++#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)		\
++  do {								\
++    const char *p = NAME;					\
++    if(*p == '*' || *p == '@' ) p++;				\
++    if(*p >= '0' && *p <= '9' ) break;				\
++    fputs ("\t.comm ", (STREAM));				\
++    assemble_name ((STREAM), (NAME));				\
++    fprintf ((STREAM), ",%lu%s", (unsigned long)(SIZE), (SIZE)>1?",2\n":"\n"); \
++  } while (0)
++#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED)		\
++  do {								\
++    const char *p = (NAME);					\
++    if(*p == '*' || *p == '@' ) p++;				\
++    if(*p >= '0' && *p <= '9' ) break;				\
++    asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)); \
++  } while(0)
++#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED)		\
++  do {								\
++    const char *p = NAME;					\
++    if(*p == '*' || *p == '@' ) p++;				\
++    if(*p >= '0' && *p <= '9' ) break;				\
++    fputs ("\t.local ", (STREAM));				\
++    assemble_name ((STREAM), (NAME));				\
++    fputs ("\n",(STREAM));					\
++    fputs ("\t.comm ", (STREAM));				\
++    assemble_name ((STREAM), (NAME));				\
++    fprintf ((STREAM), ",%lu%s", (unsigned long)(SIZE),(SIZE)>1?",2\n":"\n"); \
++  } while (0)
++/* 17.21.4 Label Output */
++/* TODO: what's this workaround for?  came in at mspgcc4 */
++#define ASM_OUTPUT_LABEL(STREAM, NAME)					\
++  {									\
++    int __msp430_data_name_workaround = (((NAME)[0] == '*') && ((NAME)[1] == '0')); \
++    if (__msp430_data_name_workaround)					\
++      {									\
++	static int repeatable_pseudolabels_resolver = 0;		\
++	fprintf (STREAM, "__");						\
++	assemble_name (STREAM, NAME);					\
++	fprintf (STREAM, "_%d", ++repeatable_pseudolabels_resolver);	\
++      }									\
++    else								\
++      assemble_name (STREAM, NAME);					\
++    fprintf (STREAM, ":\n");						\
++  }
++#define SIZE_ASM_OP "\t.size\t"
++#define TYPE_ASM_OP "\t.type\t"
++#define TYPE_OPERAND_FMT "@%s"
++#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)	\
++  msp430_asm_declare_function_name (FILE, NAME, DECL)
++#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)		\
++  do {								\
++    if (!flag_inhibit_size_directive)				\
++      {								\
++        char label[256];					\
++	static int labelno;					\
++	labelno++;						\
++	ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno);	\
++	ASM_OUTPUT_LABEL (FILE, label);				\
++	fprintf (FILE, "%s", SIZE_ASM_OP);			\
++	assemble_name (FILE, (FNAME));				\
++        fprintf (FILE, ",");					\
++	assemble_name (FILE, label);				\
++        fprintf (FILE, "-");					\
++	assemble_name (FILE, (FNAME));				\
++	fprintf (FILE,"\n;; End of function \n\n");		\
++      }								\
++  } while (0)
++#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)			\
++  do {									\
++    int __msp430_data_name_workaround = (((NAME)[0] == '*') && ((NAME)[1] == '0')); \
++    if (__msp430_data_name_workaround)					\
++      fprintf (FILE, "#");						\
++    fprintf (FILE, "%s", "\t.type\t");					\
++    assemble_name (FILE, NAME);						\
++    putc (',', FILE);							\
++    fprintf (FILE, TYPE_OPERAND_FMT, "object");				\
++    putc ('\n', FILE);							\
++    size_directive_output = 0;						\
++    if (!flag_inhibit_size_directive && DECL_SIZE (DECL))		\
++      {									\
++	size_directive_output = 1;					\
++	if (__msp430_data_name_workaround)				\
++	  fprintf (FILE, "#");						\
++	fprintf (FILE, "%s", SIZE_ASM_OP);				\
++	assemble_name (FILE, NAME);					\
++	fprintf (FILE, ",%lu\n",  int_size_in_bytes (TREE_TYPE (DECL))); \
++      }									\
++    ASM_OUTPUT_LABEL(FILE, NAME);					\
++  } while (0)
++#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END)	\
++  do {									\
++    const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0);		\
++    if (!flag_inhibit_size_directive && DECL_SIZE (DECL)		\
++	&& ! AT_END && TOP_LEVEL					\
++	&& DECL_INITIAL (DECL) == error_mark_node			\
++	&& !size_directive_output)					\
++      {									\
++	size_directive_output = 1;					\
++	fprintf (FILE, "%s", SIZE_ASM_OP);				\
++	assemble_name (FILE, name);					\
++	fprintf (FILE, ",%lu\n",  int_size_in_bytes (TREE_TYPE (DECL))); \
++      }									\
++  } while (0)
++#define ASM_WEAKEN_LABEL(FILE, NAME)		\
++  do						\
++    {						\
++      fputs ("\t.weak\t", (FILE));		\
++      assemble_name ((FILE), (NAME));		\
++      fputc ('\n', (FILE));			\
++    }						\
++  while (0)
++#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)	\
++  sprintf (STRING, "*.%s%lu", PREFIX, (unsigned long)NUM)
++#define SUPPORTS_WEAK 1
++/* Here we must catch r0 - r15 used as variable names */
++#define ASM_OUTPUT_LABELREF(FILE,NAME) 			\
++  do{							\
++    const char *p = NAME;				\
++    while(*p == '_') p++;				\
++    if(*p == 'r' || *p == 'R')				\
++      {							\
++	int val;					\
++	char *endptr;					\
++	p++;						\
++	val = strtol (p, &endptr, 10);			\
++	if(val >= 0 && val <= 15 &&			\
++	   *endptr == 0 )				\
++	  {						\
++	    asm_fprintf ((FILE), "_%U%s", (NAME));	\
++	  }						\
++	else						\
++	  asm_fprintf ((FILE), "%U%s", (NAME));		\
++      }							\
++    else						\
++      asm_fprintf ((FILE), "%U%s", (NAME));		\
++  } while(0)
++#define SET_ASM_OP "\t.set\t"
++/* 17.21.5 Initialization */
++/* 17.21.6 Macros for Initialization */
++#define HAS_INIT_SECTION 1
++/* The code that walks the [cd]tors list is not referenced in
++ * _reset_vector_ or _stop_progExec__; doing so here ensures that code
++ * is only linked in if it's actually needed. */
++#define CTORS_SECTION_ASM_OP "\t.global\t__do_global_ctors\n\t.section\t.ctors"
++#define DTORS_SECTION_ASM_OP "\t.global\t__do_global_dtors\n\t.section\t.dtors"
++/* 17.21.7 Instruction Output */
++#define REGISTER_NAMES				\
++  {						\
++    "r0", "r1", "r2", "r3",			\
++    "r4", "r5", "r6", "r7",			\
++    "r8", "r9", "r10", "r11",			\
++    "r12", "r13", "r14", "r15",			\
++    "argp", "sfp"				\
++  }
++#define PRINT_OPERAND(STREAM, X, CODE) msp430_print_operand (STREAM, X, CODE)
++#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO)		\
++{							\
++  gcc_assert (MSP430_HARD_REGISTER_NUM_P(REGNO));	\
++  fprintf (STREAM, "\tpush\tr%d", REGNO);		\
++}
++#define ASM_OUTPUT_REG_POP(STREAM, REGNO)		\
++{							\
++  gcc_assert (MSP430_HARD_REGISTER_NUM_P(REGNO));	\
++  fprintf (STREAM, "\tpop\tr%d", REGNO);		\
++}
++/* 17.21.8 Dispatch Tables */
++#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE)		\
++  msp430_output_addr_vec_elt(STREAM, VALUE)
++/* 17.21.9 Exception Region Output */
++/* 17.21.10 Alignment Output */
++#define ASM_OUTPUT_SKIP(STREAM, N)		\
++  fprintf (STREAM, "\t.skip %lu,0\n", (unsigned long)N)
++#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
++  fprintf (STREAM, "\t.p2align %d,0\n", POWER)
++
++/* 17.22 Debugging Info */
++/* 17.22.1 All Debuggers */
++#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
++/* 17.22.2 DBX Options -- not supported */
++/* 17.22.3 DBX Hooks -- not supported */
++/* 17.22.4 File Names and DBX -- not supported */
++/* 17.22.5 SDB and DWARF */
++#define DWARF2_DEBUGGING_INFO 1
++/* 17.22.6 VMS Debug -- not supported */
++
++/* 17.23 Floating Point */
++/* MSP430 doesn't have floating point, and its emulation uses IEEE.
++ * Presumably, none of this section is relevant. */
++
++/* 17.24 Mode Switching */
++/* For things like configuring an FPU to single- or double-precision
++ * mode.  Not currently relevant. */
++
++/* 17.25 Target Attributes */
++/* These are all hooks */
++
++/* 17.26 Emulated TLS */
++/* Thread Local Storage on a microcontroller?  Please. */
++
++/* 17.27 MIPS Coprocessors -- not relevant */
++
++/* 17.28 PCH Target */
++/* Pre-compiled headers might be useful, but we're not using them
++ * now. */
++
++/* 17.29 C++ ABI */
++/* These are all hooks */
++
++/* 17.30 Named Address Spaces */
++/* This might be relevant when dealing with near versus far memory.
++ * It is specifically for use by embedded processors. */
++
++/* 17.31 Misc */
++#define CASE_VECTOR_MODE HImode
++#define MOVE_MAX 2
++#define SHIFT_COUNT_TRUNCATED 1
++#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
++#define Pmode HImode
++#define FUNCTION_MODE HImode
++#define REGISTER_TARGET_PRAGMAS() do {					\
++    c_register_pragma_with_expansion (0, "vector", msp430_pr_vector);	\
++  } while (0)
++#define DOLLARS_IN_IDENTIFIERS 0
++#define NO_DOLLAR_IN_LABEL 1
++
++/* Undocumented but legitimate */
++#define OBJECT_FORMAT_ELF
++
++/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
++
++enum msp430_frame_flags_e
++{
++  MSP430_FF_prologue_push_sr = 0x0001,
++  MSP430_FF_use_reti = 0x0002,
++  MSP430_FF_prologue_eint = 0x0004,
++  MSP430_FF_prologue_dint = 0x0008,
++  MSP430_FF_epilogue_eint = 0x0010,
++  MSP430_FF_epilogue_dint = 0x0020,
++  MSP430_FF_epilogue_exit_lpm = 0x0040,
++  MSP430_FF_epilogue_pop_sr = 0x0080,
++  MSP430_FF_use_frame_saver = 0x0100,
++  MSP430_FF_preserve_registers = 0x0200,
++  MSP430_FF_allocate_frame = 0x0400,
++  MSP430_FF_inhibit_return = 0x0800,
++  MSP430_FF_treat_as_main = 0x1000,
++  MSP430_FF_ready_for_return = 0x2000
++};
++
++struct GTY(()) machine_function
++{
++  int initialized;
++  tree signal;
++  tree interrupt;
++  tree naked;
++  tree task;
++  tree wakeup;
++  tree critical;
++  tree reentrant;
++  tree saveprologue;
++  tree noint_hwmul;
++  tree hosted;
++
++  /* Aligned frame size as recorded in expand_prologue */
++  int frame_size;
++
++  /* Bit-mask indicating the registers saved in expand_prologue */
++  unsigned int saved_regs_mask;
++
++  /* Number of registers saved in expand_prologue */
++  int saved_regs_count;
++
++  /* Bit-mask from msp430_frame_flags_e */
++  unsigned int frame_flags;
++
++  /* Vector offset for interrupt: non-negative multiple of two.
++   * Negative indicates an unbound interrupt.  Field valid only if
++   * interrupt is not null. */
++  int vector_offset;
++
++  /* Non-zero if we need the frame pointer (e.g., for a SR_IRQ
++   * builtin) */
++  int frame_pointer_required;
++
++  /* An internal label to be emitted at the end of the epilog, in
++   * functions that might inhibit a return but still have a return in
++   * the middle of the code.  NULL unless frame_flags has
++   * MSP430_FF_inhibit_return set. */
++  const char *inhibited_return_label;
++};
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430.md gcc-4.6.3/gcc/config/msp430/msp430.md
+new file mode 100644
+index 0000000..d07ddea
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430.md
+@@ -0,0 +1,1344 @@
++;; -*- Mode: Scheme -*-
++;;   Machine description for GNU compiler,
++;;   for Texas Instruments msp430 MCUs
++;;   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++;;   Contributed by Dmitry Diky <diwil at mail.ru>
++;;	 GCC 4.x port by Ivan Shcherbakov <mspgcc at sysprogs.org>
++
++;; This work is partially financed by the European Commission under the
++;; Framework 6 Information Society Technologies Project
++;; "Wirelessly Accessible Sensor Populations (WASP)".
++
++; This file is part of GCC.
++
++;; GCC is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 2, or (at your option)
++;; any later version.
++
++;; GCC 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 GCC; see the file COPYING.  If not, write to
++;; the Free Software Foundation, 59 Temple Place - Suite 330,
++;; Boston, MA 02111-1307, USA.
++
++(include "constraints.md")
++(include "predicates.md")
++
++;; Special characters after '%':
++;;  A  No effect (add 0).
++;;  B  Add 1 to REG number, 2 to MEM address or CONST_INT.
++;;  C	   2		    4
++;;  D	   3		    6
++;;  S  Add 2 to memory address if using stack pointer (for pre_decr)
++
++(define_constants
++  [(REGNO_PC			0)
++   (REGNO_SP			1)
++   (REGNO_SR			2)
++   (REGNO_FP			4)
++   ]
++  )
++
++(define_constants
++  [(UNSPEC_UNDEFINED		0)
++   (UNSPEC_BITTEST_FOR_CARRY	6)
++   (UNSPEC_PUSH_MULTI		20)
++   (UNSPEC_POP_MULTI		21)
++   (UNSPEC_LOAD_SP		105)
++   ]
++)
++
++(define_constants
++  [(UNSPECV_UNDEFINED			0)
++   (UNSPECV_MPY_INHIBIT_INTR		100)
++   (UNSPECV_MPY_RESTORE_INTR		101)
++   (UNSPECV_NOP				200)
++   (UNSPECV_DINT			201)
++   (UNSPECV_EINT			202)
++   (UNSPECV_READ_STATUS_REGISTER	203)
++   (UNSPECV_WRITE_STATUS_REGISTER	204)
++   (UNSPECV_BIC_STATUS_REGISTER		205)
++   (UNSPECV_BIS_STATUS_REGISTER		206)
++   (UNSPECV_BIC_SR_IRQ			207)
++   (UNSPECV_BIS_SR_IRQ			208)
++   (UNSPECV_READ_STACK_POINTER		209)
++   (UNSPECV_WRITE_STACK_POINTER		210)
++   (UNSPECV_DELAY_CYCLES		211)
++   (UNSPECV_GET_INTERRUPT_STATE		212)
++   (UNSPECV_SET_INTERRUPT_STATE		213)
++   (UNSPECV_GET_WATCHDOG_CLEAR_VALUE	214)
++   (UNSPECV_SET_WATCHDOG_CLEAR_VALUE	215)
++   (UNSPECV_WATCHDOG_CLEAR		216)
++   (UNSPECV_RLA				300)
++   (UNSPECV_RRA				301)
++   (UNSPECV_RLC				302)
++   (UNSPECV_RRC				303)
++   (UNSPECV_RRU				304)
++   (UNSPECV_CLRC			305)
++   (UNSPECV_MWSHL8XOR			310)
++   (UNSPECV_MWSHR8XOR			311)
++   ]
++  )
++
++; Instruction impact on condition code flags specific to MSP430
++; comparison-based jump instructions.  Comparisons are equality (eq,
++; ne), signed ordered (*gt, ge, lt, *le), and unsigned ordered (*gtu,
++; geu, ltu, *leu) [* indicates a comparison not directly supported by
++; a single msp430 instruction].  Where signed ordered are supported,
++; so are unsigned ordered.
++;
++; undef : insn effect has not be categorized
++; none : No change to flags
++; clobber : Flags do not represent anything useful
++; explicit : VNZC calculated explicitly by a comparison operation, as
++;            opposed to as a side effect of an operation.  Side effect
++;            calculations can be wrong for MSP430 conditional jumps
++;            that reference the overflow flag (jge/jl).
++; VNZC : All flags are valid for comparison between two values
++; NZC : Flags are valid for equality and signed ordered comparisons
++;       with zero.  Often C=~Z.  As used here, V is expected to be
++;       cleared (CC_NO_OVERFLOW is set); thus this condition should
++;       not be used for dadd and rlam which leave its value undefined.
++; NZ : Flags are valid for signed ordered comparisons with zero.  V
++;      and C are clobbered.  Used primarily in multi-word operations.
++; N : Flags valid for signed ordered comparisons with zero, but not
++;     for equality with zero.  V, C, and Z are clobbered.  Used
++;     primarily in multi-word operations.
++(define_attr "cc" "undef,none,clobber,explicit,VNZC,NZC,NZ,N"
++  (const_string "undef"))
++
++(define_attr "type" "branch,branch1,arith"
++  (const_string "arith"))
++
++(define_attr "msp430_has_hwmul" "yes,no"
++  (const (if_then_else (symbol_ref "MSP430_HAS_HWMUL_INTERNAL")
++		       (const_string "yes")
++		       (const_string "no"))))
++
++(define_attr "msp430_noint_hwmul" "" (symbol_ref "MSP430_NOINT_HWMUL"))
++
++; Instruction formats.  Yes, it is irritating that format I (fmt1) has
++; two operands, and format II (fmt2) has one.
++;
++; fmt1 : MSP430, three words : double-operand
++; fmt2 : MSP430, two words : single-operand as dst
++; fmt2s : MSP430, two words : single-operand as src
++; emu1dd : MSP430 : fmt1 emulated dst, dst
++; condjmp : MSP430, one word : conditional jump with 10-bit word offset
++; fmt1x : MSP430X, four words : extension word, double-operand (fmt1)
++; fmt2x : MSP430X, three words : extension word, single-operand (fmt2)
++; fmtx : MSP430X, two words : no extension word, single-operand
++(define_attr "instr_format"
++  "undef,fmt1,fmt2,fmt2s,emu1dd,condjmp"
++  (const_string "undef"))
++
++; Multiplier for basic instr_format-based length when template includes
++; multiple instances of the same instruction.
++(define_attr "instr_mult"
++  ""
++  (cond [(match_operand:SI 0 "" "")
++	 (const_int 2)
++	 (match_operand:SF 0 "" "")
++	 (const_int 2)
++	 (match_operand:DI 0 "" "")
++	 (const_int 4)]
++	(const_int 1)))
++
++; Length is calculated in bytes, and depends in most cases solely on
++; the instruction format and the number of times the base instruction
++; appears in the output template (for multi-word operands).
++(define_attr "length" ""
++  (cond [(eq_attr "instr_format" "fmt1,emu1dd")		; insn, src word, dst word
++	 (mult (const_int 6) (attr "instr_mult"))
++	 (eq_attr "instr_format" "fmt2,fmt2s")		; insn, dst word
++	 (mult (const_int 4) (attr "instr_mult"))
++	 (eq_attr "instr_format" "condjmp")		; insn (assume local jump)
++	 (mult (const_int 2) (attr "instr_mult"))]
++	(const_int 0)))
++
++;; SI and SF as blobs are treated the same
++(define_mode_iterator SISF [SI SF])
++
++;; Modes to which QI can extend
++(define_mode_iterator QIEXT [DI SI HI])
++
++;; Modes to which HI can extend
++(define_mode_iterator HIEXT [DI SI])
++
++;; Integer modes that can be widened
++(define_mode_iterator WidenableINTModes [SI HI QI])
++
++;; Integer modes
++(define_mode_iterator INTModes [DI SI HI QI])
++
++;; Operand constraints for INTModes iterators
++(define_mode_attr INTModes_constraint_dst
++  [(QI "=rm")		       ; QImode goes to register or memory
++   (HI "=rm")		       ; HImode goes to register or memory
++   (SI "=rm")		       ; SImode goes to register or memory
++   (DI "=rm")])		       ; DImode goes to register or memory
++
++(define_mode_attr INTModes_constraint_src
++  [(QI "UmQi")		       ; QI, HI allow anything
++   (HI "UmQi")
++   (SI "rmQi")		       ; SI, DI remove frame and stack pointer
++   (DI "rmQi")])
++
++(define_mode_attr INTModes_constraint_matchdst
++  [(QI "0")
++   (HI "0")
++   (SI "0")
++   (DI "0")])
++
++; Variant for commutative operations
++(define_mode_attr INTModes_commutative_matchdst
++  [(QI "%0")
++   (HI "%0")
++   (SI "%0")
++   (DI "%0")])
++
++; Variants that allow operation on the frame and stack pointer for HImode
++(define_mode_attr INTModes_frameok_dst
++  [(QI "=rm")		       ; QImode goes to register or memory
++   (HI "=Um")		       ; HImode allows frame and stack pointer
++   (SI "=rm")		       ; SImode goes to register or memory
++   (DI "=rm")])		       ; DImode goes to register or memory
++
++(define_mode_attr INTModes_frameok_src
++  [(QI "UmQi")		       ; QI, HI allow anything
++   (HI "UmQi")		       ; SI, DI remove frame and stack pointer
++   (SI "rmQi")
++   (DI "rmQi")])
++
++; For LSW-first arithmetic on values that might be multiple words
++(define_mode_attr INTModes_cc_VNZC
++  [(QI "VNZC")
++   (HI "VNZC")
++   (SI "N")
++   (DI "N")])
++
++(define_mode_attr INTModes_cc_NZC
++  [(QI "NZC")
++   (HI "NZC")
++   (SI "N")
++   (DI "N")])
++
++(define_mode_attr INTModes_cc_NZ
++  [(QI "NZ")
++   (HI "NZ")
++   (SI "N")
++   (DI "N")])
++
++; For MSW-first shift through carry on values that might be multiple words
++(define_mode_attr INTModes_reversed_cc_NZ
++  [(QI "NZ")
++   (HI "NZ")
++   (SI "clobber")
++   (DI "clobber")])
++
++; Next wider mode, in lower case
++(define_mode_attr wider_mode
++  [(QI "hi")
++   (HI "si")
++   (SI "di")])
++
++; Next wider mode, in upper case
++(define_mode_attr WIDER_MODE
++  [(QI "HI")
++   (HI "SI")
++   (SI "DI")])
++
++;; Integer modes that fit in a single register
++(define_mode_iterator INTRegModes [HI QI])
++
++;; ==================
++;; Built-in functions
++
++; nop()
++(define_insn "nop"
++  [(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
++  ""
++  "nop"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")
++   ])
++
++; dint()
++(define_insn "dint"
++  [(unspec_volatile [(const_int 0)] UNSPECV_DINT)
++   (clobber (reg:HI REGNO_SR))]
++  ""
++  "dint"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")
++   ])
++
++; eint()
++(define_insn "eint"
++  [(unspec_volatile [(const_int 0)] UNSPECV_EINT)
++   (clobber (reg:HI REGNO_SR))]
++  ""
++  "eint"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")
++   ])
++
++; read_status_register(retloc)
++(define_insn "read_status_register"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++	(unspec_volatile:HI [(reg:HI REGNO_SR)] UNSPECV_READ_STATUS_REGISTER))]
++  ""
++  "mov\tr2, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++; get_interrupt_state(retloc)
++; Yes, this is equivalent to read_status_register.
++(define_insn "get_interrupt_state"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++	(unspec_volatile:HI [(reg:HI REGNO_SR)] UNSPECV_GET_INTERRUPT_STATE))]
++  ""
++  "mov\tr2, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++; write_status_register(sr_value)
++(define_insn "write_status_register"
++  [(set (reg:HI REGNO_SR)
++	(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_WRITE_STATUS_REGISTER))]
++   ""
++   "mov\t%0, r2"
++   [(set_attr "cc" "clobber")
++    (set_attr "instr_format" "fmt1")])
++
++; set_interrupt_state(istate)
++; Yes, this is equivalent to write_status_register.
++(define_insn "set_interrupt_state"
++  [(set (reg:HI REGNO_SR)
++	(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_SET_INTERRUPT_STATE))]
++   ""
++   "mov\t%0, r2"
++   [(set_attr "cc" "clobber")
++    (set_attr "instr_format" "fmt1")])
++
++; bic_status_register(sr_value)
++(define_insn "bic_status_register"
++  [(set (reg:HI REGNO_SR)
++	(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_BIC_STATUS_REGISTER))]
++   ""
++   "bic\t%0, r2"
++   [(set_attr "cc" "clobber")
++    (set_attr "instr_format" "fmt1")])
++
++; bis_status_register(sr_value)
++(define_insn "bis_status_register"
++  [(set (reg:HI REGNO_SR)
++	(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_BIS_STATUS_REGISTER))]
++   ""
++   "bis\t%0, r2"
++   [(set_attr "cc" "clobber")
++    (set_attr "instr_format" "fmt1")])
++
++; bic_status_register_on_exit(stack_reference, status_value)
++(define_insn "bic_status_register_on_exit"
++  [(set (match_operand:HI 0 "memory_operand" "=m")
++	(unspec_volatile:HI [(match_operand:HI 1 "msp430_source_operand" "rmQi")] UNSPECV_BIC_SR_IRQ))]
++   ""
++   "bic\t%1, %0"
++   [(set_attr "cc" "none")
++    (set_attr "instr_format" "fmt1")])
++ 
++; bis_status_register_on_exit(stack_reference, status_value)
++(define_insn "bis_status_register_on_exit"
++  [(set (match_operand:HI 0 "memory_operand" "=m")
++	(unspec_volatile:HI [(match_operand:HI 1 "msp430_source_operand" "rmQi")] UNSPECV_BIS_SR_IRQ))]
++   ""
++   "bis\t%1, %0"
++   [(set_attr "cc" "none")
++    (set_attr "instr_format" "fmt1")])
++ 
++; read_stack_pointer(retloc)
++(define_insn "read_stack_pointer"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++	(unspec_volatile:HI [(reg:HI REGNO_SP)] UNSPECV_READ_STACK_POINTER))]
++   ""
++   "mov\tr1, %0"
++   [(set_attr "cc" "none")
++    (set_attr "instr_format" "fmt1")])
++
++; write_stack_pointer(sr_value)
++(define_insn "write_stack_pointer"
++  [(set (reg:HI REGNO_SP)
++	(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_WRITE_STACK_POINTER))]
++   ""
++   "mov\t%0, r1"
++   [(set_attr "cc" "none")
++    (set_attr "instr_format" "fmt1")])
++
++; delay_cycles_init(loopreg, count)
++(define_insn "delay_cycles_init"
++  [(set (match_operand:HI 0 "register_operand" "=r")
++	(unspec_volatile:HI [(match_operand:HI 1 "const_int_operand" "i")] UNSPECV_DELAY_CYCLES))
++   (clobber (match_dup 0))]
++  ""
++  "mov\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++; delay_cycles_decr(loopreg)
++(define_insn "delay_cycles_decr"
++  [(set (match_operand:HI 0 "register_operand" "+r")
++	(unspec_volatile:HI [(minus:HI (match_dup 0) (const_int 1))] UNSPECV_DELAY_CYCLES))]
++  ""
++  "dec\t%0"
++  [(set_attr "cc" "VNZC")
++   (set_attr "instr_format" "fmt1")])
++
++; get_watchdog_clear_value(retloc)
++(define_insn "get_watchdog_clear_value"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++	(unspec_volatile:HI [(const_int 0)] UNSPECV_GET_WATCHDOG_CLEAR_VALUE))]
++  ""
++  "mov\t&__wdt_clear_value, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++; set_watchdog_clear_value(retloc, value)
++(define_insn "set_watchdog_clear_value"
++  [(unspec_volatile:HI [(match_operand:HI 0 "msp430_source_operand" "rmQi")] UNSPECV_SET_WATCHDOG_CLEAR_VALUE)]
++  ""
++  "mov\t%0, &__wdt_clear_value"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++  
++; watchdog_clear()
++(define_insn "watchdog_clear"
++  [(unspec_volatile [(const_int 0)] UNSPECV_WATCHDOG_CLEAR)]
++  ""
++  "mov\t&__wdt_clear_value, &__WDTCTL"
++  [(set_attr "cc" "none")
++   (set_attr "length" "6")
++   ])
++
++;; extendmn2 (sign extension)
++
++(define_insn "extend8bithi1"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "+rmQ")
++	(sign_extend:HI (subreg:QI (match_dup 0) 0)))]
++  ""
++  "sxt\t%0"
++  [(set_attr "cc" "NZC")
++   (set_attr "instr_format" "fmt2")])
++
++(define_expand "extendsidi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand" "")
++        (sign_extend:DI (match_operand:SI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_signextend (operands); DONE;")
++(define_expand "extendhi<mode>2"
++  [(set (match_operand:HIEXT 0 "nonimmediate_operand" "")
++        (sign_extend:<MODE> (match_operand:HI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_signextend (operands); DONE;")
++(define_expand "extendqi<mode>2"
++  [(set (match_operand:QIEXT 0 "nonimmediate_operand" "")
++        (sign_extend:<MODE> (match_operand:QI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_signextend (operands); DONE;")
++
++;; zero_extendmn2 (zero extension)
++
++(define_expand "zero_extendsidi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand" "")
++        (zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_zeroextend (operands); DONE;")
++(define_expand "zero_extendhi<mode>2"
++  [(set (match_operand:HIEXT 0 "nonimmediate_operand" "")
++        (zero_extend:<MODE> (match_operand:HI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_zeroextend (operands); DONE;")
++(define_expand "zero_extendqi<mode>2"
++  [(set (match_operand:QIEXT 0 "nonimmediate_operand" "")
++        (zero_extend:<MODE> (match_operand:QI 1 "general_operand" "")))]
++  ""
++  "msp430_expand_zeroextend (operands); DONE;")
++
++;; bswap (standard rtl, not standard insn)
++
++(define_insn "*bswaphi2"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++        (bswap:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
++  ""
++"swpb\t%0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2")])
++
++(define_expand "bswaphi1"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "+rm")
++	(bswap:HI (match_dup 0)))]
++  ""
++  "")
++
++;; movm
++
++(define_insn "pushqi1"
++  [(set (mem:QI (pre_modify:HI (reg:HI REGNO_SP) (plus:HI (reg:HI REGNO_SP) (const_int -2))))
++	(match_operand:QI 0 "general_operand" "rmi"))]
++  ""
++  "push.b\t%S0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")])
++
++(define_insn "loadqi2"
++  [(set (match_operand:HI 0 "register_operand" "=r")
++	(zero_extend:HI (match_operand:QI 1 "msp430_source_operand" "UmQi")))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "storeqi2"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
++	(subreg:QI (match_operand:HI 1 "register_operand" "r") 0))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "*movqi2"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
++	(match_operand:QI 1 "msp430_source_operand" "UmQi"))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_expand "movqi" 
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++	(match_operand:QI 1 "general_operand" ""))]
++  ""
++  "")
++
++; pushmhi2(num_regs, high_regno)
++(define_insn "pushmhi2"
++  [(set (reg:HI REGNO_SP)
++	(unspec:HI [(match_operand:HI 0 "const_int_operand" "i")
++		    (match_operand:HI 1 "const_int_operand" "N")]
++		   UNSPEC_PUSH_MULTI))]
++  ""
++  {
++    rtx xoperands[2];
++    xoperands[0] = operands[0];
++    xoperands[1] = gen_rtx_REG (HImode, INTVAL (operands[1]));
++    output_asm_insn ("pushm\t%0, %1", xoperands);
++    return "";
++  }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")])
++
++; popmhi2(num_regs, high_regno)
++(define_insn "popmhi2"
++  [(set (reg:HI REGNO_SP)
++	(unspec:HI [(match_operand:HI 0 "const_int_operand" "i")
++		    (match_operand:HI 1 "const_int_operand" "N")]
++		   UNSPEC_POP_MULTI))]
++  ""
++  {
++    rtx xoperands[2];
++    xoperands[0] = operands[0];
++    xoperands[1] = gen_rtx_REG (HImode, INTVAL (operands[1]));
++    output_asm_insn ("popm\t%0, %1", xoperands);
++    return "";
++  }
++  [(set_attr "cc" "none")		; not true if REGNO_SR covered
++   (set_attr "instr_format" "fmt2s")])
++
++(define_insn "pushhi1"
++  [(set (mem:HI (pre_dec:HI (reg:HI REGNO_SP)))
++	(match_operand:HI 0 "general_operand" "Wmi"))]
++  ""
++  "push\t%S0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")])
++
++(define_insn "pophi1"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,w")
++	(mem:HI (post_inc:HI (reg:HI REGNO_SP))))]
++  ""
++  "pop\t%0"
++  [(set_attr "cc" "none,clobber")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "*movhi2"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=Um")
++	(match_operand:HI 1 "msp430_source_operand" "UmQi"))]
++  ""
++  "mov\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_expand "movhi" 
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++        (match_operand:HI 1 "general_operand" ""))]
++  ""
++  "")
++
++(define_insn "*pushm<mode>1"
++  [(set (mem:SISF (pre_dec:HI (reg:HI REGNO_SP)))
++	(match_operand:SISF 0 "register_operand" "r"))]
++  "msp430_cpu & MSP430_CPU_MSP430X"
++  "pushm\t#2, %B0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")
++   (set_attr "instr_mult" "1")])
++
++(define_insn "push<mode>1"
++  [(set (mem:SISF (pre_dec:HI (reg:HI REGNO_SP)))
++	(match_operand:SISF 0 "general_operand" "ST,rmi"))]
++  ""
++  "@
++push\t2+%S0\;push\t2+%S0
++push\t%B0\;push\t%A0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")
++   (set_attr "instr_mult" "2")])
++
++(define_insn "*mov<mode>2"
++  [(set (match_operand:SISF 0 "nonimmediate_operand" "=rm")
++	(match_operand:SISF 1 "msp430_source_operand" "rmQi"))]
++  ""
++  {
++    return msp430_mov_noclobber (operands);
++  }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_expand "mov<mode>" 
++  [(set (match_operand:SISF 0 "nonimmediate_operand" "")
++        (match_operand:SISF 1 "general_operand" ""))]
++  ""
++  "")
++
++(define_insn "*pushmdi1"
++  [(set (mem:DI (pre_dec:HI (reg:HI REGNO_SP)))
++	(match_operand:DI 0 "register_operand" "r"))]
++  "msp430_cpu & MSP430_CPU_MSP430X"
++  "pushm\t#4, %D0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")
++   (set_attr "instr_mult" "1")])
++
++(define_insn "pushdi1"
++  [(set (mem:DI (pre_dec:HI (reg:HI REGNO_SP)))
++	(match_operand:DI 0 "general_operand" "ST,rmi"))]
++  ""
++  "@
++push\t6+%S0\;push\t6+%S0\;push\t6+%S0\;push\t6+%S0
++push\t%D0\;push\t%C0\;push\t%B0\;push\t%A0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt2s")
++   (set_attr "instr_mult" "4")])
++
++(define_insn "*movdi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
++	(match_operand:DI 1 "msp430_source_operand" "rmQi"))]
++  ""
++  {
++    return msp430_mov_noclobber (operands);
++  }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_expand "movdi" 
++  [(set (match_operand:DI 0 "nonimmediate_operand" "")
++        (match_operand:DI 1 "general_operand" ""))]
++  ""
++  "")
++
++;; addm3, subm3
++
++(define_split
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(plus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++		     (match_operand:<MODE> 2 "const_int_operand" "")))]
++  "CONST_INT_P (operands[2]) && MSP430_CG_INT_P(-INTVAL (operands[2])) && !MSP430_CG_INT_P(INTVAL (operands[2]))"
++  [(set (match_dup 0)
++	(minus:<MODE> (match_dup 1)
++		      (match_dup 2)))]
++  { operands[2] = gen_int_mode (-INTVAL (operands[2]), <MODE>mode); })
++
++(define_split
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(minus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++		      (match_operand:<MODE> 2 "const_int_operand" "")))]
++  "CONST_INT_P (operands[2]) && MSP430_CG_INT_P(-INTVAL (operands[2])) && !MSP430_CG_INT_P(INTVAL (operands[2]))"
++  [(set (match_dup 0)
++	(plus:<MODE> (match_dup 1)
++		     (match_dup 2)))]
++  { operands[2] = gen_int_mode (-INTVAL (operands[2]), <MODE>mode); })
++
++(define_insn "*add<mode>3_std"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_frameok_dst>")
++        (plus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "<INTModes_commutative_matchdst>")
++		     (match_operand:<MODE> 2 "msp430_source_operand" "<INTModes_frameok_src>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 2, "add", "addc", NULL); }
++  [(set_attr "cc" "<INTModes_cc_VNZC>")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "*sub<mode>3_std"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_frameok_dst>")
++        (minus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "<INTModes_constraint_matchdst>")
++		      (match_operand:<MODE> 2 "msp430_source_operand" "<INTModes_frameok_src>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 2, "sub", "subc", NULL); }
++  [(set_attr "cc" "<INTModes_cc_VNZC>")
++   (set_attr "instr_format" "fmt1")])
++
++(define_expand "add<mode>3" 
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++        (plus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++		     (match_operand:<MODE> 2 "general_operand" "")))]
++  ""
++  "")
++
++(define_expand "sub<mode>3" 
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++        (minus:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++		      (match_operand:<MODE> 2 "general_operand" "")))]
++  ""
++  "")
++
++;; one_cmplm2 (invert)
++
++(define_expand "one_cmpl<mode>2"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(not:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")))]
++  ""
++  {
++    if (! rtx_equal_p (operands[0], operands[1]))
++      {
++	emit_move_insn (operands[0], operands[1]);
++	operands[1] = operands[0];
++      }
++  })
++
++(define_insn "*one_cmpl<mode>2_insn"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "=rm")
++	(not:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "0")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 0, "inv", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_VNZC>")
++   (set_attr "instr_format" "fmt2")])
++
++;; negm2
++
++(define_insn "negsf2"
++  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,m")
++	(neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))]
++  ""
++  "xor\t#0x8000, %B0"
++  [(set_attr "cc" "clobber")
++   (set_attr "length" "4,6")])
++
++(define_expand "neg<mode>2"
++  [(match_operand:INTModes 0 "nonimmediate_operand" "")
++   (match_operand:<MODE> 1 "general_operand" "")]
++  ""
++  {
++    emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
++    emit_insn (gen_add<mode>3 (operands[0], operands[0], const1_rtx));
++    DONE;
++  })
++
++;; nandm3 (extension)
++
++(define_insn "*nand<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_constraint_dst>")
++        (and:<MODE> (not:<MODE> (match_operand:<MODE> 1 "msp430_source_operand" "<INTModes_constraint_src>"))
++		    (match_operand:<MODE> 2 "general_operand" "<INTModes_constraint_matchdst>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 1, "bic", NULL, NULL); }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++; TODO peephole use bic with op2 inverted is CG-int
++; TODO peephole andhi3 with 0xFF -> and.b or clr.b
++; TODO convert multi-word to word, apply individual optimizations e.g. and -1
++
++(define_insn "and<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_constraint_dst>")
++        (and:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "<INTModes_commutative_matchdst>")
++		    (match_operand:<MODE> 2 "msp430_source_operand" "<INTModes_constraint_src>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 2, "and", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZC>")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "ior<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_constraint_dst>")
++        (ior:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "<INTModes_commutative_matchdst>")
++		    (match_operand:<MODE> 2 "msp430_source_operand" "<INTModes_constraint_src>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 2, "bis", NULL, NULL); }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "xor<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_constraint_dst>")
++        (xor:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "<INTModes_commutative_matchdst>")
++		    (match_operand:<MODE> 2 "msp430_source_operand" "<INTModes_constraint_src>")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 2, "xor", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_VNZC>")
++   (set_attr "instr_format" "fmt1")])
++
++;; absm2
++(define_expand "abs<mode>2"
++  [(match_operand:INTModes 0 "nonimmediate_operand" "<INTModes_constraint_dst>")
++   (match_operand:<MODE> 1 "general_operand" "<INTModes_constraint_matchdst>")]
++  ""
++  {
++    rtx test_ge = gen_rtx_GE (<MODE>mode, operands[0], const0_rtx);
++    rtx dest_label = gen_label_rtx ();
++
++    emit_move_insn (operands[0], operands[1]);
++    emit_jump_insn (gen_cbranch<mode>4 (test_ge, operands[0], const0_rtx, dest_label));
++    emit_insn (gen_neg<mode>2 (operands[0], operands[0]));
++    emit_label (dest_label);
++    DONE;
++  })
++
++(define_insn "abssf2"
++  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,m")
++        (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))]
++  ""
++  "and\t#0x7fff, %B0"
++  [(set_attr "cc" "clobber,clobber")
++   (set_attr "length" "2,3")])		; BAD LENGTH
++
++;; strlenm
++
++(define_expand "strlenhi"
++  [(match_operand:HI 0 "nonimmediate_operand" "=rm")
++   (match_operand:BLK 1 "memory_operand" "m")
++   (match_operand:QI 2 "general_operand" "rmi")
++   (match_operand:QI 3 "const_int_operand" "i")]
++  ""
++  {
++    rtx sp_rtx = gen_reg_rtx (Pmode);
++    rtx sp_deref_rtx = gen_rtx_MEM (QImode, sp_rtx);
++    rtx guard_rtx = operands[2];
++    rtx loop_label = gen_label_rtx ();
++    rtx test_ne = gen_rtx_NE (QImode, sp_deref_rtx, guard_rtx);
++
++    emit_move_insn (sp_rtx, XEXP (operands[1], 0));
++    emit_insn (gen_subhi3 (sp_rtx, sp_rtx, const1_rtx));
++    emit_label (loop_label);
++    emit_insn (gen_addhi3 (sp_rtx, sp_rtx, const1_rtx));
++    emit_jump_insn (gen_cbranchqi4 (test_ne, sp_deref_rtx, guard_rtx, loop_label));
++    emit_insn (gen_subhi3 (operands[0], sp_rtx, XEXP (operands[1], 0)));
++    DONE;
++  })
++
++;;========================================================================
++;; compare
++
++(define_expand "cbranch<mode>4"
++  [(set (cc0) (compare
++               (match_operand:INTModes 1 "nonimmediate_operand")
++               (match_operand:<MODE> 2 "general_operand")))
++   (set (pc)
++        (if_then_else (match_operator 0 "comparison_operator"
++                       [(cc0) (const_int 0)])
++      (label_ref (match_operand 3 "" ""))
++      (pc)))]
++  ""
++  { msp430_expand_cbranch (operands); DONE; })
++
++(define_insn "setcc<mode>2"
++  [(set (cc0) (compare
++               (match_operand:INTRegModes 0 "nonimmediate_operand" "Um")
++               (match_operand:<MODE> 1 "general_operand" "Umi")))]
++  ""
++  { return msp430_output_template (<MODE>mode, 1, "cmp", NULL, NULL); }
++  [(set_attr "cc" "explicit")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "*bittest<mode>2"
++  [(set (cc0) (compare
++               (and:INTRegModes
++		(match_operand:<MODE> 0 "nonimmediate_operand" "Um")
++		(match_operand:<MODE> 1 "general_operand" "Umi"))
++	       (const_int 0)))]
++  ""
++  { return msp430_output_template (<MODE>mode, 1, "bit", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZ>")
++   (set_attr "instr_format" "fmt1")])
++
++(define_insn "branchcc"
++  [(set (pc)
++	(if_then_else
++	 (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
++	 (label_ref (match_operand 0 "" ""))
++	 (pc)))]
++  ""
++  { return msp430_output_branchcc (insn, operands); }
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "condjmp")])
++
++;;============================================================================
++;; call
++;;
++
++(define_expand "call"
++  [(call (match_operand:HI 0 "general_operand" "")
++         (match_operand:HI 1 "general_operand" ""))]
++  ""
++  "")
++
++(define_insn "*call_insn"
++  [(call (mem:HI (match_operand:HI 0 "general_operand" "rmi"))
++         (match_operand:HI 1 "general_operand" "X"))]
++  ""
++  "call\t%S0"
++  [(set_attr "cc" "clobber")
++   (set_attr "instr_format" "fmt2s")])
++
++(define_expand "call_value"
++  [(set (match_operand 0 "register_operand" "")
++        (call (match_operand:HI 1 "general_operand" "")
++              (match_operand:HI 2 "general_operand" "")))]
++  ""
++  "")
++
++(define_insn "*call_value_insn"
++  [(set (match_operand 0 "register_operand" "=r")
++	(call (mem:HI (match_operand:HI 1 "general_operand" "rmi"))
++	      (match_operand:HI 2 "general_operand" "X")))]
++  ""
++  "call\t%S1"
++  [(set_attr "cc" "clobber")
++   (set_attr "instr_format" "fmt2s")])
++
++;;========================================================================
++;; Multiplication 
++
++(define_insn "mpy_inhibit_intr"
++  [(set (mem:HI (pre_dec:HI (reg:HI REGNO_SP)))
++	(unspec_volatile:HI [(const_int 0)] UNSPECV_MPY_INHIBIT_INTR))]
++  ""
++  "push\tr2\;dint\;nop"
++  [(set_attr "cc" "none")
++   (set_attr "length" "6")])
++
++(define_insn "mpy_restore_intr"
++  [(set (mem:HI (post_inc:HI (reg:HI REGNO_SP)))
++	(unspec_volatile:HI [(const_int 0)] UNSPECV_MPY_RESTORE_INTR))]
++  ""
++  "pop\tr2"
++  [(set_attr "cc" "clobber")
++   (set_attr "length" "2")])
++
++(define_expand "mul<mode>3"
++  [(match_operand:INTModes 0 "nonimmediate_operand" "")
++   (match_operand:<MODE> 1 "nonimmediate_operand" "")
++   (match_operand:<MODE> 2 "general_operand" "")]  
++  ""
++  "msp430_expand_mul (operands, 1); DONE;")
++
++(define_expand "mul<mode><wider_mode>3"
++  [(match_operand:<WIDER_MODE> 0 "nonimmediate_operand" "")
++   (match_operand:WidenableINTModes 1 "nonimmediate_operand" "")
++   (match_operand:<MODE> 2 "general_operand" "")]
++  ""
++  "msp430_expand_mul (operands, 1); DONE;")
++
++(define_expand "umul<mode><wider_mode>3"
++  [(match_operand:<WIDER_MODE> 0 "nonimmediate_operand" "")
++   (match_operand:WidenableINTModes 1 "nonimmediate_operand" "")
++   (match_operand:<MODE> 2 "general_operand" "")]
++  ""
++  "msp430_expand_mul (operands, 0); DONE;")
++
++;; All division currently supported by optabs
++
++;; Shift operations
++
++(define_insn "trunchiqi"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,m") 
++	(truncate:QI (match_operand:HI 1 "register_operand" "r,r")))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none,none")
++   (set_attr "length" "1,2")])		; BAD LENGTH
++
++(define_insn "truncsihi"
++  [(set (match_operand:HI 0 "register_operand" "=r") 
++	(truncate:HI (match_operand:SI 1 "register_operand" "r")))]
++  ""
++  "mov\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "length" "1")])		; BAD LENGTH
++
++
++(define_insn "truncsiqi"
++  [(set (match_operand:QI 0 "register_operand" "=r") 
++	(truncate:QI (match_operand:SI 1 "register_operand" "r")))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "length" "1")])		; BAD LENGTH
++
++(define_insn "truncdiqi"
++  [(set (match_operand:QI 0 "register_operand" "=r") 
++	(truncate:QI (match_operand:DI 1 "register_operand" "r")))]
++  ""
++  "mov.b\t%1, %0"
++  [(set_attr "cc" "none")
++   (set_attr "length" "1")])		; BAD LENGTH
++
++(define_insn "truncdisi"
++  [(set (match_operand:SI 0 "register_operand" "=r") 
++	(truncate:SI (match_operand:DI 1 "register_operand" "r")))]
++  ""
++  "mov\t%A1, %A0\;mov\t%B1, %B0"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")])		; BAD LENGTH
++
++(define_expand "ashl<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(ashift:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++		       (match_operand:QI 2 "general_operand" "")))]
++  ""
++  "msp430_expand_ashl (operands); DONE;")
++
++(define_expand "ashr<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(ashiftrt:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++			 (match_operand:QI 2 "general_operand" "")))]
++  ""
++  "msp430_expand_ashr (operands); DONE;")
++
++(define_expand "lshr<mode>3"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "")
++	(lshiftrt:<MODE> (match_operand:<MODE> 1 "nonimmediate_operand" "")
++			 (match_operand:QI 2 "general_operand" "")))]
++  ""
++  "msp430_expand_lshr (operands); DONE;")
++
++;; Miscellaneous shift helpers
++(define_insn "clrc"
++  [(unspec_volatile [(const_int 0)] UNSPECV_CLRC)]
++  ""
++  "clrc"
++  [(set_attr "cc" "clobber")
++   (set_attr "length" "2")
++   ])
++
++(define_insn "mwshl8xor"
++  [(set (match_operand:HI 0 "register_operand" "+r")
++	(unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")] UNSPECV_MWSHL8XOR))
++   (use (match_dup 0))]
++  ""
++  "xor.b\t%1, %0\;xor\t%1, %0\;swpb\t%0"
++  [(set_attr "cc" "clobber")
++   (set_attr "instr_format" "fmt2")])
++
++(define_insn "mwshr8xor"
++  [(set (match_operand:HI 0 "register_operand" "+r")
++	(unspec_volatile:HI [(match_operand:HI 1 "register_operand" "+r")] UNSPECV_MWSHR8XOR))
++   (use (match_dup 0))
++   (use (match_dup 1))
++   (clobber (match_dup 1))]
++  ""
++  "swpb\t%1\;xor.b\t%1, %0\;xor\t%1, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++;; Arithmetic shift left multiple positions
++
++(define_expand "ashlhi_m"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
++		     (match_operand:QI 2 "const_int_operand" "")))]
++  ""
++  "")
++
++(define_insn "*ashlhi_m_insn"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
++	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
++		   (match_operand:QI 2 "const_int_operand" "M")))]
++  "msp430_cpu & MSP430_CPU_MSP430X && CONST_INT_P(operands[2]) && MSP430_CPUX_MULTISHIFT_COUNT_P(INTVAL (operands[2]))"
++  "rlam\t%2, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++;; Arithmetic shift right multiple positions
++
++(define_expand "ashrhi_m"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
++		     (match_operand:QI 2 "const_int_operand" "")))]
++  ""
++  "")
++
++(define_insn "*ashrhi_m_insn"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
++	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
++		     (match_operand:QI 2 "const_int_operand" "M")))]
++  "msp430_cpu & MSP430_CPU_MSP430X && CONST_INT_P(operands[2]) && MSP430_CPUX_MULTISHIFT_COUNT_P(INTVAL (operands[2]))"
++  "rram\t%2, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++(define_insn "ashrhi_15"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
++	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
++		     (const_int 15)))]
++  ""
++  "swpb\t%0\;sxt\t%0\;swpb\t%0\;sxt\t%0"
++  [(set_attr "cc" "clobber")
++   (set_attr "instr_mult" "4")
++   (set_attr "instr_format" "fmt2")])
++
++;; Logical shift right multiple positions (CPUX, HI only)
++
++(define_expand "lshrhi_m"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
++		     (match_operand:QI 2 "const_int_operand" "")))]
++  ""
++  "")
++
++(define_insn "*lshrhi_1_x"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "+r")
++	(lshiftrt:HI (match_dup 0) (const_int 1)))]
++  "msp430_cpu & MSP430_CPU_MSP430X"
++  "rrum\t#1, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++(define_insn "*lshrhi_m_insn"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
++	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
++		     (match_operand:QI 2 "const_int_operand" "M")))]
++  "msp430_cpu & MSP430_CPU_MSP430X && CONST_INT_P(operands[2]) && MSP430_CPUX_MULTISHIFT_COUNT_P(INTVAL (operands[2]))"
++  "rrum\t%2, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++;; Basic single-position shifts
++
++(define_insn "ashl<mode>_1"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "+rm")
++	(ashift:<MODE> (match_dup 0) (const_int 1)))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_template (<MODE>mode, 0, "rla", "rlc", NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZ>")
++   (set_attr "instr_format" "emu1dd")])        ; emulated add dst, dst
++  
++(define_insn "rla<mode>1"
++  [(set (match_operand:INTRegModes 0 "nonimmediate_operand" "+rm")
++	(ashift:<MODE>
++	 (unspec_volatile [(match_dup 0)] UNSPECV_RLA)
++	 (const_int 1)))]
++  ""
++  { return msp430_output_template (<MODE>mode, 0, "rla", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZ>")
++   (set_attr "instr_format" "emu1dd")])        ; emulated add dst, dst
++
++(define_insn "rlc<mode>1"
++  [(set (match_operand:INTRegModes 0 "nonimmediate_operand" "+rm")
++	(unspec_volatile:<MODE> [(match_dup 0)] UNSPECV_RLC))
++   (use (reg:CC REGNO_SR))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_template (<MODE>mode, 0, "rlc", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZ>")
++   (set_attr "instr_format" "emu1dd")])        ; emulated add dst, dst
++
++(define_insn "ashr<mode>_1"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "+rm")
++	(ashiftrt:<MODE> (match_dup 0) (const_int 1)))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_reverse_template (<MODE>mode, 0, "rra", "rrc", NULL); }
++  [(set_attr "cc" "<INTModes_reversed_cc_NZ>")
++   (set_attr "instr_format" "fmt2")])
++  
++(define_insn "rra<mode>1"
++  [(set (match_operand:INTRegModes 0 "nonimmediate_operand" "+rm")
++	(ashiftrt:<MODE>
++	 (unspec_volatile [(match_dup 0)] UNSPECV_RRA)
++	 (const_int 1)))]
++  ""
++  { return msp430_output_reverse_template (<MODE>mode, 0, "rra", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_reversed_cc_NZ>")
++   (set_attr "instr_format" "fmt2")])
++  
++(define_insn "rrc<mode>1"
++  [(set (match_operand:INTRegModes 0 "nonimmediate_operand" "+rm")
++	(unspec_volatile:<MODE> [(match_dup 0)] UNSPECV_RRC))
++   (use (reg:CC REGNO_SR))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_reverse_template (<MODE>mode, 0, "rrc", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_reversed_cc_NZ>")
++   (set_attr "instr_format" "fmt2")])
++  
++(define_insn "lshr<mode>_1"
++  [(set (match_operand:INTModes 0 "nonimmediate_operand" "+rm")
++	(lshiftrt:<MODE> (match_dup 0) (const_int 1)))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_reverse_template (<MODE>mode, 0, "rrc", NULL, "clrc"); }
++  [(set_attr "cc" "<INTModes_reversed_cc_NZ>")
++   (set_attr "instr_format" "fmt2")])
++
++(define_insn "*rruhi1_x"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "+r")
++	(lshiftrt:HI
++	 (unspec_volatile [(match_dup 0)] UNSPECV_RRU)
++	 (const_int 1)))]
++  "msp430_cpu & MSP430_CPU_MSP430X"
++  "rrum\t#1, %0"
++  [(set_attr "cc" "NZ")
++   (set_attr "instr_format" "fmt2")])
++
++(define_insn "rru<mode>1"
++  [(set (match_operand:INTRegModes 0 "nonimmediate_operand" "+rm")
++	(lshiftrt:<MODE>
++	 (unspec_volatile [(match_dup 0)] UNSPECV_RRU)
++	 (const_int 1)))
++   (clobber (reg:CC REGNO_SR))]
++  ""
++  { return msp430_output_reverse_template (<MODE>mode, 0, "rrc", NULL, "clrc"); }
++  [(set_attr "cc" "<INTModes_reversed_cc_NZ>")
++   (set_attr "instr_format" "fmt2")])
++
++;; =====================================================================
++;; single bit extract
++
++(define_expand "extzv"
++  [(match_operand:HI 0 "nonimmediate_operand" "") ; destination
++   (match_operand:QI 1 "nonimmediate_operand" "") ; packed value
++   (match_operand:HI 2 "const_int_operand" "")	  ; width
++   (match_operand:HI 3 "const_int_operand" "")]	  ; starting bit
++  ""
++  {
++    if (msp430_expand_extract (operands, false))
++      DONE;
++    FAIL;
++  })
++
++(define_insn "bittestforcarry<mode>2"
++  [(set
++    (reg:CC REGNO_SR)
++    (unspec:CC
++     [(match_operand:INTRegModes 0 "nonimmediate_operand" "Um")
++      (match_operand:<MODE> 1 "general_operand" "Umi")]
++     UNSPEC_BITTEST_FOR_CARRY))]
++  ""
++  { return msp430_output_template (<MODE>mode, 1, "bit", NULL, NULL); }
++  [(set_attr "cc" "<INTModes_cc_NZC>")
++   (set_attr "instr_format" "fmt1")])
++
++;;=======================================================================
++;;  various BRANCH insns...
++
++;; Unconditional jump instruction.
++(define_insn "jump"
++  [(set (pc) (label_ref (match_operand 0 "" "")))]
++  ""
++  {
++    int dist = msp430_jump_dist(operands[0],insn);
++    if (dist<500 && dist>-500)
++      return "jmp\t%0";
++    return "br\t#%0";
++  }
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")])
++
++; indirect jump
++(define_insn "indirect_jump"
++  [(set (pc) (match_operand:HI 0 "general_operand" "rmi"))]
++  ""
++  "br\t%0"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++
++;; Table helper
++(define_insn "tablejump"
++  [(set (pc) (match_operand:HI 0 "general_operand" "rRP,i,m"))
++   (use (label_ref (match_operand 1 "" "")))]
++  ""
++  "br\t%0\t; %1"
++  [(set_attr "cc" "none")
++   (set_attr "instr_format" "fmt1")])
++
++;; return insn
++(define_insn "*return_inhibited_fallthru"
++  [(return)]
++  "(reload_completed && cfun && cfun->machine
++    && (cfun->machine->frame_flags & MSP430_FF_ready_for_return)
++    && (cfun->machine->frame_flags & MSP430_FF_inhibit_return)
++    && msp430_inhibited_return_fallthru_p (insn))"
++  ""
++  [(set_attr "cc" "none")
++   (set_attr "length" "0")])
++
++(define_insn "*return_inhibited_no_fallthru"
++  [(return)]
++  "(reload_completed && cfun && cfun->machine
++    && (cfun->machine->frame_flags & MSP430_FF_ready_for_return)
++    && (cfun->machine->frame_flags & MSP430_FF_inhibit_return))"
++  {
++    struct machine_function *mfp;
++    gcc_assert (cfun);
++    mfp = cfun->machine;
++    gcc_assert (mfp);
++    gcc_assert (NULL != mfp->inhibited_return_label);
++    fprintf (asm_out_file, "\tbr\t#");
++    assemble_name (asm_out_file, mfp->inhibited_return_label);
++    return "\n";
++  }
++  [(set_attr "cc" "none")
++   (set_attr "length" "4")])
++
++(define_insn "*return_pop_sr"
++  [(return)]
++  "(reload_completed && cfun && cfun->machine
++    && (cfun->machine->frame_flags & MSP430_FF_ready_for_return)
++    && (cfun->machine->frame_flags & MSP430_FF_use_reti))"
++  "reti"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")])
++
++(define_insn "return"
++  [(return)]
++  "(reload_completed && cfun && cfun->machine
++    && (cfun->machine->frame_flags & MSP430_FF_ready_for_return))"
++  "ret"
++  [(set_attr "cc" "none")
++   (set_attr "length" "2")])
++
++(define_expand "prologue"
++  [(const_int 0)]
++  ""
++  "msp430_expand_prologue (); DONE;")
++
++(define_expand "epilogue"
++  [(const_int 0)]
++  ""
++  "msp430_expand_epilogue (); DONE;")
++
++(include "peephole.md")
+diff --git gcc-4.6.3.orig/gcc/config/msp430/msp430.opt gcc-4.6.3/gcc/config/msp430/msp430.opt
+new file mode 100644
+index 0000000..885eee9
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/msp430.opt
+@@ -0,0 +1,57 @@
++; Options for the MSP430 port of the compiler.
++; Converted from msp430.c (gcc 3.2.3 port)
++
++; For every option from this file (such as PROF_STD), a corresponding command-line option is checked and an internal GCC flag is set.
++; To check such flag one should use the TARGET_xxx macro (such as TARGET_PROF_STD).
++; This replaces the deprecated #define TARGET_SWITCHES syntax
++; String options are defined similarily and replace the #define TARGET_OPTIONS syntax
++
++;; This work is partially financed by the European Commission under the
++;; Framework 6 Information Society Technologies Project
++;; "Wirelessly Accessible Sensor Populations (WASP)".
++
++mdisable-hwmul
++Target Report Mask(NO_HWMUL)
++Disable hardware multiplier (DEPRECATED; use -mmpy=none)
++
++minline-hwmul
++Target Report Mask(INLINESIHWMUL)
++Issue inline multiplication code for 32-bit integers
++
++mnoint-hwmul
++Target Report Mask(NOINT_HWMUL)
++Assume interrupt routine does not do hardware multiply
++
++mno-volatile-workaround
++Target Report Mask(NVWA)
++(OBSOLETE) Do not perform volatile workaround for bitwise operations
++
++msave-prologue
++Target Report Mask(SAVE_PROLOGUE)
++Use subroutine call for function prologue/epilogue when possible
++
++mdisable-watchdog
++Target Var(msp430_disable_watchdog) Init(0)
++Link the crt0 modules that disable the watchdog on startup
++
++menable-libcall-shift
++Target Var(msp430_enable_libcall_shift) Init(0)
++Use library routines for non-constant shifts
++
++; ---------------------------------------- Here start the string options imported from TARGET_OPTIONS macro ----------------------------------------
++
++mmcu=
++Target RejectNegative Joined Var(msp430_mcu_name)
++-mmcu=MCU	Select the target MCU
++
++mcpu=
++Target RejectNegative Joined Var(msp430_opt_cpu)
++-mcpu=CPU	Select the CPU model: 430, 430x, 430xv2
++
++mmpy=
++Target RejectNegative Joined Var(msp430_opt_mpy)
++-mmpy=MPY	Define available hardware multiply: none, 16, 16se, 32, 32dw
++
++mivcnt=
++Target RejectNegative Joined Var(msp430_opt_ivcnt)
++-mivcnt=IVCNT	Specify number of interrupt vectors on chip: 16, 32, 64
+diff --git gcc-4.6.3.orig/gcc/config/msp430/peephole.md gcc-4.6.3/gcc/config/msp430/peephole.md
+new file mode 100644
+index 0000000..907c615
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/peephole.md
+@@ -0,0 +1,235 @@
++;; -*- Mode: Scheme -*-
++;;   Machine description for GNU compiler,
++;;   for Texas Instruments msp430 MCUs
++;;   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++;;   Contributed by Dmitry Diky <diwil at mail.ru>
++;;	 GCC 4.x port by Ivan Shcherbakov <mspgcc at sysprogs.org>
++
++;; This work is partially financed by the European Commission under the
++;; Framework 6 Information Society Technologies Project
++;; "Wirelessly Accessible Sensor Populations (WASP)".
++
++; This file is part of GCC.
++
++;; GCC is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 2, or (at your option)
++;; any later version.
++
++;; GCC 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 GCC; see the file COPYING.  If not, write to
++;; the Free Software Foundation, 59 Temple Place - Suite 330,
++;; Boston, MA 02111-1307, USA.
++
++;; Gratuitous route through register for RMW on memory with reg operand
++;; mov &m1, r0; op g3, r0; mov r0, &m1 => op g3, &m1 [r0 dead]
++; see testsuite volpeep_reg.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_dup 0) 
++	(match_operator:<MODE> 2 "msp430_rmw_operator"
++			       [(match_dup 0)
++				(match_operand:<MODE> 3 "general_operand" "")]))
++   (set (match_dup 1) (match_dup 0))]
++  "peep2_reg_dead_p (3, operands[0])"
++  [(set (match_dup 1) 
++	(match_op_dup 2 [(match_dup 1) (match_dup 3)]))]
++  "")
++
++;; Gratuitous route through register for RMW on memory with non-reg operand
++;; mov &m1, r0; mov &m3, r2; op r0, r2; mov r2, &m1 => op &m3, &m1 [r0 dead, r2 dead]
++; see testsuite volpeep_volmem.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "register_operand" "") 
++	(match_operand:<MODE> 3 "nonimmediate_operand" ""))
++   (set (match_dup 2) 
++	(match_operator:<MODE> 4 "msp430_rmw_operator"
++			       [(match_dup 2)
++				(match_dup 0)]))
++   (set (match_dup 1) (match_dup 2))]
++  "peep2_reg_dead_p (4, operands[0]) && peep2_reg_dead_p (4, operands[2])"
++  [(set (match_dup 1) 
++	(match_op_dup 4 [(match_dup 1) (match_dup 3)]))]
++  "")
++
++;; Same as above but with operands swapped (used for sub)
++;; mov &m1, r0; mov &m3, r2; op r2, r0; mov r0, &m1 => op &m3, &m1
++; see testsuite volpeep_volmem.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "register_operand" "") 
++	(match_operand:<MODE> 3 "nonimmediate_operand" ""))
++   (set (match_dup 0) 
++	(match_operator:<MODE> 4 "msp430_rmw_operator"
++			       [(match_dup 0)
++				(match_dup 2)]))
++   (set (match_dup 1) (match_dup 0))]
++  "peep2_reg_dead_p (4, operands[0]) && peep2_reg_dead_p (4, operands[2])"
++  [(set (match_dup 1) 
++	(match_op_dup 4 [(match_dup 1) (match_dup 3)]))]
++  "")
++
++;; Assignment to volatile memory through a cast constant pointer
++;; mov #c1, r0; mov &m3, r2; op4 g5, r2; mov r2, @r0 => op g4, &c1 [r0 dead, r2 dead]
++; see testsuite vwa4.c
++(define_peephole2
++  [(set (match_operand 0 "pmode_register_operand" "") 
++	(match_operand 1 "immediate_operand" ""))
++   (set (match_operand:INTRegModes 2 "register_operand" "") 
++	(match_operand:<MODE> 3 "nonimmediate_operand" ""))
++   (set (match_dup 2) 
++	(match_operator:<MODE> 4 "msp430_rmw_operator"
++			       [(match_dup 2)
++				(match_operand:<MODE> 5 "general_operand" "")]))
++   (set (mem:<MODE> (match_dup 0)) (match_dup 2))]
++  "peep2_reg_dead_p (4, operands[0]) && peep2_reg_dead_p (4, operands[2])"
++  [(set (mem:<MODE> (match_dup 1))
++	(match_op_dup 4 [(mem:<MODE> (match_dup 1)) (match_dup 5)]))]
++  "")
++
++
++;; mov &m1, r0; mov &m3, r2; op r2, r0; mov r0, &m1 => mov &m3, r2; op r2, &m1 [r0 dead, r2 live]
++; see testsuite volpeep_mem.c; vwa_error.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "register_operand" "") 
++	(match_operand:<MODE> 3 "nonimmediate_operand" ""))
++   (set (match_dup 0)
++	(match_operator:<MODE> 4 "msp430_rmw_operator"
++			       [(match_dup 0)
++				(match_dup 2)]))
++   (set (match_dup 1) (match_dup 0))]
++  "peep2_reg_dead_p (4, operands[0]) && ! MEM_VOLATILE_P (operands[3]) && ! peep2_reg_dead_p (4, operands[2])"
++  [(set (match_dup 2) (match_dup 3))
++   (set (match_dup 1) 
++	(match_op_dup 4 [(match_dup 1) (match_dup 2)]))]
++  "")
++
++;; mov &m1, r0; mov &m3, r2; nand r2, r0; mov r0, &m1 => nand &m3, &m1 [r0 dead, r2 dead]
++; see testsuite volpeep_volmem.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "register_operand" "") 
++	(match_operand:<MODE> 3 "nonimmediate_operand" ""))
++   (set (match_dup 0) 
++	(and:<MODE> (not:<MODE> (match_dup 2))
++		    (match_dup 0)))
++   (set (match_dup 1) (match_dup 0))]
++  "peep2_reg_dead_p (4, operands[0]) && peep2_reg_dead_p (4, operands[2])"
++  [(set (match_dup 1) 
++	(and:<MODE> (not:<MODE> (match_dup 3)) (match_dup 1)))]
++  "")
++
++;; mov &m1, r0; nand g2, r0; mov r0, &m1 => nand g2, &m1 [r0 dead]
++; see testsuite volpeep_reg.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_dup 0) 
++	(and:<MODE> (not:<MODE> (match_operand:<MODE> 2 "general_operand" ""))
++		    (match_dup 0)))
++   (set (match_dup 1) (match_dup 0))]
++  "peep2_reg_dead_p (3, operands[0])"
++  [(set (match_dup 1) 
++	(and:<MODE> (not:<MODE> (match_dup 2)) (match_dup 1)))]
++  "")
++
++;; mov &m1, r0; op r0, x2 => op &m1, x2 [r0 dead]
++; transiently checked with vwa5.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "nonimmediate_operand" "")
++	(match_operator:<MODE> 3 "msp430_rmw_operator"
++			       [(match_dup 2)
++				(match_dup 0)]))]
++  "peep2_reg_dead_p (2, operands[0])"
++  [(set (match_dup 2) 
++	(match_op_dup 3 [(match_dup 2) (match_dup 1)]))]
++  "")
++
++;; mov &m1, r0; nand r0, &m2 => nand &m1, &m2 [r0 dead]
++; see testsuite volpeep_volmem.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "") 
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_operand:<MODE> 2 "nonimmediate_operand" "")
++	(and:<MODE> (not:<MODE> (match_dup 0))
++		    (match_dup 2)))]
++  "peep2_reg_dead_p (2, operands[0])"
++  [(set (match_dup 2) 
++	(and:<MODE> (not:<MODE> (match_dup 1)) (match_dup 2)))]
++  "")
++
++;; mov &m1, r0; mov r0 &m2; => mov &m1, &m2 [r0 dead]
++; see testsuite volpeep_volmem.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "")
++        (match_operand:<MODE> 1 "general_operand" ""))
++   (set (match_operand:<MODE> 2 "nonimmediate_operand" "")
++        (match_dup 0))]
++  "peep2_reg_dead_p (2, operands[0])"
++  [(set (match_dup 2) (match_dup 1))]
++  "")
++
++;; mov $r2, r0 ; mov r0, g2 => mov $r2, g2 [r0 dead]
++; see testsuite builtins_read_sr.c
++(define_peephole2
++  [(set (match_operand:HI 0 "register_operand" "")
++	(unspec_volatile:HI [(reg:HI REGNO_SR)] UNSPECV_READ_STATUS_REGISTER))
++   (set (match_operand:HI 2 "nonimmediate_operand" "")
++	(match_dup 0))]
++  "peep2_reg_dead_p (2, operands[0])"
++  [(set (match_dup 2) (unspec_volatile:HI [(reg:HI REGNO_SR)] UNSPECV_READ_STATUS_REGISTER))]
++  "")
++
++;; mov $r1, r0 ; mov r0, g2 => mov $r1, g2 [r0 dead]
++; see testsuite builtins_sp.c
++(define_peephole2
++  [(set (match_operand:HI 0 "register_operand" "")
++	(unspec_volatile:HI [(reg:HI REGNO_SP)] UNSPECV_READ_STACK_POINTER))
++   (set (match_operand:HI 2 "nonimmediate_operand" "")
++	(match_dup 0))]
++  "peep2_reg_dead_p (2, operands[0])"
++  [(set (match_dup 2) (unspec_volatile:HI [(reg:HI REGNO_SP)] UNSPECV_READ_STACK_POINTER))]
++  "")
++
++;; mov m1, r0; and g2, r0 ; cmp r0, 0 ; jeq => bit g2, m1 ; jeq [r0 dead]
++; see testsuite sf3296698.c
++(define_peephole2
++  [(set (match_operand:INTRegModes 0 "register_operand" "")
++	(match_operand:<MODE> 1 "nonimmediate_operand" ""))
++   (set (match_dup 0)
++	(and:<MODE>
++	 (match_dup 0)
++	 (match_operand:<MODE> 2 "general_operand" "")))
++   (set (cc0)
++	(compare (match_dup 0)
++		 (const_int 0)))
++   (set (pc)
++	(if_then_else (match_operator:<MODE> 3 "equality_operator"
++		       [(cc0) (const_int 0)])
++		      (match_operand 4 "" "")
++		      (match_operand 5 "" "")))]
++  "peep2_reg_dead_p (4, operands[0])"
++  [(set (cc0)
++	(compare (and:<MODE> (match_dup 1) (match_dup 2))
++		 (const_int 0)))
++   (set (pc)
++	(if_then_else (match_operator:<MODE> 3 "equality_operator"
++		       [(cc0) (const_int 0)])
++		      (match_operand 4 "" "")
++		      (match_operand 5 "" "")))]
++  "")
++
+diff --git gcc-4.6.3.orig/gcc/config/msp430/predicates.md gcc-4.6.3/gcc/config/msp430/predicates.md
+new file mode 100644
+index 0000000..10f29b5
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/predicates.md
+@@ -0,0 +1,45 @@
++;; -*- Mode: Scheme -*-
++;; Predicate definitions for MSP430
++;; Copyright (C) 2006 Free Software Foundation, Inc.
++
++;; This file is part of GCC.
++
++;; GCC is free software; you can redistribute it and/or modify it
++;; under the terms of the GNU General Public License as published
++;; by the Free Software Foundation; either version 2, or (at your
++;; option) any later version.
++
++;; GCC 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 GCC; see the file COPYING.  If not, write to
++;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
++;; Boston, MA 02110-1301, USA.
++
++;; This work is partially financed by the European Commission under the
++;; Framework 6 Information Society Technologies Project
++;; "Wirelessly Accessible Sensor Populations (WASP)".
++
++;; Identify operators for which MSP430 provides a read-modify-write
++;; solution in one instruction.
++(define_predicate "msp430_rmw_operator"
++  (match_code "and,ior,xor,plus,minus"))
++
++;; Identify a post-increment memory operand
++(define_predicate "msp430_post_inc_operand"
++  (and (match_code "mem")
++       (match_code "post_inc" "0")
++       (match_code "reg" "00")))
++
++;; Extend general operand to also allow post-increment memory references
++(define_predicate "msp430_source_operand"
++  (ior (match_operand 0 "general_operand")
++       (match_operand 0 "msp430_post_inc_operand")))
++
++;; Identify identity comparisons
++(define_special_predicate "equality_operator"
++  (match_code "eq,ne"))
++
+diff --git gcc-4.6.3.orig/gcc/config/msp430/t-msp430 gcc-4.6.3/gcc/config/msp430/t-msp430
+new file mode 100644
+index 0000000..e58c19a
+--- /dev/null
++++ gcc-4.6.3/gcc/config/msp430/t-msp430
+@@ -0,0 +1,164 @@
++# Specific names for MSP430 tools
++AR_FOR_TARGET = msp430-ar
++RANLIB_FOR_TARGET = msp430-ranlib
++NM_FOR_TARGET = msp430-nm
++
++CROSS_LIBGCC1 = libgcc1-asm.a
++LIB1ASMSRC = msp430/libgcc.S
++LIB1ASMFUNCS = \
++	_cmpsi2 \
++	_ucmpsi2 \
++	_cmpdi2 \
++	_ucmpdi2 \
++	_mulqi3 \
++	_mulqihi3 \
++	_umulqihi3 \
++	_mulhi3 \
++	_mulhisi3 \
++	_umulhisi3 \
++	_mulsi3 \
++	_mulsidi3 \
++	_umulsidi3 \
++	_muldi3 \
++	_udivmod8 \
++	_divmod8 \
++	_udivmod16 \
++	_divmod16 \
++	_udivmod32 \
++	_divmod32 \
++	_udivmod64 \
++	_divmod64 \
++	__prologue_saver \
++	__epilogue_restorer \
++	__epilogue_restorer_intr \
++	_ashlqi3 \
++	_ashrqi3 \
++	_lshrqi3 \
++	_ashlhi3 \
++	_ashrhi3 \
++	_lshrhi3 \
++	_ashlsi3 \
++	_ashrsi3 \
++	_lshrsi3 \
++	_ashldi3 \
++	_ashrdi3 \
++	_lshrdi3
++	
++# libgcc...
++LIBGCC1_TEST =
++
++CRT0ASMFUNCS = \
++	_reset_vector__ \
++	__watchdog_support \
++	__init_stack \
++	__low_level_init \
++	_copy_data \
++	_clear_bss \
++	__stop_progExec__ \
++	_endless_loop__ \
++	_unexpected_ \
++	_ctors430 \
++	_dtors430
++
++CRT0ASMSRC = msp430/crt0.S
++
++crt0asmfuncs-o = $(patsubst %,$(T)%$(objext),$(CRT0ASMFUNCS))
++
++$(crt0asmfuncs-o): %$(objext): $(srcdir)/config/$(CRT0ASMSRC)
++	 $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -DL$(*F) -xassembler-with-cpp \
++	  -o $*.o -c $(srcdir)/config/$(CRT0ASMSRC)
++
++$(T)libcrt0.a: $(crt0asmfuncs-o)
++	-rm -f $@
++	$(AR) $(ARFLAGS) $@ $^
++	$(RANLIB) $@
++
++EXTRA_MULTILIB_PARTS += $(T)libcrt0.a
++
++crt0asmfuncs-dwdt-o = $(patsubst %,$(T)%-dwdt$(objext),$(CRT0ASMFUNCS))
++
++$(crt0asmfuncs-dwdt-o): %-dwdt$(objext): $(srcdir)/config/$(CRT0ASMSRC)
++	 $(GCC_FOR_TARGET) -DWITH_DISABLE_WDT $(MULTILIB_CFLAGS) -DL$(*F) -xassembler-with-cpp \
++	  -o $*-dwdt.o -c $(srcdir)/config/$(CRT0ASMSRC)
++
++$(T)libcrt0dwdt.a: $(crt0asmfuncs-dwdt-o)
++	-rm -f $@
++	$(AR) $(ARFLAGS) $@ $^
++	$(RANLIB) $@
++
++EXTRA_MULTILIB_PARTS += $(T)libcrt0dwdt.a
++
++# Interrupt vector tables.  Not part of crt0 because this is completely
++# orthogonal to multilib, and we need three alternatives.
++EXTRA_PARTS += crt0ivtbl16$(objext) crt0ivtbl32$(objext) crt0ivtbl64$(objext)
++
++$(T)crt0ivtbl16.o: $(srcdir)/config/msp430/crt0ivtbl.S $(GCC_PASSES)
++	$(GCC_FOR_TARGET) -c -DINTERRUPT_VECTOR_COUNT=16 \
++		$(srcdir)/config/msp430/crt0ivtbl.S \
++		-o $(T)crt0ivtbl16$(objext)
++
++$(T)crt0ivtbl32.o: $(srcdir)/config/msp430/crt0ivtbl.S $(GCC_PASSES)
++	$(GCC_FOR_TARGET) -c -DINTERRUPT_VECTOR_COUNT=32 \
++		$(srcdir)/config/msp430/crt0ivtbl.S \
++		-o $(T)crt0ivtbl32$(objext)
++
++$(T)crt0ivtbl64.o: $(srcdir)/config/msp430/crt0ivtbl.S $(GCC_PASSES)
++	$(GCC_FOR_TARGET) -c -DINTERRUPT_VECTOR_COUNT=64 \
++		$(srcdir)/config/msp430/crt0ivtbl.S \
++		-o $(T)crt0ivtbl64$(objext)
++
++# We do not have the DF type.
++# Most of the C functions in libgcc2 use almost all registers,
++TARGET_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc -g
++
++fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/msp430/t-msp430
++	echo '#define FLOAT' > fp-bit.c
++	echo '#define FLOAT_ONLY' >> fp-bit.c
++	echo '#define CMPtype HItype' >> fp-bit.c
++	echo '#define DF SF' >> fp-bit.c
++	echo '#define DI SI' >> fp-bit.c
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
++	echo '#define SMALL_MACHINE' >> fp-bit.c
++	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
++
++FPBIT = fp-bit.c
++
++# We do not create a multilib for 430xv2, since it is identical to 430x
++# except in terms of instruction timings.  It maps to 430x.
++TM_MSP430_CPU=430/430x
++
++# Although 16se, 32, and 32dw are valid options, currently the msp430
++# back end generates code only for the 16 variant, which works on the other
++# variants.  The other options map to 16.
++TM_MSP430_MPY=none/16
++
++MULTILIB_OPTIONS = \
++    mcpu=$(subst /,/mcpu=,$(TM_MSP430_CPU)) \
++    mmpy=$(subst /,/mmpy=,$(TM_MSP430_MPY))
++MULTILIB_MATCHES = \
++    mcpu?430x=mcpu?430xv2 \
++    mmpy?16=mmpy?16se \
++    mmpy?16=mmpy?32 \
++    mmpy?16=mmpy?32dw
++LIBGCC = stmp-multilib
++INSTALL_LIBGCC = install-multilib
++
++msp430-builtins.o: $(srcdir)/config/msp430/msp430-builtins.c $(CONFIG_H) $(SYSTEM_H) \
++    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
++	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-builtins.c
++
++msp430-function.o: $(srcdir)/config/msp430/msp430-function.c $(CONFIG_H) $(SYSTEM_H) \
++    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
++	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-function.c
++
++msp430-c.o: $(srcdir)/config/msp430/msp430-c.c $(CONFIG_H) $(SYSTEM_H) \
++    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
++	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-c.c
++
++EXTRA_GCC_OBJS += msp430-gcc.o
++
++msp430-gcc.o: $(srcdir)/config/msp430/msp430-gcc.c $(CONFIG_H) $(TM_H) $(C_COMMON_H)
++	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
++  $(DRIVER_DEFINES) \
++  -DPREFIX=\"$(prefix)\" \
++  $(srcdir)/config/msp430/msp430-gcc.c
+diff --git gcc-4.6.3.orig/gcc/configure gcc-4.6.3/gcc/configure
+index 1960d5a..6fb5855 100755
+--- gcc-4.6.3.orig/gcc/configure
++++ gcc-4.6.3/gcc/configure
+@@ -24967,6 +24967,7 @@ esac
+ # version to the per-target configury.
+ case "$cpu_type" in
+   alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze | mips \
++  | msp430 \
+   | pa | rs6000 | score | sparc | spu | xstormy16 | xtensa)
+     insn="nop"
+     ;;
+diff --git gcc-4.6.3.orig/gcc/configure.ac gcc-4.6.3/gcc/configure.ac
+index 505a54d..2310dc6 100644
+--- gcc-4.6.3.orig/gcc/configure.ac
++++ gcc-4.6.3/gcc/configure.ac
+@@ -3841,6 +3841,7 @@ esac
+ # version to the per-target configury.
+ case "$cpu_type" in
+   alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze | mips \
++  | msp430 \
+   | pa | rs6000 | score | sparc | spu | xstormy16 | xtensa)
+     insn="nop"
+     ;;
+diff --git gcc-4.6.3.orig/gcc/expr.c gcc-4.6.3/gcc/expr.c
+index 0ccdd2e..f13b3e1 100644
+--- gcc-4.6.3.orig/gcc/expr.c
++++ gcc-4.6.3/gcc/expr.c
+@@ -935,7 +935,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
+ 	  data.autinc_from = 1;
+ 	  data.explicit_inc_from = -1;
+ 	}
+-      if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
++      if (USE_LOAD_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_from)
+ 	{
+ 	  data.from_addr = copy_to_mode_reg (from_addr_mode, from_addr);
+ 	  data.autinc_from = 1;
+diff --git gcc-4.6.3.orig/gcc/gcc.c gcc-4.6.3/gcc/gcc.c
+index 75f522e..3dd8846 100644
+--- gcc-4.6.3.orig/gcc/gcc.c
++++ gcc-4.6.3/gcc/gcc.c
+@@ -258,6 +258,7 @@ static const char *replace_outfile_spec_function (int, const char **);
+ static const char *remove_outfile_spec_function (int, const char **);
+ static const char *version_compare_spec_function (int, const char **);
+ static const char *include_spec_function (int, const char **);
++static const char *include_noerr_spec_function (int, const char **);
+ static const char *find_file_spec_function (int, const char **);
+ static const char *find_plugindir_spec_function (int, const char **);
+ static const char *print_asm_header_spec_function (int, const char **);
+@@ -1231,6 +1232,7 @@ static const struct spec_function static_spec_functions[] =
+   { "remove-outfile",		remove_outfile_spec_function },
+   { "version-compare",		version_compare_spec_function },
+   { "include",			include_spec_function },
++  { "include-noerr",		include_noerr_spec_function },
+   { "find-file",		find_file_spec_function },
+   { "find-plugindir",		find_plugindir_spec_function },
+   { "print-asm-header",		print_asm_header_spec_function },
+@@ -8006,6 +8008,29 @@ include_spec_function (int argc, const char **argv)
+   return NULL;
+ }
+ 
++/* %:include_noerr builtin spec function.  This differs from
++   %include_noerr in that it can be nested inside a spec, and thus be
++   %conditionalized or referenced in DRIVER_SELF_SPECS.  It takes one
++   %argument, the filename, and looks for it in the startfile path.
++   %The result is always NULL, i.e. an empty expansion.  */
++
++static const char *
++include_noerr_spec_function (int argc, const char **argv)
++{
++  char *file;
++
++  if (argc != 1)
++    abort ();
++
++  file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
++  if (file)
++    read_specs (file, FALSE);
++  else if (verbose_flag)
++    fnotice (stderr, "could not find specs file %s\n", argv[0]);
++
++  return NULL;
++}
++
+ /* %:find-file spec function.  This function replaces its argument by
+     the file found thru find_file, that is the -print-file-name gcc
+     program option. */
+diff --git gcc-4.6.3.orig/gcc/ira-lives.c gcc-4.6.3/gcc/ira-lives.c
+index 5c5c415..2548cb0 100644
+--- gcc-4.6.3.orig/gcc/ira-lives.c
++++ gcc-4.6.3/gcc/ira-lives.c
+@@ -932,16 +932,14 @@ process_single_reg_class_operands (bool in_p, int freq)
+       if (! in_p && recog_data.operand_type[i] != OP_OUT
+ 	  && recog_data.operand_type[i] != OP_INOUT)
+ 	continue;
+-      cl = single_reg_operand_class (i);
+-      if (cl == NO_REGS)
+-	continue;
+ 
+       operand_a = NULL;
+ 
+       if (GET_CODE (operand) == SUBREG)
+ 	operand = SUBREG_REG (operand);
+ 
+-      if (REG_P (operand)
++      cl = single_reg_operand_class (i);
++      if (cl != NO_REGS && REG_P (operand)
+ 	  && (regno = REGNO (operand)) >= FIRST_PSEUDO_REGISTER)
+ 	{
+ 	  enum reg_class cover_class;
+@@ -993,13 +991,30 @@ process_single_reg_class_operands (bool in_p, int freq)
+ 	  a = OBJECT_ALLOCNO (obj);
+ 	  if (a != operand_a)
+ 	    {
+-	      /* We could increase costs of A instead of making it
+-		 conflicting with the hard register.  But it works worse
+-		 because it will be spilled in reload in anyway.  */
+-	      IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+-				reg_class_contents[cl]);
+-	      IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+-				reg_class_contents[cl]);
++	      if (cl != NO_REGS)
++		{
++		  /* We could increase costs of A instead of making it
++		     conflicting with the hard register.  But it works worse
++		     because it will be spilled in reload in anyway.  */
++		  IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
++				    reg_class_contents[cl]);
++		  IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
++				    reg_class_contents[cl]);
++		}
++	      else if (REG_P (operand)
++		       && (regno = REGNO (operand)) < FIRST_PSEUDO_REGISTER)
++		{
++		  int nregs = hard_regno_nregs[regno][GET_MODE (operand)];
++		  int r;
++
++		  for (r = 0; r < nregs; ++r)
++		    {
++		      SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj),
++					regno+r);
++		      SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
++					regno+r);
++		    }
++		}
+ 	    }
+ 	}
+     }
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/bic_sr_irq.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bic_sr_irq.c
+new file mode 100644
+index 0000000..282fe08
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bic_sr_irq.c
+@@ -0,0 +1,48 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern void * alloca (unsigned int);
++extern unsigned int use_data (void *arg);
++extern unsigned int sr_value;
++
++__attribute__ ((interrupt(1*2)))
++void clear_sr ()
++{
++  unsigned char data[14];
++  unsigned int sr_local;
++  
++  /* The following are 4-byte instructions */
++  /* { dg-final { scan-assembler "bic\[ \t\]#8, 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(8);
++  sr_local = use_data (data);
++  /* { dg-final { scan-assembler "bic\[ \t\]r15, 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(sr_local);
++  /* { dg-final { scan-assembler "bic\[ \t\]@r1, 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(*(unsigned int*)data);
++
++  /* The following are 6-byte instructions */
++  /* { dg-final { scan-assembler "bic\[ \t\]#9, 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(9);
++  /* { dg-final { scan-assembler "bic\[ \t\]&sr_value, 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(sr_value);
++  /* { dg-final { scan-assembler "bic\[ \t\]4\\(r1\\), 22\\(r1\\)" } } */
++  __bic_status_register_on_exit(*(2 + (unsigned int*)data));
++
++}
++
++__attribute__ ((interrupt(2*2)))
++void alloca_sr (int len)
++{
++  char* locbuf;
++
++  /* { dg-final { scan-assembler "bic\[ \t\]#1, @r4" } } */
++  __bic_status_register_on_exit(1);
++  locbuf = alloca(len);
++  locbuf[0] = 'A';
++  locbuf[1] = 0;
++  use_data(locbuf);
++  /* SF 3198920: This one gets stored in the wrong location, because
++   * r1 still has the locbuf allocation reflected in it. */
++  /* { dg-final { scan-assembler "bic\[ \t\]#2, @r4" } } */
++  __bic_status_register_on_exit(2);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/bis_sr_irq.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bis_sr_irq.c
+new file mode 100644
+index 0000000..56f9444
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bis_sr_irq.c
+@@ -0,0 +1,46 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern void * alloca (unsigned int);
++extern unsigned int use_data (unsigned char *arg);
++extern unsigned int sr_value;
++
++__attribute__ ((interrupt(1*2)))
++void set_sr ()
++{
++  unsigned char data[14];
++  unsigned int sr_local;
++  
++  /* The following are 4-byte instructions */
++  /* { dg-final { scan-assembler "bis\[ \t\]#8, 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(8);
++  sr_local = use_data (data);
++  /* { dg-final { scan-assembler "bis\[ \t\]r15, 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(sr_local);
++  /* { dg-final { scan-assembler "bis\[ \t\]@r1, 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(*(unsigned int*)data);
++
++  /* The following are 6-byte instructions */
++  /* { dg-final { scan-assembler "bis\[ \t\]#9, 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(9);
++  /* { dg-final { scan-assembler "bis\[ \t\]&sr_value, 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(sr_value);
++  /* { dg-final { scan-assembler "bis\[ \t\]4\\(r1\\), 22\\(r1\\)" } } */
++  __bis_status_register_on_exit(*(2 + (unsigned int*)data));
++
++}
++
++__attribute__ ((interrupt(2*2)))
++void alloca_sr (int len)
++{
++  char* locbuf;
++
++  /* { dg-final { scan-assembler "bis\[ \t\]#1, @r4" } } */
++  __bis_status_register_on_exit(1);
++  locbuf = alloca(len);
++  locbuf[0] = 'A';
++  locbuf[1] = 0;
++  use_data(locbuf);
++  /* { dg-final { scan-assembler "bis\[ \t\]#2, @r4" } } */
++  __bis_status_register_on_exit(2);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/bswap.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bswap.c
+new file mode 100644
+index 0000000..0db1432
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/bswap.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++unsigned int
++bswaphi2 (unsigned int v)
++{
++  /* { dg-final { scan-assembler "\n\tmov.b\tr15, r15\n\tswpb\tr15\n\tret\n" } } */
++  return v << 8;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtin_address.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtin_address.c
+new file mode 100644
+index 0000000..9f92c77
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtin_address.c
+@@ -0,0 +1,82 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++#if LIVE_P1_ISR
++#include <msp430.h>
++#define ISR_VECTOR PORT1_VECTOR
++#else /* LIVE_P1_ISR */
++#define ISR_VECTOR 1*2
++extern volatile unsigned char P1IV;
++#endif /* ISR_VECTOR */
++
++extern void * alloca (unsigned int len);
++
++extern void reference (void* p);
++
++void fn ()
++{
++  extern volatile void* ra_fn;
++  extern volatile void* fa_fn;
++  /* { dg-final { scan-assembler "mov\t at r4, &ra_fn *\n" } } */
++  ra_fn = __builtin_return_address(0);
++  /* { dg-final { scan-assembler "mov\tr4, &fa_fn *\n" } } */
++  fa_fn = __builtin_frame_address(0);
++}
++
++void fnl ()
++{
++  extern volatile void* ra_fnl;
++  extern volatile void* fa_fnl;
++  char data[4];
++  reference(data);
++  /* { dg-final { scan-assembler "mov\t at r4, &ra_fnl *\n" } } */
++  ra_fnl = __builtin_return_address(0);
++  /* { dg-final { scan-assembler "mov\tr4, &fa_fnl *\n" } } */
++  fa_fnl = __builtin_frame_address(0);
++}
++
++void fnd (int len)
++{
++  extern volatile void* ra_fnd;
++  extern volatile void* fa_fnd;
++  
++  char * data = alloca(len);
++  reference(data);
++  /* { dg-final { scan-assembler "mov\t at r4, &ra_fnd *\n" } } */
++  ra_fnd = __builtin_return_address(0);
++  /* { dg-final { scan-assembler "mov\tr4, &fa_fnd *\n" } } */
++  fa_fnd = __builtin_frame_address(0);
++}
++
++void fnma (int zero, int one, int two, int three, int four, int five)
++{
++  extern volatile void* ra_fnma;
++  extern volatile void* fa_fnma;
++  
++  int data[6];
++  data[0] = zero;
++  data[1] = one;
++  data[2] = two;
++  data[3] = three;
++  data[4] = four;
++  data[5] = five;
++  reference(data);
++  /* { dg-final { scan-assembler "mov\t at r4, &ra_fnma *\n" } } */
++  ra_fnma = __builtin_return_address(0);
++  /* { dg-final { scan-assembler "mov\tr4, &fa_fnma *\n" } } */
++  fa_fnma = __builtin_frame_address(0);
++}
++
++__attribute__((interrupt(ISR_VECTOR)))
++void isr ()
++{
++  extern volatile void* ra_isr;
++  extern volatile void* fa_isr;
++
++  /* Read the vector to clear the interrupt. */
++  (void)P1IV;
++  /* { dg-final { scan-assembler "mov\t2\\(r4\\), &ra_isr *\n" } } */
++  ra_isr = __builtin_return_address(0);
++  /* { dg-final { scan-assembler "mov\tr4, &fa_fnma *\n" } } */
++  fa_isr = __builtin_frame_address(0);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_1.c
+new file mode 100644
+index 0000000..757bdbf
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_1.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++void test ()
++{
++  /* { dg-final { scan-assembler "dint\n\tnop\n\teint\n\tnop\n\tret" } } */
++  __dint();
++  __eint();
++  __nop();
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_bic_sr.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_bic_sr.c
+new file mode 100644
+index 0000000..ee1e6ab
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_bic_sr.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern volatile unsigned int read_sr;
++extern unsigned int write_sr;
++extern unsigned int *sr_ptr;
++
++void test ()
++{
++  int i;
++  unsigned int sr;
++
++  /* { dg-final { scan-assembler "bic\t&write_sr, r2\n" } } */
++  __bic_status_register(write_sr);
++  /* { dg-final { scan-assembler "bic\t#4660, r2\n" } } */
++  __bic_status_register(0x1234);
++  /* { dg-final { scan-assembler "bic\t#8, r2\n" } } */
++  __bic_status_register(8);
++  /* { dg-final { scan-assembler "bic\tr15, r2\n" } } */
++  __bic_status_register(read_sr & 0x42);
++  /* { dg-final { scan-assembler "bic\t at r15, r2\n" } } */
++  __bic_status_register(*sr_ptr);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_bis_sr.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_bis_sr.c
+new file mode 100644
+index 0000000..2f8d023
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_bis_sr.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern volatile unsigned int read_sr;
++extern unsigned int write_sr;
++extern unsigned int *sr_ptr;
++
++void test ()
++{
++  int i;
++  unsigned int sr;
++
++  /* { dg-final { scan-assembler "bis\t&write_sr, r2\n" } } */
++  __bis_status_register(write_sr);
++  /* { dg-final { scan-assembler "bis\t#4660, r2\n" } } */
++  __bis_status_register(0x1234);
++  /* { dg-final { scan-assembler "bis\t#8, r2\n" } } */
++  __bis_status_register(8);
++  /* { dg-final { scan-assembler "bis\tr15, r2\n" } } */
++  __bis_status_register(read_sr & 0x42);
++  /* { dg-final { scan-assembler "bis\t at r15, r2\n" } } */
++  __bis_status_register(*sr_ptr);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_gsistate.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_gsistate.c
+new file mode 100644
+index 0000000..06cbf9b
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_gsistate.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++typedef unsigned int istate_t;
++extern volatile istate_t sv ;
++extern istate_t * volatile svp;
++
++void test ()
++{
++  istate_t sv;
++
++  /* { dg-final { scan-assembler "mov\tr2, r14\n" } } */
++  sv = __get_interrupt_state();
++  /* { dg-final { scan-assembler "mov\t\&svp, r15\n\tmov\tr2, @r15\n" } } */
++  *svp = __get_interrupt_state();
++  /* { dg-final { scan-assembler "mov\tr14, r2\n" } } */
++  __set_interrupt_state(sv);
++  /* { dg-final { scan-assembler "mov\t at r15, r2\n" } } */
++  __set_interrupt_state(*svp);
++  /* { dg-final { scan-assembler "mov\t#8, r2\n" } } */
++  __set_interrupt_state(8);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_read_sr.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_read_sr.c
+new file mode 100644
+index 0000000..f2683c1
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_read_sr.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned int read_sr;
++extern unsigned int *sr_ptr;
++
++void test ()
++{
++  int i;
++  unsigned int sr;
++
++  /* { dg-final { scan-assembler "mov\tr2, r15\n" } } */
++  sr = __read_status_register();
++  /* { dg-final { scan-assembler "mov\tr2, \&read_sr\n" } } */
++  read_sr = __read_status_register();
++  /* { dg-final { scan-assembler "mov\tr2, @r15\n" } } */
++  *sr_ptr = __read_status_register();
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_sp.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_sp.c
+new file mode 100644
+index 0000000..12b54ac
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_sp.c
+@@ -0,0 +1,29 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern void * volatile read_sp;
++extern void * write_sp;
++extern void * * sp_ptr;
++
++void test ()
++{
++  int i;
++  void * sp;
++
++  /* { dg-final { scan-assembler "mov\tr1, r15\n" } } */
++  sp = __read_stack_pointer();
++  /* { dg-final { scan-assembler "mov\tr1, \&read_sp\n" } } */
++  read_sp = __read_stack_pointer();
++  /* { dg-final { scan-assembler "mov\tr1, @r15\n" } } */
++  *sp_ptr = __read_stack_pointer();
++  /* { dg-final { scan-assembler "mov\t&write_sp, r1\n" } } */
++  __write_stack_pointer(write_sp);
++  /* { dg-final { scan-assembler "mov\t#4660, r1\n" } } */
++  __write_stack_pointer((void *)0x1234);
++  /* { dg-final { scan-assembler "mov\t#8, r1\n" } } */
++  __write_stack_pointer((void *)8);
++  /* { dg-final { scan-assembler "mov\tr15, r1\n" } } */
++  __write_stack_pointer((void *)(0x42 & (unsigned int)read_sp));
++  /* { dg-final { scan-assembler "mov\t at r15, r1\n" } } */
++  __write_stack_pointer(*sp_ptr);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_swap_bytes.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_swap_bytes.c
+new file mode 100644
+index 0000000..41f4858
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_swap_bytes.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++unsigned int vi;
++unsigned int vx;
++unsigned int vc;
++unsigned int get_v ();
++
++void test ()
++{
++  /* { dg-final { scan-assembler "mov\t#13330, \&vi\n" } } */
++  vi = __swap_bytes(0x1234);
++  /* { dg-final { scan-assembler "swpb\t\&vx\n" } } */
++  vx = __swap_bytes(vx);
++  /* { dg-final { scan-assembler "call\t#get_v\n\tswpb\tr15\n\tmov\tr15, \&vc\n" } } */
++  vc = __swap_bytes(get_v());
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/builtins_write_sr.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_write_sr.c
+new file mode 100644
+index 0000000..c891527
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/builtins_write_sr.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern volatile unsigned int read_sr;
++extern unsigned int write_sr;
++extern unsigned int *sr_ptr;
++
++void test ()
++{
++  int i;
++  unsigned int sr;
++
++  /* { dg-final { scan-assembler "mov\t&write_sr, r2\n" } } */
++  __write_status_register(write_sr);
++  /* { dg-final { scan-assembler "mov\t#4660, r2\n" } } */
++  __write_status_register(0x1234);
++  /* { dg-final { scan-assembler "mov\t#8, r2\n" } } */
++  __write_status_register(8);
++  /* { dg-final { scan-assembler "mov\tr15, r2\n" } } */
++  __write_status_register(read_sr & 0x42);
++  /* { dg-final { scan-assembler "mov\t at r15, r2\n" } } */
++  __write_status_register(*sr_ptr);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/critical_attribute.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/critical_attribute.c
+new file mode 100644
+index 0000000..b60ea3b
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/critical_attribute.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++__attribute__((critical))
++int
++critical (int a)
++{
++  /* { dg-final { scan-assembler "critical:\n\tpush\tr2\n\tdint\n\tnop\n\tadd\t#1, r15\n\tpop\tr2\n\tret\n" } } */
++  return a+1;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/elimination.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/elimination.c
+new file mode 100644
+index 0000000..22b4334
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/elimination.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "" } */
++
++static unsigned char is_initialized = 0;
++
++int putchar (int c)
++{
++  /* { dg-final { scan-assembler "\tmov\tr15, -4\\(r4\\)\n" } } */
++  if (! is_initialized) {
++    unsigned int delay;
++
++    is_initialized = 1;
++    delay = 0;
++    while (++delay);
++  }
++
++  return c;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/framesaver_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/framesaver_1.c
+new file mode 100644
+index 0000000..c1a29ad
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/framesaver_1.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern volatile int v1;
++extern volatile int v2;
++extern volatile int v3;
++extern void doit();
++
++__attribute__ ((saveprologue))
++int func (int a, int b, int c) /* { dg-warning "saveprologue no longer supported" } */
++{
++  /* NOT dg-final { scan-assembler "\tadd\t\#llo\\(-18\\), r1\n\tmov\tr0, r12\n\tbr\t#__prologue_saver" } } */
++  int l1 = v1+v2;
++  int l2 = v2+v3;
++  int l3 = v1+v3;
++  doit();
++  return a+b+c+l1+l2+l3;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/framesaver_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/framesaver_2.c
+new file mode 100644
+index 0000000..73978ef
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/framesaver_2.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern volatile int v1;
++extern volatile int v2;
++extern volatile int v3;
++extern void doit(char * data);
++
++__attribute__ ((saveprologue))
++int func (int a, int b, int c) /* { dg-warning "saveprologue no longer supported" } */
++{
++  /* NOT dg-final { scan-assembler "\tadd\t\#llo\\(-20\\), r1\n\tmov\tr0, r12\n\tbr\t#__prologue_saver" } } */
++  int l1 = v1+v2;
++  int l2 = v2+v3;
++  int l3 = v1+v3;
++  char* data = __builtin_alloca (l3);
++  doit(data);
++  return a+b+c+l1+l2+l3;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/gen_return_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/gen_return_1.c
+new file mode 100644
+index 0000000..8dac65e
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/gen_return_1.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++extern int test ();
++extern void doit ();
++
++int func ()
++{
++  if (test ())
++    /* { dg-final { scan-assembler "mov\t#2, r15\n\tret\n" } } */
++    return 2;
++  doit();
++  /* { dg-final { scan-assembler "mov\t#1, r15\n\tret\n" } } */
++  return 1;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/gen_return_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/gen_return_2.c
+new file mode 100644
+index 0000000..12d81a8
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/gen_return_2.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++extern int test ();
++extern void doit ();
++
++__attribute__ ((naked))
++int func ()
++{
++  /* { dg-final { scan-assembler-not "\tret\n" } } */
++  if (test ())
++    return 2;
++  doit();
++  return 1;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/msp430.exp gcc-4.6.3/gcc/testsuite/gcc.target/msp430/msp430.exp
+new file mode 100644
+index 0000000..735bb9b
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/msp430.exp
+@@ -0,0 +1,41 @@
++# Copyright (C) 2011 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 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 GCC; see the file COPYING3.  If not see
++# <http://www.gnu.org/licenses/>.
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Exit immediately if this isn't an MSP430 target.
++if ![istarget msp430-*-*] then {
++  return
++}
++
++# Load support procs.
++load_lib gcc-dg.exp
++
++# If a testcase doesn't have special options, use these.
++global DEFAULT_CFLAGS
++if ![info exists DEFAULT_CFLAGS] then {
++    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
++}
++
++# Initialize `dg'.
++dg-init
++
++# Main loop.
++dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
++	"" $DEFAULT_CFLAGS
++
++# All done.
++dg-finish
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/section_attribute.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/section_attribute.c
+new file mode 100644
+index 0000000..ce69a18
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/section_attribute.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++__attribute__ ((naked,section(".init2")))
++void __init_stack () /* { dg-warning "frame allocation destroys caller register due to 'task'" } */
++{
++  /* { dg-final { scan-assembler ".section\t.init2,\"ax\", at progbits" } } */
++  /* { dg-final { scan-assembler "mov\t#256, r1\n" } } */
++  __write_stack_pointer((void*)0x100);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3090574_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3090574_1.c
+new file mode 100644
+index 0000000..fec0e99
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3090574_1.c
+@@ -0,0 +1,5 @@
++/* { dg-error "PIC not supported on msp430" } */
++/* { dg-do compile } */
++/* { dg-options "-O -fpic" } */
++
++int t (int a) { return a+1; }
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3090574_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3090574_2.c
+new file mode 100644
+index 0000000..506a4a6
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3090574_2.c
+@@ -0,0 +1,5 @@
++/* { dg-error "PIC not supported on msp430" } */
++/* { dg-do compile } */
++/* { dg-options "-O -fPIC" } */
++
++int t (int a) { return a+1; }
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3104943_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_1.c
+new file mode 100644
+index 0000000..e4079da
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_1.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++struct record {
++  int data[1];
++};
++
++extern struct record ef ();
++
++struct record
++f ()
++{
++  struct record rv = { sizeof(rv) };
++  /* { dg-final { scan-assembler "mov\t#2, r15" } } */
++  return rv;
++}
++
++int
++xf ()
++{
++  struct record rv = ef();
++  /* { dg-final { scan-assembler "add\t#1, r15\n" } } */
++  return 1 + rv.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3104943_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_2.c
+new file mode 100644
+index 0000000..26401d9
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_2.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++struct record {
++  int data[2];
++};
++
++extern struct record ef ();
++
++struct record
++f ()
++{
++  struct record rv = { 1, sizeof(rv) };
++  /* { dg-final { scan-assembler "mov\t#1, r14" } } */
++  /* { dg-final { scan-assembler "mov\t#4, r15" } } */
++  return rv;
++}
++
++int
++xf ()
++{
++  struct record rv = ef();
++  /* { dg-final { scan-assembler "mov\tr14, r15" } } */
++  return 1 + rv.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3104943_3.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_3.c
+new file mode 100644
+index 0000000..931c4ab
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_3.c
+@@ -0,0 +1,30 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++struct record {
++  int data[3];
++};
++
++extern struct record ef ();
++
++struct record
++f ()
++{
++  struct record rv = { 1, 2, sizeof(rv) };
++  /* NOTE: Although this can fit in 3 registers, the middle end treats
++     the return value as a DImode integer, which cannot be placed
++     starting in r13. */
++  /* { dg-final { scan-assembler "mov\t#1, r12" } } */
++  /* { dg-final { scan-assembler "mov\t#2, r13" } } */
++  /* { dg-final { scan-assembler "mov\t#6, r14" } } */
++  /* { dg-final { scan-assembler "mov\t#0, r15" } } */
++  return rv;
++}
++
++int
++xf ()
++{
++  struct record rv = ef();
++  /* { dg-final { scan-assembler "mov\tr12, r15" } } */
++  return 1 + rv.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3104943_4.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_4.c
+new file mode 100644
+index 0000000..a809957
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_4.c
+@@ -0,0 +1,27 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++struct record {
++  int data[4];
++};
++
++extern struct record ef ();
++
++struct record
++f ()
++{
++  struct record rv = { 1, 2, 3, sizeof(rv) };
++  /* { dg-final { scan-assembler "mov\t#1, r12" } } */
++  /* { dg-final { scan-assembler "mov\t#2, r13" } } */
++  /* { dg-final { scan-assembler "mov\t#3, r14" } } */
++  /* { dg-final { scan-assembler "mov\t#8, r15" } } */
++  return rv;
++}
++
++int
++xf ()
++{
++  struct record rv = ef();
++  /* { dg-final { scan-assembler "mov\tr12, r15" } } */
++  return 1 + rv.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3104943_5.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_5.c
+new file mode 100644
+index 0000000..69085b2
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3104943_5.c
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++struct record {
++  int data[5];
++};
++
++extern struct record ef ();
++
++struct record
++f ()
++{
++  struct record rv = { 1, 2, 3, 4, sizeof(rv) };
++  /* { dg-final { scan-assembler "mov\t#1, @r15" } } */
++  /* { dg-final { scan-assembler "mov\t#2, 2\\(r15\\)" } } */
++  /* { dg-final { scan-assembler "mov\t#3, 4\\(r15\\)" } } */
++  /* { dg-final { scan-assembler "mov\t#4, 6\\(r15\\)" } } */
++  /* { dg-final { scan-assembler "mov\t#10, 8\\(r15\\)" } } */
++  return rv;
++}
++
++int
++xf ()
++{
++  struct record rv = ef();
++  /* { dg-final { scan-assembler "mov\t at r1, r15" } } */
++  return 1 + rv.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3112089.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3112089.c
+new file mode 100644
+index 0000000..ed177ba
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3112089.c
+@@ -0,0 +1,67 @@
++/* https://sourceforge.net/tracker/?func=detail&aid=3112089&group_id=277223&atid=1177287 */
++
++
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++typedef unsigned long int uint32_t;
++typedef unsigned int uint16_t;
++typedef unsigned char uint8_t;
++
++#define TIMERS_MAX 3
++#define TIMER_NULL TIMERS_MAX
++
++typedef struct{
++  uint32_t count;
++  uint32_t interval;
++  uint16_t *mbox;			/* caller supplied */
++  uint8_t prev;
++  uint8_t next;
++} TimerTCB;
++
++typedef uint8_t TimerId;
++
++volatile TimerTCB timerTable[TIMERS_MAX];
++volatile uint8_t timerListHead;
++volatile uint8_t timerListTail;
++volatile uint8_t timerFreeList;
++
++volatile uint32_t localTime;
++
++uint8_t TimerTickHandler(void);
++TimerId TimerCreate(uint32_t val, uint16_t *mbox, uint8_t options);
++
++uint8_t TimerTickHandler(void)
++{
++  uint8_t sts = 0;		/* assume no wakeup required */
++  volatile uint8_t t;
++  uint16_t *mbox;
++  uint32_t val;
++
++  localTime++;
++  if(timerListHead != TIMER_NULL){
++    timerTable[timerListHead].count--;
++
++    while((timerListHead != TIMER_NULL) && (timerTable[timerListHead].count == 0)){
++      /* What we're looking for is:
++        mov     2(r14), r15
++        mov     @r14, r14
++        jeq     .L11
++
++	except with a comparison of the newly read r14 before the jeq. */
++      /* { dg-final { scan-assembler "cmp\[ \t\]#0, r15" } } */
++      UART_SendByte('t');
++      t = timerListHead;
++
++      /* Remove from list of active timers */
++      timerListHead = timerTable[t].next;
++
++      if(timerListHead != TIMER_NULL){
++	timerTable[timerListHead].prev = TIMER_NULL;
++      }
++
++      sts = 1;
++    }
++  }
++  return sts;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3148801.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3148801.c
+new file mode 100644
+index 0000000..d10da65
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3148801.c
+@@ -0,0 +1,20 @@
++/* https://sourceforge.net/tracker/?func=detail&aid=3148801&group_id=42303&atid=432701 */
++
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++struct word5 {
++  int data[5];
++};
++
++extern struct word5 copy5 (struct word5 in);
++
++int test ()
++{
++  struct word5 local = { 1, 2, 3, 4, 5 };
++  struct word5 tmp;
++
++  /* { dg-final { scan-assembler "push\[ \t\]#5\n\[ \t\]push\[ \t\]#4\n\[ \t\]push\[ \t\]#3\n\[ \t\]push\[ \t\]#2\n" } } */
++  tmp = copy5(local);
++  return tmp.data[0];
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3177314_base.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3177314_base.c
+new file mode 100644
+index 0000000..24a3cf2
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3177314_base.c
+@@ -0,0 +1,8 @@
++/* { dg-do compile } */
++/* { dg-additional-files "sf3177314_ext.c" } */
++
++extern int longname_l10iiiviiii20iiiviiii30iiiviiii40iiiviiii50iiiviiii60iiiviiii70iiiviiii80iiiviiii90iiiviiii100iiviiii110iiviiii120iiviiii130iiviiii140iiviiii150iiviiii160iiviiii170iiviiii180iiviiii190iiviiii200iiviiii210iiviiii220iiviiii230iiviiii240iiviiii250iiviiii260iiviiii270iiviiii280iiviiii290iiviiii;
++
++int main (int argc, char* argi[]) {
++  return 0 == longname_l10iiiviiii20iiiviiii30iiiviiii40iiiviiii50iiiviiii60iiiviiii70iiiviiii80iiiviiii90iiiviiii100iiviiii110iiviiii120iiviiii130iiviiii140iiviiii150iiviiii160iiviiii170iiviiii180iiviiii190iiviiii200iiviiii210iiviiii220iiviiii230iiviiii240iiviiii250iiviiii260iiviiii270iiviiii280iiviiii290iiviiii;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3177314_ext.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3177314_ext.c
+new file mode 100644
+index 0000000..061519d
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3177314_ext.c
+@@ -0,0 +1,2 @@
++/* secondary test file referenced via sf3177314_base.c */
++int longname_l10iiiviiii20iiiviiii30iiiviiii40iiiviiii50iiiviiii60iiiviiii70iiiviiii80iiiviiii90iiiviiii100iiviiii110iiviiii120iiviiii130iiviiii140iiviiii150iiviiii160iiviiii170iiviiii180iiviiii190iiviiii200iiviiii210iiviiii220iiviiii230iiviiii240iiviiii250iiviiii260iiviiii270iiviiii280iiviiii290iiviiii;
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3188386.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3188386.c
+new file mode 100644
+index 0000000..877edb2
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3188386.c
+@@ -0,0 +1,20 @@
++/* https://sourceforge.net/tracker/?func=detail&aid=3188386&group_id=42303&atid=432701 */
++
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++struct sixbytes {
++  int data[3];
++};
++
++struct sixbytes
++f ()
++{
++  struct sixbytes rv = { 1, 2, sizeof(rv) };
++  /* { dg-final { scan-assembler "mov\[ \t\]#1, r12" } } */
++  /* { dg-final { scan-assembler "mov\[ \t\]#2, r13" } } */
++  /* { dg-final { scan-assembler "mov\[ \t\]#6, r14" } } */
++  /* { dg-final { scan-assembler "mov\[ \t\]#0, r15" } } */
++  
++  return rv;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3188386_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3188386_2.c
+new file mode 100644
+index 0000000..e18575c
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3188386_2.c
+@@ -0,0 +1,17 @@
++/* https://sourceforge.net/tracker/?func=detail&aid=3188386&group_id=42303&atid=432701 */
++
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++struct fivebytes {
++  char data[5];
++} __attribute__((packed));
++
++struct fivebytes
++f ()
++{
++  struct fivebytes rv = { 1, 2, 3, 4, sizeof(rv) };
++  
++  /* { dg-final { scan-assembler "mov\t#513, r12\n\tmov\t#1027, r13\n\tmov\t#5, r14\n\tmov\t#0, r15" } } */
++  return rv;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_1.c
+new file mode 100644
+index 0000000..6a755dc
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_1.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++int naked __attribute__((naked)); /* { dg-warning "'naked' attribute ignored" } */
++int signal __attribute__((signal)); /* { dg-warning "'signal' attribute ignored" } */
++int interrupt __attribute__((interrupt)); /* { dg-warning "'interrupt' attribute ignored" } */
++int task __attribute__((task)); /* { dg-warning "'task' attribute ignored" } */
++int wakeup __attribute__((wakeup)); /* { dg-warning "'wakeup' attribute ignored" } */
++int critical __attribute__((critical)); /* { dg-warning "'critical' attribute ignored" } */
++int reentrant __attribute__((reentrant)); /* { dg-warning "'reentrant' attribute ignored" } */
++int saveprologue __attribute__((saveprologue)); /* { dg-warning "'saveprologue' attribute ignored" } */
++int noint_hwmul __attribute__((noint_hwmul)); /* { dg-warning "'noint_hwmul' attribute ignored" } */
++
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_2.c
+new file mode 100644
+index 0000000..3e079a7
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_2.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++
++__attribute__((wakeup))
++void wakeup_requires_interrupt () { } /* { dg-warning "'wakeup' attribute ignored \\(requires 'interrupt'\\)" } */
++__attribute__((signal))
++void signal_requires_interrupt () { } /* { dg-warning "'signal' attribute ignored \\(requires 'interrupt'\\)" } */
++
++__attribute__((reentrant,naked))
++void reentrant_naked () { } /* { dg-warning "'reentrant' attribute ignored \\(incompatible with 'naked'\\)" } */
++/* { dg-warning "frame allocation destroys caller register due to 'task'" "" { target *-*-* } 9 } */
++__attribute__((critical,naked))
++void critical_naked () { } /* { dg-warning "'critical' attribute ignored \\(incompatible with 'naked'\\)" } */
++/* { dg-warning "frame allocation destroys caller register due to 'task'" "" { target *-*-* } 12 } */
++
++__attribute__((reentrant,critical))
++void no_reentrant_critical () { } /* { dg-warning "'reentrant' attribute ignored \\(incompatible with 'critical'\\)" } */
++__attribute__((reentrant,interrupt(2)))
++void no_reentrant_interrupt () { } /* { dg-warning "'reentrant' attribute ignored \\(incompatible with 'interrupt'\\)" } */
++__attribute__((critical,interrupt(4)))
++void no_critical_interrupt () { } /* { dg-warning "'critical' attribute ignored \\(incompatible with 'interrupt'\\)" } */
++
++__attribute__((naked,task))
++void no_naked_task () { } /* { dg-warning "'naked' attribute ignored \\(incompatible with 'task'\\)" } */
++/* { dg-warning "frame allocation destroys caller register due to 'task'" "" { target *-*-* } 23 } */
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_3.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_3.c
+new file mode 100644
+index 0000000..b9055d4
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_3.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern void ref (int * p);
++extern int call ();
++
++/* Task functions may allocate frames */
++__attribute__ ((task))
++int task_with_frame ()
++{
++  int v;
++  ref(&v);
++  return v;
++}
++
++/* Naked functions should not allocate frames.  SF 3264484 describes
++ * why this is a warning not an error. */
++__attribute__ ((naked))
++int naked_with_frame () /* { dg-warning "function requires 2 bytes for stack storage but frame allocation inhibited by 'naked'" } */
++{
++  int v;
++  ref(&v);
++  return v;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_4.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_4.c
+new file mode 100644
+index 0000000..f9c54e8
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_4.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++
++/* Interrupt vectors non-negative */
++__attribute__ ((interrupt(-2)))
++void negative_isr () { } /* { dg-error "interrupt vector offset -2 must be even and non-negative" } */
++
++/* Interrupt vectors even */
++__attribute__ ((interrupt(1)))
++void odd_isr () { } /* { dg-error "interrupt vector offset 1 must be even and non-negative" } */
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_5.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_5.c
+new file mode 100644
+index 0000000..9fdafd5
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_5.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++
++/* Standard syntax */
++__attribute__ ((interrupt(4*2)))
++void vectored_isr () { }
++/* { dg-final { scan-assembler "vectored_isr:\n.global\t__isr_4\n__isr_4:\n" } } */
++
++/* Old flag for non-associated ISR */
++__attribute__ ((interrupt(255)))
++void legacy_unvectored_isr () { }
++
++/* New syntax for non-associated ISR */
++__attribute__ ((interrupt))
++void unvectored_isr () { }
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_6.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_6.c
+new file mode 100644
+index 0000000..92c9937
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_6.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-mivcnt=16" } */
++
++/* Vector out of range */
++__attribute__ ((interrupt(16*2)))
++void overflowed_vector () { } /* { dg-error "interrupt vector 16 is beyond end of MCU vector table" } */
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_7.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_7.c
+new file mode 100644
+index 0000000..b291112
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_7.c
+@@ -0,0 +1,35 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++/* None of these non-hosted functions should generate a return
++ * instruction of any sort. */
++/* { dg-final { scan-assembler-not "\tret" } } */
++
++__attribute__ ((task))
++int task ()
++{
++  return 32;
++}
++
++__attribute__ ((naked))
++int naked ()
++{
++  return 33;
++}
++
++extern int v;
++
++__attribute__ ((interrupt,naked))
++void naked_isr ()
++{
++  v = 34;
++  /* { dg-final { scan-assembler "\tmov\t#34, &v\n" } } */
++}
++
++__attribute__ ((interrupt,task))
++void task_isr ()
++{
++  v = 35;
++  /* { dg-final { scan-assembler "\tmov\t#35, &v\n" } } */
++}
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3200763_8.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_8.c
+new file mode 100644
+index 0000000..4c2fd4c
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3200763_8.c
+@@ -0,0 +1,34 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++/* Hosted tasks include the return instruction */
++__attribute__ ((task,hosted))
++int hosted_task ()
++{
++  /* { dg-final { scan-assembler "\tmov\t#32, r15\n\tret\n" } } */
++  return 32;
++}
++
++/* Hosted naked include the return instruction */
++__attribute__ ((naked,hosted))
++int hosted_naked ()
++{
++  /* { dg-final { scan-assembler "\tmov\t#33, r15\n\tret\n" } } */
++  return 33;
++}
++
++extern int v;
++
++__attribute__ ((interrupt,naked,hosted))
++void hosted_naked_isr ()
++{
++  v = 34;
++  /* { dg-final { scan-assembler "\tmov\t#34, &v\n\treti\n" } } */
++}
++
++__attribute__ ((interrupt,task,hosted))
++void hosted_task_isr ()
++{
++  v = 35;
++  /* { dg-final { scan-assembler "\tmov\t#35, &v\n\treti\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3201686.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3201686.c
+new file mode 100644
+index 0000000..a81bd7a
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3201686.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++/* { dg-final { scan-assembler-not ".type\tdisappearing, at function" } } */
++extern volatile int v;
++static void disappearing ()
++{
++  v = 'd';
++}
++
++/* { dg-final { scan-assembler ".type\tpreserved, at function" } } */
++__attribute__ ((interrupt(1*2)))
++static void preserved ()
++{
++  v = 'p';
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3207853.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3207853.c
+new file mode 100644
+index 0000000..ba9072e
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3207853.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern void doit (unsigned long long int v);
++void call ()
++{
++  static const unsigned long long int value = 0x123456789abcdef0ULL;
++
++  /* Builds on 64-bit systems generate different code than ones on
++   * 32-bit systems. */
++  /* { dg-final { scan-assembler "mov\t#llo\\((-1698898192|1311768467463790320)\\), r12" } } */
++  /* { dg-final { scan-assembler "mov\t#lhi\\((-1698898192|1311768467463790320)\\), r13" } } */
++  /* { dg-final { scan-assembler "mov\t#(llo\\(305419896\\)|hlo\\(1311768467463790320\\)), r14" } } */
++  /* { dg-final { scan-assembler "mov\t#(lhi\\(305419896\\)|hhi\\(1311768467463790320\\)), r15" } } */
++  doit(value);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_1.c
+new file mode 100644
+index 0000000..6733638
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_1.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tnop\n\tret" } } */
++  __delay_cycles (1);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_11.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_11.c
+new file mode 100644
+index 0000000..57665af
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_11.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tmov\t#3, r15\n.L2:\n\tdec\tr15\n\tjne\t.L2\n\tret" } } */
++  __delay_cycles (11);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_2.c
+new file mode 100644
+index 0000000..e0bd991
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_2.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tnop\n\tnop\n\tret" } } */
++  __delay_cycles (2);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_3.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_3.c
+new file mode 100644
+index 0000000..2d51a60
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_3.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tnop\n\tnop\n\tnop\n\tret" } } */
++  __delay_cycles (3);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_4.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_4.c
+new file mode 100644
+index 0000000..1cc43b9
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_4.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tmov\t#1, r15\n.L2:\n\tdec\tr15\n\tjne\t.L2\n\tret" } } */
++  __delay_cycles (4);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_5.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_5.c
+new file mode 100644
+index 0000000..4a7b71f
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_5.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tmov\t#1, r15\n.L2:\n\tdec\tr15\n\tjne\t.L2\n\tnop\n\tret" } } */
++  __delay_cycles (5);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_6.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_6.c
+new file mode 100644
+index 0000000..7bca3fb
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_6.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tmov\t#1, r15\n.L2:\n\tdec\tr15\n\tjne\t.L2\n\tnop\n\tnop\n\tret" } } */
++  __delay_cycles (6);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_7.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_7.c
+new file mode 100644
+index 0000000..c1df8a6
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_7.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++void foo ()
++{
++  /* { dg-final { scan-assembler "foo:\n\tmov\t#2, r15\n.L2:\n\tdec\tr15\n\tjne\t.L2\n\tret" } } */
++  __delay_cycles (7);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3237005_check.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_check.c
+new file mode 100644
+index 0000000..0e02bba
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3237005_check.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++int foo (int n)
++{
++  __delay_cycles (n); /* { dg-error "__delay_cycles argument must be non-negative integer constant" } */
++  __delay_cycles (-4); /* { dg-error "__delay_cycles argument must be non-negative integer constant" } */
++  __delay_cycles(3 * 65536UL); /* ok: 196608 == 1 + 65535*3 + 2 */
++  __delay_cycles(1 + 3 * 65536UL); /* ok: 196609 == 1 + 65536*3 + 0 */
++  __delay_cycles(3 + 3 * 65536UL); /* ok: 196611 == 1 + 65536*3 + 2 */
++  __delay_cycles(4 + 3 * 65536UL); /* ok: 196612 == 1 + 65536*3 + 3 */
++  __delay_cycles(5 + 3 * 65536UL); /* ok: 196613 == 1 + 65536*3 + 1 + 1*3 */
++  __delay_cycles(196618UL); /* ok: 196618 == 1 + 65536*3 + 1 + 2*3 + 2 */
++  __delay_cycles(196619UL); /* ok: 196619 == 1 + 1 + 3 + 3 + 65536*3 + 3 */
++  __delay_cycles(0x7fffffffL); /* ok : 2 + 2 + 32766*3 + 3 + 10922 * 196611 */
++  return 0;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3257192_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3257192_1.c
+new file mode 100644
+index 0000000..034144b
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3257192_1.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern int v;
++extern void ref (int * p);
++
++__attribute__ ((reentrant,noreturn))
++void noreturn (int arg)
++{
++  int a;
++  ref(&a);
++  v = a+arg;
++  __dint();
++  __bis_status_register (0xF0);
++} /* { dg-warning "'noreturn' function does return" } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3261372.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3261372.c
+new file mode 100644
+index 0000000..f6ab6a3
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3261372.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-g" } */
++
++__attribute__((critical))
++int
++critical (int a)
++{
++  return a+1;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3273856.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3273856.c
+new file mode 100644
+index 0000000..ef92512
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3273856.c
+@@ -0,0 +1,4 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++unsigned long long int backwards_rr (unsigned char v) { return v; }
++/* { dg-final { scan-assembler "\tmov.b\tr15, r12\n\tmov\t#0, r13\n\tmov\t#0, r14\n\tmov\t#0, r15\n" } } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3290923.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3290923.c
+new file mode 100644
+index 0000000..2dbbb1b
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3290923.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++extern int longcall (unsigned long long int regs,
++		     int a1,
++		     int a2);
++
++int test ()
++{
++  int rv;
++  rv = longcall (0ULL, 1, 1);
++  /* { dg-final { scan-assembler "\n\tcall\t#longcall\n\tadd\t#4, r1\n" } } */
++  rv += longcall (0ULL, 2, 2);
++  return rv;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3296698.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3296698.c
+new file mode 100644
+index 0000000..eabf89d
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3296698.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++typedef struct {
++    int bit:1;
++    int :15;
++} type_x;
++
++static inline type_x getX() {
++    union {
++      int f;
++      type_x t;
++    } c;
++    c.f = *(int *)0x100;
++    return c.t;
++}
++
++extern void subr();
++
++void func() {
++  /* { dg-final { scan-assembler "\n\tbit.b\t#1, &256\n\tjeq\t.L1\n\tcall\t#subr\n" } } */
++  if (getX().bit)
++    subr();
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3300205.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3300205.c
+new file mode 100644
+index 0000000..745a80f
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3300205.c
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++volatile unsigned char s_char;
++volatile unsigned char s_short;
++volatile unsigned char s_int;
++volatile unsigned char s_long;
++volatile unsigned char s_longlong;
++volatile unsigned char s_float;
++volatile unsigned char s_double;
++
++void test ()
++{
++  /* { dg-final { scan-assembler "\tmov.b\t#1, \&s_char\n" } } */
++  s_char = sizeof(char);
++  /* { dg-final { scan-assembler "\tmov.b\t#2, \&s_short\n" } } */
++  s_short = sizeof(short int);
++  /* { dg-final { scan-assembler "\tmov.b\t#2, \&s_int\n" } } */
++  s_int = sizeof(int);
++  /* { dg-final { scan-assembler "\tmov.b\t#4, \&s_long\n" } } */
++  s_long = sizeof(long int);
++  /* { dg-final { scan-assembler "\tmov.b\t#8, \&s_longlong\n" } } */
++  s_longlong = sizeof(long long int);
++  /* { dg-final { scan-assembler "\tmov.b\t#4, \&s_float\n" } } */
++  s_float = sizeof(float);
++  /* { dg-final { scan-assembler "\tmov.b\t#4, \&s_double\n" } } */
++  s_double = sizeof(double);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3383371_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3383371_1.c
+new file mode 100644
+index 0000000..23801f5
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3383371_1.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern unsigned int clear_value;
++unsigned int test ()
++{
++  /* { dg-final { scan-assembler "\tmov\t&__wdt_clear_value, &clear_value\n" } } */
++  clear_value = __get_watchdog_clear_value ();
++  /* { dg-final { scan-assembler "\tmov\t&__wdt_clear_value, &__WDTCTL\n" } } */
++  __watchdog_clear ();
++  /* { dg-final { scan-assembler "\tmov\t\#4660, &__wdt_clear_value\n" } } */
++  __set_watchdog_clear_value (0x1234);
++  /* { dg-final { scan-assembler "\tmov\t&__wdt_clear_value, r15\n" } } */
++  return __get_watchdog_clear_value ();
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3383371_2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3383371_2.c
+new file mode 100644
+index 0000000..1f60be3
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3383371_2.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-Os -mdisable-watchdog" } */
++
++extern unsigned int clear_value;
++unsigned int test ()
++{
++  /* { dg-final { scan-assembler "\tmov\t#llo\\(-1\\), \&clear_value\n\tmov\t#llo\\(-1\\), r15\n" } } */
++  clear_value = __get_watchdog_clear_value ();
++  __watchdog_clear ();
++  __set_watchdog_clear_value (0x1234);
++  return __get_watchdog_clear_value ();
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3397068.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3397068.c
+new file mode 100644
+index 0000000..788c352
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3397068.c
+@@ -0,0 +1,8 @@
++/* { dg-do compile } */
++
++__attribute__ ((section(".noinit")))
++void fn_noinit_illegal () { } /* { dg-warning "only uninitialized variables can be placed in a .bss section" } */
++
++int ia_bss __attribute__ ((section(".infoa.bss")));
++int ib_init __attribute__ ((section(".infob"))) = 1;
++int ic_init_bss __attribute__ ((section(".infoc.bss"))) = 1;  /* { dg-warning "only uninitialized variables can be placed in a .bss section" } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3423822_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3423822_1.c
+new file mode 100644
+index 0000000..5307439
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3423822_1.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++
++__attribute__ ((__interrupt__(UNDEF_VECTOR)))
++static void undef_isr () /* { dg-error "interrupt vector offset 'UNDEF_VECTOR' is not an integer constant" } */
++{ }
++
++__attribute__ ((__interrupt__("0")))
++static void string_isr () /* { dg-error "interrupt vector offset must be an even non-negative integer constant" } */
++{ }
++
++__attribute__ ((__interrupt__(4, 1)))
++static void multivect_isr ()
++{ } /* { dg-error "wrong number of arguments specified for '__interrupt__' attribute" } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3426468.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3426468.c
+new file mode 100644
+index 0000000..33b9a09
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3426468.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-O -mcpu=430x" } */
++
++extern printf (char* fmt, ...);
++
++void printSI (int r15, unsigned long int v)
++{
++  printf("Value: %lx\n", v);
++  /* { dg-final { scan-assembler "pushm\t#2, r14\n" } } */
++}
++
++void printDI (unsigned long long int v)
++{
++  printf("Value: %llx\n", v);
++  /* { dg-final { scan-assembler "pushm\t#4, r15\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3428439.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3428439.c
+new file mode 100644
+index 0000000..9e39b86
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3428439.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++int mc (int* dp, int*sp, int l)
++{
++  while (0 < l--) {
++    /* { dg-final { scan-assembler "mov\t at r14\\+, @r15\n\tadd\t#2, r15\n" } } */
++    *dp++ = *sp++;
++  }
++}
++
++int sum (int* sv, int l)
++{
++  int rv = 0;
++  while (0 < l--) {
++    /* { dg-final { scan-assembler "add\t at r15\\+, r13\n" } } */
++    rv += *sv++;
++  }
++  return rv;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3433730.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3433730.c
+new file mode 100644
+index 0000000..b8d114f
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3433730.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++extern unsigned int strlen (const char *s);
++void setval (char* str, int len);
++void useval (const char* str, unsigned char len);
++
++void tryit ()
++{
++  char tmp[17];
++  setval (tmp, sizeof(tmp));
++  useval (tmp, strlen(tmp));
++  /* { dg-final { scan-assembler "sub.b\tr1, r14\n\tmov\tr1, r15\n\tcall\t#useval" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3474171.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3474171.c
+new file mode 100644
+index 0000000..3a75a02
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3474171.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++
++#pragma vector=14
++__attribute__((interrupt))
++void isr14 () { }
++/* { dg-final { scan-assembler "isr14:\n.global\t__isr_7\n__isr_7:\n" } } */
++
++#define VECT 22
++
++#pragma vector=VECT
++__attribute__((interrupt))
++void isrD22 () { }
++/* { dg-final { scan-assembler "isrD22:\n.global\t__isr_11\n__isr_11:\n" } } */
++
++#define PVECT (24)
++
++#pragma vector=PVECT
++__attribute__((interrupt))
++void isrD24 () { }
++/* { dg-final { scan-assembler "isrD24:\n.global\t__isr_12\n__isr_12:\n" } } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/sf3474171_1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3474171_1.c
+new file mode 100644
+index 0000000..6223566
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/sf3474171_1.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++
++#pragma vector 10 /* { dg-warning "missing '=' after '#pragma vector' - ignored" } */
++
++#pragma vector=id /* { dg-warning "malformed '#pragma vector' - ignored" } */
++
++#pragma vector=(10 /* { dg-warning "malformed '#pragma vector' - ignored" } */
++
++#pragma vector=11
++__attribute__((interrupt))
++void isr11 () { }  /* { dg-error "interrupt vector offset 11 must be even and non-negative" } */
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vararg-1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vararg-1.c
+new file mode 100644
+index 0000000..531fd0c
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vararg-1.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-O" } */
++
++#include <stdarg.h>
++
++int test (int a1, ...)
++{
++  int v1;
++  va_list va_arglist;
++
++  va_start (va_arglist, a1);
++  v1 = va_arg (va_arglist, int);
++  va_end (va_arglist);
++  /* { dg-final { scan-assembler "\tmov\t4\\(r1\\), r15\n\tret\n" } } */
++  return v1;
++}
++
++extern int etest (int a1, ...);
++
++int calltest ()
++{
++  /* { dg-final { scan-assembler "\tcall\t#etest\n\tadd\t#4, r1\n\tret\n" } } */
++  return etest (1, 2);
++}
++  
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/volpeep_mem.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_mem.c
+new file mode 100644
+index 0000000..d029063
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_mem.c
+@@ -0,0 +1,46 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned char ior8;
++extern volatile unsigned int ior16;
++extern volatile unsigned char and8;
++extern volatile unsigned int and16;
++extern volatile unsigned char nand8;
++extern volatile unsigned int nand16;
++extern volatile unsigned char xor8;
++extern volatile unsigned int xor16;
++extern volatile unsigned char mov8;
++extern volatile unsigned int mov16;
++extern volatile unsigned char add8;
++extern volatile unsigned int add16;
++extern volatile unsigned char sub8;
++extern volatile unsigned int sub16;
++
++unsigned char m8;
++unsigned int m16;
++
++void
++testm ()
++{
++  /* { dg-final { scan-assembler "mov.b\t\&m8, r15\n" } } */
++  ior8 |= m8; /* { dg-final { scan-assembler "bis.b\tr15, \&ior8\n" } } */
++  and8 &= m8; /* { dg-final { scan-assembler "and.b\tr15, \&and8\n" } } */
++  nand8 &= ~m8; /* { dg-final { scan-assembler "bic.b\tr15, \&nand8\n" } } */
++  xor8 ^= m8; /* { dg-final { scan-assembler "xor.b\tr15, \&xor8\n" } } */
++  add8 += m8; /* { dg-final { scan-assembler "add.b\tr15, \&add8\n" } } */
++  sub8 -= m8; /* { dg-final { scan-assembler "sub.b\tr15, \&sub8\n" } } */
++  /* { dg-final { scan-assembler "mov\t\&m16, r15\n" } } */
++  ior16 |= m16; /* { dg-final { scan-assembler "bis\tr15, \&ior16\n" } } */
++  and16 &= m16; /* { dg-final { scan-assembler "and\tr15, \&and16\n" } } */
++  nand16 &= ~m16; /* { dg-final { scan-assembler "bic\tr15, \&nand16\n" } } */
++  xor16 ^= m16; /* { dg-final { scan-assembler "xor\tr15, \&xor16\n" } } */
++  add16 += m16; /* { dg-final { scan-assembler "add\tr15, \&add16\n" } } */
++  sub16 -= m16; /* { dg-final { scan-assembler "sub\tr15, \&sub16\n" } } */
++}
++
++void
++testm2m ()
++{
++  mov8 = m8; /* { dg-final { scan-assembler "mov.b\t\&m8, \&mov8\n" } } */
++  mov16 = m16; /* { dg-final { scan-assembler "mov\t\&m16, \&mov16\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/volpeep_reg.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_reg.c
+new file mode 100644
+index 0000000..4e4fe76
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_reg.c
+@@ -0,0 +1,34 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned char ior8;
++extern volatile unsigned int ior16;
++extern volatile unsigned char and8;
++extern volatile unsigned int and16;
++extern volatile unsigned char nand8;
++extern volatile unsigned int nand16;
++extern volatile unsigned char xor8;
++extern volatile unsigned int xor16;
++extern volatile unsigned char add8;
++extern volatile unsigned int add16;
++extern volatile unsigned char sub8;
++extern volatile unsigned int sub16;
++
++void
++testr (unsigned char v8,
++       unsigned int v16)
++{
++  ior8 |= v8; /* { dg-final { scan-assembler "bis.b\tr15, \&ior8\n" } } */
++  ior16 |= v16;	/* { dg-final { scan-assembler "bis\tr14, \&ior16\n" } } */
++  and8 &= v8; /* { dg-final { scan-assembler "and.b\tr15, \&and8\n" } } */
++  and16 &= v16; /* { dg-final { scan-assembler "and\tr14, \&and16\n" } } */
++  nand8 &= ~v8; /* { dg-final { scan-assembler "bic.b\tr15, \&nand8\n" } } */
++  nand16 &= ~v16; /* { dg-final { scan-assembler "bic\tr14, \&nand16\n" } } */
++  xor8 ^= v8; /* { dg-final { scan-assembler "xor.b\tr15, \&xor8\n" } } */
++  xor16 ^= v16; /* { dg-final { scan-assembler "xor\tr14, \&xor16\n" } } */
++  add8 += v8; /* { dg-final { scan-assembler "add.b\tr15, \&add8\n" } } */
++  add16 += v16; /* { dg-final { scan-assembler "add\tr14, \&add16\n" } } */
++  sub8 -= v8; /* { dg-final { scan-assembler "sub.b\tr15, \&sub8\n" } } */
++  sub16 -= v16; /* { dg-final { scan-assembler "sub\tr14, \&sub16\n" } } */
++}
++
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/volpeep_volmem.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_volmem.c
+new file mode 100644
+index 0000000..b58de05
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/volpeep_volmem.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned char ior8;
++extern volatile unsigned int ior16;
++extern volatile unsigned char and8;
++extern volatile unsigned int and16;
++extern volatile unsigned char nand8;
++extern volatile unsigned int nand16;
++extern volatile unsigned char xor8;
++extern volatile unsigned int xor16;
++extern volatile unsigned char mov8;
++extern volatile unsigned int mov16;
++extern volatile unsigned char add8;
++extern volatile unsigned int add16;
++extern volatile unsigned char sub8;
++extern volatile unsigned int sub16;
++
++volatile unsigned char m8;
++volatile unsigned int m16;
++
++void
++testm ()
++{
++  ior8 |= m8; /* { dg-final { scan-assembler "bis.b\t\&m8, \&ior8\n" } } */
++  and8 &= m8; /* { dg-final { scan-assembler "and.b\t\&m8, \&and8\n" } } */
++  nand8 &= ~m8; /* { dg-final { scan-assembler "bic.b\t\&m8, \&nand8\n" } } */
++  xor8 ^= m8; /* { dg-final { scan-assembler "xor.b\t\&m8, \&xor8\n" } } */
++  add8 += m8; /* { dg-final { scan-assembler "add.b\t\&m8, \&add8\n" } } */
++  sub8 -= m8; /* { dg-final { scan-assembler "sub.b\t\&m8, \&sub8\n" } } */
++
++  ior16 |= m16; /* { dg-final { scan-assembler "bis\t\&m16, \&ior16\n" } } */
++  and16 &= m16; /* { dg-final { scan-assembler "and\t\&m16, \&and16\n" } } */
++  nand16 &= ~m16; /* { dg-final { scan-assembler "bic\t\&m16, \&nand16\n" } } */
++  xor16 ^= m16; /* { dg-final { scan-assembler "xor\t\&m16, \&xor16\n" } } */
++  add16 += m16; /* { dg-final { scan-assembler "add\t\&m16, \&add16\n" } } */
++  sub16 -= m16; /* { dg-final { scan-assembler "sub\t\&m16, \&sub16\n" } } */
++}
++
++void
++testm2m ()
++{
++  mov8 = m8; /* { dg-final { scan-assembler "mov.b\t\&m8, \&mov8\n" } } */
++  mov16 = m16; /* { dg-final { scan-assembler "mov\t\&m16, \&mov16\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa1.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa1.c
+new file mode 100644
+index 0000000..cb1432d
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa1.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned int periph;
++
++void vwa (unsigned int v)
++{
++  /* { dg-final { scan-assembler "\n\tand\tr15, \&periph\n" } } */
++  periph &= v;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa2.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa2.c
+new file mode 100644
+index 0000000..4f1b344
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa2.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O -fno-peephole2" } */
++
++extern volatile unsigned int periph;
++
++void vwa (unsigned int v)
++{
++  /* { dg-final { scan-assembler "\n\tmov\t\&periph, r14\n\tand\tr14, r15\n\tmov\tr15, \&periph\n" } } */
++  periph &= v;
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa3.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa3.c
+new file mode 100644
+index 0000000..5da9526
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa3.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-O -fno-peephole2" } */
++
++extern volatile unsigned char periph8;
++extern volatile unsigned int periph16;
++
++extern void use (unsigned long long int regargs,
++		 unsigned int p16,
++		 unsigned char p8);
++
++void vwa_push ()
++{
++  /* pushm1 requires vwa support */
++  /* { dg-final { scan-assembler "\n\tmov.b\t\&periph8, r14\n\tmov\t\&periph16, r15\n\tpush.b\tr14\n\tpush\tr15\n" } } */
++  use (0ULL, periph16, periph8);
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa4.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa4.c
+new file mode 100644
+index 0000000..630c905
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa4.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++#define ADDR8 1351
++#define ADDR16 1352
++
++void set_bit0 ()
++{
++  *(volatile unsigned char*)ADDR8 |= 1; /* { dg-final { scan-assembler "bis.b\t#1, \&1351\n" } } */
++  *(volatile unsigned int*)ADDR16 |= 8; /* { dg-final { scan-assembler "bis\t#8, \&1352\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa5.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa5.c
+new file mode 100644
+index 0000000..20bf44f
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa5.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned int and16;
++extern volatile unsigned int nand16;
++extern volatile unsigned int ior16;
++extern volatile unsigned int xor16;
++extern volatile unsigned int add16;
++extern volatile unsigned int sub16;
++extern volatile unsigned int mov16;
++
++void f ()
++{
++  and16 &= and16; 		/* { dg-final { scan-assembler "and\t\&and16, \&and16\n" } } */
++  nand16 &= ~nand16; 		/* { dg-final { scan-assembler "bic\t\&nand16, \&nand16\n" } } */
++  ior16 |= ior16; 		/* { dg-final { scan-assembler "bis\t\&ior16, \&ior16\n" } } */
++  add16 += add16; 		/* { dg-final { scan-assembler "add\t\&add16, \&add16\n" } } */
++  sub16 -= sub16; 		/* { dg-final { scan-assembler "sub\t\&sub16, \&sub16\n" } } */
++  mov16 = mov16;		/* { dg-final { scan-assembler "mov\t\&mov16, \&mov16\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa_error.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa_error.c
+new file mode 100644
+index 0000000..20bf9c8
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa_error.c
+@@ -0,0 +1,32 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++extern volatile unsigned char ior8;
++extern volatile unsigned int ior16;
++extern volatile unsigned char and8;
++extern volatile unsigned int and16;
++
++extern volatile unsigned char v8;
++extern volatile unsigned int v16;
++
++void
++testv1 ()
++{
++  unsigned char l8;
++  unsigned char t8;
++  unsigned int l16;
++
++  /* Note that this pattern is what "ior8 |= (l8 = v8)" normally
++   * becomes, but in this case there are sequence points which make
++   * moving the read of v8 before the read of ior8 clearly incorrect.
++   * If the original msp430_vwa_* predicates are used to subvert
++   * volatile checking in the iorqi3 insn, the combiner phase will
++   * move the read of v8 before the first read of ior8 before the
++   * peephole optimization could detect and inhibit the collapse, and
++   * the abstract machine order requirements are violated. */
++  t8 = ior8;
++  l8 = v8;
++  ior8 = t8 | l8;
++  /* { dg-final { scan-assembler "mov.b\t\&ior8, r15\n\tmov.b\t\&v8, r14\n\tbis.b\tr14, r15\n\tmov.b\tr15, \&ior8\n" } } */
++  and8 &= l8; /* { dg-final { scan-assembler "and.b\tr14, \&and8\n" } } */
++}
+diff --git gcc-4.6.3.orig/gcc/testsuite/gcc.target/msp430/vwa_regression.c gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa_regression.c
+new file mode 100644
+index 0000000..cb12a33
+--- /dev/null
++++ gcc-4.6.3/gcc/testsuite/gcc.target/msp430/vwa_regression.c
+@@ -0,0 +1,49 @@
++/* { dg-do compile } */
++/* { dg-options "-Os" } */
++
++/* This program demonstrates a code size regression upon removal of
++ * the volatile workaround from mspgcc.  RTL optimizations end up
++ * keeping &bitbuffer[1] into a register but moving the final write to
++ * epilog code.  This preserves the semantics of volatile, but results
++ * in larger code than if the write were made directly to memory.  It
++ * cannot be undone by peephole optimization.
++ */
++
++extern volatile char bitbuffer[2];
++
++void showlevel (unsigned char lvl)
++{
++  bitbuffer[0] &= 0xf1;
++  bitbuffer[1] &= 0xf0;
++
++  switch(lvl)
++  {
++  case 0:
++    bitbuffer[0] |= 0x01;
++    bitbuffer[1] |= 0x01;
++    /* { dg-final { scan-assembler ".L3:\n\tbis.b\t#1, \&bitbuffer\n\tmov.b\t\&bitbuffer\\+1, r15\n\tbis.b\t#1, r15\n\tjmp\t.L11\n" } } */
++    /* { dg-final { scan-assembler ".L11:\n\tmov.b\tr15, \&bitbuffer\\+1\n\tret\n" } } */
++    break;
++  case 1:
++    bitbuffer[0] |= 0x01;
++    bitbuffer[1] |= 0x03;
++    break;
++  case 2:
++    bitbuffer[0] |= 0x01;
++    bitbuffer[1] |= 0x07;
++    break;
++  case 3:
++    bitbuffer[0] |= 0x01;
++    bitbuffer[1] |= 0x0f;
++    break;
++  case 4:
++    bitbuffer[0] |= 0x03;
++    bitbuffer[1] |= 0x0f;
++    break;
++  case 5:
++    bitbuffer[0] |= 0x07;
++    bitbuffer[1] |= 0x0f;
++    break;
++  };
++}
++
+diff --git gcc-4.6.3.orig/gcc/tree-flow.h gcc-4.6.3/gcc/tree-flow.h
+index 77948cd..1923454 100644
+--- gcc-4.6.3.orig/gcc/tree-flow.h
++++ gcc-4.6.3/gcc/tree-flow.h
+@@ -601,6 +601,7 @@ extern void dump_dominator_optimization_stats (FILE *);
+ extern void debug_dominator_optimization_stats (void);
+ int loop_depth_of_name (tree);
+ tree degenerate_phi_result (gimple);
++bool simple_iv_increment_p (gimple);
+ 
+ /* In tree-ssa-copy.c  */
+ extern void propagate_value (use_operand_p, tree);
+diff --git gcc-4.6.3.orig/gcc/tree-ssa-dom.c gcc-4.6.3/gcc/tree-ssa-dom.c
+index c7614d7..495c506 100644
+--- gcc-4.6.3.orig/gcc/tree-ssa-dom.c
++++ gcc-4.6.3/gcc/tree-ssa-dom.c
+@@ -1396,9 +1396,10 @@ record_equality (tree x, tree y)
+    i_1 = phi (..., i_2)
+    i_2 = i_1 +/- ...  */
+ 
+-static bool
++bool
+ simple_iv_increment_p (gimple stmt)
+ {
++  enum tree_code code;
+   tree lhs, preinc;
+   gimple phi;
+   size_t i;
+@@ -1410,12 +1411,13 @@ simple_iv_increment_p (gimple stmt)
+   if (TREE_CODE (lhs) != SSA_NAME)
+     return false;
+ 
+-  if (gimple_assign_rhs_code (stmt) != PLUS_EXPR
+-      && gimple_assign_rhs_code (stmt) != MINUS_EXPR)
++  code = gimple_assign_rhs_code (stmt);
++  if (code != PLUS_EXPR
++      && code != MINUS_EXPR
++      && code != POINTER_PLUS_EXPR)
+     return false;
+ 
+   preinc = gimple_assign_rhs1 (stmt);
+-
+   if (TREE_CODE (preinc) != SSA_NAME)
+     return false;
+ 
+diff --git gcc-4.6.3.orig/gcc/tree-ssa-forwprop.c gcc-4.6.3/gcc/tree-ssa-forwprop.c
+index 7e1e7c0..c0f1d8d 100644
+--- gcc-4.6.3.orig/gcc/tree-ssa-forwprop.c
++++ gcc-4.6.3/gcc/tree-ssa-forwprop.c
+@@ -1999,10 +1999,12 @@ tree_ssa_forward_propagate_single_use_vars (void)
+ 		  else
+ 		    gsi_next (&gsi);
+ 		}
+-	      else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
+-		       && can_propagate_from (stmt))
++	      else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+ 		{
+-		  if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
++		  tree off = gimple_assign_rhs2 (stmt);
++		  if (TREE_CODE (off) == INTEGER_CST
++		      && can_propagate_from (stmt)
++		      && !simple_iv_increment_p (stmt)
+ 		      /* ???  Better adjust the interface to that function
+ 			 instead of building new trees here.  */
+ 		      && forward_propagate_addr_expr
+@@ -2014,7 +2016,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
+ 						 rhs,
+ 						 fold_convert
+ 						   (ptr_type_node,
+-						    gimple_assign_rhs2 (stmt))))))
++						    off)))))
+ 		    {
+ 		      release_defs (stmt);
+ 		      todoflags |= TODO_remove_unused_locals;
+diff --git gcc-4.6.3.orig/libgcc/config.host gcc-4.6.3/libgcc/config.host
+index 25e949e..8a5af73 100644
+--- gcc-4.6.3.orig/libgcc/config.host
++++ gcc-4.6.3/libgcc/config.host
+@@ -223,6 +223,8 @@ avr-*-*)
+     # Make HImode functions for AVR
+     tmake_file=${cpu_type}/t-avr
+ 	;;
++msp430-*-*)
++	;;
+ bfin*-elf*)
+         ;;
+ bfin*-uclinux*)
diff --git a/msp430-gcc.spec b/msp430-gcc.spec
index b355a69..3e47451 100644
--- a/msp430-gcc.spec
+++ b/msp430-gcc.spec
@@ -1,26 +1,20 @@
 %define target msp430
 
 Name:		%{target}-gcc
-Version:	3.2.3
-# There has been no release, so this is a snapshot
-Release:	7.20100805cvs%{?dist}
+Version:	4.6.3
+Release:	1%{?dist}
 Summary:	Cross Compiling GNU GCC targeted at %{target}
 Group:		Development/Languages
 License:	GPLv2+
 URL:		http://mspgcc.sf.net/
 Source0:	ftp://ftp.gnu.org/gnu/gcc/gcc-%{version}/gcc-core-%{version}.tar.bz2
-# Pulled from the mspgcc CVS.  Regenerate with:
-# cvs -z3 -d:pserver:anonymous at mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc login
-# empty password (press enter)
-# cvs -z3 -d:pserver:anonymous at mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc co -D 2009-02-10 -P gcc/gcc-3.3
-# tar -cjf mspgcc-gcc-3.3-20100805.tar.bz2 gcc
-Source1:	mspgcc-gcc-3.3-20100805.tar.bz2
+
+# Patch from mspgcc project
+Patch0:		msp430-gcc-4.6.3-20120406.patch
+
 BuildRoot:	%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 BuildRequires:	%{target}-binutils
 Requires:	%{target}-binutils
-# Build fails for ppc64 -- bug number to appear on this line after review
-# (as documented in https://fedoraproject.org/wiki/Packaging:Guidelines#Architecture_Build_Failures)
-ExcludeArch:	ppc64
 
 %description
 This is a cross compiling version of GNU GCC, which can be used to
@@ -28,11 +22,10 @@ compile for the %{target} platform, instead of for the native %{_arch}
 platform.
 
 %prep
-%setup -q -T -c
-%setup -q -T -D -a0
-%setup -q -T -D -a1
-
-cp -af gcc/gcc-3.3/* gcc-%{version}/
+%setup -q -c -n msp430-gcc
+pushd gcc-%{version}
+%patch0 -p1
+popd
 
 # Extract %%__os_install_post into os_install_post~
 cat << \EOF > os_install_post~
@@ -56,22 +49,22 @@ sed -e 's,^[ ]*/usr/lib/rpm.*/brp-strip,./brp-strip,' \
 
 
 %build
-cd gcc-%{version}
-CC="%{__cc} ${RPM_OPT_FLAGS}" ./configure --prefix=%{_prefix} --mandir=%{_mandir} \
+mkdir gcc-%{version}-build
+cd gcc-%{version}-build
+CC="%{__cc} ${RPM_OPT_FLAGS}" ../gcc-%{version}/configure --prefix=%{_prefix} --mandir=%{_mandir} \
 	--infodir=%{_infodir} --target=%{target} --disable-nls \
-	--libdir=%{_libdir} --enable-version-specific-runtime-libs
+	--libdir=%{_libdir} --enable-version-specific-runtime-libs \
+	--enable-languages=c
 # Building GCC-3.2.3 is not smp-safe
 make
 
 
 %install
 rm -rf $RPM_BUILD_ROOT
-make -C gcc-%{version} install DESTDIR=$RPM_BUILD_ROOT
+make -C gcc-%{version}-build install DESTDIR=$RPM_BUILD_ROOT
 
 # we don't want these as we are a cross version
 rm -rf $RPM_BUILD_ROOT%{_infodir}
-mv $RPM_BUILD_ROOT%{_mandir}/man1/cpp.1 $RPM_BUILD_ROOT%{_mandir}/man1/%{target}-cpp.1
-mv $RPM_BUILD_ROOT%{_mandir}/man1/gcov.1 $RPM_BUILD_ROOT%{_mandir}/man1/%{target}-gcov.1
 rm -rf $RPM_BUILD_ROOT%{_mandir}/man7
 rm -f $RPM_BUILD_ROOT%{_libdir}/libiberty.a
 
@@ -84,13 +77,17 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(-,root,root,-)
-%dir %{_libdir}/gcc-lib
-%dir %{_libdir}/gcc-lib/%{target}/
-%dir %{_libdir}/gcc-lib/%{target}/%{version}/
+%dir %{_libdir}/gcc
+%dir %{_libdir}/gcc/%{target}/
+%dir %{_libdir}/gcc/%{target}/%{version}/
+%dir %{_libdir}/gcc/%{target}/mcpu-430x
+%dir %{_libdir}/gcc/%{target}/mmpy-16
+%dir %{_libexecdir}/gcc/%{target}/%{version}
 
 %{_bindir}/%{target}-*
-%{_libdir}/gcc-lib/%{target}/%{version}/*
+%{_libdir}/gcc/%{target}/%{version}/*
 %{_mandir}/man1/%{target}-*.1.gz
+%{_libexecdir}/gcc/%{target}/%{version}/*
 
 
 %changelog
diff --git a/sources b/sources
index 59c47af..1edec7d 100644
--- a/sources
+++ b/sources
@@ -1,2 +1 @@
-66664a84b383ba8d68612cd89b9478b2  gcc-core-3.2.3.tar.bz2
-66eda7145cca0d4d213364f9019e2a44  mspgcc-gcc-3.3-20100805.tar.bz2
+766091220c6a14fcaa2c06dd573e3758  gcc-core-4.6.3.tar.bz2


More information about the scm-commits mailing list