This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: msp430 port


Ok, I think I covered everything...


[gcc]

Index: contrib/config-list.mk
===================================================================
--- contrib/config-list.mk	(revision 201184)
+++ contrib/config-list.mk	(working copy)
@@ -41,12 +41,13 @@ LIST = aarch64-elf aarch64-linux-gnu \
   mips64el-st-linux-gnu mips64octeon-linux mipsisa64r2-linux \
   mipsisa32r2-linux-gnu mipsisa64r2-sde-elf mipsisa32-elfoabi \
   mipsisa64-elfoabi mipsisa64r2el-elf mipsisa64sr71k-elf mipsisa64sb1-elf \
   mipsel-elf mips64-elf mips64vr-elf mips64orion-elf mips-rtems \
   mips-wrs-vxworks mipstx39-elf mmix-knuth-mmixware mn10300-elf moxie-elf \
   moxie-uclinux moxie-rtems pdp11-aout picochip-elfOPT-enable-obsolete \
+  msp430-elf \
   powerpc-darwin8 \
   powerpc-darwin7 powerpc64-darwin powerpc-freebsd6 powerpc-netbsd \
   powerpc-eabispe powerpc-eabisimaltivec powerpc-eabisim ppc-elf \
   powerpc-eabialtivec powerpc-xilinx-eabi powerpc-eabi \
   powerpc-rtems4.11OPT-enable-threads=yes powerpc-linux_spe \
   powerpc-linux_paired powerpc64-linux_altivec \
Index: MAINTAINERS
===================================================================
--- MAINTAINERS	(revision 201184)
+++ MAINTAINERS	(working copy)
@@ -84,12 +84,14 @@ microblaze		Michael Eager		eager@eagerco
 mips port		Eric Christopher	echristo@gmail.com
 mips port		Richard Sandiford	rdsandiford@googlemail.com
 mmix port		Hans-Peter Nilsson	hp@bitrange.com
 mn10300 port		Jeff Law		law@redhat.com
 mn10300 port		Alexandre Oliva		aoliva@redhat.com
 moxie port		Anthony Green		green@moxielogic.com
+msp430 port		DJ Delorie		dj@redhat.com
+msp430 port		Nick Clifton		nickc@redhat.com
 nds32 port		Chung-Ju Wu		jasonwucj@gmail.com
 nds32 port		Shiva Chen		shiva0217@gmail.com
 pdp11 port		Paul Koning		ni1d@arrl.net
 picochip port		Daniel Towner		dant@picochip.com
 rl78 port		DJ Delorie		dj@redhat.com
 rs6000/powerpc port	David Edelsohn		dje.gcc@gmail.com
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 201184)
+++ libgcc/config.host	(working copy)
@@ -829,12 +829,15 @@ moxie-*-elf | moxie-*-uclinux*)
 	;;
 moxie-*-rtems*)
 	tmake_file="$tmake_file moxie/t-moxie t-softfp-sfdf t-softfp-excl t-softfp"
 	# Don't use default.
 	extra_parts=
 	;;
+msp430*-*-elf)
+	tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430"
+	;;
 pdp11-*-*)
 	tmake_file="pdp11/t-pdp11 t-fdpbit"
 	;;
 picochip-*-*)
 	tmake_file="picochip/t-picochip t-fpbit"
         ;;
Index: libgcc/config/msp430/floathidf.c
===================================================================
--- libgcc/config/msp430/floathidf.c	(revision 0)
+++ libgcc/config/msp430/floathidf.c	(revision 0)
@@ -0,0 +1,33 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2013
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+extern double __floatsidf (long);
+
+double
+__floathidf (int u)
+{
+  return __floatsidf ((long)u);
+}
Index: libgcc/config/msp430/floatunhidf.c
===================================================================
--- libgcc/config/msp430/floatunhidf.c	(revision 0)
+++ libgcc/config/msp430/floatunhidf.c	(revision 0)
@@ -0,0 +1,37 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2013
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef int HItype __attribute__ ((mode (HI)));
+typedef unsigned int UHItype __attribute__ ((mode (HI)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+extern DFtype __floatunsidf (unsigned long);
+
+DFtype
+__floatunhidf (UHItype u)
+{
+  return __floatunsidf ((unsigned long)u);
+}
Index: libgcc/config/msp430/mpy.c
===================================================================
Index: libgcc/config/msp430/t-msp430
===================================================================
--- libgcc/config/msp430/t-msp430	(revision 0)
+++ libgcc/config/msp430/t-msp430	(revision 0)
@@ -0,0 +1,47 @@
+# Makefile fragment for building LIBGCC for the TI MSP430 processor.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by Red Hat.
+#
+# 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/>.
+
+# Note - we have separate versions of the lib2div<mode> files
+# as the functions are quite large and we do not want to pull
+# in unneeded division routines.
+
+LIB2ADD = \
+	$(srcdir)/config/msp430/lib2divQI.c \
+	$(srcdir)/config/msp430/lib2divHI.c \
+	$(srcdir)/config/msp430/lib2divSI.c \
+	$(srcdir)/config/msp430/lib2bitcountHI.c \
+	$(srcdir)/config/msp430/lib2mul.c \
+	$(srcdir)/config/msp430/lib2shift.c \
+	$(srcdir)/config/msp430/epilogue.S \
+	$(srcdir)/config/msp430/slli.S \
+	$(srcdir)/config/msp430/srai.S \
+	$(srcdir)/config/msp430/srli.S \
+	$(srcdir)/config/msp430/cmpsi2.S \
+	$(srcdir)/config/msp430/floatunhisf.c \
+	$(srcdir)/config/msp430/floatunhidf.c \
+	$(srcdir)/config/msp430/floathidf.c \
+	$(srcdir)/config/msp430/floathisf.c \
+	$(srcdir)/config/msp430/cmpd.c
+
+HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections
+
+# Local Variables:
+# mode: Makefile
+# End:
Index: libgcc/config/msp430/lib2mul.c
===================================================================
--- libgcc/config/msp430/lib2mul.c	(revision 0)
+++ libgcc/config/msp430/lib2mul.c	(revision 0)
@@ -0,0 +1,59 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2005, 2009, 2011
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint08_type   __attribute__ ((mode (QI)));
+
+#define C3B(a,b,c) a##b##c
+#define C3(a,b,c) C3B(a,b,c)
+
+
+#define UINT_TYPE	uint16_type
+#define BITS_MINUS_1	15
+#define NAME_MODE	hi
+
+#include "msp430-mul.h"
+
+#undef UINT_TYPE
+#undef BITS_MINUS_1
+#undef NAME_MODE
+
+#define UINT_TYPE	uint08_type
+#define BITS_MINUS_1	7
+#define NAME_MODE	qi
+
+#include "msp430-mul.h"
+
+#undef UINT_TYPE
+#undef BITS_MINUS_1
+#undef NAME_MODE
+
+#define UINT_TYPE	uint32_type
+#define BITS_MINUS_1	31
+#define NAME_MODE	si
+
+#include "msp430-mul.h"
Index: libgcc/config/msp430/msp430-divmod.h
===================================================================
--- libgcc/config/msp430/msp430-divmod.h	(revision 0)
+++ libgcc/config/msp430/msp430-divmod.h	(revision 0)
@@ -0,0 +1,118 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2005, 2009, 2011
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+UINT_TYPE C3(udivmod,NAME_MODE,4) (UINT_TYPE, UINT_TYPE, word_type);
+SINT_TYPE C3(__div,NAME_MODE,3)   (SINT_TYPE, SINT_TYPE);
+SINT_TYPE C3(__mod,NAME_MODE,3)   (SINT_TYPE, SINT_TYPE);
+UINT_TYPE C3(__udiv,NAME_MODE,3)  (UINT_TYPE, UINT_TYPE);
+UINT_TYPE C3(__umod,NAME_MODE,3)  (UINT_TYPE, UINT_TYPE);
+
+UINT_TYPE
+C3(udivmod,NAME_MODE,4) (UINT_TYPE num, UINT_TYPE den, word_type modwanted)
+{
+  UINT_TYPE bit = 1;
+  UINT_TYPE res = 0;
+
+  while (den < num && bit && !(den & (1L << BITS_MINUS_1)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+  if (modwanted)
+    return num;
+  return res;
+}
+
+SINT_TYPE
+C3(__div,NAME_MODE,3) (SINT_TYPE a, SINT_TYPE b)
+{
+  word_type neg = 0;
+  SINT_TYPE res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = C3(udivmod,NAME_MODE,4) (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+SINT_TYPE
+C3(__mod,NAME_MODE,3) (SINT_TYPE a, SINT_TYPE b)
+{
+  word_type neg = 0;
+  SINT_TYPE res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = C3(udivmod,NAME_MODE,4) (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+UINT_TYPE
+C3(__udiv,NAME_MODE,3) (UINT_TYPE a, UINT_TYPE b)
+{
+  return C3(udivmod,NAME_MODE,4) (a, b, 0);
+}
+
+UINT_TYPE
+C3(__umod,NAME_MODE,3) (UINT_TYPE a, UINT_TYPE b)
+{
+  return C3(udivmod,NAME_MODE,4) (a, b, 1);
+}
Index: libgcc/config/msp430/lib2divHI.c
===================================================================
--- libgcc/config/msp430/lib2divHI.c	(revision 0)
+++ libgcc/config/msp430/lib2divHI.c	(revision 0)
@@ -0,0 +1,43 @@
+/* HI mode divide routines for libgcc for MSP430
+   Copyright (C) 2012
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef          int  sint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef          int  sint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+typedef          int  sint08_type   __attribute__ ((mode (QI)));
+typedef unsigned int  uint08_type   __attribute__ ((mode (QI)));
+typedef int           word_type     __attribute__ ((mode (__word__)));
+
+#define C3B(a,b,c) a##b##c
+#define C3(a,b,c) C3B(a,b,c)
+
+#define UINT_TYPE	uint16_type
+#define SINT_TYPE	sint16_type
+#define BITS_MINUS_1	15
+#define NAME_MODE	hi
+
+#include "msp430-divmod.h"
Index: libgcc/config/msp430/cmpsi2.S
===================================================================
--- libgcc/config/msp430/cmpsi2.S	(revision 0)
+++ libgcc/config/msp430/cmpsi2.S	(revision 0)
@@ -0,0 +1,98 @@
+;   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file 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.
+; 
+; This file 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.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+
+#ifdef __MSP430X_LARGE__
+#define ret_	RETA
+#else
+#define ret_	RET
+#endif
+
+	.text
+
+	;;   int __cmpsi2 (signed long A, signed long B)
+	;;
+	;; Performs a signed comparison of A and B.
+	;; If A is less than B it returns 0.  If A is greater
+	;; than B it returns 2.  If they are equal it returns 1.
+
+	;;  Note - this code is also used by the __ucmpsi2 routine below.
+
+	.global	__cmpsi2
+        .type   __cmpsi2, @function
+__cmpsi2:
+	;; A is in r12 (low), r13 (high)
+	;; B is in r14 (low), r15 (high)
+	;; Result put in r12
+
+	cmp.w	r13, r15
+	jeq	.L_compare_low
+	jge	.L_less_than
+.L_greater_than:
+	mov.w	#2, r12
+	ret_
+.L_less_than:
+	mov.w	#0, r12
+	ret_
+
+.L_compare_low:
+	cmp.w	r12, r14
+	jl	.L_greater_than
+	jne     .L_less_than
+	mov.w	#1, r12
+	ret_
+
+	.size	__cmpsi2, . - __cmpsi2
+
+
+	;;   int __ucmpsi2 (unsigned long A, unsigned long B)
+	;;
+	;; Performs an unsigned comparison of A and B.
+	;; If A is less than B it returns 0.  If A is greater
+	;; than B it returns 2.  If they are equal it returns 1.
+
+;;;  Note - this function branches into the __cmpsi2 code above.
+
+	.global	__ucmpsi2
+        .type   __ucmpsi2, @function
+__ucmpsi2:
+	;; A is in r12 (low), r13 (high)
+	;; B is in r14 (low), r15 (high)
+	;; Result put in r12
+
+	tst	r13
+	jn	.L_top_bit_set_in_A
+	tst	r15
+;;; If the top bit of B is set, but A's is clear we know that A < B.
+	jn	.L_less_than
+;;; Neither A nor B has their top bit set so we can use the __cmpsi2 routine.
+;;; Note we use Jc rather than BR as that saves two bytes.  The TST insn always
+;;; sets the C bit.
+	jc	__cmpsi2
+
+.L_top_bit_set_in_A:
+	tst	r15
+;;;  If both A and B have their top bit set we can use the __cmpsi2 routine.
+	jn	__cmpsi2
+;;; Otherwise A has its top bit set and B does not so A > B.
+	jc	.L_greater_than
+
+	.size	__ucmpsi2, . - __ucmpsi2
Index: libgcc/config/msp430/srai.S
===================================================================
--- libgcc/config/msp430/srai.S	(revision 0)
+++ libgcc/config/msp430/srai.S	(revision 0)
@@ -0,0 +1,106 @@
+;   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file 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.
+; 
+; This file 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.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+	
+	.text
+
+	.macro	_srai n
+	.global __mspabi_srai_\n
+__mspabi_srai_\n:
+	RRA.W	R12
+	.endm
+
+/* Logical Right Shift - R12 -> R12 */
+	_srai	15
+	_srai	14
+	_srai	13
+	_srai	12
+	_srai	11
+	_srai	10
+	_srai	9
+	_srai	8
+	_srai	7
+	_srai	6
+	_srai	5
+	_srai	4
+	_srai	3
+	_srai	2
+	_srai	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R13
+	RRA.W	R12,R12
+	.global	__mspabi_srai
+__mspabi_srai:
+	CMP	#0,R13
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+/* Logical Right Shift - R12:R13 -> R12:R13 */
+
+	.macro	_sral	n
+	.global	__mspabi_sral_\n
+__mspabi_sral_\n:
+	RRA.W	R13
+	RRC.W	R12
+	.endm
+
+	_sral	15
+	_sral	14
+	_sral	13
+	_sral	12
+	_sral	11
+	_sral	10
+	_sral	9
+	_sral	8
+	_sral	7
+	_sral	6
+	_sral	5
+	_sral	4
+	_sral	3
+	_sral	2
+	_sral	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R14
+	RRA.W	R13
+	RRC.W	R12
+	.global	__mspabi_sral
+__mspabi_sral:
+	CMP	#0,R14
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
Index: libgcc/config/msp430/floathisf.c
===================================================================
--- libgcc/config/msp430/floathisf.c	(revision 0)
+++ libgcc/config/msp430/floathisf.c	(revision 0)
@@ -0,0 +1,36 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2013
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef int HItype __attribute__ ((mode (HI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+
+extern SFtype __floatsisf (unsigned long);
+
+SFtype
+__floathisf (HItype u)
+{
+  return __floatsisf ((unsigned long)u);
+}
Index: libgcc/config/msp430/lib2bitcountHI.c
===================================================================
--- libgcc/config/msp430/lib2bitcountHI.c	(revision 0)
+++ libgcc/config/msp430/lib2bitcountHI.c	(revision 0)
@@ -0,0 +1,50 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2012
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef          int  sint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef          int  sint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+typedef          int  sint08_type   __attribute__ ((mode (QI)));
+typedef unsigned int  uint08_type   __attribute__ ((mode (QI)));
+typedef int           word_type     __attribute__ ((mode (__word__)));
+
+#define C3B(a,b,c) a##b##c
+#define C3(a,b,c) C3B(a,b,c)
+
+/* See the comment by the definition of LIBGCC2_UNITS_PER_WORD in
+   msp430.h for why we are creating extra versions of some of the
+   functions defined in libgcc2.c.  */
+
+#define LIBGCC2_UNITS_PER_WORD 2
+
+#define L_clzsi2
+#define L_ctzsi2
+#define L_ffssi2
+#define L_paritysi2
+#define L_popcountsi2
+
+#include "libgcc2.c"
Index: libgcc/config/msp430/floatunhisf.c
===================================================================
--- libgcc/config/msp430/floatunhisf.c	(revision 0)
+++ libgcc/config/msp430/floatunhisf.c	(revision 0)
@@ -0,0 +1,37 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2013
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef int HItype __attribute__ ((mode (HI)));
+typedef unsigned int UHItype __attribute__ ((mode (HI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+
+extern SFtype __floatunsisf (unsigned long);
+
+SFtype
+__floatunhisf (UHItype u)
+{
+  return __floatunsisf ((unsigned long)u);
+}
Index: libgcc/config/msp430/cmpd.c
===================================================================
--- libgcc/config/msp430/cmpd.c	(revision 0)
+++ libgcc/config/msp430/cmpd.c	(revision 0)
@@ -0,0 +1,44 @@
+/* libgcc routines for MSP430
+   Copyright (C) 2013
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int
+__mspabi_cmpf (float x, float y)
+{
+  if (x < y)
+    return -1;
+  if (x > y)
+    return 1;
+  return 0;
+}
+int
+__mspabi_cmpd (double x, double y)
+{
+  if (x < y)
+    return -1;
+  if (x > y)
+    return 1;
+  return 0;
+}
Index: libgcc/config/msp430/slli.S
===================================================================
--- libgcc/config/msp430/slli.S	(revision 0)
+++ libgcc/config/msp430/slli.S	(revision 0)
@@ -0,0 +1,108 @@
+;   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file 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.
+; 
+; This file 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.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+	
+	.text
+
+/* Logical Left Shift - R12 -> R12 */
+
+	.macro	_slli n
+	.global __mspabi_slli_\n
+__mspabi_slli_\n:
+	ADD.W	R12,R12
+	.endm
+
+	_slli	15
+	_slli	14
+	_slli	13
+	_slli	12
+	_slli	11
+	_slli	10
+	_slli	9
+	_slli	8
+	_slli	7
+	_slli	6
+	_slli	5
+	_slli	4
+	_slli	3
+	_slli	2
+	_slli	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R13
+	ADD.W	R12,R12
+	.global	__mspabi_slli
+__mspabi_slli:
+	CMP	#0,R13
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+/* Logical Left Shift - R12:R13 -> R12:R13 */
+
+	.macro	_slll	n
+	.global	__mspabi_slll_\n
+__mspabi_slll_\n:
+	ADD.W	R12,R12
+	ADDC.W	R13,R13
+	.endm
+
+	_slll	15
+	_slll	14
+	_slll	13
+	_slll	12
+	_slll	11
+	_slll	10
+	_slll	9
+	_slll	8
+	_slll	7
+	_slll	6
+	_slll	5
+	_slll	4
+	_slll	3
+	_slll	2
+	_slll	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R14
+	ADD.W	R12,R12
+	ADDC.W	R13,R13
+	.global	__mspabi_slll
+__mspabi_slll:
+	CMP	#0,R14
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
Index: libgcc/config/msp430/lib2divQI.c
===================================================================
--- libgcc/config/msp430/lib2divQI.c	(revision 0)
+++ libgcc/config/msp430/lib2divQI.c	(revision 0)
@@ -0,0 +1,44 @@
+/* QI mode divide routines for libgcc for MSP430
+   Copyright (C) 2012
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef          int  sint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef          int  sint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+typedef          int  sint08_type   __attribute__ ((mode (QI)));
+typedef unsigned int  uint08_type   __attribute__ ((mode (QI)));
+typedef int           word_type     __attribute__ ((mode (__word__)));
+
+#define C3B(a,b,c) a##b##c
+#define C3(a,b,c) C3B(a,b,c)
+
+#define UINT_TYPE	uint08_type
+#define SINT_TYPE	sint08_type
+#define BITS_MINUS_1	7
+#define NAME_MODE	qi
+
+#include "msp430-divmod.h"
+
Index: libgcc/config/msp430/lib2shift.c
===================================================================
--- libgcc/config/msp430/lib2shift.c	(revision 0)
+++ libgcc/config/msp430/lib2shift.c	(revision 0)
@@ -0,0 +1,113 @@
+/* Shift functions for the GCC support library for the MSP430
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef          int  sint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef          int  sint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+
+uint32_type __ashlsi3 (uint32_type in, char bit);
+sint32_type __ashrsi3 (sint32_type in, char bit);
+int __clrsbhi2 (sint16_type x);
+extern int __clrsbsi2 (sint32_type x);
+
+typedef struct
+{
+  union
+  {
+    uint32_type u;
+    uint16_type h[2];
+  } u;
+} dd;
+
+uint32_type
+__ashlsi3 (uint32_type in, char bit)
+{
+  uint16_type h, l;
+  dd d;
+
+  if (bit > 32)
+    return 0;
+  if (bit < 0)
+    return in;
+
+  d.u.u = in;
+  h = d.u.h[1];
+  l = d.u.h[0];
+
+  if (bit > 15)
+    {
+      h = l;
+      l = 0;
+      bit -= 16;
+    }
+
+  while (bit)
+    {
+      h = (h << 1) | (l >> 15);
+      l <<= 1;
+      bit --;
+    }
+
+  d.u.h[1] = h;
+  d.u.h[0] = l;
+  return d.u.u;
+}
+
+sint32_type
+__ashrsi3 (sint32_type in, char bit)
+{
+  sint16_type h;
+  uint16_type l;
+  dd d;
+
+  if (bit > 32)
+    return 0;
+  if (bit < 0)
+    return in;
+
+  d.u.u = in;
+  h = d.u.h[1];
+  l = d.u.h[0];
+
+  while (bit)
+    {
+      l = (h << 15) | (l >> 1);
+      h >>= 1;
+      bit --;
+    }
+
+  d.u.h[1] = h;
+  d.u.h[0] = l;
+  return d.u.u;
+}
+
+int
+__clrsbhi2 (sint16_type x)
+{
+  if (x == 0)
+    return 15;
+  return __clrsbsi2 ((sint32_type) x) - 16;
+}
Index: libgcc/config/msp430/msp430-mul.h
===================================================================
--- libgcc/config/msp430/msp430-mul.h	(revision 0)
+++ libgcc/config/msp430/msp430-mul.h	(revision 0)
@@ -0,0 +1,43 @@
+/* libgcc routines for RL78
+   Copyright (C) 2005, 2009, 2011
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+UINT_TYPE C3(__mul,NAME_MODE,3)   (UINT_TYPE, UINT_TYPE);
+UINT_TYPE
+C3(__mul,NAME_MODE,3) (UINT_TYPE a, UINT_TYPE b)
+{
+  UINT_TYPE rv = 0;
+
+  char bit;
+
+  for (bit=0; b && bit<sizeof(UINT_TYPE)*8; bit++)
+    {
+      if (b & 1)
+	rv += a;
+      a <<= 1;
+      b >>= 1;
+    }
+  return rv;
+}
Index: libgcc/config/msp430/lib2divSI.c
===================================================================
--- libgcc/config/msp430/lib2divSI.c	(revision 0)
+++ libgcc/config/msp430/lib2divSI.c	(revision 0)
@@ -0,0 +1,43 @@
+/* SI mode divide routines for libgcc for MSP430
+   Copyright (C) 2012
+   Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef          int  sint32_type   __attribute__ ((mode (SI)));
+typedef unsigned int  uint32_type   __attribute__ ((mode (SI)));
+typedef          int  sint16_type   __attribute__ ((mode (HI)));
+typedef unsigned int  uint16_type   __attribute__ ((mode (HI)));
+typedef          int  sint08_type   __attribute__ ((mode (QI)));
+typedef unsigned int  uint08_type   __attribute__ ((mode (QI)));
+typedef int           word_type     __attribute__ ((mode (__word__)));
+
+#define C3B(a,b,c) a##b##c
+#define C3(a,b,c) C3B(a,b,c)
+
+#define UINT_TYPE	uint32_type
+#define SINT_TYPE	sint32_type
+#define BITS_MINUS_1	31
+#define NAME_MODE	si
+
+#include "msp430-divmod.h"
Index: libgcc/config/msp430/epilogue.S
===================================================================
--- libgcc/config/msp430/epilogue.S	(revision 0)
+++ libgcc/config/msp430/epilogue.S	(revision 0)
@@ -0,0 +1,51 @@
+;   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file 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.
+; 
+; This file 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.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+
+	.text
+
+	.global	__mspabi_func_epilog_7
+	.global	__mspabi_func_epilog_6
+	.global	__mspabi_func_epilog_5
+	.global	__mspabi_func_epilog_4
+	.global	__mspabi_func_epilog_3
+	.global	__mspabi_func_epilog_2
+	.global	__mspabi_func_epilog_1
+
+__mspabi_func_epilog_7:
+	POP	R4
+__mspabi_func_epilog_6:
+	POP	R5
+__mspabi_func_epilog_5:
+	POP	R6
+__mspabi_func_epilog_4:
+	POP	R7
+__mspabi_func_epilog_3:
+	POP	R8
+__mspabi_func_epilog_2:
+	POP	R9
+__mspabi_func_epilog_1:
+	POP	R10
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
Index: libgcc/config/msp430/srli.S
===================================================================
--- libgcc/config/msp430/srli.S	(revision 0)
+++ libgcc/config/msp430/srli.S	(revision 0)
@@ -0,0 +1,110 @@
+;   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file 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.
+; 
+; This file 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.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+	
+	.text
+
+	.macro	_srli n
+	.global __mspabi_srli_\n
+__mspabi_srli_\n:
+	CLRC
+	RRC.W	R12
+	.endm
+
+/* Logical Right Shift - R12 -> R12 */
+	_srli	15
+	_srli	14
+	_srli	13
+	_srli	12
+	_srli	11
+	_srli	10
+	_srli	9
+	_srli	8
+	_srli	7
+	_srli	6
+	_srli	5
+	_srli	4
+	_srli	3
+	_srli	2
+	_srli	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R13
+	CLRC
+	RRC.W	R12,R12
+	.global	__mspabi_srli
+__mspabi_srli:
+	CMP	#0,R13
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+/* Logical Right Shift - R12:R13 -> R12:R13 */
+
+	.macro	_srll	n
+	.global	__mspabi_srll_\n
+__mspabi_srll_\n:
+	CLRC
+	RRC.W	R13
+	RRC.W	R12
+	.endm
+
+	_srll	15
+	_srll	14
+	_srll	13
+	_srll	12
+	_srll	11
+	_srll	10
+	_srll	9
+	_srll	8
+	_srll	7
+	_srll	6
+	_srll	5
+	_srll	4
+	_srll	3
+	_srll	2
+	_srll	1
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
+
+1:	ADD.W	#-1,R14
+	CLRC
+	RRC.W	R13
+	RRC.W	R12
+	.global	__mspabi_srll
+__mspabi_srll:
+	CMP	#0,R14
+	JNZ	1b
+#ifdef __MSP430X_LARGE__
+	RETA
+#else
+	RET
+#endif
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 201184)
+++ gcc/doc/invoke.texi	(working copy)
@@ -794,12 +794,15 @@ Objective-C and Objective-C++ Dialects}.
 -mreturn-pointer-on-d0 @gol
 -mno-crt0  -mrelax -mliw -msetlb}
 
 @emph{Moxie Options}
 @gccoptlist{-meb -mel -mno-crt0}
 
+@emph{MSP430 Options}
+@gccoptlist{-msim -masm-hex -mmcu= -mlarge -msmall -mrelax}
+
 @emph{PDP-11 Options}
 @gccoptlist{-mfpu  -msoft-float  -mac0  -mno-ac0  -m40  -m45  -m10 @gol
 -mbcopy  -mbcopy-builtin  -mint32  -mno-int16 @gol
 -mint16  -mno-int32  -mfloat32  -mno-float64 @gol
 -mfloat64  -mno-float32  -mabshi  -mno-abshi @gol
 -mbranch-expensive  -mbranch-cheap @gol
@@ -10936,12 +10939,13 @@ platform.
 * MeP Options::
 * MicroBlaze Options::
 * MIPS Options::
 * MMIX Options::
 * MN10300 Options::
 * Moxie Options::
+* MSP430 Options::
 * PDP-11 Options::
 * picoChip Options::
 * PowerPC Options::
 * RL78 Options::
 * RS/6000 and PowerPC Options::
 * RX Options::
@@ -15872,13 +15876,13 @@ compatibility with other tools, like @co
 @item -msdram
 @opindex msdram
 Link the SDRAM-based runtime instead of the default ROM-based runtime.
 
 @item -msim
 @opindex msim
-Link the simulator runtime libraries.
+Link the simulator run-time libraries.
 
 @item -msimnovec
 @opindex msimnovec
 Link the simulator runtime libraries, excluding built-in support
 for reset and exception vectors and tables.
 
@@ -17094,12 +17098,52 @@ Generate little-endian code.
 @item -mno-crt0
 @opindex mno-crt0
 Do not link in the C run-time initialization object file.
 
 @end table
 
+@node MSP430 Options
+@subsection MSP430 Options
+@cindex MSP430 Options
+
+These options are defined for the MSP430:
+
+@table @gcctabopt
+
+@item -msim
+@opindex msim
+Link the simulator runtime libraries.
+
+@item -masm-hex
+@opindex masm-hex
+Force assembly output to always use hex constants.  Normally such
+constants are signed decimals, but this option is available for
+testsuite and/or aesthetic purposes.
+
+@item -mmcu=
+@opindex mmcu=
+Select the MCU to target.  Note that there are two ``generic'' MCUs,
+@code{msp430} and @code{msp430x}, which should be used most of the
+time.  This option is also passed to the assembler.
+
+@item -mlarge
+@opindex mlarge
+Use large-model addressing (20-bit pointers, 32-bit @code{size_t}).
+
+@item -msmall
+@opindex msmall
+Use small-model addressing (16-bit pointers, 16-bit @code{size_t}).
+
+@item -mrelax
+@opindex mrelax
+This option is passed to the assembler and linker, and allows the
+linker to perform certain optimizations that cannot be done until
+the final link.
+
+@end table
+
 @node PDP-11 Options
 @subsection PDP-11 Options
 @cindex PDP-11 Options
 
 These options are defined for the PDP-11:
 
Index: gcc/doc/contrib.texi
===================================================================
--- gcc/doc/contrib.texi	(revision 201184)
+++ gcc/doc/contrib.texi	(working copy)
@@ -173,13 +173,13 @@ Branko Cibej for more warning contributi
 
 @item
 The @uref{http://www.gnu.org/software/classpath/,,GNU Classpath project}
 for all of their merged runtime code.
 
 @item
-Nick Clifton for arm, mcore, fr30, v850, m32r, rx work,
+Nick Clifton for arm, mcore, fr30, v850, m32r, msp430 rx work,
 @option{--help}, and other random hacking.
 
 @item
 Michael Cook for libstdc++ cleanup patches to reduce warnings.
 
 @item
@@ -215,13 +215,13 @@ Bud Davis for work on the G77 and GNU Fo
 
 @item
 Mo DeJong for GCJ and libgcj bug fixes.
 
 @item
 DJ Delorie for the DJGPP port, build and libiberty maintenance,
-various bug fixes, and the M32C, MeP, and RL78 ports.
+various bug fixes, and the M32C, MeP, MSP430, and RL78 ports.
 
 @item
 Arnaud Desitter for helping to debug GNU Fortran.
 
 @item
 Gabriel Dos Reis for contributions to G++, contributions and
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	(revision 201184)
+++ gcc/doc/md.texi	(working copy)
@@ -3060,12 +3060,41 @@ A constant in the range of 0 to 255.
 
 @item N
 A constant in the range of 0 to @minus{}255.
 
 @end table
 
+@item MSP430--@file{config/msp430/constraints.md}
+@table @code
+
+@item R12
+Register R12.
+
+@item R13
+Register R13.
+
+@item K
+Integer constant 1.
+
+@item L
+Integer constant -1^20..1^19.
+
+@item M
+Integer constant 1-4.
+
+@item Ya
+Memory references which do not require an extended MOVX instruction.
+
+@item Yl
+Memory reference, labels only.
+
+@item Ys
+Memory reference, stack only.
+
+@end table
+
 @item PDP-11---@file{config/pdp11/constraints.md}
 @table @code
 @item a
 Floating point registers AC0 through AC3.  These can be loaded from/to
 memory with a single instruction.
 
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 201184)
+++ gcc/doc/install.texi	(working copy)
@@ -3951,12 +3951,19 @@ the O32 ABI.
 @heading @anchor{moxie-x-elf}moxie-*-elf
 The moxie processor.
 
 @html
 <hr />
 @end html
+@heading @anchor{msp430-x-elf}msp430-*-elf
+TI MSP430 processor.
+This configuration is intended for embedded systems.
+
+@html
+<hr />
+@end html
 @heading @anchor{powerpc-x-x}powerpc-*-*
 
 You can specify a default version for the @option{-mcpu=@var{cpu_type}}
 switch by using the configure option @option{--with-cpu-@var{cpu_type}}.
 
 You will need
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(revision 201184)
+++ gcc/cfgexpand.c	(working copy)
@@ -3151,13 +3151,20 @@ expand_debug_expr (tree exp)
 	 size_t, we need to check for mis-matched modes and correct
 	 the addend.  */
       if (op0 && op1
 	  && GET_MODE (op0) != VOIDmode && GET_MODE (op1) != VOIDmode
 	  && GET_MODE (op0) != GET_MODE (op1))
 	{
-	  if (GET_MODE_BITSIZE (GET_MODE (op0)) < GET_MODE_BITSIZE (GET_MODE (op1)))
+	  if (GET_MODE_BITSIZE (GET_MODE (op0)) < GET_MODE_BITSIZE (GET_MODE (op1))
+	      /* Don't try to sign-extend SImode to PSImode, for
+		 example.  The sign extension code in simplify_unary_operation_1()
+		 asserts extension to a larger bit size.  */
+	      || (GET_MODE_BITSIZE (GET_MODE (op0)) == GET_MODE_BITSIZE (GET_MODE (op1))
+		  && GET_MODE_CLASS (GET_MODE (op0)) == MODE_PARTIAL_INT
+		  && GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT)
+	      )
 	    op1 = simplify_gen_unary (TRUNCATE, GET_MODE (op0), op1,
 				      GET_MODE (op1));
 	  else
 	    /* We always sign-extend, regardless of the signedness of
 	       the operand, because the operand is always unsigned
 	       here even if the original C expression is signed.  */
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 201184)
+++ gcc/simplify-rtx.c	(working copy)
@@ -5884,12 +5884,23 @@ simplify_immed_subreg (enum machine_mode
 /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE)
    Return 0 if no simplifications are possible.  */
 rtx
 simplify_subreg (enum machine_mode outermode, rtx op,
 		 enum machine_mode innermode, unsigned int byte)
 {
+  /* FIXME: hack to allow building of newlib/libc.a for msp430/430x/large multilib.
+     The problem is the var-tracking is generating paradoxical SUBREGs.  Not sure why...  */
+  if (!(GET_MODE (op) == innermode
+        || GET_MODE (op) == VOIDmode)
+      || (innermode == VOIDmode)
+      )
+    {
+      debug_rtx (op);
+      return NULL_RTX;
+    }
+
   /* Little bit of sanity checking.  */
   gcc_assert (innermode != VOIDmode);
   gcc_assert (outermode != VOIDmode);
   gcc_assert (innermode != BLKmode);
   gcc_assert (outermode != BLKmode);
 
Index: gcc/dwarf2cfi.c
===================================================================
--- gcc/dwarf2cfi.c	(revision 201184)
+++ gcc/dwarf2cfi.c	(working copy)
@@ -277,12 +277,19 @@ expand_builtin_init_dwarf_reg_sizes (tre
 	    {
 	      if (save_mode == VOIDmode)
 		continue;
 	      wrote_return_column = true;
 	    }
 	  size = GET_MODE_SIZE (save_mode);
+
+          /* Entries in the dwarf_reg_size_table must be big enough to hold an _Unwind_Word
+             even if this is bigger than reg_raw_mode.  This can happen on targets where the
+             pointer size is larger than the integer size, and not a power-of-two.  (Eg MSP430).  */
+          if (size < GET_MODE_SIZE (targetm.unwind_word_mode ()))
+            size = GET_MODE_SIZE (targetm.unwind_word_mode ());
+
 	  if (offset < 0)
 	    continue;
 
 	  emit_move_insn (adjust_address (mem, mode, offset),
 			  gen_int_mode (size, mode));
 	}
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 201184)
+++ gcc/config.gcc	(working copy)
@@ -2034,12 +2034,19 @@ mn10300-*-*)
 	then
 		tm_file="${tm_file} dbx.h"
 	fi
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+msp430*-*-*)
+	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+	c_target_objs="msp430-c.o"
+	cxx_target_objs="msp430-c.o"
+	target_has_targetm_common=no
+	tmake_file="${tmake_file} msp430/t-msp430"
+	;;
 pdp11-*-*)
 	tm_file="${tm_file} newlib-stdint.h"
 	use_gcc_stdint=wrap
 	;;
 picochip-*)
 	tm_file="${tm_file} newlib-stdint.h"
Index: gcc/config/msp430/msp430-protos.h
===================================================================
--- gcc/config/msp430/msp430-protos.h	(revision 0)
+++ gcc/config/msp430/msp430-protos.h	(revision 0)
@@ -0,0 +1,44 @@
+/* Exported function prototypes from the TI MSP430 backend.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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/>.  */
+
+#ifndef GCC_MSP430_PROTOS_H
+#define GCC_MSP430_PROTOS_H
+
+void	msp430_expand_eh_return (rtx);
+void	msp430_expand_epilogue (int);
+void	msp430_expand_helper (rtx *operands, const char *, bool);
+void	msp430_expand_prologue (void);
+const char * msp430x_extendhisi (rtx *);
+void	msp430_fixup_compare_operands (enum machine_mode, rtx *);
+int	msp430_hard_regno_mode_ok (int, enum machine_mode);
+int	msp430_hard_regno_nregs (int, enum machine_mode);
+rtx	msp430_incoming_return_addr_rtx (void);
+void	msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+int	msp430_initial_elimination_offset (int, int);
+const char * msp430x_logical_shift_right (rtx);
+void	msp430_output_labelref (FILE *, const char *);
+void	msp430_register_pragmas (void);
+rtx	msp430_return_addr_rtx (int);
+void	msp430_split_movsi (rtx *);
+rtx	msp430_subreg (enum machine_mode, rtx, enum machine_mode, int);
+rtx	msp430_eh_return_stackadj_rtx (void);
+bool	msp430_modes_tieable_p (enum machine_mode, enum machine_mode);
+
+#endif /* GCC_MSP430_PROTOS_H */
Index: gcc/config/msp430/predicates.md
===================================================================
--- gcc/config/msp430/predicates.md	(revision 0)
+++ gcc/config/msp430/predicates.md	(revision 0)
@@ -0,0 +1,80 @@
+;;  Machine Description for TI MSP43* processors
+;;  Copyright (C) 2013 Free Software Foundation, Inc.
+;;  Contributed by Red Hat.
+
+;; 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/>.
+
+(define_predicate "msp_volatile_memory_operand"
+  (and (match_code "mem")
+       (match_test ("memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0), MEM_ADDR_SPACE (op))")))
+)
+
+; TRUE for any valid general operand.  We do this because
+; general_operand refuses to match volatile memory refs.
+
+(define_predicate "msp_general_operand"
+  (ior (match_operand 0 "general_operand")
+       (match_operand 0 "msp_volatile_memory_operand"))
+)
+
+; Likewise for nonimmediate_operand.
+
+(define_predicate "msp_nonimmediate_operand"
+  (ior (match_operand 0 "nonimmediate_operand")
+       (match_operand 0 "msp_volatile_memory_operand"))
+)
+
+(define_predicate "ubyte_operand"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 255)")))
+
+; TRUE for comparisons we support.
+(define_predicate "msp430_cmp_operator"
+  (match_code "eq,ne,lt,ltu,ge,geu"))
+
+; TRUE for comparisons we need to reverse.
+(define_predicate "msp430_reversible_cmp_operator"
+  (match_code "gt,gtu,le,leu"))
+
+; TRUE for constants the constant generator can produce
+(define_predicate "msp430_constgen_operator"
+  (and (match_code "const_int")
+       (match_test ("   INTVAL (op) == 0
+		     || INTVAL (op) == 1
+		     || INTVAL (op) == 2
+		     || INTVAL (op) == 4
+		     || INTVAL (op) == 8
+		     || INTVAL (op) == -1 "))))
+
+; TRUE for constants the constant generator can produce
+(define_predicate "msp430_inv_constgen_operator"
+  (and (match_code "const_int")
+       (match_test ("   INTVAL (op) == ~0
+		     || INTVAL (op) == ~1
+		     || INTVAL (op) == ~2
+		     || INTVAL (op) == ~4
+		     || INTVAL (op) == ~8
+		     || INTVAL (op) == ~(-1) "))))
+
+(define_predicate "msp430_nonsubreg_operand"
+  (match_code "reg,mem"))
+
+; TRUE for constants which are bit positions for zero_extract
+(define_predicate "msp430_bitpos"
+  (and (match_code "const_int")
+       (match_test ("   INTVAL (op) >= 0
+		     && INTVAL (op) <= 15 "))))
Index: gcc/config/msp430/msp430.md
===================================================================
--- gcc/config/msp430/msp430.md	(revision 0)
+++ gcc/config/msp430/msp430.md	(revision 0)
@@ -0,0 +1,1287 @@
+;;  Machine Description for TI MSP43* processors
+;;  Copyright (C) 2013 Free Software Foundation, Inc.
+;;  Contributed by Red Hat.
+
+;; 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/>.
+
+
+(define_constants
+  [
+   (PC_REGNO 0)
+   (SP_REGNO 1)
+   (CARRY 2)
+  ])
+
+(define_c_enum "unspec"
+  [
+   UNS_PROLOGUE_START_MARKER
+   UNS_PROLOGUE_END_MARKER
+   UNS_EPILOGUE_START_MARKER
+   UNS_EPILOGUE_HELPER
+
+   UNS_PUSHM
+   UNS_POPM
+
+   UNS_GROW_AND_SWAP
+   UNS_SWAP_AND_SHRINK
+  ])
+  
+(include "predicates.md")
+(include "constraints.md")
+
+(define_mode_iterator QHI [QI HI PSI])
+
+;; There are two basic "family" tests we do here:
+;;
+;; msp430x - true if 430X instructions are available.
+;; TARGET_LARGE - true if pointers are 20-bits
+;;
+;; Note that there are three supported cases, since the base 430
+;; doesn't have 20-bit pointers:
+;;
+;; 1. MSP430 cpu, small model
+;; 2. MSP430X cpu, small model.
+;; 3. MSP430X cpu, large model.
+
+;;------------------------------------------------------------
+;; Moves
+
+;; Push/Pop must be before the generic move patterns
+
+(define_insn "push"
+  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
+	(match_operand:HI 0 "register_operand" "r"))]
+  ""
+  "PUSH\t%0"
+  )
+
+(define_insn "pusha"
+  [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
+	(match_operand:PSI 0 "register_operand" "r"))]
+  "TARGET_LARGE"
+  "PUSHX.A\t%0"
+  )
+
+(define_insn "pushm"
+  [(unspec_volatile [(match_operand 0 "register_operand" "r")
+		     (match_operand 1 "immediate_operand" "i")] UNS_PUSHM)]
+  ""
+  "PUSHM%B0\t%1, %0"
+  )
+
+(define_insn "pop"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
+  ""
+  "POP\t%0"
+  )
+
+(define_insn "popa"
+  [(set (match_operand:PSI 0 "register_operand" "=r")
+	(mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
+  "TARGET_LARGE"
+  "POPX.A\t%0"
+  )
+
+;; This is nasty.  Operand0 is bogus.  It is only there so that we can get a
+;; mode for the %B0 to work.  We should use operand1 for this, but that does
+;; not have a mode.
+;; 
+;; Operand1 is actually a register, but we cannot accept (REG...) because the
+;; cprop_hardreg pass can and will renumber registers even inside
+;; unspec_volatiles.  So we take an integer register number parameter and
+;; fudge it to be a register name when we generate the assembler.
+;;
+;; The pushm pattern does not have this problem because of all of the
+;; frame info cruft attached to it, so cprop_hardreg leaves it alone.
+(define_insn "popm"
+  [(unspec_volatile [(match_operand 0 "register_operand" "r")
+		     (match_operand 1 "immediate_operand" "i")
+		     (match_operand 2 "immediate_operand" "i")] UNS_POPM)]
+  ""
+  "POPM%B0\t%2, r%D1"
+  )
+
+;; The next two patterns are here to support a "feature" of how GCC implements
+;; varargs.  When a function uses varargs and the *second* to last named
+;; argument is split between argument registers and the stack, gcc expects the
+;; callee to allocate space on the stack that can contain the register-based
+;; part of the argument.  This space *has* to be just before the remaining
+;; arguments (ie the ones that are fully on the stack).
+;;
+;; The problem is that the MSP430 CALL instruction pushes the return address
+;; onto the stack in the exact place where the callee wants to allocate
+;; this extra space.  So we need a sequence of instructions that can allocate
+;; the extra space and then move the return address down the stack, so that
+;; the extra space is now adjacent to the remaining arguments.
+;;
+;; This could be constructed through regular insns, but they might be split up
+;; by a misguided optimization, so an unspec volatile is used instead.
+
+(define_insn "grow_and_swap"
+  [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  { if (TARGET_LARGE)
+      return "SUBA\t#2, r1 \n MOVX.A\t2(r1), 0(r1)";
+    return "SUB\t#2, r1 \n MOV.W\t2(r1), 0(r1)";
+    }
+  )
+
+(define_insn "swap_and_shrink"
+  [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  { return TARGET_LARGE
+	   ? "MOVX.A\t0(r1), 2(r1) \n ADDA\t#2, SP"
+	   : "MOV.W\t0(r1), 2(r1) \n ADD\t#2, SP";
+  })
+
+(define_insn "movqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rYs,rm")
+	(match_operand:QI 1 "general_operand" "riYs,rmi"))]
+  ""
+  "@
+  MOV.B\t%1, %0
+  MOV%X0.B\t%1, %0"
+)
+
+(define_insn "movhi"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs,rm")
+	(match_operand:HI 1 "general_operand" "riYs,rmi"))]
+  ""
+  "@
+  MOV.W\t%1, %0
+  MOV%X0.W\t%1, %0"
+)
+
+(define_expand "movsi"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+	(match_operand:SI 1 "general_operand" ""))]
+  ""
+  ""
+  )
+  
+(define_insn_and_split "movsi_x"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+	(match_operand:SI 1 "general_operand" "rmi"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_operand:HI 2 "nonimmediate_operand")
+	(match_operand:HI 4 "general_operand"))
+   (set (match_operand:HI 3 "nonimmediate_operand")
+	(match_operand:HI 5 "general_operand"))]
+  "msp430_split_movsi (operands);"
+)
+
+;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
+(define_insn "movpsi"
+  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,Ya,rm")
+	(match_operand:PSI 1 "general_operand" "riYa,r,rmi"))]
+  ""
+  "@
+  MOV%A0\t%1, %0
+  MOV%A0\t%1, %0
+  MOV%X0.%A0\t%1, %0")
+
+; This pattern is identical to the truncsipsi2 pattern except
+; that it uses a SUBREG instead of a TRUNC.  It is needed in
+; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
+; into (SET:PSI (PSI)).
+;
+; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
+
+(define_insn "movsipsi2"
+  [(set (match_operand:PSI            0 "register_operand" "=r")
+	(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
+  "TARGET_LARGE"
+  "PUSH.W %H1 { PUSH.W %1 { POPM.A #1, %0"
+)
+
+;;------------------------------------------------------------
+;; Math
+
+(define_insn "addpsi3"
+  [(set (match_operand:PSI           0 "nonimmediate_operand" "=r,rm")
+	(plus:PSI (match_operand:PSI 1 "nonimmediate_operand" "%0,0")
+		  (match_operand:PSI 2 "general_operand"      "rLs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  ADDA\t%2, %0
+  ADDX.A\t%2, %0"
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI          0 "nonimmediate_operand" "=rYs,rm")
+	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
+		 (match_operand:QI 2 "general_operand"      "riYs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   ADD.B\t%2, %0
+   ADD%X0.B\t%2, %0"
+)
+
+(define_insn "addqi3_ze"
+  [(set (match_operand:HI          0 "nonimmediate_operand" "=r,r")
+	(zero_extend:HI (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
+				 (match_operand:QI 2 "general_operand"      "riYs,rmi"))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   ADD.B\t%2, %0
+   ADD%X0.B\t%2, %0"
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI           0 "nonimmediate_operand" "=rYs,rm")
+	(plus:HI (match_operand:HI  1 "nonimmediate_operand" "%0,0")
+		  (match_operand:HI 2 "general_operand"      "riYs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   ADD.W\t%2, %0
+   ADD%X0.W\t%2, %0"
+)
+
+; This pattern is needed in order to avoid reload problems.
+; It takes an SI pair of registers, adds a value to them, and
+; then converts them into a single PSI register.
+
+(define_insn "addsipsi3"
+  [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0)
+	(plus:SI (match_operand:SI    1 "register_operand" "0")
+		 (match_operand       2 "general_operand" "rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "ADD.W\t%L2, %L0 { ADDC.W\t%H2, %H0 { PUSH.W %H0 { PUSH.W %L0 { POPM.A #1, %0"
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm")
+	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+		 (match_operand:SI 2 "general_operand" "r,mi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   ADD\t%L2, %L0 { ADDC\t%H2, %H0
+   ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
+)
+
+; Version of addhi that exposes the carry operations, for SImode adds.
+;
+; We have these two add patterns and the splitter that follows because
+; our tests have shown that this results in a significant reduction in
+; code size - because GCC is able to discard any unused part of the
+; addition.  We have to annotate the patterns with the set and use of
+; the carry flag because otherwise GCC will discard parts of the
+; addition when they are actually needed.
+
+(define_insn "addhi3_cy"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
+	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
+		 (match_operand:HI 2 "general_operand" "ri,rmi")))
+   (set (reg:CC CARRY)
+   	(compare (plus:SI (match_dup 1) (match_dup 2))
+		 (const_int 0)))
+   ]
+  ""
+  "@
+   ADD %2, %1 ; cy
+   ADD%X0 %2, %1 ; cy"
+  )
+
+; Version of addhi that adds the carry, for SImode adds.
+(define_insn "addchi4_cy"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
+	(plus:HI (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
+			  (match_operand:HI 2 "general_operand" "ri,rmi"))
+		 (ltu:HI (reg:CC CARRY) (const_int 0))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   ADDC %2, %1
+   ADDC%X0 %2, %1"
+  )
+
+; Split an SImode add into two HImode adds, keeping track of the carry
+; so that gcc knows when it can and can't optimize away the two
+; halves.
+(define_split
+  [(set (match_operand:SI 0 "msp430_nonsubreg_operand" "=&rm")
+	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+		 (match_operand:SI 2 "general_operand" "rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  [(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm")
+		   (plus:HI (match_dup 4)
+			    (match_dup 5)))
+	      (set (reg:CC CARRY)
+		   (compare (plus:SI (match_dup 4) (match_dup 5))
+			    (const_int 0)))]
+
+	      )
+   (parallel [(set (match_operand:HI 6 "nonimmediate_operand" "=&rm")
+		   (plus:HI (plus:HI (match_dup 7)
+				     (match_dup 8))
+			    (ltu:HI (reg:CC CARRY) (const_int 0))))
+	      (clobber (reg:CC CARRY))
+	      ])
+   ]
+  "
+   operands[3] = msp430_subreg (HImode, operands[0], SImode, 0);
+   operands[4] = msp430_subreg (HImode, operands[1], SImode, 0);
+   operands[5] = msp430_subreg (HImode, operands[2], SImode, 0);
+   operands[6] = msp430_subreg (HImode, operands[0], SImode, 2);
+   operands[7] = msp430_subreg (HImode, operands[1], SImode, 2);
+   operands[8] = msp430_subreg (HImode, operands[2], SImode, 2);
+   if (GET_CODE (operands[5]) == CONST_INT)
+     {
+       operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
+     }
+   else
+     {
+       operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
+     }
+   "
+  )
+
+
+;; Alternatives 2 and 3 are to handle cases generated by reload.
+(define_insn "subpsi3"
+  [(set (match_operand:PSI            0 "nonimmediate_operand" "=r,   rm, &?r, ?&r")
+	(minus:PSI (match_operand:PSI 1 "general_operand"       "0,   0,   !r,  !i")
+		   (match_operand:PSI 2 "general_operand"       "rLs, rmi, rmi,  r")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  SUBA\t%2, %0
+  SUBX.A\t%2, %0
+  MOVX.A\t%1, %0 { SUBX.A\t%2, %0
+  MOVX.A\t%1, %0 { SUBA\t%2, %0"
+)
+
+;; Alternatives 2 and 3 are to handle cases generated by reload.
+(define_insn "subqi3"
+  [(set (match_operand:QI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
+	(minus:QI (match_operand:QI 1 "general_operand"       "0,    0,    !r,  !i")
+		  (match_operand:QI 2 "general_operand"      " riYs, rmi, rmi,   r")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  SUB.B\t%2, %0
+  SUB%X0.B\t%2, %0
+  MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
+  MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
+)
+
+;; Alternatives 2 and 3 are to handle cases generated by reload.
+(define_insn "subhi3"
+  [(set (match_operand:HI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
+	(minus:HI (match_operand:HI 1 "general_operand"       "0,    0,    !r,  !i")
+		  (match_operand:HI 2 "general_operand"      " riYs, rmi, rmi,   r")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  SUB.W\t%2, %0
+  SUB%X0.W\t%2, %0
+  MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
+  MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI           0 "nonimmediate_operand" "=&rm")
+	(minus:SI (match_operand:SI 1 "nonimmediate_operand"   "0")
+		  (match_operand:SI 2 "general_operand"        "rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
+)
+
+(define_insn "*bic<mode>_cg"
+  [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
+	(and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0")
+		 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
+  ""
+  "@
+   BIC%x0%B0\t#%I2, %0
+   BIC%X0%B0\t#%I2, %0"
+)
+
+(define_insn "bic<mode>3"
+  [(set (match_operand:QHI                   0 "msp_nonimmediate_operand" "=rYs,rm")
+	(and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand"       "rYs,rmn"))
+		 (match_operand:QHI          2 "msp_nonimmediate_operand"  "0,0")))]
+  ""
+  "@
+   BIC%x0%B0\t%1, %0
+   BIC%X0%B0\t%1, %0"
+)
+
+(define_insn "and<mode>3"
+  [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
+	(and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
+		 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   AND%x0%B0\t%2, %0
+   AND%X0%B0\t%2, %0"
+)
+
+(define_insn "ior<mode>3"
+  [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
+	(ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
+		 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   BIS%x0%B0\t%2, %0
+   BIS%X0%B0\t%2, %0"
+)
+
+(define_insn "xor<mode>3"
+  [(set (match_operand:QHI 0 "nonimmediate_operand" "=rYs,rm")
+	(xor:QHI (match_operand:QHI 1 "nonimmediate_operand" "%0,0")
+		 (match_operand:QHI 2 "general_operand" "riYs,rmi")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   XOR%x0%B0\t%2, %0
+   XOR%X0%B0\t%2, %0"
+)
+
+;; Macro : XOR #~0, %0
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:QHI 0 "nonimmediate_operand" "=rYs,m")
+	(not:QHI (match_operand:QHI 1 "nonimmediate_operand" "0,0")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   INV%x0%B0\t%0
+   INV%X0%B0\t%0"
+)
+
+(define_insn "extendqihi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs,m")
+	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,0")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   SXT%X0\t%0
+   SXT%X0\t%0"
+)
+
+;; Note: QImode moves to registers clear the top byte
+(define_insn "zero_extendqihi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs,m,r,r")
+	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,0,rYs,m")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   AND\t#0xff, %0
+   AND%X0\t#0xff, %0
+   MOV.B\t%1,%0
+   MOV%X0.B\t%1,%0"
+)
+
+;; Eliminate extraneous zero-extends mysteriously created by gcc.
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand")
+	(zero_extend:HI (match_operand:QI 1 "general_operand")))
+   (set (match_operand:HI 2 "register_operand")
+	(zero_extend:HI (match_operand:QI 3 "register_operand")))]
+  "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
+  [(set (match_dup 0)
+	(zero_extend:HI (match_dup 1)))]
+)
+   
+(define_insn "zero_extendhipsi2"
+  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,m")
+	(zero_extend:PSI (match_operand:HI 1 "nonimmediate_operand" "rm,r")))]
+  ""
+  "MOVX\t%1, %0"
+)
+
+(define_insn "truncpsihi2"
+  [(set (match_operand:HI               0 "nonimmediate_operand" "=rm")
+	(truncate:HI (match_operand:PSI 1 "register_operand"      "r")))]
+  ""
+  "MOVX\t%1, %0"
+)
+
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  { return msp430x_extendhisi (operands); }
+)
+
+(define_insn "extendhipsi2"
+  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
+	(subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))
+   (clobber (reg:CC CARRY))
+   ]
+  "TARGET_LARGE"
+  "RLAM #4, %0 { RRAM #4, %0"
+)
+
+;; Look for cases where integer/pointer conversions are suboptimal due
+;; to missing patterns, despite us not having opcodes for these
+;; patterns.  Doing these manually allows for alternate optimization
+;; paths.
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))]
+  "TARGET_LARGE"
+  "MOV.W\t#0,%H0"
+)
+
+(define_insn "zero_extendhisipsi2"
+  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
+	(subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))
+   (clobber (reg:CC CARRY))
+   ]
+  "TARGET_LARGE"
+  "@
+   AND.W\t#-1,%0
+   MOV.W\t%1,%0"
+)
+
+(define_insn "extend_and_shift1_hipsi2"
+  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
+	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
+		   (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  "TARGET_LARGE"
+  "RLAM #4, %0 { RRAM #3, %0"
+)
+
+(define_insn "extend_and_shift2_hipsi2"
+  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
+	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
+		   (const_int 2)))
+   (clobber (reg:CC CARRY))
+   ]
+  "TARGET_LARGE"
+  "RLAM #4, %0 { RRAM #2, %0"
+)
+
+; Nasty - we are sign-extending a 20-bit PSI value in one register into
+; two adjacent 16-bit registers to make an SI value.  There is no MSP430X
+; instruction that will do this, so we push the 20-bit value onto the stack
+; and then pop it off as two 16-bit values.
+;
+; FIXME: The MSP430X documentation does not specify if zero-extension or
+; sign-extension happens when the 20-bit value is pushed onto the stack.
+; It is probably zero-extension, but if not this pattern will not work
+; when the PSI value is negative..
+;
+; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
+
+(define_insn "zero_extendpsisi2"
+  [(set (match_operand:SI                  0 "register_operand" "=r")
+	(zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "*
+    if (REGNO (operands[1]) == SP_REGNO)
+      /* If the source register is the stack pointer, the value
+         stored in the stack slot will be the value *after* the
+	 stack pointer has been decremented.  So allow for that
+	 here.  */
+      return \"PUSHM.A #1, %1 { ADDX.W #4, @r1 { POPX.W %0 { POPX.W %H0\";
+    else
+      return \"PUSHM.A #1, %1 { POPX.W %0 { POPX.W %H0\";
+  "
+)
+
+; See the movsipsi2 pattern above for another way that GCC performs this
+; conversion.
+(define_insn "truncsipsi2"
+  [(set (match_operand:PSI              0 "register_operand" "=r")
+	(truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "PUSH.W %H1 { PUSH.W %1 { POPM.A #1, %0"
+)
+
+;;------------------------------------------------------------
+;; Shift Functions
+
+;; Note:  We do not use the RPT ... SHIFT instruction sequence
+;; when the repeat count is in a register, because even though RPT
+;; accepts counts in registers, it does not work if the count is
+;; zero, and the actual count in the register has to be one less
+;; than the required number of iterations.  We could encode a
+;; seqeunce like this:
+;;
+;;   bit #0xf, Rn
+;;   bz  1f
+;;   dec Rn
+;;   rpt Rn
+;;   <shift> Rm
+;;   inc Rn
+;; 1:
+;;
+;; But is longer than calling a helper function, and we are mostly
+;; concerned with code size.  FIXME: Maybe enable a sequence like
+;; this at -O3 and above ?
+;;
+;; Note - we ignore shift counts of less than one or more than 15.
+;; This is permitted by the ISO C99 standard as such shifts result
+;; in "undefined" behaviour.  [6.5.7 (3)]
+
+;; signed A << C
+
+(define_expand "ashlhi3"
+  [(set (match_operand:HI            0 "nonimmediate_operand")
+	(ashift:HI (match_operand:HI 1 "general_operand")
+		   (match_operand:HI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  {
+    if (msp430x
+        && REG_P (operands[0])
+        && REG_P (operands[1])
+        && CONST_INT_P (operands[2]))
+      emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2]));
+    else		 
+      msp430_expand_helper (operands, \"__mspabi_slli\", true);
+    DONE;
+  }
+)
+
+(define_insn "slli_1"
+  [(set (match_operand:HI            0 "nonimmediate_operand" "=rm")
+	(ashift:HI (match_operand:HI 1 "general_operand"       "0")
+		   (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RLA.W\t%0" ;; Note - this is a macro for ADD
+)
+
+(define_insn "430x_shift_left"
+  [(set (match_operand:HI            0 "register_operand" "=r")
+	(ashift:HI (match_operand:HI 1 "register_operand"  "0")
+		   (match_operand    2 "immediate_operand" "n")))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  "*
+  if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
+    return \"rpt\t%2 { rlax.w\t%0\";
+  return \"# nop left shift\";
+  "
+)
+
+(define_insn "slll_1"
+  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
+	(ashift:SI (match_operand:SI 1 "general_operand"       "0")
+		   (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RLA.W\t%L0 { RLC.W\t%H0"
+)
+
+(define_insn "slll_2"
+  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
+	(ashift:SI (match_operand:SI 1 "general_operand"       "0")
+		   (const_int 2)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
+)
+
+(define_expand "ashlsi3"
+  [(set (match_operand:SI            0 "nonimmediate_operand")
+	(ashift:SI (match_operand:SI 1 "general_operand")
+		   (match_operand:SI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "msp430_expand_helper (operands, \"__mspabi_slll\", true);
+   DONE;"
+)
+
+;;----------
+
+;; signed A >> C
+
+(define_expand "ashrhi3"
+  [(set (match_operand:HI              0 "nonimmediate_operand")
+	(ashiftrt:HI (match_operand:HI 1 "general_operand")
+		     (match_operand:HI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  {
+    if (msp430x
+        && REG_P (operands[0])
+        && REG_P (operands[1])
+        && CONST_INT_P (operands[2]))
+      emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2]));
+    else		 
+       msp430_expand_helper (operands, \"__mspabi_srai\", true);
+   DONE;
+   }
+)
+
+(define_insn "srai_1"
+  [(set (match_operand:HI              0 "nonimmediate_operand" "=rm")
+	(ashiftrt:HI (match_operand:HI 1 "general_operand"      "0")
+		     (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RRA.W\t%0"
+)
+
+(define_insn "430x_arithmetic_shift_right"
+  [(set (match_operand:HI              0 "register_operand" "=r")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand"  "0")
+		     (match_operand    2 "immediate_operand" "n")))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  "*
+  if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
+    return \"rpt\t%2 { rrax.w\t%0\";
+  return \"# nop arith right shift\";
+  "
+)
+
+(define_insn "srap_1"
+  [(set (match_operand:PSI              0 "register_operand" "=r")
+	(ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
+		      (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  "RRAM.A #1,%0"
+)
+
+(define_insn "srap_2"
+  [(set (match_operand:PSI              0 "register_operand" "=r")
+	(ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
+		      (const_int 2)))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  "RRAM.A #2,%0"
+)
+
+(define_insn "sral_1"
+  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+	(ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
+		     (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RRA.W\t%H0 { RRC.W\t%L0"
+)
+
+(define_insn "sral_2"
+  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+	(ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
+		     (const_int 2)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
+)
+
+(define_expand "ashrsi3"
+  [(set (match_operand:SI              0 "nonimmediate_operand")
+	(ashiftrt:SI (match_operand:SI 1 "general_operand")
+		     (match_operand:SI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "msp430_expand_helper (operands, \"__mspabi_sral\", true);
+   DONE;"
+)
+
+;;----------
+
+;; unsigned A >> C
+
+(define_expand "lshrhi3"
+  [(set (match_operand:HI              0 "nonimmediate_operand")
+	(lshiftrt:HI (match_operand:HI 1 "general_operand")
+		     (match_operand:HI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  {
+    if (msp430x
+        && REG_P (operands[0])
+        && REG_P (operands[1])
+        && CONST_INT_P (operands[2]))
+      emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2]));
+    else		 
+      msp430_expand_helper (operands, \"__mspabi_srli\", true);
+    DONE;
+  }
+)
+
+(define_insn "srli_1"
+  [(set (match_operand:HI              0 "nonimmediate_operand" "=rm")
+	(lshiftrt:HI (match_operand:HI 1 "general_operand"       "0")
+		     (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "CLRC { RRC.W\t%0"
+)
+
+(define_insn "430x_logical_shift_right"
+  [(set (match_operand:HI              0 "register_operand" "=r")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand"  "0")
+		     (match_operand    2 "immediate_operand" "n")))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  {
+    return msp430x_logical_shift_right (operands[2]);
+  }
+)
+
+(define_insn "srlp_1"
+  [(set (match_operand:PSI              0 "register_operand" "=r")
+	(lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
+		      (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "RRUM.A #1,%0"
+)
+
+(define_insn "srll_1"
+  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
+	(lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
+		     (const_int 1)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
+)
+
+(define_insn "srll_2x"
+  [(set (match_operand:SI              0 "nonimmediate_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
+		     (const_int 2)))
+   (clobber (reg:CC CARRY))
+   ]
+  "msp430x"
+  "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
+)
+
+(define_expand "lshrsi3"
+  [(set (match_operand:SI              0 "nonimmediate_operand")
+	(lshiftrt:SI (match_operand:SI 1 "general_operand")
+		     (match_operand:SI 2 "general_operand")))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "msp430_expand_helper (operands, \"__mspabi_srll\", true);
+   DONE;"
+)
+
+;;------------------------------------------------------------
+;; Function Entry/Exit
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "msp430_expand_prologue (); DONE;"
+  )
+
+(define_expand "epilogue"
+  [(const_int 0)]
+  ""
+  "msp430_expand_epilogue (0); DONE;"
+  )
+
+
+(define_insn "epilogue_helper"
+  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)]
+  ""
+  "BR%A0\t#__mspabi_func_epilog_%D0"
+  )
+
+
+(define_insn "prologue_start_marker"
+  [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
+  ""
+  "; start of prologue"
+  )
+
+(define_insn "prologue_end_marker"
+  [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
+  ""
+  "; end of prologue"
+  )
+
+(define_insn "epilogue_start_marker"
+  [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
+  ""
+  "; start of epilogue"
+  )
+
+;;------------------------------------------------------------
+;; Jumps
+
+(define_expand "call"
+  [(call:HI (match_operand 0 "")
+	 (match_operand 1 ""))]
+  ""
+  ""
+)
+
+(define_insn "call_internal"
+  [(call (mem:HI (match_operand 0 "general_operand" "rmi"))
+	 (match_operand 1 ""))]
+  ""
+  "CALL%A0\t%0"
+)
+
+(define_expand "call_value"
+  [(set (match_operand          0 "register_operand")
+	(call:HI (match_operand 1 "general_operand")
+		 (match_operand 2 "")))]
+  ""
+  ""
+)
+
+(define_insn "call_value_internal"
+  [(set (match_operand               0 "register_operand" "=r")
+	(call (mem:HI (match_operand 1 "general_operand" "rmi"))
+	      (match_operand 2 "")))]
+  ""
+  "CALL%A0\t%1"
+)
+
+(define_insn "msp_return"
+  [(return)]
+  ""
+  { return TARGET_LARGE ? "RETA" : "RET"; }
+)
+
+;; This pattern is NOT, as expected, a return pattern.  It's called
+;; before reload and must only store its operands, and emit a
+;; placeholder where the epilog needs to be.  AFTER reload, the
+;; placeholder should get expanded into a regular-type epilogue that
+;; also does the EH return.
+(define_expand "eh_return"
+  [(match_operand:HI 0 "" "")]
+  ""
+  "msp430_expand_eh_return (operands[0]);
+   emit_jump_insn (gen_msp430_eh_epilogue ());
+   emit_barrier ();
+   DONE;"
+)
+
+;; This is the actual EH epilogue.  We emit it in the pattern above,
+;; before reload, and convert it to a real epilogue after reload.
+(define_insn_and_split "msp430_eh_epilogue"
+  [(eh_return)]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "msp430_expand_epilogue (1); DONE;"
+  )
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "BR%A0\t#%l0"
+)
+
+;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
+;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand 0 "nonimmediate_operand" "rYl"))]
+  ""
+  "BR%A0\t%0"
+)
+
+;;------------------------------------------------------------
+;; Various Conditionals
+
+(define_expand "cbranch<mode>4"
+  [(parallel [(set (pc) (if_then_else
+			 (match_operator 0 ""
+					 [(match_operand:QHI 1 "nonimmediate_operand")
+					  (match_operand:QHI 2 "general_operand")])
+			 (label_ref (match_operand 3 "" ""))
+			 (pc)))
+	      (clobber (reg:CC CARRY))]
+  )]
+  ""
+  "msp430_fixup_compare_operands (<MODE>mode, operands);"
+  )
+
+(define_insn "cbranchpsi4_real"
+  [(set (pc) (if_then_else
+	      (match_operator                     0 "msp430_cmp_operator"
+			      [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm")
+			       (match_operand:PSI 2 "general_operand"      "rLs,rYsi,rmi")])
+              (label_ref (match_operand           3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  CMP%A0\t%2, %1 { J%0\t%l3
+  CMPX.A\t%2, %1 { J%0\t%l3
+  CMPX.A\t%2, %1 { J%0\t%l3"
+  )
+
+(define_insn "cbranchqi4_real"
+  [(set (pc) (if_then_else
+	      (match_operator                    0 "msp430_cmp_operator"
+			      [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
+			       (match_operand:QI 2 "general_operand"      "rYsi,rmi")])
+              (label_ref (match_operand          3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   CMP.B\t%2, %1 { J%0\t%l3
+   CMP%X0.B\t%2, %1 { J%0\t%l3"
+  )
+
+(define_insn "cbranchhi4_real"
+  [(set (pc) (if_then_else
+	      (match_operator                    0 "msp430_cmp_operator"
+			      [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
+			       (match_operand:HI 2 "general_operand"      "rYsi,rmi")])
+              (label_ref (match_operand          3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   CMP.W\t%2, %1 { J%0\t%l3
+   CMP%X0.W\t%2, %1 { J%0\t%l3"
+  )
+
+(define_insn "cbranchpsi4_reversed"
+  [(set (pc) (if_then_else
+	      (match_operator                     0 "msp430_reversible_cmp_operator"
+			      [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
+			       (match_operand:PSI 2 "general_operand" "r,rYs,rm")])
+              (label_ref (match_operand           3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+  CMP%A0\t%1, %2 { J%R0\t%l3
+  CMPX.A\t%1, %2 { J%R0\t%l3
+  CMPX.A\t%1, %2 { J%R0\t%l3"
+  )
+
+(define_insn "cbranchqi4_reversed"
+  [(set (pc) (if_then_else
+	      (match_operator                    0 "msp430_reversible_cmp_operator"
+			      [(match_operand:QI 1 "general_operand" "rYsi,rmi")
+			       (match_operand:QI 2 "general_operand" "rYs,rm")])
+              (label_ref (match_operand          3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   CMP.B\t%1, %2 { J%R0\t%l3
+   CMP%X0.B\t%1, %2 { J%R0\t%l3"
+  )
+
+(define_insn "cbranchhi4_reversed"
+  [(set (pc) (if_then_else
+	      (match_operator                    0 "msp430_reversible_cmp_operator"
+			      [(match_operand:HI 1 "general_operand" "rYsi,rmi")
+			       (match_operand:HI 2 "general_operand" "rYs,rm")])
+              (label_ref (match_operand          3 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   CMP.W\t%1, %2 { J%R0\t%l3
+   CMP%X0.W\t%1, %2 { J%R0\t%l3"
+  )
+
+
+(define_insn "*bitbranch<mode>4"
+  [(set (pc) (if_then_else
+	      (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
+			   (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi"))
+		  (const_int 0))
+              (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   BIT%x0%B0\t%1, %0 { JNE\t%l2
+   BIT%X0%B0\t%1, %0 { JNE\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4"
+  [(set (pc) (if_then_else
+	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
+		  (const_int 0))
+              (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%x0%X0%B0\t%1, %0 { JEQ\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4"
+  [(set (pc) (if_then_else
+	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
+		  (const_int 0))
+              (pc)
+	      (label_ref (match_operand 2 "" ""))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%X0%B0\t%1, %0 { JNE\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4"
+  [(set (pc) (if_then_else
+	      (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
+		  (const_int 0))
+              (pc)
+	      (label_ref (match_operand 2 "" ""))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%X0%B0\t%1, %0 { JEQ\t%l2"
+  )
+
+;;------------------------------------------------------------
+;; zero-extend versions of the above
+
+(define_insn "*bitbranch<mode>4_z"
+  [(set (pc) (if_then_else
+	      (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
+				    (const_int 1)
+				    (match_operand 1 "msp430_bitpos" "i,i"))
+		  (const_int 0))
+              (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "@
+   BIT%x0%B0\t%p1, %0 { JNE\t%l2
+   BIT%X0%B0\t%p1, %0 { JNE\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4_z"
+  [(set (pc) (if_then_else
+	      (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+				   (const_int 1)
+				   (match_operand 1 "msp430_bitpos" "i"))
+		  (const_int 0))
+              (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%x0%X0%B0\t%p1, %0 { JEQ\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4_z"
+  [(set (pc) (if_then_else
+	      (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+				   (const_int 1)
+				   (match_operand 1 "msp430_bitpos" "i"))
+		  (const_int 0))
+              (pc)
+	      (label_ref (match_operand 2 "" ""))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%X0%B0\t%p1, %0 { JNE\t%l2"
+  )
+
+(define_insn "*bitbranch<mode>4_z"
+  [(set (pc) (if_then_else
+	      (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+				   (const_int 1)
+				   (match_operand 1 "msp430_bitpos" "i"))
+		  (const_int 0))
+              (pc)
+	      (label_ref (match_operand 2 "" ""))))
+   (clobber (reg:CC CARRY))
+   ]
+  ""
+  "BIT%X0%B0\t%p1, %0 { JEQ\t%l2"
+  )
+
+;;------------------------------------------------------------
+;; Misc
+
+(define_insn "nop"
+  [(const_int 0)]
+  "1"
+  "NOP"
+)
+  
Index: gcc/config/msp430/constraints.md
===================================================================
--- gcc/config/msp430/constraints.md	(revision 0)
+++ gcc/config/msp430/constraints.md	(revision 0)
@@ -0,0 +1,74 @@
+;;  Machine Description for TI MSP43* processors
+;;  Copyright (C) 2013 Free Software Foundation, Inc.
+;;  Contributed by Red Hat.
+
+;; 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/>.
+
+(define_register_constraint "R12" "R12_REGS"
+  "Register R12.")
+
+(define_register_constraint "R13" "R13_REGS"
+  "Register R13.")
+
+(define_constraint "K"
+  "Integer constant 1."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 1, 1)")))
+
+(define_constraint "L"
+  "Integer constant -1^20..1^19."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, -1 << 20, 1 << 19)")))
+
+(define_constraint "M"
+  "Integer constant 1-4."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 1, 4)")))
+
+;; We do not allow arbitrary constants, eg symbols or labels,
+;; because their address may be above the 16-bit address limit
+;; supported by the offset used in the MOVA instruction.
+(define_constraint "Ya"
+  "Memory reference, any type, but restricted range of constants"
+  (and (match_code "mem")
+       (ior (match_code "reg" "0")
+	    (and (match_code "plus" "0")
+		 (match_code "reg" "00")
+		 (match_test ("CONST_INT_P (XEXP (XEXP (op, 0), 1))")))
+	    (match_test "CONSTANT_P (XEXP (op, 0))")
+	    )))
+
+(define_constraint "Yl"
+  "Memory reference, labels only."
+  (and (match_code "mem")
+       (match_code "label_ref" "0")))
+
+
+;; These are memory references that are safe to use with the X suffix,
+;; because we know/assume they need not index across the 64k boundary.
+(define_constraint "Ys"
+  "Memory reference, stack only."
+  (and (match_code "mem")
+       (ior
+	(and (match_code "plus" "0")
+	     (and (match_code "reg" "00")
+		  (match_test ("CONST_INT_P (XEXP (XEXP (op, 0), 1))"))
+		  (match_test ("IN_RANGE (INTVAL (XEXP (XEXP (op, 0), 1)), -1 << 15, (1 << 15)-1)"))))
+	(match_code "reg" "0")
+	)))
+  
+
Index: gcc/config/msp430/t-msp430
===================================================================
--- gcc/config/msp430/t-msp430	(revision 0)
+++ gcc/config/msp430/t-msp430	(revision 0)
@@ -0,0 +1,43 @@
+# Makefile fragment for building GCC for the TI MSP430 target.
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Red Hat.
+#
+# 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/>.
+
+# Enable multilibs:
+
+MULTILIB_OPTIONS    = mmcu=msp430x mlarge
+MULTILIB_DIRNAMES   = 430x large
+
+# Match msp430X with msp430x.
+MULTILIB_MATCHES    = mmcu?msp430x=mmcu?msp430X
+
+# each supported MCU needs a line like this:
+# MULTILIB_MATCHES  += mmcu?msp430x123=mmcu?msp430x
+
+# The only way I figured this out was to hack the script to SHOW me
+# what it's doing.  It's non-obvious, but it matches the directory
+# structure of the multilib tree, but using the options, not the
+# directory names.  A shell CASE statement is generated from these, so
+# the usual CASE wildcards are supported.
+
+MULTILIB_EXCEPTIONS = mlarge
+
+MULTILIB_EXTRA_OPTS =
+
+msp430-c.o: $(srcdir)/config/msp430/msp430-c.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	(revision 0)
+++ gcc/config/msp430/msp430.c	(revision 0)
@@ -0,0 +1,1754 @@
+/* Subroutines used for code generation on TI MSP430 processors.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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 "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "function.h"
+#include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "reload.h"
+#include "df.h"
+#include "ggc.h"
+#include "tm_p.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
+#include "langhooks.h"
+#include "msp430-protos.h"
+#include "dumpfile.h"
+#include "opts.h"
+
+
+
+static void msp430_compute_frame_info (void);
+
+
+
+/* Run-time Target Specification */
+
+bool msp430x = false;
+
+struct GTY(()) machine_function
+{
+  /* If set, the rest of the fields have been computed.  */
+  int computed;
+  /* Which registers need to be saved in the pro/epilogue.  */
+  int need_to_save [FIRST_PSEUDO_REGISTER];
+
+  /* These fields describe the frame layout...  */
+  /* arg pointer */
+  /* 2/4 bytes for saved PC */
+  int framesize_regs;
+  /* frame pointer */
+  int framesize_locals;
+  int framesize_outgoing;
+  /* stack pointer */
+  int framesize;
+
+  /* How much we adjust the stack when returning from an exception
+     handler.  */
+  rtx eh_stack_adjust;
+};
+
+/* This is our init_machine_status, as set in
+   msp_option_override.  */
+static struct machine_function *
+msp430_init_machine_status (void)
+{
+  struct machine_function *m;
+
+  m = ggc_alloc_cleared_machine_function ();
+
+  return m;
+}
+
+#undef  TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION msp430_handle_option
+
+bool
+msp430_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
+		      struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+		      const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
+		      location_t loc ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+#undef  TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE		msp430_option_override
+
+static void
+msp430_option_override (void)
+{
+  init_machine_status = msp430_init_machine_status;
+
+  if (target_cpu
+      && (strstr (target_cpu, "430x")
+	  || strstr (target_cpu, "430X")))
+    msp430x = true;
+
+  if (TARGET_LARGE && !msp430x)
+    error ("-mlarge requires a 430X-compatible -mcpu=");
+
+  if (flag_exceptions || flag_non_call_exceptions
+      || flag_unwind_tables || flag_asynchronous_unwind_tables)
+    flag_omit_frame_pointer = false;
+  else
+    flag_omit_frame_pointer = true;
+
+  /* This is a hack to work around a problem with the newlib build
+     mechanism.  Newlib always appends CFLAGS to the end of the GCC
+     command line and always sets -O2 in CFLAGS.  Thus it is not
+     possible to build newlib with -Os enabled.  Until now...  */
+  if (TARGET_OPT_SPACE && optimize < 3)
+    optimize_size = 1;
+}
+
+
+
+/* Storage Layout */
+
+#undef  TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
+
+bool
+msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+
+
+/* Register Usage */
+
+/* Implements HARD_REGNO_NREGS.  MSP430X registers can hold a single
+   PSImode value, but not an SImode value.  */
+int
+msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
+			 enum machine_mode mode)
+{
+  if (mode == PSImode && msp430x)
+    return 1;
+  return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+	  / UNITS_PER_WORD);
+}
+
+/* Implements HARD_REGNO_MODE_OK.  */
+int
+msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
+			   enum machine_mode mode)
+{
+  return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
+}
+
+/* Implements MODES_TIEABLE_P.  */
+bool
+msp430_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+  if ((mode1 == PSImode || mode2 == SImode)
+      || (mode1 == SImode || mode2 == PSImode))
+    return false;
+
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
+
+#undef  TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
+
+static bool
+msp430_frame_pointer_required (void)
+{
+  return false;
+}
+
+#undef  TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE		msp430_can_eliminate
+
+static bool
+msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
+		      const int to_reg ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+/* Implements INITIAL_ELIMINATION_OFFSET.  */
+int
+msp430_initial_elimination_offset (int from ATTRIBUTE_UNUSED,
+				   int to ATTRIBUTE_UNUSED)
+{
+  int rv = 0; /* as if arg to arg */
+
+  msp430_compute_frame_info ();
+
+  switch (to)
+    {
+    case STACK_POINTER_REGNUM:
+      rv += cfun->machine->framesize_outgoing;
+      rv += cfun->machine->framesize_locals;
+      /* Fall through.  */
+    case FRAME_POINTER_REGNUM:
+      rv += cfun->machine->framesize_regs;
+      /* Allow for the saved return address.  */
+      rv += (TARGET_LARGE ? 4 : 2);
+      /* NB/ No need to allow for crtl->args.pretend_args_size.
+         GCC does that for us.  */
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  switch (from)
+    {
+    case FRAME_POINTER_REGNUM:
+      /* Allow for the fall through above.  */
+      rv -= (TARGET_LARGE ? 4 : 2);
+      rv -= cfun->machine->framesize_regs;
+    case ARG_POINTER_REGNUM:
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return rv;
+}
+
+/* Named Address Space support */
+
+
+/* Return the appropriate mode for a named address pointer.  */
+#undef  TARGET_ADDR_SPACE_POINTER_MODE
+#define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
+#undef  TARGET_ADDR_SPACE_ADDRESS_MODE
+#define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
+
+static enum machine_mode
+msp430_addr_space_pointer_mode (addr_space_t addrspace)
+{
+  switch (addrspace)
+    {
+    default:
+    case ADDR_SPACE_GENERIC:
+      return Pmode;
+    case ADDR_SPACE_NEAR:
+      return HImode;
+    case ADDR_SPACE_FAR:
+      return PSImode;
+    }
+}
+
+/* Function pointers are stored in unwind_word sized
+   variables, so make sure that unwind_word is big enough.  */
+#undef  TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
+
+static enum machine_mode
+msp430_unwind_word_mode (void)
+{
+  return TARGET_LARGE ? SImode : HImode;
+}
+
+/* Determine if one named address space is a subset of another.  */
+#undef  TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
+static bool
+msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
+{
+  if (subset == superset)
+    return true;
+  else
+    return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
+}
+
+#undef  TARGET_ADDR_SPACE_CONVERT
+#define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
+/* Convert from one address space to another.  */
+static rtx
+msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
+{
+  addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
+  addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
+  rtx result;
+
+  if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
+    {
+      /* This is unpredictable, as we're truncating off usable address
+	 bits.  */
+
+      if (CONSTANT_P (op))
+	return gen_rtx_CONST (HImode, op);
+
+      result = gen_reg_rtx (HImode);
+      emit_insn (gen_truncpsihi2 (result, op));
+      return result;
+    }
+  else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
+    {
+      /* This always works.  */
+
+      if (CONSTANT_P (op))
+	return gen_rtx_CONST (PSImode, op);
+
+      result = gen_reg_rtx (PSImode);
+      emit_insn (gen_zero_extendhipsi2 (result, op));
+      return result;
+    }
+  else
+    gcc_unreachable ();
+}
+
+/* Stack Layout and Calling Conventions.  */
+
+/* For each function, we list the gcc version and the TI version on
+   each line, where we're converting the function names.  */
+static char const * const special_convention_function_names [] =
+{
+  "__muldi3", "__mspabi_mpyll",
+  "__udivdi3", "__mspabi_divull",
+  "__umoddi3", "__mspabi_remull",
+  "__divdi3", "__mspabi_divlli",
+  "__moddi3", "__mspabi_remlli",
+  "__mspabi_srall",
+  "__mspabi_srlll",
+  "__mspabi_sllll",
+  "__adddf3", "__mspabi_addd",
+  "__subdf3", "__mspabi_subd",
+  "__muldf3", "__mspabi_mpyd",
+  "__divdf3", "__mspabi_divd",
+  "__mspabi_cmpd",
+  NULL
+};
+
+/* TRUE if the function passed is a "speical" function.  Special
+   functions pass two DImode parameters in registers.  */
+static bool
+msp430_special_register_convention_p (const char *name)
+{
+  int i;
+
+  for (i = 0; special_convention_function_names [i]; i++)
+    if (! strcmp (name, special_convention_function_names [i]))
+      return true;
+
+  return false;
+}
+
+#undef  TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
+
+bool
+msp430_function_value_regno_p (unsigned int regno)
+{
+  return regno == 12;
+}
+
+
+#undef  TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE msp430_function_value
+
+rtx
+msp430_function_value (const_tree ret_type,
+		       const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+		       bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE (ret_type), 12);
+}
+
+#undef  TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE msp430_libcall_value
+
+rtx
+msp430_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, 12);
+}
+
+/* Implements INIT_CUMULATIVE_ARGS.  */
+void
+msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
+			     tree fntype ATTRIBUTE_UNUSED,
+			     rtx libname ATTRIBUTE_UNUSED,
+			     tree fndecl ATTRIBUTE_UNUSED,
+			     int n_named_args ATTRIBUTE_UNUSED)
+{
+  const char *fname;
+  memset (ca, 0, sizeof(*ca));
+
+  ca->can_split = 1;
+
+  if (fndecl)
+    fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+  else if (libname)
+    fname = XSTR (libname, 0);
+  else
+    fname = NULL;
+
+  if (fname && msp430_special_register_convention_p (fname))
+    ca->special_p = 1;
+}
+
+/* Helper function for argument passing; this function is the common
+   code that determines where an argument will be passed.  */
+static void
+msp430_evaluate_arg (cumulative_args_t cap,
+		     enum machine_mode mode,
+		     const_tree type ATTRIBUTE_UNUSED,
+		     bool named)
+{
+  CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
+  int nregs = GET_MODE_SIZE (mode);
+  int i;
+
+  ca->reg_count = 0;
+  ca->mem_count = 0;
+
+  if (!named)
+    return;
+
+  if (mode == PSImode)
+    nregs = 1;
+  else
+    nregs = (nregs + 1) / 2;
+
+  if (ca->special_p)
+    {
+      /* Function is passed two DImode operands, in R8:R11 and
+	 R12:15.  */
+      ca->start_reg = 8;
+      ca->reg_count = 4;
+      return;
+    }
+
+  switch (nregs)
+    {
+    case 1:
+      for (i = 0; i < 4; i++)
+	if (! ca->reg_used [i])
+	  {
+	    ca->reg_count = 1;
+	    ca->start_reg = CA_FIRST_REG + i;
+	    return;
+	  }
+      break;
+    case 2:
+      for (i = 0; i < 3; i++)
+	if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
+	  {
+	    ca->reg_count = 2;
+	    ca->start_reg = CA_FIRST_REG + i;
+	    return;
+	  }
+      if (! ca->reg_used [3] && ca->can_split)
+	{
+	  ca->reg_count = 1;
+	  ca->mem_count = 2;
+	  ca->start_reg = CA_FIRST_REG + 3;
+	  return;
+	}
+      break;
+    case 3:
+    case 4:
+      ca->can_split = 0;
+      if (! ca->reg_used [0]
+	  && ! ca->reg_used [1]
+	  && ! ca->reg_used [2]
+	  && ! ca->reg_used [3])
+	{
+	  ca->reg_count = 4;
+	  ca->start_reg = CA_FIRST_REG;
+	  return;
+	}
+      break;
+    }
+}
+
+#undef  TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
+
+bool
+msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+#undef  TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG msp430_function_arg
+
+rtx
+msp430_function_arg (cumulative_args_t cap,
+		     enum machine_mode mode,
+		     const_tree type,
+		     bool named)
+{
+  CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
+
+  msp430_evaluate_arg (cap, mode, type, named);
+
+  if (ca->reg_count)
+    return gen_rtx_REG (mode, ca->start_reg);
+
+  return 0;
+}
+
+#undef  TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
+
+int
+msp430_arg_partial_bytes (cumulative_args_t cap,
+			  enum machine_mode mode,
+			  tree type,
+			  bool named)
+{
+  CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
+
+  msp430_evaluate_arg (cap, mode, type, named);
+
+  if (ca->reg_count && ca->mem_count)
+    return ca->reg_count * UNITS_PER_WORD;
+
+  return 0;
+}
+
+#undef  TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
+
+static bool
+msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
+			  enum machine_mode mode,
+			  const_tree type,
+			  bool named ATTRIBUTE_UNUSED)
+{
+  return (mode == BLKmode
+	  || (type && TREE_CODE (type) == RECORD_TYPE)
+	  || (type && TREE_CODE (type) == UNION_TYPE));
+}
+
+#undef  TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES msp430_callee_copies
+
+static bool
+msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
+                     enum machine_mode mode ATTRIBUTE_UNUSED,
+                     const_tree type ATTRIBUTE_UNUSED,
+                     bool named ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+#undef  TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
+
+void
+msp430_function_arg_advance (cumulative_args_t cap,
+			     enum machine_mode mode,
+			     const_tree type,
+			     bool named)
+{
+  CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
+  int i;
+
+  msp430_evaluate_arg (cap, mode, type, named);
+
+  if (ca->start_reg >= CA_FIRST_REG)
+    for (i = 0; i < ca->reg_count; i ++)
+      ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
+
+  ca->special_p = 0;
+}
+
+#undef  TARGET_FUNCTION_ARG_BOUNDARY
+#define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
+
+static unsigned int
+msp430_function_arg_boundary (enum machine_mode mode, const_tree type)
+{
+  if (mode == BLKmode
+      && int_size_in_bytes (type) > 1)
+    return 16;
+  if (GET_MODE_BITSIZE (mode) > 8)
+    return 16;
+  return 8;
+}
+
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
+
+static bool
+msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode = TYPE_MODE (ret_type);
+
+  if (mode == BLKmode
+      || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
+      || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
+    return true;
+
+  if (GET_MODE_SIZE (mode) > 8)
+    return true;
+
+  return false;
+}
+
+#undef  TARGET_GET_RAW_ARG_MODE
+#define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
+
+static enum machine_mode
+msp430_get_raw_arg_mode (int regno)
+{
+  return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
+}
+
+#undef  TARGET_GET_RAW_RESULT_MODE
+#define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
+
+static enum machine_mode
+msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
+{
+  return Pmode;
+}
+
+/* Addressing Modes */
+
+#undef  TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
+
+static bool
+reg_ok_for_addr (rtx r, bool strict)
+{
+  int rn = REGNO (r);
+
+  if (strict && rn >= FIRST_PSEUDO_REGISTER)
+    rn = reg_renumber [rn];
+  if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
+    return true;
+  if (!strict)
+    return true;
+  return false;
+}
+
+bool
+msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			     rtx x ATTRIBUTE_UNUSED,
+			     bool strict ATTRIBUTE_UNUSED)
+{
+  switch (GET_CODE (x))
+    {
+    case MEM:
+      return false;
+
+    case PLUS:
+      if (REG_P (XEXP (x, 0)))
+	{
+	  if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
+	    return false;
+	  if (!reg_ok_for_addr (XEXP (x, 0), strict))
+	    return false;
+	  switch (GET_CODE (XEXP (x, 1)))
+	    {
+	    case CONST:
+	    case SYMBOL_REF:
+	    case CONST_INT:
+	      return true;
+	    default:
+	      return false;
+	    }
+	}
+      return false;
+
+    case REG:
+      if (!reg_ok_for_addr (x, strict))
+	return false;
+      /* else... */
+    case CONST:
+    case SYMBOL_REF:
+    case CONST_INT:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+#undef  TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
+
+static bool
+msp430_legitimate_constant (enum machine_mode mode, rtx x)
+{
+  return ! CONST_INT_P (x)
+    || mode != PSImode
+    /* GCC does not know the width of the PSImode, so make
+       sure that it does not try to use a constant value that
+       is out of range.  */
+    || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20));
+}
+
+
+#undef  TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS msp430_rtx_costs
+
+static bool msp430_rtx_costs (rtx   x ATTRIBUTE_UNUSED,
+			      int   code,
+			      int   outer_code ATTRIBUTE_UNUSED,
+			      int   opno ATTRIBUTE_UNUSED,
+			      int * total,
+			      bool  speed ATTRIBUTE_UNUSED)
+{
+  switch (code)
+    {
+    case SIGN_EXTEND:
+      if (GET_MODE (x) == SImode && outer_code == SET)
+	{
+	  *total = COSTS_N_INSNS (4);
+	  return true;
+	}
+      break;
+    case ASHIFT:
+    case ASHIFTRT:
+    case LSHIFTRT:
+      if (!msp430x)
+	{
+	  *total = COSTS_N_INSNS (100);
+	  return true;
+	}
+      break;
+    }
+  return false;
+}
+
+/* Function Entry and Exit */
+
+/* The MSP430 call frame looks like this:
+
+   <higher addresses>
+   +--------------------+
+   |                    |
+   | Stack Arguments    |
+   |                    |
+   +--------------------+ <-- "arg pointer"
+   |                    |
+   | PC from call       |  (2 bytes for 430, 4 for TARGET_LARGE)
+   |                    |
+   +--------------------+  <-- SP before prologue, also AP
+   |                    |
+   | Saved Regs         |  (2 bytes per reg for 430, 4 per for TARGET_LARGE)
+   |                    |
+   +--------------------+  <-- "frame pointer"
+   |                    |
+   | Locals             |
+   |                    |
+   +--------------------+
+   |                    |
+   | Outgoing Args      |
+   |                    |
+   +--------------------+  <-- SP during function
+   <lower addresses>
+
+*/
+
+/* We use this to wrap all emitted insns in the prologue, so they get
+   the "frame-related" (/f) flag set.  */
+static rtx
+F (rtx x)
+{
+  RTX_FRAME_RELATED_P (x) = 1;
+  return x;
+}
+
+/* This is the one spot that decides if a register is to be saved and
+   restored in the prologue/epilogue.  */
+static bool
+msp430_preserve_reg_p (int regno)
+{
+  /* PC, SP, SR, and the constant generator.  */
+  if (regno <= 3)
+    return false;
+
+  /* FIXME: add interrupt, EH, etc.  */
+  if (crtl->calls_eh_return)
+    return true;
+
+  /* Shouldn't be more than the above, but just in case...  */
+  if (fixed_regs [regno])
+    return false;
+
+  if (!call_used_regs [regno]
+      && df_regs_ever_live_p (regno))
+    return true;
+
+  return false;
+}
+
+/* Compute all the frame-related fields in our machine_function
+   structure.  */
+static void
+msp430_compute_frame_info (void)
+{
+  int i;
+
+  cfun->machine->computed = 1;
+  cfun->machine->framesize_regs = 0;
+  cfun->machine->framesize_locals = get_frame_size ();
+  cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
+
+  for (i = 0; i < 16; i ++)
+    if (msp430_preserve_reg_p (i))
+      {
+	cfun->machine->need_to_save [i] = 1;
+	cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
+      }
+    else
+      cfun->machine->need_to_save [i] = 0;
+
+  if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
+    cfun->machine->framesize_locals ++;
+
+  cfun->machine->framesize = (cfun->machine->framesize_regs
+			      + cfun->machine->framesize_locals
+			      + cfun->machine->framesize_outgoing);
+}
+
+#undef  TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE	msp430_start_function
+
+static void
+msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
+{
+  int r, n;
+
+  fprintf (outfile, "; start of function\n");
+  fprintf (outfile, "; framesize_regs:     %d\n", cfun->machine->framesize_regs);
+  fprintf (outfile, "; framesize_locals:   %d\n", cfun->machine->framesize_locals);
+  fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
+  fprintf (outfile, "; framesize:          %d\n", cfun->machine->framesize);
+  fprintf (outfile, "; elim ap -> fp       %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
+  fprintf (outfile, "; elim fp -> sp       %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
+
+  n = 0;
+  fprintf (outfile, "; saved regs:");
+  for (r = 0; r < 16; r++)
+    if (cfun->machine->need_to_save [r])
+      {
+	fprintf (outfile, " %s", reg_names [r]);
+	n = 1;
+      }
+  if (n == 0)
+    fprintf (outfile, "(none)");
+  fprintf (outfile, "\n");
+}
+
+/* Common code to change the stack pointer.  */
+static void
+increment_stack (HOST_WIDE_INT amount)
+{
+  rtx inc;
+  rtx sp =  stack_pointer_rtx;
+
+  if (amount == 0)
+    return;
+
+  if (amount < 0)
+    {
+      inc = GEN_INT (- amount);
+      if (TARGET_LARGE)
+	F (emit_insn (gen_subpsi3 (sp, sp, inc)));
+      else
+	F (emit_insn (gen_subhi3 (sp, sp, inc)));
+    }
+  else
+    {
+      inc = GEN_INT (amount);
+      if (TARGET_LARGE)
+	emit_insn (gen_addpsi3 (sp, sp, inc));
+      else
+	emit_insn (gen_addhi3 (sp, sp, inc));
+    }
+}
+
+void
+msp430_expand_prologue (void)
+{
+  int i, j;
+  int fs;
+  /* Always use stack_pointer_rtx instead of calling
+     rtx_gen_REG ourselves.  Code elsewhere in GCC assumes
+     that there is a single rtx representing the stack pointer,
+     namely stack_pointer_rtx, and uses == to recognize it.  */
+  rtx sp = stack_pointer_rtx;
+  rtx p;
+
+  emit_insn (gen_prologue_start_marker ());
+
+  if (!cfun->machine->computed)
+    msp430_compute_frame_info ();
+
+  if (flag_stack_usage_info)
+    current_function_static_stack_size = cfun->machine->framesize;
+  
+  if (crtl->args.pretend_args_size)
+    {
+      rtx note;
+
+      gcc_assert (crtl->args.pretend_args_size == 2);
+      
+      p = emit_insn (gen_grow_and_swap ());
+
+      /* Document the stack decrement...  */
+      note = F (gen_rtx_SET (Pmode, stack_pointer_rtx,
+			     gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
+      add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
+
+      /* ...and the establishment of a new location for the return address.  */
+      note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode,
+						 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))),
+			     pc_rtx));
+      add_reg_note (p, REG_CFA_OFFSET, note);
+      F (p);
+    }
+
+  for (i = 15; i >= 4; i--)
+    if (cfun->machine->need_to_save [i])
+      {
+	int seq, count;
+	rtx note;
+
+	for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
+	  ;
+	count = i - seq;
+
+	if (msp430x)
+	  {
+	    /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger.  */
+	    p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
+					 GEN_INT (count))));
+
+	    note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
+
+	    XVECEXP (note, 0, 0)
+	      = F (gen_rtx_SET (VOIDmode,
+			     stack_pointer_rtx,
+			     gen_rtx_PLUS (Pmode,
+					   stack_pointer_rtx,
+					   GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
+
+	    /* *sp-- = R[i-j] */
+	    /* sp+N	R10
+	       ...
+	       sp	R4  */
+	    for (j = 0; j < count; j ++)
+	      {
+		rtx addr;
+		int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
+
+		if (ofs)
+		  addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
+		else
+		  addr = stack_pointer_rtx;
+
+		XVECEXP (note, 0, j + 1) = 
+		  F (gen_rtx_SET (VOIDmode,
+				  gen_rtx_MEM (Pmode, addr),
+				  gen_rtx_REG (Pmode, i - j)) );
+	      }
+
+	    add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
+	    i -= count - 1;
+	  }
+	else
+	  F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
+      }
+
+  if (frame_pointer_needed)
+    F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
+
+  fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
+
+  increment_stack (- fs);
+
+  emit_insn (gen_prologue_end_marker ());
+}
+
+void
+msp430_expand_epilogue (int is_eh)
+{
+  int i;
+  int fs;
+  int helper_n = 0;
+
+  if (cfun->machine->need_to_save [10])
+    {
+      /* Check for a helper function.  */
+      helper_n = 7; /* for when the loop below never sees a match.  */
+      for (i = 9; i >= 4; i--)
+	if (!cfun->machine->need_to_save [i])
+	  {
+	    helper_n = 10 - i;
+	    for (; i >= 4; i--)
+	      if (cfun->machine->need_to_save [i])
+		{
+		  helper_n = 0;
+		  break;
+		}
+	    break;
+	  }
+    }
+
+  emit_insn (gen_epilogue_start_marker ());
+
+  fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
+
+  increment_stack (fs);
+
+  if (is_eh)
+    {
+      /* We need to add the right "SP" register save just after the
+	 regular ones, so that when we pop it off we're in the EH
+	 return frame, not this one.  This overwrites our own return
+	 address, but we're not going to be returning anyway.  */
+      rtx r12 = gen_rtx_REG (Pmode, 12);
+      rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
+
+      /* R12 will hold the new SP.  */
+      i = cfun->machine->framesize_regs;
+      emit_move_insn (r12, stack_pointer_rtx);
+      emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
+      emit_insn (addPmode (r12, r12, GEN_INT (i)));
+      emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
+    }
+
+  for (i = 4; i <= 15; i++)
+    if (cfun->machine->need_to_save [i])
+      {
+	int seq, count;
+
+	for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
+	  ;
+	count = seq - i;
+
+	if (msp430x)
+	  {
+	    /* Note: With TARGET_LARGE we still use POPM as POPX.A is two
+	       bytes bigger.
+	       Note: See the popm pattern for the explanation of the strange
+	       arguments.  */
+	    emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
+				 GEN_INT (count)));
+	    i += count - 1;
+	  }
+	else if (i == 11 - helper_n
+		 && crtl->args.pretend_args_size == 0
+		 /* Calling the helper takes as many bytes as the POP;RET sequence.  */
+		 && helper_n != 1
+		 && !is_eh)
+	  {
+	    emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
+	    return;
+	  }
+	else
+	  emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
+      }
+
+  if (is_eh)
+    {
+      /* Also pop SP, which puts us into the EH return frame.  Except
+	 that you can't "pop" sp, you have to just load it off the
+	 stack.  */
+      emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
+    }
+
+  if (crtl->args.pretend_args_size)
+    emit_insn (gen_swap_and_shrink ());
+    
+  emit_jump_insn (gen_msp_return ());
+}
+
+/* Implements EH_RETURN_STACKADJ_RTX.  Saved and used later in
+   m32c_emit_eh_epilogue.  */
+rtx
+msp430_eh_return_stackadj_rtx (void)
+{
+  if (!cfun->machine->eh_stack_adjust)
+    {
+      rtx sa;
+
+      sa = gen_rtx_REG (Pmode, 15);
+      cfun->machine->eh_stack_adjust = sa;
+    }
+  return cfun->machine->eh_stack_adjust;
+}
+
+/* This function is called before reload, to "fix" the stack in
+   preparation for an EH return.  */
+void
+msp430_expand_eh_return (rtx eh_handler)
+{
+  /* These are all Pmode */
+  rtx ap, sa, ra, tmp;
+
+  ap = arg_pointer_rtx;
+  sa = msp430_eh_return_stackadj_rtx ();
+  ra = eh_handler;
+
+  tmp = ap;
+  tmp = gen_rtx_PLUS (Pmode, ap, sa);
+  tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
+  tmp = gen_rtx_MEM (Pmode, tmp);
+  emit_move_insn (tmp, ra);
+}
+
+/* This is a list of MD patterns that implement fixed-count shifts.  */
+static struct {
+  const char *name;
+  int count;
+  int need_430x;
+  rtx (*genfunc)(rtx,rtx);
+} const_shift_helpers[] = {
+#define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
+
+  CSH ("slli", 1, 1, slli_1),
+  CSH ("slll", 1, 1, slll_1),
+  CSH ("slll", 2, 1, slll_2),
+
+  CSH ("srai", 1, 0, srai_1),
+  CSH ("sral", 1, 0, sral_1),
+  CSH ("sral", 2, 0, sral_2),
+
+  CSH ("srll", 1, 0, srll_1),
+  CSH ("srll", 2, 1, srll_2x),
+  { 0, 0, 0, 0 }
+#undef CSH
+};
+
+/* The MSP430 ABI defines a number of helper functions that should be
+   used for, for example, 32-bit shifts.  This function is called to
+   emit such a function, using the table above to optimize some
+   cases.  */
+void
+msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
+{
+  rtx c, f;
+  char *helper_const = NULL;
+  int arg2 = 13;
+  int arg1sz = 1;
+  enum machine_mode arg0mode = GET_MODE (operands[0]);
+  enum machine_mode arg1mode = GET_MODE (operands[1]);
+  enum machine_mode arg2mode = GET_MODE (operands[2]);
+  int have_430x = msp430x ? 1 : 0;
+
+  if (CONST_INT_P (operands[2]))
+    {
+      int i;
+
+      for (i=0; const_shift_helpers[i].name; i++)
+	{
+	  if (const_shift_helpers[i].need_430x <= have_430x
+	      && strcmp (helper_name, const_shift_helpers[i].name) == 0
+	      && INTVAL (operands[2]) == const_shift_helpers[i].count)
+	    {
+	      emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
+	      return;
+	    }
+	}
+    }
+
+  if (arg1mode == VOIDmode)
+    arg1mode = arg0mode;
+  if (arg2mode == VOIDmode)
+    arg2mode = arg0mode;
+
+  if (arg1mode == SImode)
+    {
+      arg2 = 14;
+      arg1sz = 2;
+    }
+
+  if (const_variants
+      && CONST_INT_P (operands[2])
+      && INTVAL (operands[2]) >= 1
+      && INTVAL (operands[2]) <= 15)
+    {
+      /* Note that the INTVAL is limited in value and length by the conditional above.  */
+      int len = strlen (helper_name) + 4;
+      helper_const = (char *) xmalloc (len);
+      snprintf (helper_const, len, "%s_%ld", helper_name, (int) INTVAL (operands[2]));
+    }
+
+  emit_move_insn (gen_rtx_REG (arg1mode, 12),
+		  operands[1]);
+  if (!helper_const)
+    emit_move_insn (gen_rtx_REG (arg2mode, arg2),
+		    operands[2]);
+
+  c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
+			       gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
+			       GEN_INT (0));
+  c = emit_call_insn (c);
+  RTL_CONST_CALL_P (c) = 1;
+
+  f = 0;
+  use_regs (&f, 12, arg1sz);
+  if (!helper_const)
+    use_regs (&f, arg2, 1);
+  add_function_usage_to (c, f);
+
+  emit_move_insn (operands[0],
+		  gen_rtx_REG (arg0mode, 12));
+}
+
+/* Called by cbranch<mode>4 to coerce operands into usable forms.  */
+void
+msp430_fixup_compare_operands (enum machine_mode my_mode, rtx * operands)
+{
+  /* constants we're looking for, not constants which are allowed.  */
+  int const_op_idx = 1;
+
+  if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
+    const_op_idx = 2;
+
+  if (GET_CODE (operands[const_op_idx]) != REG
+      && GET_CODE (operands[const_op_idx]) != MEM)
+    operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
+}
+
+/* Simplify_gen_subreg() doesn't handle memory references the way we
+   need it to below, so we use this function for when we must get a
+   valid subreg in a "natural" state.  */
+rtx
+msp430_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
+{
+  rtx rv;
+
+  if (GET_CODE (r) == SUBREG
+      && SUBREG_BYTE (r) == 0)
+    {
+      rtx ireg = SUBREG_REG (r);
+      enum machine_mode imode = GET_MODE (ireg);
+
+      /* special case for (HI (SI (PSI ...), 0)) */
+      if (imode == PSImode
+	  && mode == HImode
+	  && byte == 0)
+	rv = gen_rtx_SUBREG (mode, ireg, byte);
+      else
+	rv = simplify_gen_subreg (mode, ireg, imode, byte);
+    }
+  else if (GET_CODE (r) == MEM)
+    rv = adjust_address (r, mode, byte);
+  else
+    rv = simplify_gen_subreg (mode, r, omode, byte);
+
+  if (!rv)
+    gcc_unreachable ();
+
+  return rv;
+}
+
+/* Called by movsi_x to generate the HImode operands.  */
+void
+msp430_split_movsi (rtx *operands)
+{
+  rtx op00, op02, op10, op12;
+
+  op00 = msp430_subreg (HImode, operands[0], SImode, 0);
+  op02 = msp430_subreg (HImode, operands[0], SImode, 2);
+
+  if (GET_CODE (operands[1]) == CONST
+      || GET_CODE (operands[1]) == SYMBOL_REF)
+    {
+      op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
+      op10 = gen_rtx_CONST (HImode, op10);
+      op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
+      op12 = gen_rtx_CONST (HImode, op12);
+    }
+  else
+    {
+      op10 = msp430_subreg (HImode, operands[1], SImode, 0);
+      op12 = msp430_subreg (HImode, operands[1], SImode, 2);
+    }
+
+  if (rtx_equal_p (operands[0], operands[1]))
+    {
+      operands[2] = op02;
+      operands[4] = op12;
+      operands[3] = op00;
+      operands[5] = op10;
+    }
+  else if (rtx_equal_p (op00, op12)
+	   /* Catch the case where we are loading (rN, rN+1) from mem (rN).  */
+	   || (REG_P (op00) && reg_mentioned_p (op00, op10))
+	   /* Or storing (rN) into mem (rN).  */
+	   || (REG_P (op10) && reg_mentioned_p (op10, op00))
+	   )
+    {
+      operands[2] = op02;
+      operands[4] = op12;
+      operands[3] = op00;
+      operands[5] = op10;
+    }
+  else
+    {
+      operands[2] = op00;
+      operands[4] = op10;
+      operands[3] = op02;
+      operands[5] = op12;
+    }
+}
+
+
+
+/* The MSPABI specifies the names of various helper functions, many of
+   which are compatible with GCC's helpers.  This table maps the GCC
+   name to the MSPABI name.  */
+static const struct
+{
+  char const * const gcc_name;
+  char const * const ti_name;
+}
+  helper_function_name_mappings [] =
+{
+  /* Floating point to/from integer conversions.  */
+  { "__truncdfsf2", "__mspabi_cvtdf" },
+  { "__extendsfdf2", "__mspabi_cvtfd" },
+  { "__fixdfhi", "__mspabi_fixdi" },
+  { "__fixdfsi", "__mspabi_fixdli" },
+  { "__fixdfdi", "__mspabi_fixdlli" },
+  { "__fixunsdfhi", "__mspabi_fixdu" },
+  { "__fixunsdfsi", "__mspabi_fixdul" },
+  { "__fixunsdfdi", "__mspabi_fixdull" },
+  { "__fixsfhi", "__mspabi_fixfi" },
+  { "__fixsfsi", "__mspabi_fixfli" },
+  { "__fixsfdi", "__mspabi_fixflli" },
+  { "__fixunsfhi", "__mspabi_fixfu" },
+  { "__fixunsfsi", "__mspabi_fixful" },
+  { "__fixunsfdi", "__mspabi_fixfull" },
+  { "__floathisf", "__mspabi_fltif" },
+  { "__floatsisf", "__mspabi_fltlif" },
+  { "__floatdisf", "__mspabi_fltllif" },
+  { "__floathidf", "__mspabi_fltid" },
+  { "__floatsidf", "__mspabi_fltlid" },
+  { "__floatdidf", "__mspabi_fltllid" },
+  { "__floatunhisf", "__mspabi_fltuf" },
+  { "__floatunsisf", "__mspabi_fltulf" },
+  { "__floatundisf", "__mspabi_fltullf" },
+  { "__floatunhidf", "__mspabi_fltud" },
+  { "__floatunsidf", "__mspabi_fltuld" },
+  { "__floatundidf", "__mspabi_fltulld" },
+
+  /* Floating point comparisons.  */
+  /* GCC uses individual functions for each comparison, TI uses one
+     compare <=> function.  */
+
+  /* Floating point arithmatic */
+  { "__adddf3", "__mspabi_addd" },
+  { "__addsf3", "__mspabi_addf" },
+  { "__divdf3", "__mspabi_divd" },
+  { "__divsf3", "__mspabi_divf" },
+  { "__muldf3", "__mspabi_mpyd" },
+  { "__mulsf3", "__mspabi_mpyf" },
+  { "__subdf3", "__mspabi_subd" },
+  { "__subsf3", "__mspabi_subf" },
+  /* GCC does not use helper functions for negation */
+
+  /* Integer multiply, divide, remainder.  */
+  /* Note: gcc doesn't know about hardware multiply options (yet?)  */
+  { "__mulhi3", "__mspabi_mpyi" },
+  { "__mulsi3", "__mspabi_mpyl" },
+  { "__muldi3", "__mspabi_mpyll" },
+#if 0
+  /* Clarify signed vs unsigned first.  */
+  { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
+  { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
+#endif
+
+  { "__divhi3", "__mspabi_divi" },
+  { "__divsi3", "__mspabi_divli" },
+  { "__divdi3", "__mspabi_divlli" },
+  { "__udivhi3", "__mspabi_divu" },
+  { "__udivsi3", "__mspabi_divlu" },
+  { "__udivdi3", "__mspabi_divllu" },
+  { "__modhi3", "__mspabi_remi" },
+  { "__modsi3", "__mspabi_remli" },
+  { "__moddi3", "__mspabi_remlli" },
+  { "__umodhi3", "__mspabi_remu" },
+  { "__umodsi3", "__mspabi_remul" },
+  { "__umoddi3", "__mspabi_remull" },
+
+  /* Bitwise operations.  */
+  /* Rotation - no rotation support yet.  */
+  /* Logical left shift - gcc already does these itself.  */
+  /* Arithmetic left shift - gcc already does these itself.  */
+  /* Arithmetic right shift - gcc already does these itself.  */
+
+  { NULL, NULL }
+};
+
+/* This function does the same as the default, but it will replace GCC
+   function names with the MSPABI-specified ones.  */
+void
+msp430_output_labelref (FILE *file, const char *name)
+{
+  int i;
+
+  for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
+    if (! strcmp (helper_function_name_mappings [i].gcc_name, name))
+      {
+	fputs (helper_function_name_mappings [i].ti_name, file);
+	return;
+      }
+
+  fputs (name, file);
+}
+
+#undef  TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND		msp430_print_operand
+
+/* Common code for msp430_print_operand().  */
+static void
+msp430_print_operand_raw (FILE * file, rtx op, int letter ATTRIBUTE_UNUSED)
+{
+  int i;
+
+  switch (GET_CODE (op))
+    {
+    case REG:
+      fprintf (file, "%s", reg_names [REGNO (op)]);
+      break;
+
+    case CONST_INT:
+      i = INTVAL (op);
+      if (TARGET_ASM_HEX)
+	fprintf (file, "%#x", i);
+      else
+	fprintf (file, "%d", i);
+      break;
+
+    case CONST:
+    case PLUS:
+    case MINUS:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      output_addr_const (file, op);
+      break;
+
+    default:
+      print_rtl (file, op);
+      break;
+    }
+}
+
+static void
+msp430_print_operand (FILE * file, rtx op, int letter)
+{
+  rtx addr;
+
+  /* We can't use c, n, a, or l.  */
+  switch (letter)
+    {
+    case 'Z':
+      gcc_assert (CONST_INT_P (op));
+      /* Print the constant value, less one.  */
+      fprintf (file, "#%ld", INTVAL (op) - 1);
+      return;
+    case 'Y':
+      gcc_assert (CONST_INT_P (op));
+      /* Print the constant value, less four.  */
+      fprintf (file, "#%ld", INTVAL (op) - 4);
+      return;
+    case 'D':
+      /* print a decimal value without a leading '#'.  */
+      if (GET_CODE (op) == CONST_INT)
+	{
+	  int i = INTVAL (op);
+	  fprintf (file, "%d", i);
+	  return;
+	}
+      break;
+    case 'I':
+      if (GET_CODE (op) == CONST_INT)
+	{
+	  /* Inverse of constants */
+	  int i = INTVAL (op);
+	  fprintf (file, "%d", ~i);
+	  return;
+	}
+      op = XEXP (op, 0);
+      break;
+    case 'r': /* Conditional jump where the condition is reversed.  */
+      switch (GET_CODE (op))
+	{
+	case EQ: fprintf (file, "NE"); break;
+	case NE: fprintf (file, "EQ"); break;
+	case GEU: fprintf (file, "LO"); break;
+	case LTU: fprintf (file, "HS"); break;
+	case GE: fprintf (file, "L"); break;
+	case LT: fprintf (file, "GE"); break;
+	  /* Assume these have reversed operands.  */
+	case GTU: fprintf (file, "HS"); break;
+	case LEU: fprintf (file, "LO"); break;
+	case GT: fprintf (file, "GE"); break;
+	case LE: fprintf (file, "L"); break;
+	default:
+	  msp430_print_operand_raw (file, op, letter);
+	  break;
+	}
+      return;
+    case 'R': /* Conditional jump where the operands are reversed.  */
+      switch (GET_CODE (op))
+	{
+	case GTU: fprintf (file, "LO"); break;
+	case LEU: fprintf (file, "HS"); break;
+	case GT: fprintf (file, "L"); break;
+	case LE: fprintf (file, "GE"); break;
+	default:
+	  msp430_print_operand_raw (file, op, letter);
+	  break;
+	}
+      return;
+    case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc.  */
+      gcc_assert (CONST_INT_P (op));
+      fprintf (file, "#%d", 1 << INTVAL (op));
+      return;
+    case 'B':
+      switch (GET_MODE (op))
+	{
+	case QImode: fprintf (file, ".B"); return;
+	case HImode: fprintf (file, ".W"); return;
+	case PSImode: fprintf (file, ".A"); return;
+	case SImode: fprintf (file, ".A"); return;
+	default:
+	  return;
+	}
+    case 'L': /* Low half.  */
+      switch (GET_CODE (op))
+	{
+	case MEM:
+	  op = adjust_address (op, Pmode, 0);
+	  break;
+	case REG:
+	  break;
+	case CONST_INT:
+	  op = GEN_INT (INTVAL (op) & 0xffff);
+	  letter = 0;
+	  break;
+	default:
+	  /* If you get here, figure out a test case :-) */
+	  gcc_unreachable ();
+	}
+      break;
+    case 'H': /* high half */
+      switch (GET_CODE (op))
+	{
+	case MEM:
+	  op = adjust_address (op, Pmode, 2);
+	  break;
+	case REG:
+	  op = gen_rtx_REG (Pmode, REGNO (op) + 1);
+	  break;
+	case CONST_INT:
+	  op = GEN_INT (INTVAL (op) >> 16);
+	  letter = 0;
+	  break;
+	default:
+	  /* If you get here, figure out a test case :-) */
+	  gcc_unreachable ();
+	}
+      break;
+
+    case 'X':
+      /* This is used to turn, for example, an ADD opcode into an ADDX
+	 opcode when we're using 20-bit addresses.  */
+      if (TARGET_LARGE)
+	fprintf (file, "X");
+      /* We don't care which operand we use, but we want 'X' in the MD
+	 file, so we do it this way.  */
+      return;
+
+    case 'x':
+      /* Similarly, but only for PSImodes.  BIC, for example, needs this.  */
+      if (TARGET_LARGE && GET_MODE (op) == PSImode)
+	fprintf (file, "X");
+      return;
+
+    case 'A':
+      /* Likewise, for BR -> BRA.  */
+      if (TARGET_LARGE)
+	fprintf (file, "A");
+      return;
+    }
+
+  switch (GET_CODE (op))
+    {
+    case REG:
+      msp430_print_operand_raw (file, op, letter);
+      break;
+
+    case MEM:
+      addr = XEXP (op, 0);
+      switch (GET_CODE (addr))
+	{
+	case REG:
+	  fprintf (file, "@%s", reg_names [REGNO (addr)]);
+	  break;
+	case PLUS:
+	  msp430_print_operand_raw (file, XEXP (addr, 1), letter);
+	  fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
+	  break;
+	case CONST:
+	case CONST_INT:
+	case SYMBOL_REF:
+	case LABEL_REF:
+	  fprintf (file, "&");
+	  msp430_print_operand_raw (file, addr, letter);
+	  break;
+
+	default:
+	  print_rtl (file, addr);
+	  break;
+	}
+      break;
+
+    case CONST_INT:
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      if (letter == 0)
+	fprintf (file, "#");
+      msp430_print_operand_raw (file, op, letter);
+      break;
+
+    case EQ: fprintf (file, "EQ"); break;
+    case NE: fprintf (file, "NE"); break;
+    case GEU: fprintf (file, "HS"); break;
+    case LTU: fprintf (file, "LO"); break;
+    case GE: fprintf (file, "GE"); break;
+    case LT: fprintf (file, "L"); break;
+
+    default:
+      print_rtl (file, op);
+      break;
+    }
+
+}
+
+
+/* Frame stuff.  */
+
+rtx
+msp430_return_addr_rtx (int count)
+{
+  int ra_size;
+  if (count)
+    return NULL_RTX;
+
+  ra_size = TARGET_LARGE ? 4 : 2;
+  if (crtl->args.pretend_args_size)
+    ra_size += 2;
+
+  return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
+}
+
+rtx
+msp430_incoming_return_addr_rtx (void)
+{
+  return gen_rtx_MEM (Pmode, stack_pointer_rtx);
+}
+
+/* Instruction generation stuff.  */
+
+/* Generate a sequence of instructions to sign-extend an HI
+   value into an SI value.  Handles the tricky case where
+   we are overwriting the destination.  */
+
+const char *
+msp430x_extendhisi (rtx * operands)
+{
+  if (REGNO (operands[0]) == REGNO (operands[1]))
+    /* Low word of dest == source word.  */
+    return "BIT.W #0x8000, %L0 { SUBC.W %H0, %H0 { INV.W %H0, %H0"; /* 8-bytes.  */
+
+  if (! msp430x)
+    /* Note: This sequence is approximately the same length as invoking a helper
+       function to perform the sign-extension, as in:
+       
+         MOV.W  %1, %L0
+	 MOV.W  %1, r12
+	 CALL   __mspabi_srai_15
+	 MOV.W  r12, %H0
+
+       but this version does not involve any function calls or using argument
+       registers, so it reduces register pressure.  */
+    return "MOV.W %1, %L0 { BIT.W #0x8000, %L0 { SUBC.W %H0, %H0 { INV.W %H0, %H0"; /* 10-bytes.  */
+  
+  if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
+    /* High word of dest == source word.  */
+    return "MOV.W %1, %L0 { RPT #15 { RRAX.W %H0"; /* 6-bytes.  */
+
+  /* No overlap between dest and source.  */
+  return "MOV.W %1, %L0 { MOV.W %1, %H0 { RPT #15 { RRAX.W %H0"; /* 8-bytes.  */
+}
+
+/* Likewise for logical right shifts.  */
+const char *
+msp430x_logical_shift_right (rtx amount)
+{
+  /* The MSP430X's logical right shift instruction - RRUM - does
+     not use an extension word, so we cannot encode a repeat count.
+     Try various alternatives to work around this.  If the count
+     is in a register we are stuck, hence the assert.  */
+  gcc_assert (CONST_INT_P (amount));
+
+  if (INTVAL (amount) <= 0
+      || INTVAL (amount) >= 16)
+    return "# nop logical shift.";
+
+  if (INTVAL (amount) > 0	    
+      && INTVAL (amount) < 5)
+    return "rrum.w\t%2, %0"; /* Two bytes.  */
+
+  if (INTVAL (amount) > 4	    
+      && INTVAL (amount) < 9)
+    return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes.  */
+
+  /* First we logically shift right by one.  Now we know
+     that the top bit is zero and we can use the arithmetic
+     right shift instruction to perform the rest of the shift.  */
+  return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes.  */
+}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-msp430.h"
Index: gcc/config/msp430/msp430-c.c
===================================================================
--- gcc/config/msp430/msp430-c.c	(revision 0)
+++ gcc/config/msp430/msp430-c.c	(revision 0)
@@ -0,0 +1,36 @@
+/* MSP430 C-specific support
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   Contributed by Red Hat, 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 "tm.h"
+#include "tree.h"
+#include "c-family/c-common.h"
+#include "msp430-protos.h"
+
+/* Implements REGISTER_TARGET_PRAGMAS.  */
+void
+msp430_register_pragmas (void)
+{
+  c_register_addr_space ("__near", ADDR_SPACE_NEAR);
+  if (msp430x)
+    c_register_addr_space ("__far", ADDR_SPACE_FAR);
+}
Index: gcc/config/msp430/msp430.opt
===================================================================
--- gcc/config/msp430/msp430.opt	(revision 0)
+++ gcc/config/msp430/msp430.opt	(revision 0)
@@ -0,0 +1,26 @@
+msim
+Target
+Use simulator runtime
+
+masm-hex
+Target Mask(ASM_HEX)
+Force assembly output to always use hex constants
+
+mmcu=
+Target Joined RejectNegative Var(target_cpu)
+Specify the cpu to build for.  If the name begins with 'msp430x' then the 430X instructions are enabled
+
+mlarge
+Target Mask(LARGE) RejectNegative
+Select large model - 20-bit addresses/pointers
+
+msmall
+Target InverseMask(LARGE) RejectNegative
+Select small model - 16-bit addresses/pointers (default)
+
+mrelax
+Target Report
+Optimize opcode sizes at link time
+
+mOs
+Target Undocumented Mask(OPT_SPACE)
Index: gcc/config/msp430/msp430-modes.def
===================================================================
--- gcc/config/msp430/msp430-modes.def	(revision 0)
+++ gcc/config/msp430/msp430-modes.def	(revision 0)
@@ -0,0 +1,3 @@
+/* 20-bit address */
+PARTIAL_INT_MODE (SI);
+
Index: gcc/config/msp430/README.txt
===================================================================
--- gcc/config/msp430/README.txt	(revision 0)
+++ gcc/config/msp430/README.txt	(revision 0)
@@ -0,0 +1,7 @@
+Random Notes
+------------
+
+The MSP430 port does not use leading underscores.  However, the
+assembler has no way of differentiating between, for example, register
+R12 and symbol R12.  So, if you do "int r12;" in your C program, you
+may get an assembler error, and will certainly have runtime problems.
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	(revision 0)
+++ gcc/config/msp430/msp430.h	(revision 0)
@@ -0,0 +1,399 @@
+/* GCC backend definitions for the TI MSP430 Processor
+   Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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/>.  */
+
+
+/* Run-time Target Specification */
+
+/* True if the MSP430x extensions are enabled.  */
+#ifndef IN_LIBGCC2
+extern bool msp430x;
+#endif
+
+#define TARGET_CPU_CPP_BUILTINS()               \
+  do                                            \
+    {                                           \
+      builtin_define ("__MSP430__"); 		\
+      if (msp430x)				\
+	{					\
+	  builtin_define ("__MSP430X__");	\
+	  builtin_assert ("cpu=MSP430X");	\
+	  if (TARGET_LARGE)			\
+	    builtin_define ("__MSP430X_LARGE__");	\
+	}					\
+      else					\
+	builtin_assert ("cpu=MSP430"); 		\
+    }                                           \
+  while (0)
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:crt0.o%s} crtbegin.o%s"
+
+/* -lgcc is included because crtend.o needs __mspabi_func_epilog_1.  */
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s -lgcc"
+
+#define ASM_SPEC "-mP " /* Enable polymorphic instructions.  */ \
+  "%{mmcu=msp430x:-mmcu=msp430X;mmcu=*:-mmcu=%*} " /* Pass the MCU type on to the assembler.  */  \
+  "%{mrelax=-mQ} " /* Pass the relax option on to the assembler.  */ \
+  "%{mlarge:-ml} " /* Tell the assembler if we are building for the LARGE pointer model.  */ \
+  "%{ffunction-sections:-gdwarf-sections}" /* If function sections are being created then create DWARF line number sections as well.  */
+
+/* Enable linker section garbage collection by default, unless we
+   are creating a relocatable binary (gc does not work) or debugging
+   is enabled  (the GDB testsuite relies upon unused entities not being deleted).  */
+#define LINK_SPEC "%{mrelax:--relax} %{mlarge:%{!r:%{!g:--gc-sections}}}"
+
+#undef  LIB_SPEC
+#define LIB_SPEC "					\
+--start-group						\
+-lc							\
+-lgcc							\
+%{msim:-lsim}						\
+%{!msim:-lnosys}					\
+--end-group					   	\
+%{!T*: %{msim: %{mlarge:%Tmsp430xl-sim.ld}%{!mlarge:%Tmsp430-sim.ld}}%{!msim:%Tmsp430.ld}}	\
+"
+
+
+/* Storage Layout */
+
+#define BITS_BIG_ENDIAN 		0
+#define BYTES_BIG_ENDIAN 		0
+#define WORDS_BIG_ENDIAN 		0
+
+
+#ifdef IN_LIBGCC2
+/* This is to get correct SI and DI modes in libgcc2.c (32 and 64 bits).  */
+#define	UNITS_PER_WORD			4
+/* We have a problem with libgcc2.  It only defines two versions of
+   each function, one for "int" and one for "long long".  Ie it assumes
+   that "sizeof (int) == sizeof (long)".  For the MSP430 this is not true
+   and we need a third set of functions.  We explicitly define
+   LIBGCC2_UNITS_PER_WORD here so that it is clear that we are expecting
+   to get the SI and DI versions from the libgcc2.c sources, and we
+   provide our own set of HI functions, which is why this
+   definition is surrounded by #ifndef..#endif.  */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD 		4
+#endif
+#else
+/* Actual width of a word, in units (bytes).  */
+#define	UNITS_PER_WORD 			2
+#endif
+
+#define SHORT_TYPE_SIZE			16
+#define INT_TYPE_SIZE			16
+#define LONG_TYPE_SIZE			32
+#define LONG_LONG_TYPE_SIZE		64
+
+#define FLOAT_TYPE_SIZE 		32
+#define DOUBLE_TYPE_SIZE 		64
+#define LONG_DOUBLE_TYPE_SIZE		64 /*DOUBLE_TYPE_SIZE*/
+
+#define LIBGCC2_HAS_DF_MODE		1
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE   64
+
+#define DEFAULT_SIGNED_CHAR		0
+
+#define STRICT_ALIGNMENT 		1
+#define FUNCTION_BOUNDARY 		16
+#define BIGGEST_ALIGNMENT 		16
+#define STACK_BOUNDARY 			16
+#define PARM_BOUNDARY 			8
+#define PCC_BITFIELD_TYPE_MATTERS	1
+
+#define STACK_GROWS_DOWNWARD		1
+#define FRAME_GROWS_DOWNWARD		1
+#define FIRST_PARM_OFFSET(FNDECL) 	0
+
+#define MAX_REGS_PER_ADDRESS 		1
+
+#define Pmode 				(TARGET_LARGE ? PSImode : HImode)
+/* Note: 32 is a lie.  Large pointers are actually 20-bits wide.  But gcc
+   thinks that any non-power-of-2 pointer size equates to BLKmode, which
+   causes all kinds of problems...  */
+#define POINTER_SIZE			(TARGET_LARGE ? 32 : 16)
+#define	POINTERS_EXTEND_UNSIGNED	1
+
+#define ADDR_SPACE_NEAR	1
+#define ADDR_SPACE_FAR	2
+
+#define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas()
+
+#if 1 /* XXX */
+/* Define this macro if it is advisable to hold scalars in registers
+   in a wider mode than that declared by the program.  In such cases,
+   the value is constrained to be within the bounds of the declared
+   type, but kept valid in the wider mode.  The signedness of the
+   extension may differ from that of the type.  */
+
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)	\
+  if (GET_MODE_CLASS (MODE) == MODE_INT		\
+      && GET_MODE_SIZE (MODE) < 2)      	\
+    (MODE) = HImode;
+#endif
+
+/* Layout of Source Language Data Types */
+
+#undef  SIZE_TYPE
+#define SIZE_TYPE			(TARGET_LARGE ? "long unsigned int" : "unsigned int")
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE			(TARGET_LARGE ? "long int" : "int")
+#undef  WCHAR_TYPE
+#define WCHAR_TYPE			"long int"
+#undef  WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE			BITS_PER_WORD
+#define FUNCTION_MODE 			HImode
+#define CASE_VECTOR_MODE		Pmode
+#define HAS_LONG_COND_BRANCH		0
+#define HAS_LONG_UNCOND_BRANCH		0
+
+#define LOAD_EXTEND_OP(M)		ZERO_EXTEND
+/*#define WORD_REGISTER_OPERATIONS	1*/
+
+#define MOVE_MAX 			8
+#define STARTING_FRAME_OFFSET		0
+
+#define INCOMING_RETURN_ADDR_RTX \
+  msp430_incoming_return_addr_rtx ()
+
+#define RETURN_ADDR_RTX(COUNT, FA)		\
+  msp430_return_addr_rtx (COUNT)
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)   1
+
+#define SLOW_BYTE_ACCESS		0
+
+
+/* Register Usage */
+
+/* gas doesn't recognize PC (R0), SP (R1), and SR (R2) as register
+   names.  */
+#define REGISTER_NAMES						\
+{								\
+  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",		\
+    "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",	\
+  "argptr"							\
+}
+
+enum reg_class
+{
+  NO_REGS,
+  R12_REGS,
+  R13_REGS,
+  GEN_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define REG_CLASS_NAMES \
+{			\
+  "NO_REGS",		\
+  "R12_REGS",		\
+  "R13_REGS",		\
+  "GEN_REGS",		\
+  "ALL_REGS"		\
+}
+
+#define REG_CLASS_CONTENTS \
+{			   \
+  0x00000000,		   \
+  0x00001000,		   \
+  0x00002000,		   \
+  0x0000fff2,		   \
+  0x0001ffff		   \
+}
+
+#define GENERAL_REGS			GEN_REGS
+#define BASE_REG_CLASS  		GEN_REGS
+#define INDEX_REG_CLASS			GEN_REGS
+#define N_REG_CLASSES			(int) LIM_REG_CLASSES
+
+#define PC_REGNUM 		        0
+#define STACK_POINTER_REGNUM 	        1
+#define CC_REGNUM                       2
+#define FRAME_POINTER_REGNUM 		4 /* not usually used, call preserved */
+#define ARG_POINTER_REGNUM 		16
+#define STATIC_CHAIN_REGNUM 		5 /* FIXME */
+
+#define FIRST_PSEUDO_REGISTER 		17
+
+#define REGNO_REG_CLASS(REGNO)          ((REGNO) < 17 \
+					 ? GEN_REGS : NO_REGS)
+
+#define TRAMPOLINE_SIZE			4 /* FIXME */
+#define TRAMPOLINE_ALIGNMENT		16 /* FIXME */
+
+#define ELIMINABLE_REGS					\
+{{ ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM },	\
+ { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM },	\
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }}
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)	\
+  (OFFSET) = msp430_initial_elimination_offset ((FROM), (TO))
+
+
+#define FUNCTION_ARG_REGNO_P(N)	  	((N) >= 8 && (N) < ARG_POINTER_REGNUM)
+#define DEFAULT_PCC_STRUCT_RETURN	0
+
+/* 1 == register can't be used by gcc, in general
+   0 == register can be used by gcc, in general */
+#define FIXED_REGISTERS					\
+{							\
+  1,0,1,1, 0,0,0,0,					\
+  0,0,0,0, 0,0,0,0,					\
+  1,							\
+}
+
+/* 1 == value changes across function calls
+   0 == value is the same after a call      */
+/* R4 through R10 are callee-saved */
+#define CALL_USED_REGISTERS				\
+{							\
+  1,0,1,1, 0,0,0,0,					\
+  0,0,0,1, 1,1,1,1,					\
+  1,						\
+}
+
+#define REG_ALLOC_ORDER					\
+  { 12, 13, 14, 15, 10, 9, 8, 7, 6, 5, 4, 11, 0, 1, 2, 3, 16 }
+/*  { 11, 15, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 0, 1, 2, 3, 16 }*/
+
+#define REGNO_OK_FOR_BASE_P(regno)	1
+#define REGNO_OK_FOR_INDEX_P(regno)	1
+
+
+
+typedef struct {
+  /* These two are the current argument status.  */
+  char reg_used[4];
+#define CA_FIRST_REG 12
+  char can_split;
+  /* These two are temporaries used internally.  */
+  char start_reg;
+  char reg_count;
+  char mem_count;
+  char special_p;
+} CUMULATIVE_ARGS;
+
+#define INIT_CUMULATIVE_ARGS(CA, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
+  msp430_init_cumulative_args (&CA, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS)
+
+
+/* FIXME */
+#define NO_PROFILE_COUNTERS     1
+#define PROFILE_BEFORE_PROLOGUE 1
+
+#define FUNCTION_PROFILER(FILE, LABELNO)	\
+    fprintf (FILE, "\tcall\t__mcount\n");
+
+#define HARD_REGNO_NREGS(REGNO, MODE)            \
+  msp430_hard_regno_nregs (REGNO, MODE)
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 			\
+  msp430_hard_regno_mode_ok (REGNO, MODE)
+
+#define MODES_TIEABLE_P(MODE1, MODE2)				\
+  msp430_modes_tieable_p (MODE1, MODE2)
+
+/* Exception Handling */
+
+/* R12,R13,R14 - EH data
+   R15 - stack adjustment */
+
+#define EH_RETURN_DATA_REGNO(N) \
+  (((N) < 3) ? ((N) + 12) : INVALID_REGNUM)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM(Pmode, gen_rtx_PLUS (Pmode, gen_rtx_REG(Pmode, SP_REGNO), gen_rtx_REG (Pmode, 15)))
+
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 15)
+
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) DW_EH_PE_udata4
+
+
+/* Stack Layout and Calling Conventions */
+
+
+/* Addressing Modes */
+
+
+
+#define TEXT_SECTION_ASM_OP ".text"
+#define DATA_SECTION_ASM_OP ".data"
+#define BSS_SECTION_ASM_OP   "\t.section .bss"
+
+#define ASM_COMMENT_START	" ;"
+#define ASM_APP_ON		""
+#define ASM_APP_OFF 		""
+#define LOCAL_LABEL_PREFIX	".L"
+#undef  USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX	""
+
+#define GLOBAL_ASM_OP 		"\t.global\t"
+
+#define ASM_OUTPUT_LABELREF(FILE, SYM) msp430_output_labelref ((FILE), (SYM))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+  fprintf (FILE, "\t.long .L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+   Note: The local label referenced by the "3b" below is emitted by
+   the tablejump insn.  */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+  fprintf (FILE, "\t.long .L%d - 1b\n", VALUE)
+
+
+#define ASM_OUTPUT_ALIGN(STREAM, LOG)		\
+  do						\
+    {						\
+      if ((LOG) == 0)				\
+        break;					\
+      fprintf (STREAM, "\t.balign %d\n", 1 << (LOG));	\
+    }						\
+  while (0)
+
+#define JUMP_TABLES_IN_TEXT_SECTION	1
+
+#undef	DWARF2_ADDR_SIZE
+#define	DWARF2_ADDR_SIZE			4
+
+#define INCOMING_FRAME_SP_OFFSET		(POINTER_SIZE / BITS_PER_UNIT)
+
+#undef  PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#define DWARF2_ASM_LINE_DEBUG_INFO		1
+
+/* Prevent reload (and others) from choosing HImode stack slots
+   when spilling hard registers when they may contain PSImode values.  */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO,NREGS,MODE) \
+  ((TARGET_LARGE && ((NREGS) <= 2)) ? PSImode : choose_hard_reg_mode ((REGNO), (NREGS), false))
+
+/* Also stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)).  */
+#define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
+  (   ((TO) == PSImode && (FROM) == SImode)	\
+   || ((TO) == SImode  && (FROM) == PSImode)    \
+   || ((TO) == DImode  && (FROM) == PSImode)    \
+   || ((TO) == PSImode && (FROM) == DImode)     \
+      )
+
+#define ACCUMULATE_OUTGOING_ARGS 1

[wwwdocs]

? htdocs/.#index.html.1.882
Index: htdocs/backends.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/backends.html,v
retrieving revision 1.46
diff -p -U 5 -r1.46 backends.html
--- htdocs/backends.html	16 Jul 2012 21:19:20 -0000	1.46
+++ htdocs/backends.html	23 Jul 2013 21:17:58 -0000
@@ -90,10 +90,11 @@ mep      |       F C       p g  d t s
 microblaze         CB          bd   s
 mips     |     Q   CB   qr p   bda  s
 mmix     | HM  Q   C    q  p   b a e 
 mn10300  | ??             c  g      s
 ms1      |   S   F  B      p g bd
+msp430   |    L  FI    l   p g      s
 pa       |   ? Q   CBD  qr    m da e 
 pdp11    |    L   IC    qrcp       e 
 rs6000   |     Q   C    qr      da   
 s390     |   ? Q        qr p g bda e 
 sh       |     Q   CB   qr     bda   
Index: htdocs/index.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/index.html,v
retrieving revision 1.887
diff -p -U 5 -r1.887 index.html
--- htdocs/index.html	31 May 2013 11:41:08 -0000	1.887
+++ htdocs/index.html	23 Jul 2013 21:17:58 -0000
@@ -51,10 +51,14 @@ mission statement</a>.</p>
 
 <h2 style="margin-top:0pt;" id="news">News</h2>
 
 <dl class="news">
 
+<dt><span>TI MSP430 support</span>
+    <span class="date">[2013-05-09]</span></dt>
+<dd>A port for the TI MSP430 has been contributed by Red Hat Inc.</dd>
+
 <dt><span><a href="gcc-4.8/">GCC 4.8.1</a> released</span>
     <span class="date">[2013-05-31]</span></dt>
     <dd></dd>
 
 <dt><span><a href="gcc-4.6/">GCC 4.6.4</a> released</span>
Index: htdocs/readings.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/readings.html,v
retrieving revision 1.231
diff -p -U 5 -r1.231 readings.html
--- htdocs/readings.html	1 Apr 2013 10:49:54 -0000	1.231
+++ htdocs/readings.html	23 Jul 2013 21:17:58 -0000
@@ -213,10 +213,15 @@ Intel&reg;64 and IA-32 Architectures Sof
  <li>mn10300
   <br />Manufacturer: Matsushita
   <br />Alternate chip name: AM30
   <br />GDB includes a simulator.
  </li>
+
+ <li>msp430
+  <br />Manufacturer: Texas Instruments
+  <br />GDB includes a simulator.
+ </li>
  
  <li>ns32k
   <br />Manufacturer: National Semiconductor
   <br /><a href="http://www.national.com/pf/NS/NS32FX200.html";>NS32FX200 Home Page</a>
  </li>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]