diff -ruNp gcc-4.x/gcc/config/msp430/framehelpers.inl gcc-4.4.5/gcc/config/msp430/framehelpers.inl
--- gcc-4.x/gcc/config/msp430/framehelpers.inl	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/framehelpers.inl	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,111 @@
+#pragma once
+
+extern void *ggc_alloc(size_t);
+
+/*
+This function is used to test, how certain generated INSNs are actually matched and written to the
+assembly file.
+The typical test scenario for msp430_codegen_test() is:
+1. Create a C file containing the following
+int test()
+{
+__msp430_codegen_test_entry();
+}
+2. Examine the output with "msp430-gcc -S 0.c -o 0.S && less 0.S"
+3. Compare the output in 0.S with the expected result of msp430_codegen_test() run
+*/
+
+/*
+Functions beginning with msp430_fh_ are prologue/epilogue (frame) helpers.
+*/
+static inline void msp430_fh_emit_push_reg(int reg_num)
+{
+	rtx pushword = gen_rtx_MEM (HImode, gen_rtx_PRE_DEC (HImode, stack_pointer_rtx));
+	//rtx insn = emit_insn(gen_rtx_SET(VOIDmode, pushword, gen_rtx_REG (HImode, reg_num)));
+	rtx insn = emit_insn(gen_pushhi_prologue(gen_rtx_REG (HImode, reg_num), pushword));
+	RTX_FRAME_RELATED_P(insn) = 1;
+}
+
+static inline void msp430_fh_emit_pop_reg(int reg_num)
+{
+	/*rtx popword  = gen_rtx_MEM (HImode, gen_rtx_POST_INC (HImode, stack_pointer_rtx));
+	rtx insn = emit_insn(gen_rtx_SET(VOIDmode, gen_rtx_REG (HImode, reg_num), popword));
+	RTX_FRAME_RELATED_P(insn) = 1;*/
+
+	rtx insn = emit_insn(gen_pophi_reg(gen_rtx_REG (HImode, reg_num)));
+}
+
+static inline void msp430_fh_sub_sp_const(int num_bytes)
+{
+	rtx insn = emit_move_insn (stack_pointer_rtx,
+//		gen_rtx_MINUS (HImode, stack_pointer_rtx, gen_int_mode (num_bytes, HImode)));
+		gen_rtx_PLUS (HImode, stack_pointer_rtx, gen_int_mode (-num_bytes, HImode)));
+	RTX_FRAME_RELATED_P(insn) = 1;
+}
+
+static inline void msp430_fh_add_sp_const(int num_bytes)
+{
+	rtx insn = emit_move_insn (stack_pointer_rtx,
+		gen_rtx_PLUS (HImode, stack_pointer_rtx, gen_int_mode (num_bytes, HImode)));
+	RTX_FRAME_RELATED_P(insn) = 1;
+}
+
+static inline void msp430_fh_add_reg_const(int reg_num, int num_bytes)
+{
+	rtx reg_rtx = gen_rtx_REG (HImode, reg_num);
+	rtx insn = emit_move_insn (reg_rtx,
+		gen_rtx_PLUS (HImode, reg_rtx, gen_int_mode (num_bytes, HImode)));
+	RTX_FRAME_RELATED_P(insn) = 1;
+}
+
+static inline void msp430_fh_gen_mov_r2r(int dest_reg, int src_reg)
+{
+	rtx insn = emit_move_insn (gen_rtx_REG (HImode, dest_reg), gen_rtx_REG (HImode, src_reg));
+	RTX_FRAME_RELATED_P(insn) = 1;
+}
+
+static inline void msp430_fh_gen_mov_pc_to_reg(int dest_reg)
+{
+	rtx insn = emit_insn(gen_save_pc_to_reg(gen_rtx_REG (HImode, dest_reg)));
+}
+
+static inline const char *msp430_format_sym_plus_off(const char *sym_name, int offset)
+{
+	char *pBuf;
+	if (!offset)
+		return sym_name;
+	pBuf = (char *)ggc_alloc(strlen(sym_name) + 20);
+	sprintf(pBuf, "(%s%s%d)", sym_name, (offset >= 0) ? "+" : "", offset);
+	return pBuf;
+}
+
+static inline void msp430_fh_load_sp_with_sym_plus_off(const char *sym_name, int offset)
+{
+	rtx insn;
+
+	insn = emit_move_insn (stack_pointer_rtx, gen_rtx_SYMBOL_REF(HImode, msp430_format_sym_plus_off(sym_name, offset)));
+}
+
+/*
+	WARNING! This function is called from 2 places:
+		* Prologue saver
+		* Exit from main()
+	As the "explicit_br" INSN does not report to be modifying PC, this may screw up DWARF2 frame info generation.
+	Optimally, the "explicit_br" INSN should be replaced by something similar to "call_prologue_saves" INSN from
+	the AVR implementation. As for return from main, the question is still open.
+*/
+static inline void msp430_fh_br_to_symbol_plus_offset(const char *sym_name, int offset)
+{
+	rtx insn;
+	insn = gen_explicit_br(gen_rtx_SYMBOL_REF(HImode, msp430_format_sym_plus_off(sym_name, offset)));
+	/*insn = gen_rtx_SET (VOIDmode,
+						pc_rtx,
+						gen_rtx_LABEL_REF(VOIDmode, gen_rtx_SYMBOL_REF(HImode, msp430_format_sym_plus_off(sym_name, offset))));*/
+	emit_insn (insn);
+}
+
+static inline void msp430_fh_bic_deref_sp(int mask)
+{
+	rtx insn, sp_deref = gen_rtx_MEM (HImode, stack_pointer_rtx);
+	insn = emit_insn(gen_nandhi(sp_deref, gen_int_mode(mask, HImode), sp_deref));
+}
\ No newline at end of file
diff -ruNp gcc-4.x/gcc/config/msp430/generate_chip_data.py gcc-4.4.5/gcc/config/msp430/generate_chip_data.py
--- gcc-4.x/gcc/config/msp430/generate_chip_data.py	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/generate_chip_data.py	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,263 @@
+# This text should be extracted from msp430.c
+text = '''
+	/* F1xx family */
+	{"msp430x110",   MSP430_ISA_11, 0},
+	{"msp430x112",   MSP430_ISA_11, 0},
+
+	{"msp430x1101",  MSP430_ISA_110, 0},
+	{"msp430x1111",  MSP430_ISA_110, 0},
+	{"msp430x1121",  MSP430_ISA_110, 0},
+	{"msp430x1122",  MSP430_ISA_110, 0},
+	{"msp430x1132",  MSP430_ISA_110, 0},
+
+	{"msp430x122",   MSP430_ISA_12, 0},
+	{"msp430x123",   MSP430_ISA_12, 0},
+	{"msp430x1222",  MSP430_ISA_12, 0},
+	{"msp430x1232",  MSP430_ISA_12, 0},
+
+	{"msp430x133",   MSP430_ISA_13, 0},
+	{"msp430x135",   MSP430_ISA_13, 0},
+	{"msp430x1331",  MSP430_ISA_13, 0},
+	{"msp430x1351",  MSP430_ISA_13, 0},
+
+	{"msp430x147",   MSP430_ISA_14, 1},
+	{"msp430x148",   MSP430_ISA_14, 1},
+	{"msp430x149",   MSP430_ISA_14, 1},
+	{"msp430x1471",  MSP430_ISA_14, 1},
+	{"msp430x1481",  MSP430_ISA_14, 1},
+	{"msp430x1491",  MSP430_ISA_14, 1},
+
+	{"msp430x155",   MSP430_ISA_15, 0},
+	{"msp430x156",   MSP430_ISA_15, 0},
+	{"msp430x157",   MSP430_ISA_15, 0},
+
+	{"msp430x167",   MSP430_ISA_16, 1},
+	{"msp430x168",   MSP430_ISA_16, 1},
+	{"msp430x169",   MSP430_ISA_16, 1},
+	{"msp430x1610",  MSP430_ISA_16, 1},
+	{"msp430x1611",  MSP430_ISA_16, 1},
+	{"msp430x1612",  MSP430_ISA_16, 1},
+
+	/* F2xx family */
+	{"msp430x2001",  MSP430_ISA_20, 0},
+	{"msp430x2011",  MSP430_ISA_20, 0},
+
+	{"msp430x2002",  MSP430_ISA_20, 0},
+	{"msp430x2012",  MSP430_ISA_20, 0},
+
+	{"msp430x2003",  MSP430_ISA_20, 0},
+	{"msp430x2013",  MSP430_ISA_20, 0},
+
+	{"msp430x2101",  MSP430_ISA_21, 0},
+	{"msp430x2111",  MSP430_ISA_21, 0},
+	{"msp430x2121",  MSP430_ISA_21, 0},
+	{"msp430x2131",  MSP430_ISA_21, 0},
+
+	{"msp430x2112",  MSP430_ISA_22, 0},
+	{"msp430x2122",  MSP430_ISA_22, 0},
+	{"msp430x2132",  MSP430_ISA_22, 0},
+
+	{"msp430x2201",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2211",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2221",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2231",  MSP430_ISA_22, 0}, /* Value-Line */
+
+	{"msp430x2232",  MSP430_ISA_22, 0},
+	{"msp430x2252",  MSP430_ISA_22, 0},
+	{"msp430x2272",  MSP430_ISA_22, 0},
+
+	{"msp430x2234",  MSP430_ISA_22, 0},
+	{"msp430x2254",  MSP430_ISA_22, 0},
+	{"msp430x2274",  MSP430_ISA_22, 0},
+
+	{"msp430x233",   MSP430_ISA_23, 1},
+	{"msp430x235",   MSP430_ISA_23, 1},
+
+	{"msp430x2330",  MSP430_ISA_23, 1},
+	{"msp430x2350",  MSP430_ISA_23, 1},
+	{"msp430x2370",  MSP430_ISA_23, 1},
+
+	{"msp430x247",   MSP430_ISA_24, 1},
+	{"msp430x248",   MSP430_ISA_24, 1},
+	{"msp430x249",   MSP430_ISA_24, 1},
+	{"msp430x2410",  MSP430_ISA_24, 1},
+	{"msp430x2471",  MSP430_ISA_24, 1},
+	{"msp430x2481",  MSP430_ISA_24, 1},
+	{"msp430x2491",  MSP430_ISA_24, 1},
+
+	{"msp430x2416",  MSP430_ISA_241, 1},
+	{"msp430x2417",  MSP430_ISA_241, 1},
+	{"msp430x2418",  MSP430_ISA_241, 1},
+	{"msp430x2419",  MSP430_ISA_241, 1},
+
+	{"msp430x2616",  MSP430_ISA_26, 1},
+	{"msp430x2617",  MSP430_ISA_26, 1},
+	{"msp430x2618",  MSP430_ISA_26, 1},
+	{"msp430x2619",  MSP430_ISA_26, 1},
+
+	/* 3xx family (ROM) */
+	{"msp430x311",   MSP430_ISA_31, 0},
+	{"msp430x312",   MSP430_ISA_31, 0},
+	{"msp430x313",   MSP430_ISA_31, 0},
+	{"msp430x314",   MSP430_ISA_31, 0},
+	{"msp430x315",   MSP430_ISA_31, 0},
+
+	{"msp430x323",   MSP430_ISA_32, 0},
+	{"msp430x325",   MSP430_ISA_32, 0},
+
+	{"msp430x336",   MSP430_ISA_33, 1},
+	{"msp430x337",   MSP430_ISA_33, 1},
+
+	/* F4xx family */
+	{"msp430x412",   MSP430_ISA_41, 0},
+	{"msp430x413",   MSP430_ISA_41, 0},
+	{"msp430x415",   MSP430_ISA_41, 0},
+	{"msp430x417",   MSP430_ISA_41, 0},
+
+	{"msp430x423",   MSP430_ISA_42, 1},
+	{"msp430x425",   MSP430_ISA_42, 1},
+	{"msp430x427",   MSP430_ISA_42, 1},
+
+	{"msp430x4250",  MSP430_ISA_42, 0},
+	{"msp430x4260",  MSP430_ISA_42, 0},
+	{"msp430x4270",  MSP430_ISA_42, 0},
+
+	{"msp430xG4250", MSP430_ISA_42, 0},
+	{"msp430xG4260", MSP430_ISA_42, 0},
+	{"msp430xG4270", MSP430_ISA_42, 0},
+
+	{"msp430xE423",  MSP430_ISA_42, 1},
+	{"msp430xE425",  MSP430_ISA_42, 1},
+	{"msp430xE427",  MSP430_ISA_42, 1},
+
+	{"msp430xE4232", MSP430_ISA_42, 1},
+	{"msp430xE4242", MSP430_ISA_42, 1},
+	{"msp430xE4252", MSP430_ISA_42, 1},
+	{"msp430xE4272", MSP430_ISA_42, 1},
+
+	{"msp430xW423",  MSP430_ISA_42, 0},
+	{"msp430xW425",  MSP430_ISA_42, 0},
+	{"msp430xW427",  MSP430_ISA_42, 0},
+
+	{"msp430xG437",  MSP430_ISA_43, 0},
+	{"msp430xG438",  MSP430_ISA_43, 0},
+	{"msp430xG439",  MSP430_ISA_43, 0},
+
+	{"msp430x435",   MSP430_ISA_43, 0},
+	{"msp430x436",   MSP430_ISA_43, 0},
+	{"msp430x437",   MSP430_ISA_43, 0},
+
+	{"msp430x4351",  MSP430_ISA_43, 0},
+	{"msp430x4361",  MSP430_ISA_43, 0},
+	{"msp430x4371",  MSP430_ISA_43, 0},
+
+	{"msp430x447",   MSP430_ISA_44, 1},
+	{"msp430x448",   MSP430_ISA_44, 1},
+	{"msp430x449",   MSP430_ISA_44, 1},
+
+	{"msp430xG4616", MSP430_ISA_46, 1},
+	{"msp430xG4617", MSP430_ISA_46, 1},
+	{"msp430xG4618", MSP430_ISA_46, 1},
+	{"msp430xG4619", MSP430_ISA_46, 1},
+
+	{"msp430x4783",  MSP430_ISA_47, 1},
+	{"msp430x4784",  MSP430_ISA_47, 1},
+	{"msp430x4793",  MSP430_ISA_47, 1},
+	{"msp430x4794",  MSP430_ISA_47, 1},
+        
+	{"msp430x47166", MSP430_ISA_471, 1},
+	{"msp430x47176", MSP430_ISA_471, 1},
+	{"msp430x47186", MSP430_ISA_471, 1},
+	{"msp430x47196", MSP430_ISA_471, 1},
+
+	{"msp430x47167", MSP430_ISA_471, 1},
+	{"msp430x47177", MSP430_ISA_471, 1},
+	{"msp430x47187", MSP430_ISA_471, 1},
+	{"msp430x47197", MSP430_ISA_471, 1},
+
+	/* F5xxx family */
+	{"msp430x5418",  MSP430_ISA_54, 1},
+	{"msp430x5419",  MSP430_ISA_54, 1},
+	{"msp430x5435",  MSP430_ISA_54, 1},
+	{"msp430x5436",  MSP430_ISA_54, 1},
+	{"msp430x5437",  MSP430_ISA_54, 1},
+	{"msp430x5438",  MSP430_ISA_54, 1},
+
+        {"msp430x5510",  MSP430_ISA_54, 1},
+        {"msp430x5513",  MSP430_ISA_54, 1},
+        {"msp430x5514",  MSP430_ISA_54, 1},
+        {"msp430x5515",  MSP430_ISA_54, 1},
+        {"msp430x5517",  MSP430_ISA_54, 1},
+        {"msp430x5519",  MSP430_ISA_54, 1},
+        {"msp430x5521",  MSP430_ISA_54, 1},
+        {"msp430x5522",  MSP430_ISA_54, 1},
+        {"msp430x5524",  MSP430_ISA_54, 1},
+        {"msp430x5525",  MSP430_ISA_54, 1},
+        {"msp430x5526",  MSP430_ISA_54, 1},
+        {"msp430x5527",  MSP430_ISA_54, 1},
+        {"msp430x5528",  MSP430_ISA_54, 1},
+        {"msp430x5529",  MSP430_ISA_54, 1},
+        {"msp430x6638",  MSP430_ISA_54, 1},
+
+	/* CC430 family */
+	{"cc430x5133",   MSP430_ISA_54, 1},
+	{"cc430x5125",   MSP430_ISA_54, 1},
+	{"cc430x6125",   MSP430_ISA_54, 1},
+	{"cc430x6135",   MSP430_ISA_54, 1},
+	{"cc430x6126",   MSP430_ISA_54, 1},
+	{"cc430x5137",   MSP430_ISA_54, 1},
+	{"cc430x6127",   MSP430_ISA_54, 1},
+	{"cc430x6137",   MSP430_ISA_54, 1},
+'''
+
+import re
+
+pattern_re = re.compile('.*"(.*)".*MSP430_ISA_(\d*),\s*([01])')
+
+exemplary_chip = { 'msp1' : 'msp430x110',
+                   'msp2' : 'msp430x336',
+                   'msp3' : 'msp430xG4616',
+                   'msp4' : 'msp430x4783',
+                   'msp5' : 'msp430x47166',
+                   'msp6' : 'msp430x5418' }
+
+generated =  { }
+seen_chip = { }
+
+for line in text.splitlines():
+    mo = pattern_re.match(line)
+    if mo is None:
+        continue
+    (chip, ctype, hwm) = mo.groups()
+    ctype = int(ctype)
+    hwm = int(hwm)
+    '''
+    if hwm:
+        print 'mmcu?msp2=mmcu?%s' % (chip,)
+    else:
+        print 'mmcu?msp1=mmcu?%s' % (chip,)
+    '''
+    mlib = None
+    if not hwm:
+        mlib = 'msp1'
+    else:
+        if ctype in (26, 241, 46,):
+            mlib = 'msp3'
+        elif ctype in (47,):
+            mlib = 'msp4'
+        elif ctype in (471,):
+            mlib = 'msp5'
+        elif ctype in (54,):
+            mlib = 'msp6'
+        else:
+            mlib = 'msp2'
+    aux_cbs = ''
+    if (exemplary_chip[mlib] == chip):
+        aux_cbs = '|mmcu=%s' % (mlib,)
+    generated.setdefault('MULTILIB_MATCHES', []).append("\tmmcu?%s=mmcu?%s" % (mlib, chip))
+    generated.setdefault('CPP_SPEC', []).append('%%{mmcu=%s:%%(cpp_%s) -D__%s__}' % (chip, mlib, chip.replace('x', '_').upper()))
+    generated.setdefault('LINK_SPEC', []).append('%%{mmcu=%s:-m %s }' % (chip, chip))
+    generated.setdefault('CRT_BINUTILS_SPECS', []).append('%%{mmcu=%s%s:crt%s.o%%s}' % (chip, aux_cbs, chip.replace('msp', '')))
+    
+for (k, v) in generated.items():
+    file(k, 'w').write(" \\\n".join(v))
diff -ruNp gcc-4.x/gcc/config/msp430/libgcc.S gcc-4.4.5/gcc/config/msp430/libgcc.S
--- gcc-4.x/gcc/config/msp430/libgcc.S	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/libgcc.S	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,1339 @@
+/*  -*- Mode: Asm -*-  */
+
+
+	.section .text.libgcc, "ax", @progbits
+
+#if defined(MSP430_HAS_HWMUL)
+#if defined(__MSP430X2__)
+__MPY=0x4c0
+#else
+__MPY=0x130
+#endif	
+__MPYS=(__MPY   + 0x02)
+__MAC=(__MPY    + 0x04)
+__MACS=(__MPY   + 0x06)
+__OP2=(__MPY    + 0x08)
+__RESLO=(__MPY  + 0x0a)
+__RESHI=(__MPY  + 0x0c)
+__SUMEXT=(__MPY + 0x0e)
+#endif
+
+#if defined (L_cmpdi2)
+	
+	.global	__cmpdi2
+	.func	__cmpdi2
+__cmpdi2:
+	sub     2(r1), r12	; a = a-b;
+	subc    4(r1), r13
+	subc    6(r1), r14
+	subc    8(r1), r15
+	
+	tst     r15		; c<0 ? return -1;
+	jge     .L2
+	
+	mov     #-1, r15	; yes, return -1
+	ret
+.L2:
+	bis     r12, r14	; check if zero
+	bis     r13, r15
+	bis     r14, r15
+	tst     r15
+	jeq     .L4		; test result or or'ing all nibbles
+	
+	mov     #1, r15		; no, positive, return 1
+	ret
+.L4:
+	mov     #0, r15		; return 0
+	ret
+.endfunc
+#endif
+
+#if defined (L_cmpsf2)
+	.global __cmpsf2
+	.func	__cmpsf2
+__cmpsf2:
+/* prologue: frame size = 0; addenum 0; alloca:0, varargs:0 , fpr:0*/
+.L__FrameSize___cmpsf2=0x0
+.L__FrameOffset___cmpsf2=0x4
+/* prologue end (size=2) */
+        cmp     r12, r14	;  11  cmpsi   [length = 3]
+        jne     .L2
+        cmp     r13, r15
+        jne     .L2      	;  12  bne     [length = 1]
+        mov     #llo(0), r15	;  15  *movhi3/7       [length = 1]
+	ret
+.L2:
+        tst     r15		;  20  tstsi   [length = 1]
+        jge     .L3		;  21  bge     [length = 1]
+        tst     r13		;  22  tstsi   [length = 1]
+        jge     .L3		;  23  bge     [length = 1]
+        xor     #lhi(-2147483648), r15		;  27  *xorsi3_3       [length = 2]
+        xor     #lhi(-2147483648), r13		;  29  *xorsi3_3       [length = 2]
+.L3:
+        sub     r14, r12	;  64  *subsi3_3       [length = 2]
+        subc    r15, r13
+        jge     .L4		;  33  bge     [length = 1]
+        mov     #llo(1), r15	;  36  *movhi3/7       [length = 1]
+	ret
+.L4:
+        mov     #llo(-1), r15	;  43  *movhi3/7       [length = 1]
+.L1:
+/* epilogue: frame size=0 */
+        ret
+/* epilogue end (size=3) */
+/* function __cmpsf2 size 25 (20) */
+
+.endfunc
+
+#endif
+
+
+
+/*******************************************************
+               Multiplication  8 x 8
+*******************************************************/
+#if defined (L_mulqi3)
+/* 
+	a = reg:qi 10	clobber
+	b = reg:qi 12	clobber
+	res = reg:qi 14
+*/
+
+	.global	__mulqi3
+	.func	__mulqi3
+__mulqi3:
+	clr	r14
+.L__mulqiloop:
+	tst.b	r10
+	jz	.L__mulqiexit
+	clrc
+	rrc.b	r12
+	jnc	+2
+	add.b	r10, r14
+	rla.b	r10
+	tst.b	r12
+	jne	.L__mulqiloop
+.L__mulqiexit:
+	ret
+	.endfunc
+#endif 	/* defined (L_mulqi3) */
+
+
+#if defined (L_mulqihi3)
+	.global	__mulqihi3
+	.func	__mulqihi3
+__mulqihi3:
+	sxt	r10
+	sxt	r12
+	br	#__mulhi3
+.endfunc
+#endif /* defined (L_mulqihi3) */
+
+#if defined (L_umulqihi3)
+	.global	__umulqihi3
+	.func	__umulqihi3
+__umulqihi3:
+	and.b	#-1, r10
+	and.b	#-1, r12
+	br	#__mulhi3
+	.endfunc
+#endif /* defined (L_umulqihi3) */
+
+/*******************************************************
+               Multiplication  16 x 16
+*******************************************************/
+#if defined (L_mulhi3)
+/* 
+	a = reg:hi 10	clobber
+	b = reg:hi 12	clobber
+	res = reg:hi 14
+*/
+
+	.global	__mulhi3
+	.func	__mulhi3
+__mulhi3:
+	clr	r14
+.L__mulhiloop:
+	tst	r10
+	jz	.L__mulhiexit
+	clrc
+	rrc	r12
+	jnc	+2
+	add	r10, r14
+	rla	r10
+	tst     r12
+	jne	.L__mulhiloop
+.L__mulhiexit:
+	ret
+	.endfunc
+#endif /* defined (L_mulhi3) */
+
+#if defined (L_mulhisi3)
+/* clobber r11, r13 */
+	.global	__mulhisi3
+	.func	__mulhisi3
+__mulhisi3:
+	br	#__mulsi3
+	.endfunc
+#endif /* defined (L_mulhisi3) */
+
+#if defined (L_umulhisi3)
+	.global	__umulhisi3
+	.func	__umulhisi3
+__umulhisi3:
+	br	#__mulsi3
+	.endfunc
+#endif /* defined (L_umulhisi3) */
+
+#if defined (L_mulsi3)
+/*******************************************************
+               Multiplication  32 x 32
+*******************************************************/
+/*
+res = a*b
+	a - reg:SI 10 clobber
+	b - reg:SI 12 clobber
+	res - reg: SI 14
+*/
+	.global	__mulsi3
+	.func	__mulsi3
+
+__mulsi3:
+	clr	r14
+	clr	r15
+	jmp	.L__mulsi3st
+.L__mulsi3loop:
+	clrc
+	rrc	r13		;	b >>= 1
+	rrc 	r12
+	jnc	+4		;	
+	add	r10, r14	;	res = res + a
+	addc	r11, r15
+	rla	r10
+	rlc	r11		;	a <<= 1
+.L__mulsi3st:
+	tst	r12		; if b ne 0 goto L__mulsi3loop
+	jne	.L__mulsi3loop
+	tst	r13
+	jne	.L__mulsi3loop
+	ret
+	.endfunc
+
+#endif
+
+#if defined (L_mulsi3hw)
+	
+	.global	__umulsi3hw
+	.func	__umulsi3hw
+__umulsi3hw:
+	mov	r12, &__MPY
+	mov	r10, &__OP2
+	mov	r12, &__MAC
+	mov	&__RESLO, r14
+	mov	&__RESHI, &__RESLO
+	mov	r11, &__OP2
+	mov	r13, &__MAC
+	mov	r10, &__OP2
+	mov	&__RESLO, r15
+	ret
+.endfunc
+
+#endif
+
+	
+/*******************************************************
+       Division 8 / 8 => (result + remainder)
+*******************************************************/
+
+#define r_rem   r14	/* remainder */
+#define r_arg1  r12	/* dividend, quotient */
+#define r_arg2  r10	/* divisor */
+#define r_cnt   r11	/* loop count */
+#define r_tmp	r13	/* save carry flag */
+
+
+#if defined (L_udivmodqi4)
+	.global	__udivmodqi4
+	.func	__udivmodqi4
+__udivmodqi4:
+	xor.b	r_rem, r_rem		; clear reminder and carry
+	mov.b	#9, r_cnt
+	jmp	.L__udivmodqi4_ep
+.L__udivmodqi4_loop:	
+	rrc	r_tmp			; restore carry bit
+	rlc.b	r_rem
+	cmp.b	r_arg2, r_rem
+	jlo	.L__udivmodqi4_ep
+	sub.b	r_arg2, r_rem		; FIXME: will this clobber carry ?
+.L__udivmodqi4_ep:
+	rlc.b	r_arg1			; shift divident
+	rlc	r_tmp			; save carry bit
+	dec.b	r_cnt			; this clobbers C bit.
+	jnz	.L__udivmodqi4_loop
+	ret
+	.endfunc
+#endif /* defined (L_udivmodqi4) */
+
+
+#if defined (L_divmodqi4)
+	.global	__divmodqi4
+	.func	__divmodqi4
+__divmodqi4:
+	clr	r_tmp
+	bit	#0x80, r_arg1		; save divident sign
+	jnc	.L__divmodqi4arg1pos
+	inv.b	r_arg1			; negate
+	inc.b	r_arg1
+	bis	#4, r_tmp
+
+.L__divmodqi4arg1pos:
+	bit	#0x80, r_arg2		; check divisor sign
+	jnc	.L__divmodqi4arg2pos
+	inv.b	r_arg2			; negate
+	inc.b	r_arg2
+	bis	#8, r_tmp
+
+.L__divmodqi4arg2pos:
+	
+	call	#__udivmodqi4		; do unsigned division
+	rrc	r_tmp			; restore carry and sign bits
+
+	bit	#4, r_tmp		; is divident < 0 ?
+	jnc	.L__divmodqi4rem	; no. skip
+	inv.b	r_rem			; negate remainder
+	inc.b	r_rem
+
+;;	bit	#8, r_tmp
+;;	jc	.L__divmodqi4end
+	inv.b	r_arg1			; negate quotient
+	inc.b	r_arg1
+
+.L__divmodqi4rem:
+	bit	#8, r_tmp
+	jnc	.L__divmodqi4end
+	inv.b	r_arg1
+	inc.b	r_arg1
+
+.L__divmodqi4end:
+	ret
+
+	.endfunc
+#endif /* defined (L_divmodqi4) */
+
+#undef r_rem
+#undef r_arg1
+#undef r_arg2
+#undef r_cnt 
+#undef r_tmp
+
+
+/*******************************************************
+       Division 16 / 16 => (result + remainder)
+*******************************************************/
+
+#define r_rem   r14	/* remainder */
+#define r_arg1  r12	/* dividend, quotient */
+#define r_arg2  r10	/* divisor */
+#define r_cnt   r11	/* loop count */
+#define r_tmp	r13
+
+
+#if defined (L_udivmodhi4)
+	.global	__udivmodhi4
+	.func	__udivmodhi4
+__udivmodhi4:
+	xor	r_rem, r_rem		; clear reminder and carry
+	mov	#17, r_cnt
+	jmp	.L__udivmodhi4_ep
+.L__udivmodhi4_loop:	
+	rrc	r_tmp			; restore carry bit
+	rlc	r_rem
+	cmp	r_arg2, r_rem
+	jlo	.L__udivmodhi4_ep
+	sub	r_arg2, r_rem
+.L__udivmodhi4_ep:
+	rlc	r_arg1
+	rlc	r_tmp			; save carry bit
+	dec	r_cnt			; this clobbers C bit.
+	jnz	.L__udivmodhi4_loop
+	ret
+	.endfunc
+#endif /* defined (L_udivmodhi4) */
+
+
+#if defined (L_divmodhi4)
+#define r_rem   r14     /* remainder */
+#define r_arg1  r12     /* dividend, quotient */
+#define r_arg2  r10     /* divisor */   
+#define r_cnt   r11     /* loop count */
+#define r_tmp   r13
+
+
+	.global	__divmodhi4
+	.func	__divmodhi4
+__divmodhi4:
+	clr	r_tmp			; clear reg is cheaper than clr 2 bits.
+	bit	#0x8000, r_arg1		; save divident sign
+	jnc	.L__divmodhi4arg1pos
+	inv	r_arg1			; negate
+	inc	r_arg1
+	bis	#4, r_tmp
+
+.L__divmodhi4arg1pos:
+	bit	#0x8000, r_arg2		; check divisor sign
+	jnc	.L__divmodhi4arg2pos
+	inv	r_arg2			; negate
+	inc	r_arg2
+	bis	#8, r_tmp
+
+.L__divmodhi4arg2pos:	
+	call	#__udivmodhi4		; do unsigned division
+	rrc	r_tmp			; restore carry and sign bits
+
+	bit	#4, r_tmp		; is divident < 0 ?
+	jnc	.L__divmodhi4rem	; no. skip
+	inv	r_rem			; negate remainder
+	inc	r_rem
+
+;;	bit	#8, r_tmp
+;;	jc	.L__divmodhi4end
+	inv	r_arg1			; negate quotient
+	inc	r_arg1
+
+.L__divmodhi4rem:
+	bit	#8, r_tmp
+	jnc	.L__divmodhi4end
+	inv	r_arg1
+	inc	r_arg1
+
+.L__divmodhi4end:
+	ret
+	.endfunc
+#endif /* defined (L_divmodhi4) */
+
+#undef r_rem
+#undef r_arg1
+#undef r_arg2
+#undef r_cnt 
+#undef r_tmp
+
+/*******************************************************
+       Division 32 / 32 => (result + remainder)
+*******************************************************/
+
+#if defined (L_udivmodsi4)
+
+#define r_remh  r15  
+#define r_reml  r14	/* remainder */
+#define r_arg1h r13
+#define r_arg1l r12	/* dividend, quotient */
+#define r_arg2h r11   
+#define r_arg2l r10	/* divisor */
+#define r_cnt   r9	/* loop count */
+#define r_tmp   r8
+
+	.global	__udivmodsi4
+	.func	__udivmodsi4
+__udivmodsi4:
+	xor	r_remh, r_remh		; clear reminder and carry
+	xor	r_reml, r_reml
+	mov	#33, r_cnt
+	jmp	.L__udivmodsi4_ep
+.L__udivmodsi4_loop:	
+	rrc	r_tmp			; restore carry bit
+	rlc	r_reml
+	rlc	r_remh
+
+	cmp	r_arg2h, r_remh		; is reminder < divisor ?
+	jlo	.L__udivmodsi4_ep	; yes, skip correction
+	jne	+4
+					; they equal. check LSBytes
+	cmp	r_arg2l, r_reml
+	jlo	.L__udivmodsi4_ep	; is reminder still < divisor ?
+
+	sub	r_arg2l, r_reml		; adjust reminder
+	subc	r_arg2h, r_remh
+
+.L__udivmodsi4_ep:
+	rlc	r_arg1l
+	rlc	r_arg1h
+	rlc	r_tmp
+	dec	r_cnt			; this clobbers C bit.
+	jnz	.L__udivmodsi4_loop
+	ret
+	.endfunc
+
+#undef r_remh
+#undef r_reml  
+#undef r_arg1h
+#undef r_arg1l
+#undef r_arg2h
+#undef r_arg2l
+
+#undef r_cnt
+#undef r_tmp
+
+#endif /* defined (L_udivmodsi4) */
+
+
+#if defined (L_divmodsi4)
+#define r_remh  r15  
+#define r_reml  r14     /* remainder */
+#define r_arg1h r13
+#define r_arg1l r12     /* dividend, quotient */
+#define r_arg2h r11   
+#define r_arg2l r10     /* divisor */   
+#define r_cnt   r9      /* loop count */
+#define r_tmp   r8
+
+	.global	__divmodsi4
+	.func	__divmodsi4
+__divmodsi4:
+	clr	r_tmp			; clear reg is cheaper than clr 2 bits.
+	bit	#0x8000, r_arg1h		; save divident sign
+	jz	.L__divmodsi4arg1pos
+	inv	r_arg1h			; negate
+	inv	r_arg1l
+	inc	r_arg1l
+	adc	r_arg1h
+	bis	#4, r_tmp
+
+.L__divmodsi4arg1pos:
+	bit	#0x8000, r_arg2h		; check divisor sign
+	jz	.L__divmodsi4arg2pos
+	inv	r_arg2h			; negate
+	inv	r_arg2l
+	inc	r_arg2l
+	adc	r_arg2h
+	bis	#8, r_tmp		; save divisor sign
+
+.L__divmodsi4arg2pos:
+	
+	call	#__udivmodsi4		; do unsigned division
+	rrc	r_tmp			; restore carry and sign bits
+
+	bit	#4, r_tmp		; is divident < 0 ?
+	jz	.L__divmodsi4rem	; no. skip
+	inv	r_reml			; negate remainder
+	inv	r_remh
+	inc	r_reml
+	adc	r_remh
+
+;;	bit	#8, r_tmp
+;;	jc	.L__divmodsi4end
+	inv	r_arg1l			; negate quotient
+	inv	r_arg1h
+	inc	r_arg1l
+	adc	r_arg1h
+
+.L__divmodsi4rem:
+	bit	#8, r_tmp
+	jz	.L__divmodsi4end
+	inv	r_arg1l
+	inv	r_arg1h
+	inc	r_arg1l
+	adc	r_arg1h
+
+.L__divmodsi4end:
+	ret
+	.endfunc
+
+#undef r_remh  
+#undef r_reml  
+#undef r_arg1h 
+#undef r_arg1l
+#undef r_arg2h
+#undef r_arg2l
+
+#undef r_cnt
+#undef r_tmp
+
+#endif /* defined (L_divmodsi4) */
+
+
+/******* CRT support functions *********/
+
+#if defined(L_reset_vector__)
+/*****************************************************************
+ * Program starts here.
+ *   overwriting this label in the user program
+ *   causes removing all strtup code except __do_global_ctors
+ *****************************************************************/
+	.section .init0, "ax", @progbits
+
+	.global	_reset_vector__
+	.weak   _reset_vector__
+
+	.func   _reset_vector__
+
+_reset_vector__:
+
+    /* link following functions if library _reset_vector__ used */
+
+;    stack can be initialized in main() prologue,
+;    but setting stack pointer here allows to call subroutines 
+;    from startup code and call constructors of statically allocated C++ objects.
+;    Stack pointer will have the same value entering main() as here,
+;    so -mno-stack-init can be used to reduce code size.
+;    initial stack value can be set in ld script as __stack symbol 
+;    (end of RAM by default), or via -defsym __stack=<address> ld option
+;    or via -Wl,defsym,__stack=<address> gcc option, or by redefining
+;    __init_stack function as fololws:
+;
+;#if defined (__cplusplus)
+;extern "C" 
+;#endif
+;__attribute__((__naked__)) __attribute__((section(".init2"))) void __init_stack()
+;{
+;    asm volatile("\tmov\t#stack_addr, r1\n");
+;}
+;
+
+	.global	__init_stack
+
+	.global	__low_level_init
+	.global	__do_copy_data
+	.global	__do_clear_bss
+	.global	__jump_to_main
+
+	.endfunc
+#endif  /* defined(L_reset_vector__) */
+    
+#if defined(L__init_stack)
+/*****************************************************************
+ * Set stack pointer
+ * can be overwriten
+ *****************************************************************/
+	.section .init2, "ax", @progbits
+
+	.global	__init_stack
+	.weak   __init_stack
+
+	.func   __init_stack
+
+__init_stack:
+	mov     #__stack, r1
+
+	.endfunc
+#endif
+
+#if defined(L__low_level_init)
+/*****************************************************************
+ * Initialize peripherial, particularly disable watchdog
+ * can be overwriten
+ *****************************************************************/
+	.section .init3, "ax", @progbits
+
+	.global	__low_level_init
+	.weak   __low_level_init
+
+	.func   __low_level_init
+
+__low_level_init:
+	mov     #0x5a80, &0x120
+
+	.endfunc
+#endif
+
+#if defined(L_copy_data)
+/*****************************************************************
+ * Initialize data: copy data 
+ * from __data_load_start ( = _etext) to __data_start
+ * can be overwriten
+ *****************************************************************/
+	.section .init4, "ax", @progbits
+
+	.global __do_copy_data
+	.weak   __do_copy_data
+
+	.func   __do_copy_data
+
+__do_copy_data:
+	mov     #__data_size, r15
+	tst     r15
+	jz      .L__copy_data_end
+.L__copy_data_loop:
+	decd    r15
+	mov.w   __data_load_start(r15), __data_start(r15)    ; data section is word-aligned, so word transfer is acceptable
+	jne     .L__copy_data_loop
+.L__copy_data_end:
+
+	.endfunc
+#endif /* defined(L_copy_data) */
+    
+#if defined(L_clear_bss)
+/*****************************************************************
+ * Initialize data: clear .bss
+ * can be overwriten
+ *****************************************************************/
+	.section .init4, "ax", @progbits
+
+	.global __do_clear_bss
+	.weak   __do_clear_bss
+
+	.func   __do_clear_bss
+
+__do_clear_bss:
+	mov     #__bss_size, r15
+	tst     r15
+	jz      .L__clear_bss_end
+.L__clear_bss_loop:
+	dec     r15
+	clr.b   __bss_start(r15)
+	jne     .L__clear_bss_loop
+.L__clear_bss_end:
+
+	.endfunc
+#endif  /* defined(L_clear_bss) */
+
+#if defined(L_ctors)
+/*****************************************************************
+ * Call C++ global and static objects constructors
+ * can be overwriten
+ *****************************************************************/
+	.section .init6, "ax", @progbits
+	.global __do_global_ctors
+	.weak   __do_global_ctors
+    
+	.func   __do_global_ctors
+
+__do_global_ctors:
+	mov     #__ctors_start, r11
+	mov     #__ctors_end,   r10
+.L__ctors_loop:
+	call	@r11+	; call constructor
+	cmp     r10, r11
+	jne     .L__ctors_loop
+
+	.endfunc
+#endif
+    
+#if defined(L__jump_to_main)
+/*****************************************************************
+ * jump to main.
+ * can be overwriten
+ *****************************************************************/
+	.section .init9, "ax", @progbits
+
+	.global	__jump_to_main
+	.weak   __jump_to_main
+
+	.func   __jump_to_main
+
+__jump_to_main:
+	br      #main
+	.endfunc
+#endif
+
+#if defined(L__stop_progExec__)
+/*****************************************************************
+ * return from main.
+ * can be overwriten
+ *****************************************************************/
+	.section .fini9, "ax", @progbits
+	.global __stop_progExec__
+	.weak	__stop_progExec__
+
+	.func  __stop_progExec__
+
+__stop_progExec__:
+
+	.endfunc
+#endif
+
+#if defined(L_dtors)
+/*****************************************************************
+ * Call C++ global and static objects destructors
+ * can be overwriten
+ *****************************************************************/
+	.section .fini6,"ax",@progbits
+	.global __do_global_dtors
+	.weak   __do_global_dtors
+    
+	.func   _dtors
+
+__do_global_dtors:
+	mov     #__dtors_start, r11
+	mov     #__dtors_end, r10
+.L__dtors_loop:
+	call    @r11+
+	cmp     r10, r11
+	jne     .L__dtors_loop
+
+	.endfunc
+#endif
+
+#if defined(L__stop_progExec__)
+/*****************************************************************
+ * endless loop
+ * can be overwriten
+ *****************************************************************/
+	.section .fini0, "ax", @progbits
+
+	.func   _endless_loop__
+1:
+	jmp  1b
+
+	.endfunc
+#endif
+
+/********* PROLOGE / EPILOGUE aux routines ******************/
+#if defined (L__prologue_saver)
+	.global __prologue_saver
+	.func	__prologue_saver
+__prologue_saver:
+	mov	r4, 0(r1)
+	mov	r5, 2(r1)
+	mov	r6, 4(r1)
+	mov	r7, 6(r1)
+	mov	r8, 8(r1)
+	mov	r9, 10(r1)
+	mov	r10, 12(r1)
+	mov	r11, 14(r1)
+	br	r12	; now jump to the function body
+.endfunc
+
+#endif
+
+
+#if defined (L__epilogue_restorer)
+	.global __epilogue_restorer
+	.func	__epilogue_restorer
+__epilogue_restorer:
+	pop	r4
+	pop	r5
+	pop	r6
+	pop	r7
+	pop	r8
+	pop	r9
+	pop	r10
+	pop	r11
+	ret
+.endfunc
+
+#endif
+
+
+#if defined (L__epilogue_restorer_intr)
+	.global __epilogue_restorer_intr
+	.func	__epilogue_restorer_intr
+__epilogue_restorer_intr:
+	pop	r4
+	pop	r5
+	pop	r6
+	pop	r7
+	pop	r8
+	pop	r9
+	pop	r10
+	pop	r11
+	pop	r12
+	pop	r13
+	pop	r14
+	pop	r15
+	reti
+.endfunc
+
+#endif
+
+/******************************************
+ * quot/rem = 64/64
+ ******************************************/
+
+#if defined (L_udivmoddi3_parts) || defined (L_udivdi3) || defined (L_umoddi3) || defined (L_divdi3) || defined (L_moddi3)
+
+#define r_remhh  r11  	/* remainder */
+#define r_remhl  r10
+#define r_remlh	 r9
+#define r_remll	 r8
+
+#define r_arg1hh r15	/* dividend, quotient */
+#define r_arg1hl r14
+#define r_arg1lh r13
+#define r_arg1ll r12
+
+#define r_arg2hh r7	/* divisor */
+#define r_arg2hl r6
+#define r_arg2lh r5
+#define r_arg2ll r4
+
+#define r_cnt   2(r1)	/* loop count */
+#define r_tmp   0(r1)	/* we'll save carry and signs here */
+
+#endif
+
+
+#if defined (L_udivmoddi3_parts)
+
+	.global	__udivmoddi3_parts
+	.func	__udivmoddi3_parts
+__udivmoddi3_parts:
+	xor	r_remhh, r_remhh	; clear reminder and carry
+	xor	r_remhl, r_remhl 
+	xor	r_remlh, r_remlh
+	xor	r_remll, r_remll
+	
+	mov	#65, 2+r_cnt
+	jmp	.L__udivmoddi3_ep
+
+.L__udivmoddi3_loop:	
+	rrc	2+r_tmp			; restore carry bit
+	
+	rlc	r_remll			; shift carry in.
+	rlc	r_remlh
+	rlc	r_remhl
+	rlc	r_remhh
+	
+	cmp     r_arg2hh, r_remhh       ; is reminder < divisor ?
+	jlo     .L__udivmoddi3_ep       ; yes, skip correction
+	jne     .L_udmdcrt
+					; they equal. check LSBytes
+	cmp     r_arg2hl, r_remhl
+	jlo     .L__udivmoddi3_ep       ; is reminder still < divisor ?
+	jne     .L_udmdcrt
+
+	cmp     r_arg2lh, r_remlh
+	jlo     .L__udivmoddi3_ep
+	jne     .L_udmdcrt
+
+	cmp     r_arg2ll, r_remll
+	jlo     .L__udivmoddi3_ep
+	jne     .L_udmdcrt
+
+.L_udmdcrt:
+	sub	r_arg2ll, r_remll	; adjust reminder
+	subc	r_arg2lh, r_remlh
+	subc	r_arg2hl, r_remhl
+	subc	r_arg2hh, r_remhh
+	
+.L__udivmoddi3_ep:
+	rlc	r_arg1ll		; shift carry into arg1
+	rlc	r_arg1lh
+	rlc	r_arg1hl
+	rlc	r_arg1hh
+	
+	rlc	2+r_tmp			; save carry
+	dec	2+r_cnt			; this clobbers C bit.
+	jnz	.L__udivmoddi3_loop
+	
+	ret
+	.endfunc
+
+#endif /* defined (L_udivmoddi3_parts) */
+
+
+#if defined (L_udivdi3)
+
+;;  First arg will be in r15:r12 
+;;  next on stack
+;;	return in r15:r12
+;; rearrange them as:
+;;	r15:r12 	-> 	r_arg1hh:r_arg1ll
+;;	stack+8:stack+2 -> 	r_arg2hh:r_arg2ll
+
+	.global	__udivdi3
+	.func	__udivdi3
+__udivdi3:
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	r8
+	push	r9
+	push	r10
+	push	r11
+	
+	mov	18+0(r1), r_arg2ll	; 18 is a stack offset
+	mov	18+2(r1), r_arg2lh	; so move arg 2 in.
+	mov	18+4(r1), r_arg2hl
+	mov	18+6(r1), r_arg2hh
+	
+	sub	#4, r1
+	call	#__udivmoddi3_parts
+	add	#4, r1
+	
+	pop	r11
+	pop	r10
+	pop	r9
+	pop	r8
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	ret
+	.endfunc
+#endif
+
+
+#if defined (L_umoddi3)
+	.global	__umoddi3
+	.func	__umoddi3
+__umoddi3:
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	r8
+	push	r9
+	push	r10
+	push	r11
+	
+	mov	18+0(r1), r_arg2ll	
+	mov	18+2(r1), r_arg2lh
+	mov	18+4(r1), r_arg2hl
+	mov	18+6(r1), r_arg2hh
+
+	sub	#4, r1
+	call    #__udivmoddi3_parts
+	add	#4, r1
+	
+	mov	r_remhh, r15	; move reminder to (reg:DI 12)
+	mov	r_remhl, r14
+	mov	r_remlh, r13
+	mov	r_remll, r12
+	
+	pop	r11
+	pop	r10
+	pop	r9
+	pop	r8
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	ret
+	.endfunc
+#endif
+
+
+#if defined (L_divdi3)
+	.global	__divdi3
+	.func	__divdi3
+__divdi3:
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	r8
+	push	r9
+	push	r10
+	push	r11
+	
+	mov	18+0(r1), r_arg2ll	
+	mov	18+2(r1), r_arg2lh
+	mov	18+4(r1), r_arg2hl
+	mov	18+6(r1), r_arg2hh
+	
+	sub	#4, r1
+	
+	clr	r_tmp
+	bit     #0x8000, r_arg1hh
+	jnc     .L__divdi3rempos
+	inv	r_arg1hh
+	inv     r_arg1hl
+	inv     r_arg1lh
+	inv     r_arg1ll
+	inc	r_arg1ll
+	adc     r_arg1lh
+	adc     r_arg1hl
+	adc     r_arg1hh
+	bis     #4, r_tmp
+	
+.L__divdi3rempos:
+	bit     #0x8000, r_arg2hh
+	jnc     .L__divdi3arg2pos	
+	inv	r_arg2hh
+	inv     r_arg2hl
+	inv     r_arg2lh
+	inv     r_arg2ll
+	inc	r_arg2ll
+	adc     r_arg2lh
+	adc     r_arg2hl
+	adc     r_arg2hh
+	xor     #4, r_tmp	; this is a trick - invert bit 4 =>
+				; do not perform double negation.
+.L__divdi3arg2pos:
+	call	#__udivmoddi3_parts
+	
+	rrc     r_tmp	; restore sign bits
+
+	bit     #4, r_tmp
+	jz      .L__divdi3end
+	inv     r_arg1hh
+	inv     r_arg1hl
+	inv     r_arg1lh
+	inv     r_arg1ll
+	inc	r_arg1ll
+	adc     r_arg1lh
+	adc     r_arg1hl
+	adc     r_arg1hh
+	
+.L__divdi3end:
+	add	#4, r1
+	pop	r11
+	pop	r10
+	pop	r9
+	pop	r8
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	ret
+	.endfunc
+#endif
+
+
+#if defined (L_moddi3)
+	.global	__moddi3
+	.func	__moddi3
+__moddi3:
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	r8
+	push	r9
+	push	r10
+	push	r11
+	
+	mov	18+0(r1), r_arg2ll	
+	mov	18+2(r1), r_arg2lh
+	mov	18+4(r1), r_arg2hl
+	mov	18+6(r1), r_arg2hh
+	
+	sub	#4, r1
+	
+	clr	r_tmp
+	bit     #0x8000, r_arg1hh
+	jnc     .L__moddi3rempos
+	inv	r_arg1hh
+	inv     r_arg1hl
+	inv     r_arg1lh
+	inv     r_arg1ll
+	inc	r_arg1ll
+	adc     r_arg1lh
+	adc     r_arg1hl
+	adc     r_arg1hh
+	bis     #4, r_tmp
+	
+.L__moddi3rempos:
+	bit     #0x8000, r_arg2hh
+	jnc     .L__moddi3arg2pos	
+	inv	r_arg2hh
+	inv     r_arg2hl
+	inv     r_arg2lh
+	inv     r_arg2ll
+	inc	r_arg2ll
+	adc     r_arg2lh
+	adc     r_arg2hl
+	adc     r_arg2hh
+
+.L__moddi3arg2pos:
+	call	#__udivmoddi3_parts
+	
+	rrc     r_tmp
+
+	bit     #4, r_tmp
+	jz      .L__moddi3rem
+	
+	inv	r_remhh
+	inv     r_remhl
+	inv     r_remlh
+	inv     r_remll
+	inc	r_remll
+	adc     r_remlh
+	adc     r_remhl
+	adc     r_remhh
+
+.L__moddi3rem:
+	mov	r_remhh, r15
+	mov	r_remhl, r14
+	mov	r_remlh, r13
+	mov	r_remll, r12
+
+	add	#4, r1
+	pop	r11
+	pop	r10
+	pop	r9
+	pop	r8
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	ret
+	.endfunc
+#endif
+
+
+/**************************************************************
+ * Multiplication 64 = 64 x 64
+ **************************************************************/
+#if defined(L_muldi3) && !defined(MSP430_HAS_HWMUL)
+
+#define r_reshh  r11  	/* res = arg1 * arg2 */
+#define r_reshl  r10
+#define r_reslh	 r9
+#define r_resll	 r8
+
+#define r_arg1hh r15	/* arg1 */
+#define r_arg1hl r14
+#define r_arg1lh r13
+#define r_arg1ll r12
+
+#define r_arg2hh r7	/* arg2 */
+#define r_arg2hl r6
+#define r_arg2lh r5
+#define r_arg2ll r4
+
+	.global	__muldi3
+	.func	__muldi3
+__muldi3:
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	r8
+	push	r9
+	push	r10
+	push	r11
+	
+	mov	18+0(r1), r_arg2ll	; 18 is a stack offset
+	mov	18+2(r1), r_arg2lh	; so move arg 2 in.
+	mov	18+4(r1), r_arg2hl
+	mov	18+6(r1), r_arg2hh
+
+	clr	r_reshh
+	clr	r_reshl
+	clr	r_reslh
+	clr	r_resll
+	
+.L_muldi3_loop:
+	clrc
+	rrc	r_arg2hh		; arg2 >>= 1 (shift LSB into carry)
+	rrc	r_arg2hl
+	rrc	r_arg2lh
+	rrc	r_arg2ll
+	
+	jnc	+8			; check if bit is set
+					; yes, it is.
+	add	r_arg1ll, r_resll	; res += arg1
+	addc	r_arg1lh, r_reslh
+	addc	r_arg1hl, r_reshl
+	addc	r_arg1hh, r_reshh
+	
+	rla	r_arg1ll		; arg1 <<= 1
+	rlc	r_arg1lh
+	rlc	r_arg1hl
+	rlc	r_arg1hh
+	
+	tst	r_arg2ll		; arg2 !=0 ?  loop again , exit otherwise.
+	jne	.L_muldi3_loop
+	tst	r_arg2lh
+	jne	.L_muldi3_loop
+	tst	r_arg2hl
+	jne	.L_muldi3_loop
+	tst	r_arg2hh
+	jne	.L_muldi3_loop
+
+	; move result to proper location
+	mov	r_resll, r12
+	mov	r_reslh, r13
+	mov	r_reshl, r14
+	mov	r_reshh, r15
+
+	pop	r11
+	pop	r10
+	pop	r9
+	pop	r8
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	ret
+	.endfunc
+#endif
+
+#if defined(L_muldi3) && defined(MSP430_HAS_HWMUL)
+
+#define r_reshh  r11    /* res = arg1 * arg2 */
+#define r_reshl  r10
+#define r_reslh  r9
+#define r_resll  r8
+
+#define r_arg1hh r15    /* arg1 */
+#define r_arg1hl r14
+#define r_arg1lh r13
+#define r_arg1ll r12
+
+#define r_arg2hh r7     /* arg2 */
+#define r_arg2hl r6
+#define r_arg2lh r5
+#define r_arg2ll r4
+
+          .global __muldi3
+          .func   __muldi3
+__muldi3:
+
+        push    r4
+        push    r5
+        push    r6
+        push    r7
+        push    r8
+        push    r9
+        push    r10
+        push    r11
+
+        mov     18+0(r1), r_arg2ll      ; 18 is a stack offset
+        mov     18+2(r1), r_arg2lh      ; so move arg 2 in.
+        mov     18+4(r1), r_arg2hl
+        mov     18+6(r1), r_arg2hh
+
+;;      r15:r14:r13:r12 * r7:r6:r5:r4 -> r11:r10:r9:r8
+;; actual code follows....
+
+        mov     r_arg1ll,&__MPY
+        mov     r_arg2ll,&__OP2           ;;                      LL1xLL2
+        mov     &__RESLO,r_resll
+        mov     &__RESHI,&__RESLO
+        mov     &__SUMEXT,&__RESHI
+
+        mov     r_arg1ll,&__MAC
+        mov     r_arg2lh,&__OP2           ;;                  LL1xLH2
+        mov     r_arg1lh,&__MAC
+        mov     r_arg2ll,&__OP2           ;;                  LH1xLL2
+        mov     &__RESLO,r_reslh
+        mov     &__RESHI,&__RESLO
+        mov     &__SUMEXT,&__RESHI
+
+        mov     r_arg2lh,&__OP2           ;;              LH1xLH2
+        mov     r_arg1ll,&__MAC
+        mov     r_arg2hl,&__OP2           ;;              LL1xHL2
+        mov     r_arg1hl,&__MAC
+        mov     r_arg2ll,&__OP2           ;;              HL1xLL2
+        mov     &__RESLO,r_reshl
+        mov     &__RESHI,&__RESLO
+
+        mov     r_arg2lh,&__OP2           ;;          HL1xLH2
+        mov     r_arg1ll,&__MAC
+        mov     r_arg2hh,&__OP2           ;;          LL1xHH2
+        mov     r_arg1lh,&__MAC
+        mov     r_arg2hl,&__OP2           ;;          LH1xHL2
+        mov     r_arg1hh,&__MAC
+        mov     r_arg2ll,&__OP2           ;;          HH1xLL2
+        mov     &__RESLO,r_reshh
+
+;; reload result
+        mov     r_resll, r12
+        mov     r_reslh, r13
+        mov     r_reshl, r14
+        mov     r_reshh, r15
+
+        pop     r11
+        pop     r10
+        pop     r9
+        pop     r8
+        pop     r7
+        pop     r6
+        pop     r5
+        pop     r4
+        ret
+.endfunc
+#endif
diff -ruNp gcc-4.x/gcc/config/msp430/libgcc.c gcc-4.4.5/gcc/config/msp430/libgcc.c
--- gcc-4.x/gcc/config/msp430/libgcc.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/libgcc.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,73 @@
+/*
+	Stages of division:
+	0. Clear carry flag, et all.
+	1. Shift divident into divider. 
+	   Shift carry bit into divident.
+	2. Check if the remainder >= divider
+	3.	if yes, remainder -= divider
+		this MUST set carry flag
+	4. 	if not, clear carry flag
+	
+	repeat from 1 sizeof(type) times
+ */
+
+
+typedef unsigned long __XX;
+
+__XX
+__udivmodXI3 ( __XX a,  __XX b)
+{
+    __XX al = a;	// quotant
+    __XX ah = 0;	// reminder
+    __XX tmpf;
+    int i;
+
+    for (i = sizeof(__XX)*8; i > 0; i--)
+    {
+        ah = (ah << 1) | (al >> (sizeof(__XX)*8-1) );
+        tmpf = (ah >= b) ? 1 : 0;
+        ah -= ((tmpf) ? b : 0);
+        al = (al << 1) | tmpf;
+    }
+
+    return al;    // for __udivXi3
+    return ah;    // for __umodXi3
+}
+
+/* Signed: */
+
+__XX
+__divmodXI3 ( __XX a,  __XX b)
+{
+    unsigned at = abs(a);
+    unsigned bt = abs(b);
+    unsigned al, ah;
+
+    __udivmodXI3 (at, bt);
+
+    // now we get al, ah
+
+    if (a < 0)
+        ah = -ah, al = -al;
+
+    if (b < 0)
+        al = -al;
+
+    return al;
+    return ah;
+}
+
+#if 1
+int main()
+{
+    __XX a,b, r;
+
+    a = 100;
+    b = 0;
+    r = __udivmodXI3(a,b);
+    printf("R=%d\n",r);
+
+}
+#endif
+
+
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-builtins.c gcc-4.4.5/gcc/config/msp430/msp430-builtins.c
--- gcc-4.x/gcc/config/msp430/msp430-builtins.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-builtins.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,190 @@
+/* This work is partially financed by the European Commission under the
+* Framework 6 Information Society Technologies Project
+* "Wirelessly Accessible Sensor Populations (WASP)".
+*/
+
+/*
+GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "tree.h"
+#include "output.h"
+#include "expr.h"
+#include "toplev.h"
+#include "obstack.h"
+#include "function.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "insn-codes.h"
+#include "ggc.h"
+#include "langhooks.h"
+
+#if GCC_VERSION_INT < 0x430
+#define add_builtin_function lang_hooks.builtin_function
+#endif
+
+
+/* The following functions are defined in this file and used by msp430.c */
+void msp430_init_builtins (void);
+rtx msp430_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+
+
+static const struct {
+	const char *name;
+	int md_code;
+} msp430builtins[4] = {
+	{"__bic_sr_irq", CODE_FOR_bic_sr_irq},
+	{"__bis_sr_irq", CODE_FOR_bis_sr_irq},
+	{"__get_frame_address", CODE_FOR_get_frame_address},
+	{0, 0}
+};
+
+static int msp430_codegen_test_entry_idx = 3;	/* Still redefined later */
+
+void msp430_init_builtins(void)
+{
+	tree args;
+	int builtin_idx = 0;
+
+	args = tree_cons (NULL_TREE, integer_type_node, void_list_node);
+
+	add_builtin_function (msp430builtins[builtin_idx].name, 
+		build_function_type (void_type_node, args),
+		builtin_idx, BUILT_IN_MD, NULL, NULL_TREE);
+
+	builtin_idx++;
+
+	add_builtin_function (msp430builtins[builtin_idx].name, 
+		build_function_type (void_type_node, args),
+		builtin_idx, BUILT_IN_MD, NULL, NULL_TREE);
+
+	builtin_idx++;
+
+	args = tree_cons (NULL_TREE, void_type_node, void_list_node);
+	add_builtin_function (msp430builtins[builtin_idx].name, 
+		build_function_type (ptr_type_node, args),
+		builtin_idx, BUILT_IN_MD, NULL, NULL_TREE);
+
+	builtin_idx++;
+
+	args = tree_cons (NULL_TREE, void_type_node, void_list_node);
+	add_builtin_function ("__msp430_codegen_test_entry", 
+		build_function_type (void_type_node, args),
+		builtin_idx, BUILT_IN_MD, NULL, NULL_TREE);
+
+	msp430_codegen_test_entry_idx = builtin_idx;
+
+	builtin_idx++;
+}
+
+#include "framehelpers.inl"
+
+static void msp430_codegen_test(void)
+{
+	emit_insn(gen_nop());
+
+	/*
+	msp430_fh_emit_push_reg(7);
+	msp430_fh_sub_sp_const(6);
+	msp430_fh_gen_mov_r2r(7, 6);
+	*/
+	//msp430_fh_load_sp_with_sym_plus_off("__stack", -10);
+	//msp430_fh_br_to_symbol_plus_offset("some_jump_target", -10);
+	msp430_fh_bic_deref_sp(0x0f);
+	/*
+	msp430_fh_add_sp_const(6);
+	msp430_fh_emit_pop_reg(7);
+	*/
+
+	emit_insn(gen_nop());
+}
+
+rtx msp430_expand_builtin(tree exp, rtx target ATTRIBUTE_UNUSED, 
+					  rtx subtarget ATTRIBUTE_UNUSED, 
+					  enum machine_mode mode ATTRIBUTE_UNUSED, 
+					  int ignore ATTRIBUTE_UNUSED)
+{
+	rtx arg=0, retval = 0;
+	rtx frame_offset_n;
+	rtx insn=0;
+	rtx symb, plus, con;
+	char *pos;
+	tree fndecl, argtree;
+	int i,  code;
+	rtx x = DECL_RTL (current_function_decl);
+	const char *fnname = XSTR (XEXP (x, 0), 0);
+
+#if GCC_VERSION_INT < 0x430
+	fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+#else
+	fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+#endif
+
+	argtree = TREE_OPERAND (exp, 1);
+	i = DECL_FUNCTION_CODE (fndecl);
+
+	if (i == msp430_codegen_test_entry_idx)
+	{
+		msp430_codegen_test();
+		return NULL;
+	}
+
+	code = msp430builtins[i].md_code;
+
+	pos = (char*)ggc_alloc(16+strlen(fnname)+1);
+	snprintf(pos,16+strlen(fnname)+1,".L__FrameOffset_%s",fnname);
+
+	symb = gen_rtx_REG(HImode,1);
+	con = gen_rtx_SYMBOL_REF(HImode, pos);
+	plus = gen_rtx_PLUS(HImode, symb, con);  
+	frame_offset_n = gen_rtx_MEM(HImode, plus);
+
+	if(code == CODE_FOR_bic_sr_irq || code == CODE_FOR_bis_sr_irq)
+	{
+#if GCC_VERSION_INT < 0x430
+		arg = expand_expr (TREE_VALUE (argtree), NULL_RTX, VOIDmode, 0);
+#else
+		arg = expand_expr (CALL_EXPR_ARG(exp, 0), NULL_RTX, VOIDmode, 0);
+#endif
+	}
+
+	if(code == CODE_FOR_bic_sr_irq)
+		insn = gen_rtx_SET(HImode, frame_offset_n,
+		gen_rtx_UNSPEC_VOLATILE(HImode,
+		gen_rtvec(2,arg, GEN_INT(4100001)),41));
+	else if(code == CODE_FOR_bis_sr_irq)
+		insn = gen_rtx_SET(HImode, frame_offset_n,
+		gen_rtx_UNSPEC_VOLATILE(HImode,
+		gen_rtvec(2,arg, GEN_INT(4200002)),42));
+	else if(code == CODE_FOR_get_frame_address)
+	{
+		retval = gen_reg_rtx(HImode);
+		insn = gen_rtx_SET(HImode, retval, 
+			gen_rtx_UNSPEC_VOLATILE(HImode,
+			gen_rtvec(2,frame_offset_n, GEN_INT(4300003)),43));
+	}
+	else
+		error("Unknown built-in function");
+
+	if(insn)
+		emit_insn(insn);
+	else
+		error("Unknown built-in function");
+
+	return retval;
+}
\ No newline at end of file
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-cbranch.c gcc-4.4.5/gcc/config/msp430/msp430-cbranch.c
--- gcc-4.x/gcc/config/msp430/msp430-cbranch.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-cbranch.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,680 @@
+/* This work is partially financed by the European Commission under the
+* Framework 6 Information Society Technologies Project
+* "Wirelessly Accessible Sensor Populations (WASP)".
+*/
+
+/*
+GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "tree.h"
+#include "output.h"
+#include "expr.h"
+#include "toplev.h"
+#include "obstack.h"
+#include "function.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "insn-codes.h"
+#include "ggc.h"
+#include "langhooks.h"
+
+static const char *msp430_emit_blt0si (rtx operands[], int len);
+static const char *msp430_emit_beq (rtx operands[], int len);
+static const char *msp430_emit_bne (rtx operands[], int len);
+static const char *msp430_emit_bgt (rtx operands[], int len);
+static const char *msp430_emit_bgtu (rtx operands[], int len);
+static const char *msp430_emit_blt (rtx operands[], int len);
+static const char *msp430_emit_bltnoovfl (rtx operands[], int len);
+static const char *msp430_emit_bltu (rtx operands[], int len);
+static const char *msp430_emit_bge (rtx operands[], int len);
+static const char *msp430_emit_bgeu (rtx operands[], int len);
+static const char *msp430_emit_ble (rtx operands[], int len);
+static const char *msp430_emit_bleu (rtx operands[], int len);
+
+static int msp430_cc_source (rtx, enum rtx_code, rtx, rtx);
+
+#define OUT_INSN(x,p,o) \
+	do {                            \
+	if(!x) output_asm_insn (p,o);   \
+	} while(0)
+
+
+const char *msp430_cbranch (rtx insn, rtx operands[], int *len, int is_cc0_branch)
+{
+	rtx ops[3];
+	enum rtx_code code;
+	rtx locs[3];
+	int dummy = 0;
+	enum machine_mode mode;
+	int quater = 0;
+	rtx loc = operands[0];
+	int distance = msp430_jump_dist (loc, insn);
+	int predist = 0;
+	int nooverflow = 0;
+
+#define ECOND(f,x) do{if(!len)msp430_emit_b##f(locs,predist + x);dummy+=(predist + x);}while(0)
+	locs[0] = operands[0];
+	ops[0] = operands[2];
+	ops[1] = operands[3];
+
+	if (ops[1] && ops[0])
+	{
+		mode = GET_MODE (operands[2]);
+		code = GET_CODE (operands[1]);
+		quater = (mode == QImode);
+	}
+	else
+	{
+		mode = HImode;
+		code = GET_CODE (operands[1]);
+	}
+
+	/* here check wiered conditions */
+	if (ops[1] && GET_CODE (ops[1]) == CONST_INT
+		&& (code == GT || code == LE || code == GTU || code == LEU))
+	{
+		int x = INTVAL (ops[1]);
+		switch (code)
+		{
+		case GT:
+			ops[1] = GEN_INT (x + 1);
+			code = GE;
+			break;
+		case LE:
+			ops[1] = GEN_INT (x + 1);
+			code = LT;
+			break;
+		case GTU:
+			ops[1] = GEN_INT (x + 1);
+			code = GEU;
+			break;
+		case LEU:
+			ops[1] = GEN_INT (x + 1);
+			code = LTU;
+			break;
+		default:
+			break;
+		}
+	}
+	else if (ops[1] && CONSTANT_P (ops[1]) && GET_MODE(ops[1]) == HImode
+		&& (code == GT || code == LE || code == GTU || code == LEU))
+	{
+		/* Handle pointers here */
+		ops[1] = gen_rtx_CONST(HImode,gen_rtx_PLUS(HImode,ops[1],GEN_INT(1)));
+
+		switch (code)
+		{
+		case GT:
+			code = GE;
+			break;
+		case LE:
+			code = LT;
+			break;
+		case GTU:
+			code = GEU;
+			break;
+		case LEU:
+			code = LTU;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!is_cc0_branch && ops[0] != cc0_rtx && ops[1] && ops[0])
+	{
+		if (code == NE || code == EQ)
+		{
+			/* check if op0 is zero shited - win 1 byte */
+			if (indexed_location (ops[0]) && !CONSTANT_P (ops[1]))
+			{
+				rtx x = ops[0];
+				ops[0] = ops[1];
+				ops[1] = x;
+			}
+		}
+
+		/* check if compares were not issued */
+		if ((mode == QImode || mode == HImode)
+			&& msp430_cc_source (insn, code, ops[0], ops[1]))
+		{
+			/* check if overflow can be usefull here. */
+			if( ops[1] == const0_rtx 
+				|| (GET_CODE(ops[1]) == CONST_INT
+				&& INTVAL(ops[1]) == 0 ))
+			{
+				if(code == LT || code == GE)
+					nooverflow = 1;
+			}
+		}
+		else if (mode == QImode || mode == HImode)
+		{
+			/* check if previous insns did not set CC correctly */
+			if (quater)
+				OUT_INSN (len, "cmp.b\t%1, %0", ops);
+			else
+				OUT_INSN (len, "cmp\t%1, %0", ops);
+			dummy += 3;
+			if (REG_P (ops[0]))
+				dummy--;
+			if (REG_P (ops[1]))
+				dummy--;
+			if (indexed_location (ops[1]))
+				dummy--;
+			if (GET_CODE (ops[1]) == CONST_INT)
+			{
+				int x = INTVAL (ops[1]) & 0xffff;
+				if (x == 0 || x == -1 || x == 1 || x == 2 || x == 4 || x == 8)
+					dummy--;
+			}
+		}
+
+		/* adjust distance */
+		distance -= dummy;
+
+		if (mode == SImode && (code == EQ || code == NE))
+		{
+			/* compare against zero and can we clobber source register ? */
+			if (((GET_CODE (ops[1]) == CONST_INT
+				&& INTVAL (ops[1]) == 0)
+				|| ops[1] == const0_rtx)
+				&& REG_P (ops[0]) && dead_or_set_p (insn, ops[0]))
+			{
+				OUT_INSN (len, "bis\t%A0, %B0", ops);
+				OUT_INSN (len, "tst\t%B0", ops);
+				dummy += 2;
+			}
+			else
+			{
+				/* cannot clobber or something... */
+				OUT_INSN (len, "cmp\t%A1, %A0", ops);
+				dummy += 3;
+				if (REG_P (ops[0]))
+					dummy--;
+				if (REG_P (ops[1]))
+					dummy--;
+				if (indexed_location (ops[1]))
+					dummy--;
+				if (GET_CODE (ops[1]) == CONST_INT)
+				{
+					int x = INTVAL (ops[1]) & 0xffff;
+					if (x == 0 || x == 1 || x == -1 || x == 2 || x == 4
+						|| x == 8)
+						dummy--;
+				}
+				distance -= dummy;
+				if (distance > 500 || distance < -500)
+					predist = 3;
+				else
+					predist = 1;
+
+				if (code == EQ)
+				{
+					OUT_INSN (len, "jne\t.LcmpSIe%=", ops);
+					OUT_INSN (len, "cmp\t%B1, %B0", ops);
+					dummy++;
+				}
+				else
+				{
+					ECOND (ne, 0);
+					OUT_INSN (len, "cmp\t%B1, %B0", ops);
+				}
+
+				dummy += 3;
+				if (REG_P (ops[0]))
+					dummy--;
+				if (REG_P (ops[1]))
+					dummy--;
+				if (GET_CODE (ops[1]) == CONST_INT)
+				{
+					int x = (INTVAL (ops[1]) >> 16) & 0xffff;
+					if (x == 0 || x == 0xffff || x == 1 || x == 2 || x == 4
+						|| x == 8)
+						dummy--;
+				}
+			}
+		}
+		else if (mode == SImode)
+		{
+			int dl = 0;
+			rtx oops[3];
+			oops[0] = ops[0];
+			oops[1] = ops[0];
+			oops[2] = ops[1];
+
+			if (len)
+				msp430_subsi_code (insn, oops, &dl);
+			else
+				msp430_subsi_code (insn, oops, NULL);
+
+			if (len)
+			{
+				/* not handeled by adjust_insn_len() */
+				dummy += dl;
+				if (GET_CODE (ops[1]) == CONST_INT)
+				{
+					int x = (INTVAL (ops[1]) >> 16) & 0xffff;
+					if (x == 0 || x == 1 || x == -1 || x == 2 || x == 4
+						|| x == 8)
+						dummy--;
+					x = (INTVAL (ops[1]) >> 0) & 0xffff;
+					if (x == 0 || x == 1 || x == -1 || x == 2 || x == 4
+						|| x == 8)
+						dummy--;
+				}
+			}
+		}
+	}
+
+	distance -= dummy;
+
+	if (distance > 500 || distance < -500)
+		predist = 3;
+	else
+		predist = 1;
+
+	/* out assembler commands if required */
+	switch (code)
+	{
+	case EQ:
+		ECOND (eq, 0);
+		if (mode == SImode)
+		{
+			OUT_INSN (len, ".LcmpSIe%=:", operands);
+		}
+		break;
+	case NE:
+		ECOND (ne, 0);
+		break;
+	case LT:
+		if(nooverflow)
+			ECOND (ltnoovfl,0);
+		else
+			ECOND (lt, 0);
+		break;
+	case GE:
+		if(nooverflow)
+		{
+			if(len) *len += 2;
+			if(mode == QImode)
+				OUT_INSN (len, "bit.b\t#0x80, %0",ops);
+			else
+				OUT_INSN (len, "bit\t#0x8000, %0",ops);
+		}
+		ECOND (ge, 0);
+		break;
+	case LTU:
+		ECOND (ltu, 0);
+		break;
+	case GEU:
+		ECOND (geu, 0);
+		break;
+		/* hopfully the following will not occure */
+	case LEU:
+		ECOND (leu, 1);
+		break;
+	case GT:
+		ECOND (gt, 1);
+		break;
+	case GTU:
+		ECOND (gtu, 1);
+		break;
+	case LE:
+		ECOND (le, 1);
+		break;
+
+	default:
+		break;
+	}
+
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+
+static const char *msp430_emit_blt0si (rtx operands[], int len)
+{
+	output_asm_insn ("tst\t%B2", operands);
+	switch (len)
+	{
+	case 2:
+		output_asm_insn ("jl\t%0", operands);
+		break;
+	case 4:
+		output_asm_insn ("jge\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_beq (rtx operands[], int len)
+{
+
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jeq\t%0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jne\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bne (rtx operands[], int len)
+{
+
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jne\t%0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jeq\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bgt (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 2:
+		output_asm_insn ("jeq\t+2", operands);
+		output_asm_insn ("jge\t%0", operands);
+
+		break;
+	case 4:
+		output_asm_insn ("jeq\t+6", operands);
+		output_asm_insn ("jl\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bgtu (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 2:
+		output_asm_insn ("jeq\t+2", operands);
+		output_asm_insn ("jhs\t%0", operands);
+
+		break;
+	case 4:
+		output_asm_insn ("jeq\t+6", operands);
+		output_asm_insn ("jlo\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_blt (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jl\t%0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jge\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+
+static const char *msp430_emit_bltnoovfl (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jn\t%0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jn\t+2",operands);
+		output_asm_insn ("jmp\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bltu (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jlo\t%0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jhs\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bge (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jge\t%l0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jl\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bgeu (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 1:
+	case 2:
+		output_asm_insn ("jhs\t%l0", operands);
+		break;
+	case 3:
+	case 4:
+		output_asm_insn ("jlo\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_ble (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 2:
+		output_asm_insn ("jeq\t%0", operands);
+		output_asm_insn ("jl\t%0", operands);
+		break;
+	case 4:
+		output_asm_insn ("jeq\t+2", operands);
+		output_asm_insn ("jge\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+static const char *msp430_emit_bleu (rtx operands[], int len)
+{
+	switch (len)
+	{
+	case 2:
+		output_asm_insn ("jeq\t%0", operands);
+		output_asm_insn ("jlo\t%0", operands);
+		break;
+	case 4:
+		output_asm_insn ("jeq\t+2", operands);
+		output_asm_insn ("jhs\t+4", operands);
+		output_asm_insn ("br\t#%0", operands);
+		break;
+	default:
+		return "bug!!!";
+	}
+
+	return "";
+}
+
+/*  x - dst
+y - src */
+static int msp430_cc_source (rtx insn, enum rtx_code code, rtx x, rtx y)
+{
+	rtx prev = insn;
+	enum attr_cc cc;
+	rtx set;
+	rtx src, dst;
+	rtx x1 = 0;
+
+	if(GET_CODE(x) == MEM)
+	{
+		x1 = XEXP(x,0);
+		if(GET_CODE(x1) == PLUS)
+		{
+			x1 = XEXP(x1,0);
+		}
+
+		if(!REG_P(x1)) x1 = 0;
+	}
+
+	while (0 != (prev = PREV_INSN (prev)))
+	{
+		if (GET_CODE (prev) == CODE_LABEL
+			|| GET_CODE (prev) == BARRIER || GET_CODE (prev) == CALL_INSN)
+			return 0;
+
+		if (GET_CODE (prev) == INSN)
+		{
+			set = single_set (prev);
+
+			if(!set)
+				return 0;
+
+			cc = get_attr_cc (prev);
+
+			if (cc == CC_NONE)	/* does not change CC */
+			{
+				/*The one spot by Nick C. */
+				dst = SET_DEST (set);
+				if((dst && rtx_equal_p (x, dst)) ||
+					(x1 && dst && rtx_equal_p (x1, dst)))
+					return 0;
+				else
+					continue;
+			}
+
+			if (cc == CC_CLOBBER)	/* clobber */
+				return 0;
+
+			if (cc == CC_OPER)	/* post-incremental stuff */
+			{
+				src = SET_SRC (set);
+				if (GET_CODE (set) == IOR)	/* does not change CC */
+				{
+					dst = SET_DEST (set);
+					if(dst && rtx_equal_p (x, dst))
+						return 0;
+					else
+						continue;
+				}
+			}
+
+			/* all other attributes are bit messy.
+			So, we'll record destination and check if 
+			this matches 'x' and compare is against zero */
+			dst = SET_DEST (set);
+			if (rtx_equal_p (x, dst) && rtx_equal_p (y, const0_rtx))
+				return 1;
+			else
+				return 0;
+		}
+		else if (GET_CODE (prev) == JUMP_INSN)
+		{
+			/* if 2 consequent jump insns were issued, this means
+			that operands (more likely src) are different.
+			however, some jumps optimization can equalize these operands
+			and everything will be bad. Therefore, assume that
+			any jump insn clobbers condition codes.*/
+			return 0;
+		}
+	}
+	return 0;
+}
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-emit-cbranch.c gcc-4.4.5/gcc/config/msp430/msp430-emit-cbranch.c
--- gcc-4.x/gcc/config/msp430/msp430-emit-cbranch.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-emit-cbranch.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,235 @@
+/* This work is partially financed by the European Commission under the
+* Framework 6 Information Society Technologies Project
+* "Wirelessly Accessible Sensor Populations (WASP)".
+*/
+
+/*
+GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "tree.h"
+#include "output.h"
+#include "expr.h"
+#include "toplev.h"
+#include "obstack.h"
+#include "function.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "insn-codes.h"
+#include "ggc.h"
+#include "langhooks.h"
+
+struct rtx_def *msp430_compare_op0;
+struct rtx_def *msp430_compare_op1;
+
+void msp430_emit_cbranch (enum rtx_code code, rtx loc)
+{
+	rtx op0 = msp430_compare_op0;
+	rtx op1 = msp430_compare_op1;
+	rtx condition_rtx, loc_ref, branch;
+	enum machine_mode mode;
+	int mem_volatil=0;
+
+	if (!msp430_compare_op0 && !msp430_compare_op1)
+	{
+		/* this is a branch upon previous insn issued */
+		loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+		condition_rtx = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
+
+		branch = gen_rtx_SET (VOIDmode,
+			pc_rtx,
+			gen_rtx_IF_THEN_ELSE (VOIDmode,
+			condition_rtx,
+			loc_ref, pc_rtx));
+		emit_jump_insn (branch);
+		return;
+	}
+
+	mode = GET_MODE (op0);
+	if (mode != SImode && mode != HImode && mode != QImode)
+		abort ();
+
+
+	/* now convert codes */
+	code = msp430_canonicalize_comparison (code, &op0, &op1);
+
+	/* for HI and QI modes everything is simple.
+	Also, if code is eq or ne in SI mode, no clobbers required. */
+
+	if (mode == SImode && !(code == EQ || code == NE))
+	{
+		/* check if only high nibbles required */
+		if (GET_CODE (op1) == CONST_INT
+			&& INTVAL (op1) == 0 && (code == LT || code == GE))
+		{
+			mem_volatil = MEM_VOLATILE_P(op0);
+			MEM_VOLATILE_P(op0) = 0;
+			op0 = gen_highpart (HImode, op0);
+			MEM_VOLATILE_P(op0) = mem_volatil;
+			mode = HImode;
+			PUT_MODE (op1, VOIDmode);	/* paranoia ? */
+		}
+		else if (GET_CODE (op1) == CONST_INT
+			&& ((INTVAL (op1) + 1) & 0xffff) == 0
+			&& (code == GT || code == GTU || code == LE || code == LEU))
+		{
+			/* check if this can be done simple. 
+			we will not clobber const operand. */
+			int x = INTVAL (op1);
+			x++;
+			x >>= 16;
+			MEM_VOLATILE_P(op0) = 0;
+			op0 = gen_highpart (HImode, op0);
+			MEM_VOLATILE_P(op0) = mem_volatil;
+			mode = HImode;
+			op1 = GEN_INT (trunc_int_for_mode (x, HImode));
+
+			if (code == GT)
+				code = GE;
+			else if (code == GTU)
+				code = GEU;
+			else if (code == LEU)
+				code = LTU;
+			else if (code == LE)
+				code = LT;
+		}
+		else
+		{
+			rtvec vec;
+			/* the redudant move will be deleted */
+			op0 = copy_to_mode_reg (SImode, op0);
+			condition_rtx = gen_rtx_fmt_ee (code, mode, op0, op1);
+			loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+			branch = gen_rtx_SET (VOIDmode, pc_rtx,
+				gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+				loc_ref, pc_rtx));
+			vec = gen_rtvec (2, branch, gen_rtx_CLOBBER (SImode, op0));
+			emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+			msp430_compare_op0 = 0;
+			msp430_compare_op1 = 0;
+			return;
+		}
+	}
+	else if(mode == SImode && code == NE
+		&& GET_CODE(op1)!= CONST_INT && op1 != const0_rtx)
+	{
+		rtx op0lo, op0hi, op1lo, op1hi;
+
+		mem_volatil = MEM_VOLATILE_P(op0);
+		op0lo = gen_lowpart(HImode, op0);
+		op0hi = gen_highpart(HImode, op0);
+		MEM_VOLATILE_P(op0) = mem_volatil;
+
+		mem_volatil = MEM_VOLATILE_P(op1);
+		op1lo = gen_lowpart(HImode, op1);
+		op1hi = gen_highpart(HImode, op1);
+		MEM_VOLATILE_P(op1) = mem_volatil;
+
+		condition_rtx = gen_rtx_fmt_ee (NE,HImode,op0lo,op1lo);
+		loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+		branch = gen_rtx_SET (VOIDmode, pc_rtx,
+			gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+			loc_ref, pc_rtx));
+		emit_jump_insn (branch);
+		condition_rtx = gen_rtx_fmt_ee (NE,HImode,op0hi,op1hi);
+		branch = gen_rtx_SET (VOIDmode, pc_rtx,
+			gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+			loc_ref, pc_rtx));
+		emit_jump_insn (branch);
+		msp430_compare_op0 = 0;
+		msp430_compare_op1 = 0;
+		return;
+	}
+	else if(mode == SImode && code == EQ && GET_CODE(op1)!= CONST_INT )
+	{
+		rtx tlabel = gen_label_rtx();
+		rtx tloc_ref;
+		rtx op0lo, op0hi, op1lo, op1hi;
+
+		mem_volatil = MEM_VOLATILE_P(op0);
+		op0lo = gen_lowpart(HImode, op0);
+		op0hi = gen_highpart(HImode, op0);
+		MEM_VOLATILE_P(op0) = mem_volatil;
+
+		mem_volatil = MEM_VOLATILE_P(op1);
+		op1lo = gen_lowpart(HImode, op1);
+		op1hi = gen_highpart(HImode, op1);
+		MEM_VOLATILE_P(op1) = mem_volatil;
+
+		condition_rtx = gen_rtx_fmt_ee (NE,HImode,op0lo,op1lo);
+		tloc_ref = gen_rtx_LABEL_REF (VOIDmode, tlabel);
+		branch = gen_rtx_SET (VOIDmode, pc_rtx,
+			gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+			tloc_ref, pc_rtx));
+		emit_jump_insn (branch);
+
+		condition_rtx = gen_rtx_fmt_ee (EQ,HImode,op0hi,op1hi);
+		loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+		branch = gen_rtx_SET (VOIDmode, pc_rtx,
+			gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+			loc_ref, pc_rtx));
+		emit_jump_insn (branch);
+		emit_label(tlabel);
+		msp430_compare_op0 = 0;
+		msp430_compare_op1 = 0;
+		return ;
+	}
+
+	condition_rtx = gen_rtx_fmt_ee (code, mode, op0, op1);
+	loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+	branch = gen_rtx_SET (VOIDmode, pc_rtx,
+		gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
+		loc_ref, pc_rtx));
+
+	emit_jump_insn (branch);
+
+	msp430_compare_op0 = 0;
+	msp430_compare_op1 = 0;
+	return;
+}
+
+RTX_CODE msp430_canonicalize_comparison (RTX_CODE code, rtx *op0, rtx *op1)
+{
+	RTX_CODE rc = code;
+
+	if ( CONSTANT_P(*op1) )
+	{
+		;				/* nothing to be done */
+	}
+	else
+	{
+		switch (code)
+		{
+		case GT:
+		case LE:
+		case GTU:
+		case LEU:
+			{
+				rtx x;
+				rc = swap_condition (code);
+				x = *op0;
+				*op0 = *op1;
+				*op1 = x;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return rc;
+}
\ No newline at end of file
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-function.c gcc-4.4.5/gcc/config/msp430/msp430-function.c
--- gcc-4.x/gcc/config/msp430/msp430-function.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-function.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,781 @@
+/* This work is partially financed by the European Commission under the
+* Framework 6 Information Society Technologies Project
+* "Wirelessly Accessible Sensor Populations (WASP)".
+*/
+
+/*
+GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "tree.h"
+#include "output.h"
+#include "expr.h"
+#include "toplev.h"
+#include "obstack.h"
+#include "function.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "insn-codes.h"
+#include "ggc.h"
+#include "langhooks.h"
+#include "msp430-predicates.inl"
+
+#if GCC_VERSION_INT < 0x430
+static inline int df_regs_ever_live_p(int reg)
+{
+	return regs_ever_live[reg];
+}
+#endif
+
+extern int msp430_commands_in_file;
+extern int msp430_commands_in_prologues;
+extern int msp430_commands_in_epilogues;
+
+/* ret/reti issue indicator for _current_ function */
+static int return_issued = 0;
+
+/* Prologue/Epilogue size in words */
+static int prologue_size;
+static int epilogue_size;
+
+/* Size of all jump tables in the current function, in words.  */
+static int jump_tables_size;
+
+/* This holds the last insn address.  */
+static int last_insn_address = 0;
+
+static int msp430_func_num_saved_regs (void);
+
+/* actual frame offset */
+static int msp430_current_frame_offset = 0;
+
+/* registers used for incoming funct arguments */
+static char arg_register_used[16];
+
+#define FIRST_CUM_REG 16
+static CUMULATIVE_ARGS *cum_incoming = 0;
+
+static int msp430_num_arg_regs (enum machine_mode mode, tree type);
+static int msp430_saved_regs_frame (void);
+
+void msp430_function_end_prologue (FILE * file);
+void msp430_function_begin_epilogue (FILE * file);
+
+int msp430_epilogue_uses (int regno ATTRIBUTE_UNUSED)
+{
+	if (reload_completed 
+		&& cfun->machine
+		&& (cfun->machine->is_interrupt || cfun->machine->is_signal))
+		return 1;
+	return 0;
+}
+
+
+void msp430_function_end_prologue (FILE * file)
+{
+	HOST_WIDE_INT frameSize = get_frame_size();
+	rtx functionExp = DECL_RTL (current_function_decl);
+	const char *functionName = XSTR (XEXP (functionExp, 0), 0);
+
+	if (cfun->machine->is_naked)
+	{
+		fprintf (file, "\t/* prologue: naked */\n");
+		fprintf (file, ".L__FrameSize_%s=0x%x\n", functionName, (unsigned)frameSize);
+	}
+	else
+	{
+		int offset = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - 2;
+		fprintf (file, "\t/* prologue ends here (frame size = %d) */\n", (unsigned)frameSize);
+		fprintf (file, ".L__FrameSize_%s=0x%x\n", functionName, (unsigned)frameSize);
+		fprintf (file, ".L__FrameOffset_%s=0x%x\n", functionName, (unsigned)offset);
+	}
+}
+
+void msp430_function_begin_epilogue (FILE * file)
+{
+	if (cfun->machine->is_OS_task)
+		fprintf (file, "\n\t/* epilogue: empty, task functions never return */\n");
+	else if (cfun->machine->is_naked)
+		fprintf (file, "\n\t/* epilogue: naked */\n");
+	else if (msp430_empty_epilogue ())
+		fprintf (file, "\n\t/* epilogue: not required */\n");
+	else
+		fprintf (file, "\n\t/* epilogue: frame size = %d */\n", (unsigned)get_frame_size());
+}
+
+static int msp430_get_stack_reserve(void);
+
+static int msp430_get_stack_reserve(void)
+{
+	int stack_reserve = 0;
+	tree ss = lookup_attribute ("reserve", DECL_ATTRIBUTES (current_function_decl));
+	if (ss)
+	{
+		ss = TREE_VALUE (ss);
+		if (ss)
+		{
+			ss = TREE_VALUE (ss);
+			if (ss)
+				stack_reserve = TREE_INT_CST_LOW (ss);
+			stack_reserve++;
+			stack_reserve &= ~1;
+		}
+	}
+	return stack_reserve;
+}
+
+#include "framehelpers.inl"
+
+void expand_prologue (void)
+{
+	int i;
+	int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
+	int stack_reserve = 0;
+	int offset;
+	int save_prologue_p = msp430_save_prologue_function_p (current_function_decl);
+	int num_saved_regs;
+	HOST_WIDE_INT size = get_frame_size();
+
+	rtx insn;	/* Last generated instruction */
+
+	return_issued = 0;
+	last_insn_address = 0;
+	jump_tables_size = 0;
+	prologue_size = 0;
+
+	cfun->machine->is_naked = msp430_naked_function_p (current_function_decl);
+	cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
+	cfun->machine->is_OS_task = msp430_task_function_p (current_function_decl);
+	
+	cfun->machine->is_noint_hwmul = noint_hwmul_function_p (current_function_decl);
+	cfun->machine->is_critical = msp430_critical_function_p(current_function_decl);
+	cfun->machine->is_reenterant = msp430_reentrant_function_p(current_function_decl);
+	cfun->machine->is_wakeup = wakeup_function_p (current_function_decl);
+	cfun->machine->is_signal = signal_function_p (current_function_decl);
+
+
+	/* check attributes compatibility */
+
+	if ((cfun->machine->is_critical && cfun->machine->is_reenterant) || (cfun->machine->is_reenterant && cfun->machine->is_interrupt))
+	{
+		warning (OPT_Wattributes, "attribute 'reentrant' ignored");
+		cfun->machine->is_reenterant = 0;
+	}
+
+	if (cfun->machine->is_critical && cfun->machine->is_interrupt)
+	{
+		warning (OPT_Wattributes, "attribute 'critical' ignored");
+		cfun->machine->is_critical = 0;
+	}
+
+	if (cfun->machine->is_signal && !cfun->machine->is_interrupt)
+	{
+		warning (OPT_Wattributes, "attribute 'signal' has no meaning on MSP430 without 'interrupt' attribute.");
+		cfun->machine->is_signal = 0;
+	}
+
+	/* naked function discards everything */
+	if (cfun->machine->is_naked)
+		return;
+
+	stack_reserve = msp430_get_stack_reserve();
+	offset = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - 2;
+
+	msp430_current_frame_offset = offset;
+
+	if (cfun->machine->is_signal && cfun->machine->is_interrupt)
+	{
+		prologue_size += 1;
+
+		insn = emit_insn (gen_enable_interrupt());
+		/* fprintf (file, "\teint\t; enable nested interrupt\n"); */
+	}
+
+	if (main_p)
+	{
+		if (TARGET_NO_STACK_INIT)
+		{
+			if (size || stack_reserve)
+			{
+				/* fprintf (file, "\tsub\t#%d, r1\t", size + stack_reserve); */
+
+				msp430_fh_sub_sp_const(size + stack_reserve);
+			}
+			
+			if (frame_pointer_needed)
+			{
+				/* fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM); */
+				insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+				RTX_FRAME_RELATED_P (insn) = 1;
+
+				prologue_size += 1;
+			}
+			
+			if (size)
+				prologue_size += 2;
+			if (size == 1 || size == 2 || size == 4 || size == 8)
+				prologue_size--;
+		}
+		else
+		{
+			/*fprintf (file, "\tmov\t#(%s-%d), r1\n", msp430_init_stack, size + stack_reserve);*/
+			msp430_fh_load_sp_with_sym_plus_off(msp430_init_stack, -(size + stack_reserve));
+
+			if (frame_pointer_needed)
+			{
+				/* fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM); */
+
+				insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+				RTX_FRAME_RELATED_P (insn) = 1;
+
+				prologue_size += 1;
+			}
+			prologue_size += 2;
+		}
+		if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
+			msp430_fh_sub_sp_const(crtl->outgoing_args_size);
+	}
+	else	/* not a main() function */
+	{
+		/* Here, we've got a chance to jump to prologue saver */
+		num_saved_regs = msp430_func_num_saved_regs ();
+
+		if (!cfun->machine->is_interrupt && cfun->machine->is_critical)
+		{
+			prologue_size += 3;
+			/*fprintf (file, "\tpush\tr2\n");
+			fprintf (file, "\tdint\n");
+			if (!size)
+				fprintf (file, "\tnop\n");*/
+
+			insn = emit_insn (gen_push_sreg()); /* Pushing R2 using normal push creates a faulty INSN */
+			RTX_FRAME_RELATED_P (insn) = 1;
+			
+			insn = emit_insn (gen_disable_interrupt());
+			if (!size)
+				insn = emit_insn (gen_nop());
+		}
+
+		if ((TARGET_SAVE_PROLOGUE || save_prologue_p)
+			&& !cfun->machine->is_interrupt && !arg_register_used[12] && num_saved_regs > 4)
+		{
+			/* TODO: Expand this as a separate INSN called "call prologue saver", having a meaning of pushing the registers and decreasing SP, 
+				so that the debug info generation code will handle this correctly */
+			
+			/*fprintf (file, "\tsub\t#16, r1\n");
+			fprintf (file, "\tmov\tr0, r12\n");
+			fprintf (file, "\tadd\t#8, r12\n");
+			fprintf (file, "\tbr\t#__prologue_saver+%d\n", (8 - num_saved_regs) * 4);*/
+
+			msp430_fh_sub_sp_const(16);
+			msp430_fh_gen_mov_pc_to_reg(12);
+			msp430_fh_add_reg_const(12, 8);
+			msp430_fh_br_to_symbol_plus_offset("__prologue_saver", (8 - num_saved_regs) * 4);
+
+			if (cfun->machine->is_critical && 8 - num_saved_regs)
+			{
+				int n = 16 - num_saved_regs * 2;
+				/*fprintf (file, "\tadd\t#%d, r1\n", n);*/
+				msp430_fh_add_sp_const(n);
+				if (n != 0 && n != 1 && n != 2 && n != 4 && n != 8)
+					prologue_size += 1;
+			}
+			else
+				size -= 16 - num_saved_regs * 2;
+
+			prologue_size += 7;
+		}
+		else if(!cfun->machine->is_OS_task)
+		{
+			for (i = 15; i >= 4; i--)
+			{
+				if ((df_regs_ever_live_p(i) && (!call_used_regs[i] || cfun->machine->is_interrupt)) || 
+					(!cfun->machine->is_leaf && (call_used_regs[i] && (cfun->machine->is_interrupt))))
+				{
+					/*fprintf (file, "\tpush\tr%d\n", i);*/
+					msp430_fh_emit_push_reg(i);
+					prologue_size += 1;
+				}
+			}
+		}
+
+		if (size)
+		{
+			/* The next is a hack... I do not understand why, but if there
+			ARG_POINTER_REGNUM and FRAME/STACK are different, 
+			the compiler fails to compute corresponding
+			displacement */
+			if (!optimize && !optimize_size
+				&& df_regs_ever_live_p(ARG_POINTER_REGNUM))
+			{
+				int o = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - size;
+				
+				/* fprintf (file, "\tmov\tr1, r%d\n", ARG_POINTER_REGNUM);
+				fprintf (file, "\tadd\t#%d, r%d\n", o, ARG_POINTER_REGNUM); */
+
+				insn = emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
+				RTX_FRAME_RELATED_P (insn) = 1;
+				msp430_fh_add_reg_const(ARG_POINTER_REGNUM, o);
+
+				prologue_size += 2;
+				if (o != 0 && o != 1 && o != 2 && o != 4 && o != 8)
+					prologue_size += 1;
+			}
+
+			/* adjust frame ptr... */
+			if (size < 0)
+			{
+				int subtracted = (size + 1) & ~1;
+				/*fprintf (file, "\tsub\t#%d, r1\t;	%d, fpn %d\n", subtracted, size, frame_pointer_needed);*/
+				msp430_fh_sub_sp_const(subtracted);
+				
+			}
+			else
+			{
+				int added;
+				size = -size;
+				added = (size + 1) & ~1;
+				/*fprintf (file, "\tadd\t#%d, r1\t;    %d, fpn %d\n", (size + 1) & ~1, size, frame_pointer_needed);*/
+				msp430_fh_add_sp_const(added);
+			}
+
+			if (size == 1 || size == 2 || size == 4 || size == 8)
+				prologue_size += 1;
+			else
+				prologue_size += 2;
+		}
+
+		if (frame_pointer_needed)
+		{
+			/*fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM);*/
+
+			insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+			RTX_FRAME_RELATED_P (insn) = 1;
+
+			prologue_size += 1;
+		}
+
+		if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
+			msp430_fh_sub_sp_const(crtl->outgoing_args_size);
+
+			/* disable interrupt for reentrant function */
+		if (!cfun->machine->is_interrupt && cfun->machine->is_reenterant)
+		{
+			prologue_size += 1;
+			/*fprintf (file, "\tdint\n");*/
+			insn = emit_insn (gen_disable_interrupt());
+		}
+	}
+
+	/*fprintf (file, "\t/ * prologue end (size=%d) * /\n\n", prologue_size);*/
+}
+
+
+/* Output function epilogue */
+
+void expand_epilogue (void)
+{
+	int i;
+	int interrupt_func_p = cfun->machine->is_interrupt;
+	int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
+	int wakeup_func_p = cfun->machine->is_wakeup;
+	int cfp = cfun->machine->is_critical;
+	int ree = cfun->machine->is_reenterant;
+	int save_prologue_p = msp430_save_prologue_function_p (current_function_decl);
+	/*int function_size;*/
+	HOST_WIDE_INT size = get_frame_size();
+
+	rtx insn;
+
+
+	last_insn_address = 0;
+	jump_tables_size = 0;
+	epilogue_size = 0;
+	/*function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ())) - INSN_ADDRESSES (INSN_UID (get_insns ())));*/
+
+	if (cfun->machine->is_OS_task || cfun->machine->is_naked)
+	{
+		emit_jump_insn (gen_return ());	/* Otherwise, epilogue with 0 instruction causes a segmentation fault */
+		return;
+	}
+
+	if (msp430_empty_epilogue ())
+	{
+		if (!return_issued)
+		{
+			/*fprintf (file, "\t%s\n", msp430_emit_return (NULL, NULL, NULL));*/
+			emit_jump_insn (gen_return ());
+			epilogue_size++;
+		}
+		/*fprintf (file, "\n\t/ * epilogue: not required * /\n");*/
+		goto done_epilogue;
+	}
+
+	if ((cfp || interrupt_func_p) && ree)
+		ree = 0;
+	if (cfp && interrupt_func_p)
+		cfp = 0;
+
+	/*fprintf (file, "\n\t/ * epilogue : frame size = %d * /\n", size);*/
+
+	if (main_p)
+	{
+		int totalsize = (size + 1) & ~1;
+		if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
+			totalsize += crtl->outgoing_args_size;
+		if (totalsize)
+		{
+			msp430_fh_add_sp_const(totalsize);
+			/*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/
+		}
+		/*fprintf (file, "\tbr\t#%s\n", msp430_endup);*/
+		msp430_fh_br_to_symbol_plus_offset(msp430_endup, 0);
+		epilogue_size += 4;
+		if (size == 1 || size == 2 || size == 4 || size == 8)
+			epilogue_size--;
+	}
+	else
+	{
+		int totalsize = (size + 1) & ~1;
+		if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
+			totalsize += crtl->outgoing_args_size;
+
+			if (ree)
+		{
+			/*fprintf (file, "\teint\n");*/
+
+			insn = emit_insn (gen_enable_interrupt());
+
+			epilogue_size += 1;
+		}
+
+		if (totalsize)
+		{
+			/*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/
+			msp430_fh_add_sp_const(totalsize);
+
+			if (size == 1 || size == 2 || size == 4 || size == 8)
+				epilogue_size += 1;
+			else
+				epilogue_size += 2;
+		}
+
+		if ((TARGET_SAVE_PROLOGUE || save_prologue_p)
+			&& !interrupt_func_p && msp430_func_num_saved_regs () > 2)
+		{
+			/*fprintf (file, "\tbr\t#__epilogue_restorer+%d\n",(8 - msp430_func_num_saved_regs ()) * 2);*/
+
+			msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer", (8 - msp430_func_num_saved_regs ()) * 2);
+
+			epilogue_size += 2;
+		}
+		else if ((TARGET_SAVE_PROLOGUE || save_prologue_p) && interrupt_func_p)
+		{
+			/*fprintf (file, "\tbr\t#__epilogue_restorer_intr+%d\n", (12 - msp430_func_num_saved_regs ()) * 2);*/
+			msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer_intr", (12 - msp430_func_num_saved_regs ()) * 2);
+		}
+		else
+		{
+			for (i = 4; i < 16; i++)
+			{
+				if ((df_regs_ever_live_p(i)
+					&& (!call_used_regs[i]
+				|| interrupt_func_p))
+					|| (!cfun->machine->is_leaf && (call_used_regs[i] && interrupt_func_p)))
+				{
+					/*fprintf (file, "\tpop\tr%d\n", i);*/
+					msp430_fh_emit_pop_reg(i);
+					epilogue_size += 1;
+				}
+			}
+
+			if (interrupt_func_p && wakeup_func_p)
+			{
+				/*fprintf (file, "\tbic\t#0xf0,0(r1)\n");*/
+				msp430_fh_bic_deref_sp(0xF0);
+				epilogue_size += 3;
+			}
+			emit_jump_insn (gen_return ());
+			/*fprintf (file, "\tret\n");*/
+			epilogue_size += 1;
+		}
+	}
+
+	/*fprintf (file, "\t/ * epilogue end (size=%d) * /\n", epilogue_size);*/
+done_epilogue:
+	/*fprintf (file, "\t/ * function %s size %d (%d) * /\n", current_function_name, prologue_size + function_size + epilogue_size, function_size);*/
+
+	msp430_commands_in_file += prologue_size + /*function_size +*/ epilogue_size;
+	msp430_commands_in_prologues += prologue_size;
+	msp430_commands_in_epilogues += epilogue_size;
+}
+
+/* Returns a number of pushed registers */
+static int msp430_func_num_saved_regs (void)
+{
+	int i;
+	int saves = 0;
+	int interrupt_func_p = interrupt_function_p (current_function_decl);
+
+	for (i = 4; i < 16; i++)
+	{
+		if ((df_regs_ever_live_p(i)
+			&& (!call_used_regs[i]
+		|| interrupt_func_p))
+			|| (!cfun->machine->is_leaf && (call_used_regs[i] && interrupt_func_p)))
+		{
+			saves += 1;
+		}
+	}
+
+	return saves;
+}
+
+const char *msp430_emit_return (rtx insn ATTRIBUTE_UNUSED, rtx operands[] ATTRIBUTE_UNUSED, int *len ATTRIBUTE_UNUSED)
+{
+	return_issued = 1;
+	if (msp430_critical_function_p (current_function_decl) || interrupt_function_p(current_function_decl))
+		return "reti";
+
+	return "ret";
+}
+
+void msp430_output_addr_vec_elt (FILE *stream, int value)
+{
+	fprintf (stream, "\t.word	.L%d\n", value);
+	jump_tables_size++;
+}
+
+/* Output all insn addresses and their sizes into the assembly language
+output file.  This is helpful for debugging whether the length attributes
+in the md file are correct.
+Output insn cost for next insn.  */
+
+void final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, int num_operands ATTRIBUTE_UNUSED)
+{
+	int uid = INSN_UID (insn);
+
+	if (TARGET_ALL_DEBUG)
+	{
+		fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
+			INSN_ADDRESSES (uid),
+			INSN_ADDRESSES (uid) - last_insn_address,
+			rtx_cost (PATTERN (insn), INSN, !optimize_size));
+	}
+	last_insn_address = INSN_ADDRESSES (uid);
+}
+
+/* Controls whether a function argument is passed
+in a register, and which register. */
+rtx function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED)
+{
+	int regs = msp430_num_arg_regs (mode, type);
+
+	if (cum->nregs && regs <= cum->nregs)
+	{
+		int regnum = cum->regno - regs;
+
+		if (cum == cum_incoming)
+		{
+			arg_register_used[regnum] = 1;
+			if (regs >= 2)
+				arg_register_used[regnum + 1] = 1;
+			if (regs >= 3)
+				arg_register_used[regnum + 2] = 1;
+			if (regs >= 4)
+				arg_register_used[regnum + 3] = 1;
+		}
+
+		return gen_rtx_REG (mode, regnum);
+	}
+	return NULL_RTX;
+}
+
+/* the same in scope of the cum.args., buf usefull for a
+function call */
+void init_cumulative_incoming_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
+{
+	int i;
+	cum->nregs = 4;
+	cum->regno = FIRST_CUM_REG;
+	if (!libname)
+	{
+		int stdarg = (TYPE_ARG_TYPES (fntype) != 0
+			&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+			!= void_type_node));
+		if (stdarg)
+			cum->nregs = 0;
+	}
+
+	for (i = 0; i < 16; i++)
+		arg_register_used[i] = 0;
+
+	cum_incoming = cum;
+}
+
+/* Initializing the variable cum for the state at the beginning
+of the argument list.  */
+void init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname, int indirect ATTRIBUTE_UNUSED)
+{
+	cum->nregs = 4;
+	cum->regno = FIRST_CUM_REG;
+	if (!libname)
+	{
+		int stdarg = (TYPE_ARG_TYPES (fntype) != 0
+			&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+			!= void_type_node));
+		if (stdarg)
+			cum->nregs = 0;
+	}
+}
+
+
+/* Update the summarizer variable CUM to advance past an argument
+in the argument list.  */
+void function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED)
+{
+	int regs = msp430_num_arg_regs (mode, type);
+
+	cum->nregs -= regs;
+	cum->regno -= regs;
+
+	if (cum->nregs <= 0)
+	{
+		cum->nregs = 0;
+		cum->regno = FIRST_CUM_REG;
+	}
+}
+
+/* Returns the number of registers to allocate for a function argument.  */
+static int msp430_num_arg_regs (enum machine_mode mode, tree type)
+{
+	int size;
+
+	if (mode == BLKmode)
+		size = int_size_in_bytes (type);
+	else
+		size = GET_MODE_SIZE (mode);
+
+	if (size < 2)
+		size = 2;
+
+	/* we do not care if argument is passed in odd register
+	so, do not align the size ...
+	BUT!!! even char argument passed in 16 bit register
+	so, align the size */
+	return ((size + 1) & ~1) >> 1;
+}
+
+static int msp430_saved_regs_frame (void)
+{
+	int interrupt_func_p = interrupt_function_p (current_function_decl);
+	int cfp = msp430_critical_function_p (current_function_decl);
+	int offset = interrupt_func_p ? 0 : (cfp ? 2 : 0);
+	int reg;
+
+	for (reg = 4; reg < 16; ++reg)
+	{
+		if ((!cfun->machine->is_leaf && call_used_regs[reg] && (interrupt_func_p))
+			|| (df_regs_ever_live_p(reg)
+			&& (!call_used_regs[reg] || interrupt_func_p)))
+		{
+			offset += 2;
+		}
+	}
+
+	return offset;
+}
+
+int msp430_empty_epilogue (void)
+{
+	int cfp = msp430_critical_function_p (current_function_decl);
+	int ree = msp430_reentrant_function_p (current_function_decl);
+	int nfp = msp430_naked_function_p (current_function_decl);
+	int ifp = interrupt_function_p (current_function_decl);
+	int wup = wakeup_function_p (current_function_decl);
+	int size = msp430_saved_regs_frame ();
+	int fs = get_frame_size ();
+
+	if (cfp && ree)
+		ree = 0;
+
+	/* the following combination of attributes forces to issue
+	some commands in function epilogue */
+	if (ree
+		|| nfp || fs || wup || MAIN_NAME_P (DECL_NAME (current_function_decl)))
+		return 0;
+
+	size += fs;
+
+	/* <= 2 necessary for first call */
+	if (size <= 2 && cfp)
+		return 2;
+	if (size == 0 && !cfp && !ifp)
+		return 1;
+	if (size == 0 && ifp)
+		return 2;
+
+	return 0;
+}
+
+/* cfp minds the fact that the function may save r2 */
+int initial_elimination_offset (int from, int to)
+{
+	int outgoingArgsSize = 0;
+	if((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
+		outgoingArgsSize = crtl->outgoing_args_size;
+
+	/*
+		'Reloading' is mapping pseudo-registers into hardware registers and stack slots.
+		More information here: http://gcc.gnu.org/onlinedocs/gccint/RTL-passes.html
+		
+		Apparently the leaf_function_p() can erroneously return 1 if called after the reload has 
+		completed. To handle this, we use the AVR port behavior, caching the is_leaf flag before
+		reload and using it from cache afterwards.
+	*/
+
+	if (!reload_completed)
+		cfun->machine->is_leaf = leaf_function_p();
+
+	int reg;
+	if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+		return outgoingArgsSize;
+	else if (from == ARG_POINTER_REGNUM)
+	{
+		int interrupt_func_p = interrupt_function_p (current_function_decl);
+		int cfp = msp430_critical_function_p (current_function_decl);
+		int offset = interrupt_func_p ? 0 : (cfp ? 2 : 0);
+		
+		gcc_assert((to == FRAME_POINTER_REGNUM) || (to == STACK_POINTER_REGNUM));
+
+		for (reg = 4; reg < 16; ++reg)
+		{
+			if ((!cfun->machine->is_leaf && call_used_regs[reg] && (interrupt_func_p))
+				|| (df_regs_ever_live_p(reg)
+				&& (!call_used_regs[reg] || interrupt_func_p)))
+			{
+				offset += 2;
+			}
+		}
+		if (to == FRAME_POINTER_REGNUM)
+			return get_frame_size () + offset + 2;
+		else
+			return get_frame_size () + offset + 2 + outgoingArgsSize;
+	}
+	gcc_unreachable();
+}
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-predicates.inl gcc-4.4.5/gcc/config/msp430/msp430-predicates.inl
--- gcc-4.x/gcc/config/msp430/msp430-predicates.inl	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-predicates.inl	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,52 @@
+#pragma once
+
+static inline int msp430_attribute_exists(tree func, const char *attr_name)
+{
+	gcc_assert(TREE_CODE (func) == FUNCTION_DECL);
+	return lookup_attribute (attr_name, DECL_ATTRIBUTES (func)) != NULL_TREE;
+}
+
+static inline int msp430_naked_function_p(tree func)
+{
+	return msp430_attribute_exists(func, "naked");
+}
+
+static inline int msp430_task_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "task");
+}
+
+static inline int msp430_save_prologue_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "saveprologue");
+}
+
+static inline int interrupt_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "interrupt");
+}
+
+static inline int msp430_critical_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "critical");
+}
+
+static inline int msp430_reentrant_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "reentrant");
+}
+
+static inline int noint_hwmul_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "noint_hwmul");
+}
+
+static inline int signal_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "signal");
+}
+
+static inline int wakeup_function_p (tree func)
+{
+	return msp430_attribute_exists(func, "wakeup");
+}
diff -ruNp gcc-4.x/gcc/config/msp430/msp430-protos.h gcc-4.4.5/gcc/config/msp430/msp430-protos.h
--- gcc-4.x/gcc/config/msp430/msp430-protos.h	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430-protos.h	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,293 @@
+/* Prototypes for exported functions defined in msp430.c
+   
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Dmitry Diky <diwil@mail.ru>
+
+   This file is part of GNU CC.
+
+   GNU CC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+extern void   bootloader_section PARAMS ((void));
+extern void   infomem_section PARAMS ((void));
+
+extern void   asm_file_start            PARAMS ((FILE *file));
+extern void   asm_file_end              PARAMS ((FILE *file));
+extern void   msp430_init_once          PARAMS ((void));
+extern void   msp430_override_options   PARAMS ((void));
+/*extern void   function_prologue         PARAMS ((FILE *file, int size));
+extern void   function_epilogue         PARAMS ((FILE *file, int size));*/
+extern void   gas_output_limited_string PARAMS ((FILE *file, const char *str));
+extern void   gas_output_ascii          PARAMS ((FILE *file, const char *str,
+							 size_t length));
+extern void   order_regs_for_local_alloc PARAMS ((void));
+extern void msp430_trampoline_template PARAMS ((FILE *fd));
+
+
+extern int frame_pointer_required_p PARAMS ((void));
+extern int msp430_empty_epilogue PARAMS ((void));
+
+int msp430_regno_ok_for_base_p PARAMS ((int));
+
+
+#ifdef HAVE_MACHINE_MODES
+extern int    msp430_hard_regno_mode_ok PARAMS ((int regno,
+					     enum machine_mode mode));
+#endif
+
+extern int initial_elimination_offset PARAMS ((int, int));
+
+
+
+#ifdef TREE_CODE
+extern void   asm_output_external          PARAMS ((FILE *file, tree decl,
+						   char *name));
+extern void   unique_section               PARAMS ((tree decl, int reloc));
+extern void   encode_section_info          PARAMS ((tree decl));
+extern void   asm_output_section_name      PARAMS ((FILE *file, tree decl,
+						   const char *name,
+						   int reloc));
+extern int    valid_machine_type_attribute PARAMS ((tree type, tree attributes,
+						   tree identifier,
+						   tree args));
+extern int    valid_machine_decl_attribute PARAMS ((tree decl, tree attributes,
+						   tree attr, tree args));
+extern void asm_declare_function_name PARAMS ((FILE *, const char *, tree));
+unsigned int msp430_section_type_flags PARAMS (( tree DECL, const char *NAME, int RELOC));
+
+
+#ifdef RTX_CODE /* inside TREE_CODE */
+extern rtx    msp430_function_value          PARAMS ((tree type, tree func));
+extern void   init_cumulative_args           PARAMS ((CUMULATIVE_ARGS *cum,
+						   tree fntype, rtx libname,
+						   int indirect));
+extern rtx    function_arg         PARAMS ((CUMULATIVE_ARGS *cum,
+					   enum machine_mode mode,
+					   tree type, int named));
+extern void   init_cumulative_incoming_args           PARAMS ((CUMULATIVE_ARGS *cum,
+						   tree fntype, rtx libname));
+extern rtx    function_incoming_arg         PARAMS ((CUMULATIVE_ARGS *cum,
+					   enum machine_mode mode,
+					   tree type, int named));
+
+
+
+#endif /* RTX_CODE inside TREE_CODE */
+
+#ifdef HAVE_MACHINE_MODES /* inside TREE_CODE */
+extern void   function_arg_advance PARAMS ((CUMULATIVE_ARGS *cum,
+					   enum machine_mode mode, tree type,
+					   int named));
+#endif /* HAVE_MACHINE_MODES inside TREE_CODE*/
+#endif /* TREE_CODE */
+
+#ifdef RTX_CODE
+
+
+extern enum rtx_code msp430_canonicalize_comparison PARAMS ((enum rtx_code,rtx *,rtx *));
+
+
+extern void msp430_emit_cbranch PARAMS ((enum rtx_code, rtx));
+extern void msp430_emit_cset PARAMS ((enum rtx_code, rtx));
+
+extern int dead_or_set_in_peep PARAMS ((int, rtx, rtx));
+extern void msp430_initialize_trampoline PARAMS ((rtx,rtx,rtx));   
+
+
+extern enum reg_class msp430_reg_class_from_letter PARAMS ((int));
+extern enum reg_class preferred_reload_class PARAMS ((rtx,enum reg_class));
+enum reg_class msp430_regno_reg_class PARAMS ((int));
+
+extern RTX_CODE followed_compare_condition PARAMS ((rtx));
+
+extern const char * msp430_movesi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_movedi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_addsi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_subsi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_andsi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_iorsi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_xorsi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_adddi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_subdi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_anddi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_iordi_code PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_xordi_code PARAMS ((rtx insn, rtx operands[], int *l));
+
+
+extern int zero_shifted PARAMS ((rtx ));
+extern int indexed_location PARAMS ((rtx ));
+
+
+extern int regsi_ok_safe PARAMS ((rtx operands[]));
+extern int regsi_ok_clobber PARAMS ((rtx operands[]));
+extern int regdi_ok_safe PARAMS ((rtx operands[]));
+extern int regdi_ok_clobber PARAMS ((rtx operands[]));
+extern int sameoperand PARAMS ((rtx operands[], int));
+
+extern int general_operand_msp430 PARAMS ((rtx, enum machine_mode )); 
+extern int nonimmediate_operand_msp430 PARAMS ((rtx, enum machine_mode ));
+extern int memory_operand_msp430 PARAMS ((rtx, enum machine_mode ));
+extern int halfnibble_constant PARAMS ((rtx, enum machine_mode ));
+extern int halfnibble_integer PARAMS ((rtx, enum machine_mode ));
+extern int halfnibble_constant_shift PARAMS ((rtx, enum machine_mode ));
+extern int halfnibble_integer_shift PARAMS ((rtx, enum machine_mode ));
+extern int which_nibble PARAMS ((int));
+extern int which_nibble_shift PARAMS ((int));
+
+
+extern void   asm_output_external_libcall PARAMS ((FILE *file, rtx symref));
+extern int    legitimate_address_p    PARAMS ((enum machine_mode mode, rtx x,
+					int strict));
+extern int    compare_diff_p  PARAMS ((rtx insn));
+
+extern int    emit_indexed_arith PARAMS ((rtx insn, rtx operands[], int, const char *, int));
+
+extern const char * msp430_emit_abssi    PARAMS ((rtx insn, rtx operands[], int *l));
+extern const char * msp430_emit_absdi    PARAMS ((rtx insn, rtx operands[], int *l));
+
+extern const char * msp430_emit_indexed_add2 PARAMS ((rtx insn, rtx op[], int *l));
+extern const char * msp430_emit_indexed_add4 PARAMS ((rtx insn, rtx op[], int *l));
+
+extern const char * msp430_emit_indexed_sub2 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_sub4 PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * msp430_emit_indexed_and2 PARAMS ((rtx insn, rtx op[], int *l));
+extern const char * msp430_emit_indexed_and4 PARAMS ((rtx insn, rtx op[], int *l));
+extern const char * msp430_emit_immediate_and2 PARAMS ((rtx insn, rtx op[], int *l));
+extern const char * msp430_emit_immediate_and4 PARAMS ((rtx insn, rtx op[], int *l));
+
+extern const char * msp430_emit_indexed_ior2 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_ior4 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_immediate_ior2 PARAMS ((rtx insn, rtx op[], int *l));
+extern const char * msp430_emit_immediate_ior4 PARAMS ((rtx insn, rtx op[], int *l));
+
+
+extern int msp430_emit_indexed_mov PARAMS ((rtx insn, rtx operands[], int len, const char *));       
+extern const char * movstrsi_insn PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * clrstrsi_insn PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * movstrhi_insn PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * clrstrhi_insn PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_mov2 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_mov4 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * movsisf_regmode PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * movdidf_regmode PARAMS ((rtx insn, rtx operands[], int *len));
+
+
+extern int is_shift_better_in_reg PARAMS ((rtx operands[]));
+extern int msp430_emit_shift_cnt PARAMS ((int (*funct)(rtx, int, int), const char *, rtx insn, rtx operands[], int *len, int));
+extern const char * msp430_emit_ashlqi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashlhi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashlsi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashldi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashrqi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashrhi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashrsi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_ashrdi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_lshrqi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_lshrhi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_lshrsi3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_lshrdi3 PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * signextendqihi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * signextendqisi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * signextendqidi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * signextendhisi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * signextendhidi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * signextendsidi PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * msp430_emit_indexed_sub2 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_sub4 PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * msp430_emit_indexed_xor2 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_xor4 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_xor2_3 PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_indexed_xor4_3 PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * zeroextendqihi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * zeroextendqisi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * zeroextendqidi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * zeroextendhisi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * zeroextendhidi PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * zeroextendsidi PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern const char * msp430_pushsisf PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_pushdi   PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_pushhi   PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_pushqi   PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char * msp430_emit_call (rtx operands[]);
+
+extern const char * msp430_emit_return PARAMS ((rtx insn, rtx operands[], int *len));
+extern const char *msp430_cbranch PARAMS ((rtx insn, rtx operands[], int *len, int is_cc0_branch));
+extern const char *msp430_cset PARAMS ((rtx insn, rtx operands[], int *len));
+
+extern void   notice_update_cc       PARAMS ((rtx body, rtx insn));
+extern int    msp430_peep2_scratch_safe PARAMS ((rtx reg_rtx));
+extern int    test_hard_reg_class    PARAMS ((enum reg_class class, rtx x));
+extern void   machine_dependent_reorg PARAMS ((rtx first_insn));
+extern void msp430_output_addr_vec_elt PARAMS ((FILE *stream, int value));
+extern void   final_prescan_insn     PARAMS ((rtx insn, rtx *operand,
+							int num_operands));
+extern int    adjust_insn_length     PARAMS ((rtx insn, int len));
+
+
+extern int    msp430_address_cost    PARAMS ((rtx x));
+extern int    extra_constraint       PARAMS ((rtx x, int c));
+extern rtx    legitimize_address     PARAMS ((rtx x, rtx oldx,
+					     enum machine_mode mode));
+extern rtx    msp430_libcall_value   PARAMS ((enum machine_mode mode));
+extern int    default_rtx_costs      PARAMS ((rtx X, RTX_CODE code,
+					     RTX_CODE outer_code));
+extern void   asm_output_char        PARAMS ((FILE *file, rtx value));
+extern void   asm_output_short       PARAMS ((FILE *file, rtx value));
+extern void   asm_output_byte        PARAMS ((FILE *file, int value));
+
+extern void   print_operand          PARAMS ((FILE *file, rtx x, int code));
+extern void   print_operand_address  PARAMS ((FILE *file, rtx addr));
+extern int    reg_unused_after       PARAMS ((rtx insn, rtx reg));
+extern int    msp430_jump_dist       PARAMS ((rtx x, rtx insn));
+extern int    call_insn_operand      PARAMS ((rtx op, enum machine_mode mode));
+extern int    msp430_branch_mode     PARAMS ((rtx x, rtx insn));
+
+extern int 	msp430_easy_mul PARAMS ((rtx [],int));
+extern int	msp430_mul3_guard	PARAMS ((rtx [], int ));
+extern int      msp430_umul3_guard       PARAMS ((rtx [], int ));
+extern int	msp430_mulhisi_guard PARAMS ((rtx [] ));
+extern int	msp430_umulhisi_guard	PARAMS ((rtx [] ));
+extern int	msp430_ashlhi3 		PARAMS ((rtx [] ));
+extern int      msp430_ashlsi3          PARAMS ((rtx [] ));
+extern int      msp430_ashrhi3          PARAMS ((rtx [] ));
+extern int      msp430_ashrsi3          PARAMS ((rtx [] ));
+extern int      msp430_lshrhi3          PARAMS ((rtx [] ));
+extern int      msp430_lshrsi3          PARAMS ((rtx [] ));
+
+extern void expand_prologue (void);
+extern void expand_epilogue (void);
+extern int msp430_epilogue_uses (int regno);
+
+#endif /* RTX_CODE */
+
+#ifdef HAVE_MACHINE_MODES
+extern int    class_max_nregs        PARAMS ((enum reg_class class,
+					     enum machine_mode mode));
+#endif /* HAVE_MACHINE_MODES */
+
+#ifdef REAL_VALUE_TYPE
+
+extern void   asm_output_float       PARAMS ((FILE *file, REAL_VALUE_TYPE n));
+
+#endif
+
+
diff -ruNp gcc-4.x/gcc/config/msp430/msp430.c gcc-4.4.5/gcc/config/msp430/msp430.c
--- gcc-4.x/gcc/config/msp430/msp430.c	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430.c	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,8537 @@
+/* This work is partially financed by the European Commission under the
+* Framework 6 Information Society Technologies Project
+* "Wirelessly Accessible Sensor Populations (WASP)".
+*/
+
+/*
+	GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+*/
+
+/* Subroutines for insn-output.c for Texas Instruments MSP430 MCU
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+Contributed by Dmitry Diky <diwil@mail.ru>
+
+This file is part of GNU CC. 
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "tree.h"
+#include "output.h"
+#include "expr.h"
+#include "toplev.h"
+#include "obstack.h"
+#include "function.h"
+#include "recog.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
+#include "insn-codes.h"
+#include "ggc.h"
+#include "langhooks.h"
+#include "msp430-predicates.inl"
+
+#define TARGET_REORDER 0
+
+#if GCC_VERSION_INT < 0x430
+static inline int df_regs_ever_live_p(int reg)
+{
+	return regs_ever_live[reg];
+}
+
+#endif
+
+
+/* Commands count in the compiled file */
+int msp430_commands_in_file;
+
+/* Commands in the functions prologues in the compiled file */
+int msp430_commands_in_prologues;
+
+/* Commands in the functions epilogues in the compiled file */
+int msp430_commands_in_epilogues;
+
+/* the size of the stack space freed during mdr pass */
+
+/* push helper */
+int self_push(rtx);
+
+int msp430_case_values_threshold = 30000;
+int msp430_has_hwmul = 0;
+
+enum msp430_arch
+{
+	MSP430_ISA_1 = 1,
+	MSP430_ISA_2 = 2,
+	MSP430_ISA_110 = 110,
+	MSP430_ISA_11 = 11,
+	MSP430_ISA_12 = 12,
+	MSP430_ISA_13 = 13,
+	MSP430_ISA_14 = 14,
+	MSP430_ISA_15 = 15,
+	MSP430_ISA_16 = 16,
+	MSP430_ISA_20 = 20,
+	MSP430_ISA_21 = 21,
+	MSP430_ISA_22 = 22,
+	MSP430_ISA_23 = 23,
+	MSP430_ISA_24 = 24,
+	MSP430_ISA_241 = 241,
+	MSP430_ISA_26 = 26,
+	MSP430_ISA_31 = 31,
+	MSP430_ISA_32 = 32,
+	MSP430_ISA_33 = 33,
+	MSP430_ISA_41 = 41,
+	MSP430_ISA_42 = 42,
+	MSP430_ISA_43 = 43,
+	MSP430_ISA_44 = 44,
+	MSP430_ISA_46 = 46,
+	MSP430_ISA_47 = 47,
+	MSP430_ISA_471 = 471,
+	MSP430_ISA_54 = 54,
+};
+
+struct mcu_type_s
+{
+	const char *name;
+	enum msp430_arch arch;
+	int has_hwmul;
+};
+
+
+
+static struct mcu_type_s msp430_mcu_types[] = {
+
+	/* Match binutils generic types */
+	{"msp1",         MSP430_ISA_11, 0}, /* anything without hardware multiply */
+	{"msp2",         MSP430_ISA_14, 1}, /* older chips with hardware multiply */
+	{"msp3",         MSP430_ISA_46, 1},
+	{"msp4",         MSP430_ISA_47, 1},
+	{"msp5",         MSP430_ISA_471, 1},
+	{"msp6",         MSP430_ISA_54, 1},
+
+	/* F1xx family */
+	{"msp430x110",   MSP430_ISA_11, 0},
+	{"msp430x112",   MSP430_ISA_11, 0},
+
+	{"msp430x1101",  MSP430_ISA_110, 0},
+	{"msp430x1111",  MSP430_ISA_110, 0},
+	{"msp430x1121",  MSP430_ISA_110, 0},
+	{"msp430x1122",  MSP430_ISA_110, 0},
+	{"msp430x1132",  MSP430_ISA_110, 0},
+
+	{"msp430x122",   MSP430_ISA_12, 0},
+	{"msp430x123",   MSP430_ISA_12, 0},
+	{"msp430x1222",  MSP430_ISA_12, 0},
+	{"msp430x1232",  MSP430_ISA_12, 0},
+
+	{"msp430x133",   MSP430_ISA_13, 0},
+	{"msp430x135",   MSP430_ISA_13, 0},
+	{"msp430x1331",  MSP430_ISA_13, 0},
+	{"msp430x1351",  MSP430_ISA_13, 0},
+
+	{"msp430x147",   MSP430_ISA_14, 1},
+	{"msp430x148",   MSP430_ISA_14, 1},
+	{"msp430x149",   MSP430_ISA_14, 1},
+	{"msp430x1471",  MSP430_ISA_14, 1},
+	{"msp430x1481",  MSP430_ISA_14, 1},
+	{"msp430x1491",  MSP430_ISA_14, 1},
+
+	{"msp430x155",   MSP430_ISA_15, 0},
+	{"msp430x156",   MSP430_ISA_15, 0},
+	{"msp430x157",   MSP430_ISA_15, 0},
+
+	{"msp430x167",   MSP430_ISA_16, 1},
+	{"msp430x168",   MSP430_ISA_16, 1},
+	{"msp430x169",   MSP430_ISA_16, 1},
+	{"msp430x1610",  MSP430_ISA_16, 1},
+	{"msp430x1611",  MSP430_ISA_16, 1},
+	{"msp430x1612",  MSP430_ISA_16, 1},
+
+	/* F2xx family */
+	{"msp430x2001",  MSP430_ISA_20, 0},
+	{"msp430x2011",  MSP430_ISA_20, 0},
+
+	{"msp430x2002",  MSP430_ISA_20, 0},
+	{"msp430x2012",  MSP430_ISA_20, 0},
+
+	{"msp430x2003",  MSP430_ISA_20, 0},
+	{"msp430x2013",  MSP430_ISA_20, 0},
+
+	{"msp430x2101",  MSP430_ISA_21, 0},
+	{"msp430x2111",  MSP430_ISA_21, 0},
+	{"msp430x2121",  MSP430_ISA_21, 0},
+	{"msp430x2131",  MSP430_ISA_21, 0},
+
+	{"msp430x2112",  MSP430_ISA_22, 0},
+	{"msp430x2122",  MSP430_ISA_22, 0},
+	{"msp430x2132",  MSP430_ISA_22, 0},
+
+	{"msp430x2201",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2211",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2221",  MSP430_ISA_22, 0}, /* Value-Line */
+	{"msp430x2231",  MSP430_ISA_22, 0}, /* Value-Line */
+
+	{"msp430x2232",  MSP430_ISA_22, 0},
+	{"msp430x2252",  MSP430_ISA_22, 0},
+	{"msp430x2272",  MSP430_ISA_22, 0},
+
+	{"msp430x2234",  MSP430_ISA_22, 0},
+	{"msp430x2254",  MSP430_ISA_22, 0},
+	{"msp430x2274",  MSP430_ISA_22, 0},
+
+	{"msp430x233",   MSP430_ISA_23, 1},
+	{"msp430x235",   MSP430_ISA_23, 1},
+
+	{"msp430x2330",  MSP430_ISA_23, 1},
+	{"msp430x2350",  MSP430_ISA_23, 1},
+	{"msp430x2370",  MSP430_ISA_23, 1},
+
+	{"msp430x247",   MSP430_ISA_24, 1},
+	{"msp430x248",   MSP430_ISA_24, 1},
+	{"msp430x249",   MSP430_ISA_24, 1},
+	{"msp430x2410",  MSP430_ISA_24, 1},
+	{"msp430x2471",  MSP430_ISA_24, 1},
+	{"msp430x2481",  MSP430_ISA_24, 1},
+	{"msp430x2491",  MSP430_ISA_24, 1},
+
+	{"msp430x2416",  MSP430_ISA_241, 1},
+	{"msp430x2417",  MSP430_ISA_241, 1},
+	{"msp430x2418",  MSP430_ISA_241, 1},
+	{"msp430x2419",  MSP430_ISA_241, 1},
+
+	{"msp430x2616",  MSP430_ISA_26, 1},
+	{"msp430x2617",  MSP430_ISA_26, 1},
+	{"msp430x2618",  MSP430_ISA_26, 1},
+	{"msp430x2619",  MSP430_ISA_26, 1},
+
+	/* 3xx family (ROM) */
+	{"msp430x311",   MSP430_ISA_31, 0},
+	{"msp430x312",   MSP430_ISA_31, 0},
+	{"msp430x313",   MSP430_ISA_31, 0},
+	{"msp430x314",   MSP430_ISA_31, 0},
+	{"msp430x315",   MSP430_ISA_31, 0},
+
+	{"msp430x323",   MSP430_ISA_32, 0},
+	{"msp430x325",   MSP430_ISA_32, 0},
+
+	{"msp430x336",   MSP430_ISA_33, 1},
+	{"msp430x337",   MSP430_ISA_33, 1},
+
+	/* F4xx family */
+	{"msp430x412",   MSP430_ISA_41, 0},
+	{"msp430x413",   MSP430_ISA_41, 0},
+	{"msp430x415",   MSP430_ISA_41, 0},
+	{"msp430x417",   MSP430_ISA_41, 0},
+
+	{"msp430x423",   MSP430_ISA_42, 1},
+	{"msp430x425",   MSP430_ISA_42, 1},
+	{"msp430x427",   MSP430_ISA_42, 1},
+
+	{"msp430x4250",  MSP430_ISA_42, 0},
+	{"msp430x4260",  MSP430_ISA_42, 0},
+	{"msp430x4270",  MSP430_ISA_42, 0},
+
+	{"msp430xG4250", MSP430_ISA_42, 0},
+	{"msp430xG4260", MSP430_ISA_42, 0},
+	{"msp430xG4270", MSP430_ISA_42, 0},
+
+	{"msp430xE423",  MSP430_ISA_42, 1},
+	{"msp430xE425",  MSP430_ISA_42, 1},
+	{"msp430xE427",  MSP430_ISA_42, 1},
+
+	{"msp430xE4232", MSP430_ISA_42, 1},
+	{"msp430xE4242", MSP430_ISA_42, 1},
+	{"msp430xE4252", MSP430_ISA_42, 1},
+	{"msp430xE4272", MSP430_ISA_42, 1},
+
+	{"msp430xW423",  MSP430_ISA_42, 0},
+	{"msp430xW425",  MSP430_ISA_42, 0},
+	{"msp430xW427",  MSP430_ISA_42, 0},
+
+	{"msp430xG437",  MSP430_ISA_43, 0},
+	{"msp430xG438",  MSP430_ISA_43, 0},
+	{"msp430xG439",  MSP430_ISA_43, 0},
+
+	{"msp430x435",   MSP430_ISA_43, 0},
+	{"msp430x436",   MSP430_ISA_43, 0},
+	{"msp430x437",   MSP430_ISA_43, 0},
+
+	{"msp430x4351",  MSP430_ISA_43, 0},
+	{"msp430x4361",  MSP430_ISA_43, 0},
+	{"msp430x4371",  MSP430_ISA_43, 0},
+
+	{"msp430x447",   MSP430_ISA_44, 1},
+	{"msp430x448",   MSP430_ISA_44, 1},
+	{"msp430x449",   MSP430_ISA_44, 1},
+
+	{"msp430xG4616", MSP430_ISA_46, 1},
+	{"msp430xG4617", MSP430_ISA_46, 1},
+	{"msp430xG4618", MSP430_ISA_46, 1},
+	{"msp430xG4619", MSP430_ISA_46, 1},
+
+	{"msp430x4783",  MSP430_ISA_47, 1},
+	{"msp430x4784",  MSP430_ISA_47, 1},
+	{"msp430x4793",  MSP430_ISA_47, 1},
+	{"msp430x4794",  MSP430_ISA_47, 1},
+        
+	{"msp430x47166", MSP430_ISA_471, 1},
+	{"msp430x47176", MSP430_ISA_471, 1},
+	{"msp430x47186", MSP430_ISA_471, 1},
+	{"msp430x47196", MSP430_ISA_471, 1},
+
+	{"msp430x47167", MSP430_ISA_471, 1},
+	{"msp430x47177", MSP430_ISA_471, 1},
+	{"msp430x47187", MSP430_ISA_471, 1},
+	{"msp430x47197", MSP430_ISA_471, 1},
+
+	/* F5xxx family */
+	{"msp430x5418",  MSP430_ISA_54, 1},
+	{"msp430x5419",  MSP430_ISA_54, 1},
+	{"msp430x5435",  MSP430_ISA_54, 1},
+	{"msp430x5436",  MSP430_ISA_54, 1},
+	{"msp430x5437",  MSP430_ISA_54, 1},
+	{"msp430x5438",  MSP430_ISA_54, 1},
+
+        {"msp430x5510",  MSP430_ISA_54, 1},
+        {"msp430x5513",  MSP430_ISA_54, 1},
+        {"msp430x5514",  MSP430_ISA_54, 1},
+        {"msp430x5515",  MSP430_ISA_54, 1},
+        {"msp430x5517",  MSP430_ISA_54, 1},
+        {"msp430x5519",  MSP430_ISA_54, 1},
+        {"msp430x5521",  MSP430_ISA_54, 1},
+        {"msp430x5522",  MSP430_ISA_54, 1},
+        {"msp430x5524",  MSP430_ISA_54, 1},
+        {"msp430x5525",  MSP430_ISA_54, 1},
+        {"msp430x5526",  MSP430_ISA_54, 1},
+        {"msp430x5527",  MSP430_ISA_54, 1},
+        {"msp430x5528",  MSP430_ISA_54, 1},
+        {"msp430x5529",  MSP430_ISA_54, 1},
+        {"msp430x6638",  MSP430_ISA_54, 1},
+
+	/* CC430 family */
+	{"cc430x5133",   MSP430_ISA_54, 1},
+	{"cc430x5125",   MSP430_ISA_54, 1},
+	{"cc430x6125",   MSP430_ISA_54, 1},
+	{"cc430x6135",   MSP430_ISA_54, 1},
+	{"cc430x6126",   MSP430_ISA_54, 1},
+	{"cc430x5137",   MSP430_ISA_54, 1},
+	{"cc430x6127",   MSP430_ISA_54, 1},
+	{"cc430x6137",   MSP430_ISA_54, 1},
+
+	/* Add new chips to MULTILIB_MATCHES in t-msp430 as well */
+	{NULL, 0, 0}
+};
+
+static void msp430_globalize_label (FILE *, const char *);
+static void msp430_file_start (void);
+static void msp430_file_end (void);
+static bool msp430_function_ok_for_sibcall PARAMS((tree, tree));
+static bool msp430_rtx_costs (rtx, int, int, int *);
+int msp430_address_costs (rtx);
+
+/* Defined in msp430-builtins.c */
+void msp430_init_builtins (void);
+rtx msp430_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+
+/* Defined in msp430-function.c */
+void msp430_function_end_prologue (FILE * file);
+void msp430_function_begin_epilogue (FILE * file);
+
+static struct machine_function *msp430_init_machine_status (void)
+{
+	return ((struct machine_function *) ggc_alloc_cleared (sizeof (struct machine_function)));
+}
+
+
+const struct attribute_spec msp430_attribute_table[];
+static tree msp430_handle_fndecl_attribute
+PARAMS ((tree *, tree, tree, int, bool *));
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
+
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START msp430_file_start
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END msp430_file_end
+
+/* Hardcoded prologue/epilogue was replaced by flexible expand_prologue()/expand_epilogue() */
+/*#undef 	TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE msp430_function_prologue
+#undef 	TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE msp430_function_epilogue*/
+
+#undef TARGET_ASM_FUNCTION_END_PROLOGUE
+#define TARGET_ASM_FUNCTION_END_PROLOGUE msp430_function_end_prologue
+#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
+#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE msp430_function_begin_epilogue
+
+#undef 	TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
+#undef 	TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
+#undef 	TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS msp430_rtx_costs
+#undef	TARGET_ADDRESS_COST
+#define	TARGET_ADDRESS_COST msp430_address_costs
+#undef  TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL msp430_function_ok_for_sibcall
+#undef  TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL msp430_globalize_label
+#undef  TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS msp430_init_builtins
+#undef  TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN msp430_expand_builtin
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS msp430_init_once
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/****** ATTRIBUTES TO FUNCTION *************************************/
+const struct attribute_spec msp430_attribute_table[] = {
+	/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+	{"reserve", 1, 1, false, false, false, msp430_handle_fndecl_attribute},
+	{"signal", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"interrupt", 1, 1, true, false, false, msp430_handle_fndecl_attribute},
+	{"naked", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"task", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"wakeup", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"critical", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"reentrant", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"saveprologue", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{"noint_hwmul", 0, 0, true, false, false, msp430_handle_fndecl_attribute},
+	{NULL, 0, 0, false, false, false, NULL}
+};
+
+int msp430_current_function_noint_hwmul_function_p (void)
+{
+	int rval;
+	if (!current_function_decl)
+		return (TARGET_NOINT_HWMUL);
+	rval = noint_hwmul_function_p (current_function_decl);
+
+	return (TARGET_NOINT_HWMUL || rval);
+}
+
+unsigned int
+msp430_section_type_flags (tree decl, const char *name, int reloc)
+
+{
+	unsigned int flags = 0;
+
+	if (!strcmp (name, ".infomemnobits") || !strcmp (name, ".noinit"))
+		flags = SECTION_BSS;
+
+	flags |= default_section_type_flags (decl, name, reloc);
+	return flags;
+}
+
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+struct attribute_spec.handler.  */
+static tree
+msp430_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+	if (TREE_CODE (*node) != FUNCTION_DECL)
+	{
+		warning (OPT_Wattributes, "%s' attribute only applies to functions.",
+			IDENTIFIER_POINTER (name));
+		*no_add_attrs = true;
+	}
+	return NULL_TREE;
+}
+
+enum msp430_arch msp430_get_arch (void);
+
+enum msp430_arch
+msp430_get_arch (void)
+{
+	const struct mcu_type_s *t;
+
+	for (t = msp430_mcu_types; t->name; t++)
+	{
+		if (strcmp (t->name, msp430_mcu_name) == 0)
+			break;
+	}
+
+	if (!t->name)
+	{
+		error ("MCU %s not supported", msp430_mcu_name);
+		fprintf (stderr, "Known MCU names:\n");
+		for (t = msp430_mcu_types; t->name; t++)
+			fprintf (stderr, "   %s\n", t->name);
+		abort ();
+		return -1;
+	}
+	return t->arch;
+}
+
+void
+msp430_override_options (void)
+{
+	const struct mcu_type_s *t;
+
+        if (flag_pic)
+          error ("PIC not supported on msp430");
+
+	for (t = msp430_mcu_types; t->name; t++)
+	{
+		if (strcmp (t->name, msp430_mcu_name) == 0)
+			break;
+	}
+
+	if (!t->name)
+	{
+		error ("MCU %s not supported", msp430_mcu_name);
+		fprintf (stderr, "Known MCU names:\n");
+		for (t = msp430_mcu_types; t->name; t++)
+			fprintf (stderr, "   %s\n", t->name);
+		abort ();
+		return;
+	}
+
+	msp430_has_hwmul = t->has_hwmul || TARGET_FORCE_HWMUL;
+
+	if (TARGET_NO_HWMUL)
+		msp430_has_hwmul = 0;
+
+	msp430_case_values_threshold = 8;	/* ? or there is a better value ? */
+	init_machine_status = msp430_init_machine_status;
+}
+
+rtx mpy_rtx, mpys_rtx, mac_rtx, macs_rtx, op2_rtx, reslo_rtx, reshi_rtx,
+sumext_rtx, ressi_rtx;
+
+
+static char __dummy[1024];
+rtx sym_ref(enum machine_mode mode,  char *arg);
+
+rtx sym_ref(enum machine_mode mode,  char *arg)
+{
+	rtx rt;
+	static int i = 0;
+	rt = (rtx) &__dummy[i];
+	i += sizeof(*rt);
+	memset(rt,0,4);
+	PUT_CODE(rt,SYMBOL_REF);
+	PUT_MODE(rt,mode);
+	XSTR(rt,0) = arg;
+
+	return rt;
+}
+
+
+rtx gen_rtx_HWREG(const char *name);
+
+rtx gen_rtx_HWREG(const char *name)
+{
+	rtx ret = gen_rtx_MEM (HImode, sym_ref (HImode, name));
+	//MEM_VOLATILE_P(ret) = 1;
+	return ret;
+}
+
+void msp430_init_once (void)
+{
+	/* Module register addresses chip-specific, added by msp430_file_start */
+	mpy_rtx 	= gen_rtx_HWREG ("__MPY");
+	mpys_rtx 	= gen_rtx_HWREG ("__MPYS");
+	mac_rtx 	= gen_rtx_HWREG ("__MAC");
+	macs_rtx 	= gen_rtx_HWREG ("__MACS");
+	op2_rtx 	= gen_rtx_HWREG ("__OP2");
+	reslo_rtx = gen_rtx_HWREG ("__RESLO");
+	reshi_rtx = gen_rtx_HWREG ("__RESHI");
+	sumext_rtx = gen_rtx_HWREG ("__SUMEXT");
+	ressi_rtx = gen_rtx_HWREG ("__RESLO");
+	return;
+}
+
+static char error_here_if_register_count_invalid[(FIRST_VIRTUAL_REGISTER == 17) ? 1 : -1];
+static int reg_class_tab[FIRST_VIRTUAL_REGISTER] = {
+	PC_REG, STACK_REGS, CG_REGS, CG_REGS,
+	GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, 
+	GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+	GENERAL_REGS, GENERAL_REGS,	GENERAL_REGS, GENERAL_REGS,	/* r0 - r15 */
+	GENERAL_REGS,	/* regp */
+};
+
+
+int msp430_regno_ok_for_base_p (int r)
+{
+
+	if (r == 2)
+		return 0;
+	if (r == 3)
+		return 0;
+	if (r < FIRST_PSEUDO_REGISTER && r > 0)
+		return 1;
+	if (reg_renumber
+		&& reg_renumber[r] < FIRST_PSEUDO_REGISTER
+		&& reg_renumber[r] > 0 && reg_renumber[r] != 2 && reg_renumber[r] != 3)
+		return 1;
+
+	return 0;
+
+}
+
+enum reg_class
+msp430_regno_reg_class (int r)
+{
+	if (r < (sizeof(reg_class_tab) / sizeof(reg_class_tab[0])))
+		return reg_class_tab[r];
+
+	return NO_REGS;
+}
+
+
+enum reg_class
+msp430_reg_class_from_letter (
+							  int c)
+{
+	switch (c)
+	{
+	case 'd':
+		return SP_REG;
+	default:
+		break;
+	}
+
+	return NO_REGS;
+}
+
+
+
+#define NOVECTOR	0xff
+
+void
+asm_declare_function_name (
+						   FILE *file,
+						   const char *name,
+						   tree decl ATTRIBUTE_UNUSED)
+{
+	int interrupt_func_p;
+	tree ss = 0;
+	int vector = -1;
+	int vectors_start;
+	int cfp = msp430_critical_function_p (current_function_decl);
+	int ree = msp430_reentrant_function_p (current_function_decl);
+
+	interrupt_func_p = interrupt_function_p (current_function_decl);
+
+	if (interrupt_func_p)
+	{
+		/*
+		* .global This_func1
+		* .set vector11, This_func1
+		* .type   This_func1,@function
+		*
+		*/
+		switch (msp430_get_arch())
+		{
+		case MSP430_ISA_241:
+		case MSP430_ISA_26:
+		case MSP430_ISA_46:
+			vectors_start = 0xffc0;
+			break;
+		case MSP430_ISA_54:
+			vectors_start = 0xff80;
+			break;
+		default:
+			vectors_start = 0xffe0;
+		}
+
+		ss = lookup_attribute ("interrupt",
+			DECL_ATTRIBUTES (current_function_decl));
+		ss = TREE_VALUE (ss);
+		if (ss)
+		{
+			ss = TREE_VALUE (ss);
+			if (ss)
+				vector = TREE_INT_CST_LOW (ss);
+
+			if (vector != NOVECTOR)
+				vector += vectors_start;
+		}
+
+		if (vector == -1)
+		{
+			warning (OPT_Wattributes, "No valid interrupt vector assigned to ISR `%s'.", name);
+		}
+
+		if ((vector < vectors_start || vector > 0xfffe || (vector & 1))
+			&& (vector != NOVECTOR && vector != -1))
+		{
+			warning
+				(0, "Interrupt vector 0x%x assigned to ISR `%s' is invalid.",
+				vector, name);
+		}
+
+		if (vector != NOVECTOR)
+		{
+			fprintf (file, ".global	vector_%04x\n", vector);
+		}
+		fprintf (file, "%s", TYPE_ASM_OP);
+		assemble_name (file, name);
+		putc (',', file);
+		fprintf (file, TYPE_OPERAND_FMT, "function");
+		putc ('\n', file);
+		fprintf (file, "/***********************\n");
+		fprintf (file, " * Interrupt %sRoutine `",
+			(vector != NOVECTOR) ? "Service " : "Sub-");
+		assemble_name (file, name);
+		fprintf (file, "' at 0x%04x\n", vector);
+		fprintf (file, " ***********************/\n");
+
+		if (vector != NOVECTOR)
+		{
+			fprintf (file, "vector_%04x:\n", vector);
+		}
+
+		ASM_OUTPUT_LABEL (file, name);
+	}
+	else
+	{
+		fprintf (file, "%s", TYPE_ASM_OP);
+		assemble_name (file, name);
+		putc (',', file);
+		fprintf (file, TYPE_OPERAND_FMT, "function");
+		putc ('\n', file);
+		fprintf (file, "/***********************\n");
+		fprintf (file, " * Function `");
+		assemble_name (file, name);
+		fprintf (file, "' %s\n ***********************/\n",
+			cfp ? "(OS critical)" : ree ? "(reentrant)" : "");
+		ASM_OUTPUT_LABEL (file, name);
+	}
+}
+
+
+/* Attempts to replace X with a valid
+memory address for an operand of mode MODE  */
+/* FIXME: broken call */
+rtx
+legitimize_address (x, oldx, mode)
+rtx x;
+rtx oldx ATTRIBUTE_UNUSED;
+enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+	/*    if (GET_CODE (oldx) == MEM
+	&& GET_CODE (XEXP(oldx,0)) == PLUS
+	&& GET_CODE (XEXP(XEXP(oldx,0),0)) == MEM)
+	{
+	x = force_operand (oldx,0);
+	return x;
+	}
+
+	return oldx;
+	*/
+	return x;
+}
+
+int
+legitimate_address_p (mode, operand, strict)
+enum machine_mode mode ATTRIBUTE_UNUSED;
+rtx operand;
+int strict;
+{
+	rtx xfoob, x = operand;
+
+	xfoob = XEXP (operand, 0);
+
+	/* accept @Rn (Rn points to operand address ) */
+	if (GET_CODE (operand) == REG
+		&& (strict ? REG_OK_FOR_BASE_STRICT_P (x)
+		: REG_OK_FOR_BASE_NOSTRICT_P (x)))
+		goto granted;
+
+	/* accept address */
+	if (CONSTANT_P (operand))
+		goto granted;
+
+	/* accept X(Rn) Rn + X points to operand address */
+	if (GET_CODE (operand) == PLUS
+		&& GET_CODE (XEXP (operand, 0)) == REG
+		&& CONSTANT_P (XEXP (operand, 1))
+		&& (strict ? (REG_OK_FOR_BASE_STRICT_P (xfoob))
+		: (REG_OK_FOR_BASE_NOSTRICT_P (xfoob))))
+		goto granted;
+
+	if (TARGET_ALL_DEBUG)
+		fprintf (stderr, "Address Failed\n");
+	return 0;
+
+granted:
+	if (TARGET_ALL_DEBUG)
+		fprintf (stderr, "Address granted\n");
+	return 1;
+}
+
+
+void
+print_operand_address (file, addr)
+FILE *file;
+rtx addr;
+{
+	/* hopefully will be never entered. */
+	switch (GET_CODE (addr))
+	{
+	case REG:
+		fprintf (file, "r%d", REGNO (addr));
+		return;
+	case POST_INC:
+		fprintf (file, "@r%d+", REGNO (XEXP(addr,0)));
+		return;
+	case SYMBOL_REF:
+	case LABEL_REF:
+	case CONST:
+		fprintf (file, "#");
+		break;
+	case CODE_LABEL:
+		break;
+	default:
+		abort ();
+		fprintf (file, "&");
+	}
+	output_addr_const (file, addr);
+}
+
+void print_sub_operand PARAMS ((FILE *, rtx, int));
+
+const char *trim_array[] = { "llo", "lhi", "hlo", "hhi" };
+
+
+
+void
+print_sub_operand (file, x, code)
+FILE *file;
+rtx x;
+int code;
+{
+
+	if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+	{
+		output_addr_const (file, x);
+		return;
+	}
+	else if (GET_CODE (x) == CONST)
+	{
+		print_sub_operand (file, XEXP (x, 0), code);
+		return;
+	}
+	else if (GET_CODE (x) == PLUS)
+	{
+		print_sub_operand (file, XEXP (x, 0), code);
+		fprintf (file, "+");
+		print_sub_operand (file, XEXP (x, 1), code);
+		return;
+	}
+	else if (GET_CODE (x) == CONST_INT)
+	{
+		fprintf (file, "%d", INTVAL (x));
+		return;
+	}
+	else
+		abort ();
+}
+
+void print_operand (FILE *file, rtx x, int code)
+{
+	int shift = 0;
+	int ml = GET_MODE_SIZE (x->mode);
+	int source_reg = 0;
+
+
+	if (ml > 1)
+		ml = 2;
+
+	if (code >= 'A' && code <= 'D')
+		shift = code - 'A';
+
+	if (code >= 'E' && code <= 'H')
+	{
+		shift = code - 'E';
+		source_reg = 1;
+	}
+
+	if (code >= 'I' && code <= 'L')
+	{
+		ml = 1;
+		shift = code - 'I';
+	}
+
+	if (GET_CODE (x) == PLUS)
+	{
+		fprintf (file, "add%s", shift ? "c" : "");
+	}
+	else if (GET_CODE (x) == MINUS)
+	{
+		fprintf (file, "sub%s", shift ? "c" : "");
+	}
+	else if (GET_CODE (x) == AND)
+	{
+		fprintf (file, "and");
+	}
+	else if (GET_CODE (x) == IOR)
+	{
+		fprintf (file, "bis");
+	}
+	else if (GET_CODE (x) == XOR)
+	{
+		fprintf (file, "xor");
+	}
+	else if (REG_P (x))
+	{
+		fprintf (file, reg_names[true_regnum (x) + shift]);
+	}
+	else if (GET_CODE (x) == CONST_INT)
+	{
+		if (code != 'F')
+		{
+			int intval = INTVAL (x);
+			if (!shift && !(intval & ~0xFFFF)) /* For improved ASM readability, omit #llo(const) for small constants*/
+				fprintf (file, "#%d", intval);	
+			else
+				fprintf (file, "#%s(%d)", trim_array[shift], intval);
+		}
+		else
+			fprintf (file, "%d", INTVAL (x));
+	}
+	else if (GET_CODE (x) == MEM)
+	{
+		rtx addr = XEXP (x, 0);
+
+		if (GET_CODE (addr) == POST_INC)
+		{
+			fprintf (file, "@r%d+", REGNO (XEXP(addr,0)));
+		}
+		else if (GET_CODE (addr) == REG)
+		{			/* for X(Rn) */
+			if (shift || !source_reg)
+			{
+				if (shift)
+					fprintf (file, "%d(r%d)", shift * ml, REGNO (addr));
+				else
+					fprintf (file, "@r%d", REGNO (addr));
+			}
+			else if (source_reg)
+			{
+				fprintf (file, "r%d", REGNO (addr) + shift);
+			}
+			else
+			{
+				fprintf (file, "@r%d", REGNO (addr));
+			}
+		}
+		else if (GET_CODE (addr) == SYMBOL_REF)
+		{
+			fprintf (file, "&");
+			output_addr_const (file, addr);
+			if (shift)
+				fprintf (file, "+%d", shift * ml);
+		}
+		else if (GET_CODE (addr) == CONST || GET_CODE (addr) == CONST_INT)
+		{
+			fputc ('&', file);
+			output_addr_const (file, addr);
+			if (shift)
+				fprintf (file, "+%d", shift * ml);
+		}
+		else if (GET_CODE (addr) == PLUS)
+		{
+
+			print_sub_operand (file, XEXP (addr, 1), code);
+
+			/* shift if the indirect pointer register is the stack pointer */
+			if ((code >= 'M' && code <= 'N') && (REGNO (XEXP (addr, 0)) == 1))
+				shift = code - 'M';
+
+			if (shift)
+				fprintf (file, "+%d", shift * ml);
+
+			if (REG_P (XEXP (addr, 0)))
+				fprintf (file, "(r%d)", REGNO (XEXP (addr, 0)));
+			else
+				abort ();
+		}
+		else if (GET_CODE (addr) == MEM)
+		{
+			fprintf (file, "@(Invalid addressing mode)");
+			print_operand (file, addr, code);
+		}
+		else
+		{
+			fprintf (file, "Unknown operand. Please check.");
+		}
+	}
+	else if (GET_CODE (x) == SYMBOL_REF)
+	{
+		fprintf (file, "#");
+		output_addr_const (file, x);
+		if (shift)
+			fprintf (file, "+%d", shift * ml);
+	}
+	else if (GET_CODE (x) == CONST_DOUBLE)
+	{
+		if (GET_MODE (x) == VOIDmode)	/* FIXME: may be long long?? */
+		{
+			if (shift < 2)
+				fprintf (file, "#%s(%d)", trim_array[shift], CONST_DOUBLE_LOW (x));
+			else
+				fprintf (file, "#%s(%d)", trim_array[shift - 2],
+				CONST_DOUBLE_HIGH (x));
+		}
+		else if (GET_MODE (x) == SFmode || GET_MODE (x) == SImode)
+		{
+			long val;
+			REAL_VALUE_TYPE rv;
+			REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+			REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+			asm_fprintf (file, "#%s(0x%lx)", trim_array[shift], val);
+		}
+		else
+		{
+			fatal_insn ("Internal compiler bug. Unknown mode:", x);
+		}
+	}
+	else
+		print_operand_address (file, x);
+}
+
+/* mode for branch instruction */
+int
+msp430_jump_dist (rtx x, rtx insn)
+{
+	if(insn_addresses_)
+	{
+		int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
+			? XEXP (x, 0) : x));
+		int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
+		int jump_distance = dest_addr - cur_addr;
+
+		return jump_distance;
+	}
+	else
+		return 1024;
+}
+
+
+rtx
+msp430_libcall_value (mode)
+enum machine_mode mode;
+{
+	int offs = GET_MODE_SIZE (mode);
+	offs >>= 1;
+	if (offs < 1)
+		offs = 1;
+	return gen_rtx_REG (mode, (RET_REGISTER + 1 - offs));
+}
+
+rtx
+msp430_function_value (type, func)
+tree type;
+tree func ATTRIBUTE_UNUSED;
+{
+	int offs;
+	if (TYPE_MODE (type) != BLKmode)
+		return msp430_libcall_value (TYPE_MODE (type));
+
+	offs = int_size_in_bytes (type);
+	offs >>= 1;
+	if (offs < 1)
+		offs = 1;
+	if (offs > 1 && offs < (GET_MODE_SIZE (SImode) >> 1))
+		offs = GET_MODE_SIZE (SImode) >> 1;
+	else if (offs > (GET_MODE_SIZE (SImode) >> 1)
+		&& offs < (GET_MODE_SIZE (DImode) >> 1))
+		offs = GET_MODE_SIZE (DImode) >> 1;
+
+	return gen_rtx_REG (BLKmode, (RET_REGISTER + 1 - offs));
+}
+
+int
+halfnibble_integer (op, mode)
+rtx op;
+enum machine_mode mode;
+{
+	int hi, lo;
+	int val;
+
+	if (!const_int_operand (op, mode))
+		return 0;
+
+	/* this integer is the one of form:
+	0xXXXX0000 or 0x0000XXXX,
+	where XXXX not one of -1,1,2,4,8 
+	*/
+	val = INTVAL (op);
+	hi = ((val & 0xffff0000ul) >> 16) & 0xffff;
+	lo = (val & 0xffff);
+
+	if (hi && lo)
+		return 0;
+
+	if (hi && hi != 0xffff && hi != 1 && hi != 2 && hi != 4 && hi != 8)
+		return 1;
+	if (lo && lo != 0xffff && lo != 1 && lo != 2 && lo != 4 && lo != 8)
+		return 1;
+
+	return 0;
+}
+
+
+int
+halfnibble_constant (op, mode)
+rtx op;
+enum machine_mode mode;
+{
+	int hi, lo;
+	int val;
+
+	if (!const_int_operand (op, mode))
+		return 0;
+
+	/* this integer is the one of form:
+	0xXXXX0000 or 0x0000XXXX,
+	where XXXX one of -1,1,2,4,8 
+	*/
+	val = INTVAL (op);
+	hi = ((val & 0xffff0000ul) >> 16) & 0x0000ffff;
+	lo = (val & 0x0000ffff);
+
+	if ((hi && lo) || (!hi && !lo))
+		return 0;
+
+	if (hi == 0xffff || hi == 1 || hi == 2 || hi == 4 || hi == 8)
+		return 1;
+	if (lo == 0xffff || lo == 1 || lo == 2 || lo == 4 || lo == 8)
+		return 1;
+
+	if (!(hi && lo))
+		return 1;
+
+	return 0;
+}
+
+
+int
+halfnibble_integer_shift (op, mode)
+rtx op;
+enum machine_mode mode;
+{
+	int hi, lo;
+	int val;
+
+	if (!immediate_operand (op, mode))
+		return 0;
+
+	/* this integer is the one of form:
+	0xXXXX0000 or 0x0000XXXX,
+	where XXXX not one of -1,1,2,4,8 
+	*/
+	val = 1 << INTVAL (op);
+	hi = ((val & 0xffff0000ul) >> 16) & 0x0000ffff;
+	lo = (val & 0x0000ffff);
+
+	if (hi && lo)
+		return 0;
+
+	if (hi && hi != 0xffff && hi != 1 && hi != 2 && hi != 4 && hi != 8)
+		return 1;
+	if (lo && lo != 0xffff && lo != 1 && lo != 2 && lo != 4 && lo != 8)
+		return 1;
+
+	return 0;
+}
+
+
+int
+halfnibble_constant_shift (op, mode)
+rtx op;
+enum machine_mode mode;
+{
+	int hi, lo;
+	int val;
+
+	if (!immediate_operand (op, mode))
+		return 0;
+
+	/* this integer is the one of form:
+	0xXXXX0000 or 0x0000XXXX,
+	where XXXX one of -1,1,2,4,8 
+	*/
+	val = 1 << INTVAL (op);
+	hi = ((val & 0xffff0000ul) >> 16) & 0x0000ffff;
+	lo = (val & 0x0000ffff);
+
+	if (hi && lo)
+		return 0;
+
+	if (hi && hi == 0xffff && hi == 1 && hi == 2 && hi == 4 && hi == 8)
+		return 1;
+	if (lo && lo == 0xffff && lo == 1 && lo == 2 && lo == 4 && lo == 8)
+		return 1;
+
+	return 0;
+}
+
+
+int
+which_nibble (val)
+int val;
+{
+	if (val & 0xffff0000ul)
+		return 1;
+	return 0;
+}
+
+
+int
+which_nibble_shift (val)
+int val;
+{
+	if (val & 0xffff0000ul)
+		return 1;
+	return 0;
+}
+
+
+int
+extra_constraint (x, c)
+rtx x;
+int c;
+{
+
+	if (c == 'R')
+	{
+		if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
+		{
+			rtx xx = XEXP (x, 0);
+			int regno = REGNO (xx);
+			if (regno >= 4 || regno == 1)
+				return 1;
+		}
+	}
+	else if (c == 'Q')
+	{
+		if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
+		{
+			rtx xx = XEXP (x, 0);
+			int regno = REGNO (xx);
+			if (regno >= 4 || regno == 1)
+				return 1;
+		}
+
+		if (GET_CODE (x) == MEM
+			&& GET_CODE (XEXP (x, 0)) == PLUS
+			&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+		{
+			rtx xx = XEXP (XEXP (x, 0), 0);
+			int regno = REGNO (xx);
+			if (regno >= 4 || regno == 1)
+				return 1;
+		}
+
+		if (GET_CODE (x) == MEM
+			&& GET_CODE (XEXP (x, 0)) == PLUS && REG_P (XEXP (XEXP (x, 0), 0)))
+		{
+			return 1;
+		}
+
+	}
+	else if (c == 'S')
+	{
+		if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
+		{
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int
+indexed_location (x)
+rtx x;
+{
+	int r = 0;
+
+	if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
+	{
+		r = 1;
+	}
+
+	if (TARGET_ALL_DEBUG)
+	{
+		fprintf (stderr, "indexed_location %s: %s  \n",
+			r ? "granted" : "failed",
+			reload_completed ? "reload completed" : "reload in progress");
+		debug_rtx (x);
+	}
+
+	return r;
+}
+
+
+int
+zero_shifted (x)
+rtx x;
+{
+	int r = 0;
+
+	if (GET_CODE (x) == MEM &&
+		GET_CODE (XEXP (x, 0)) == REG
+		&& REGNO (XEXP (x, 0)) != STACK_POINTER_REGNUM
+		&& REGNO (XEXP (x, 0)) != FRAME_POINTER_REGNUM
+		/* the following is Ok, cause we do not corrupt r4 within ISR */
+		/*&& REGNO(XEXP (x,0)) != ARG_POINTER_REGNUM */ )
+	{
+		r = 1;
+	}
+	return r;
+}
+
+
+
+void
+order_regs_for_local_alloc ()
+{
+	unsigned int i;
+
+	if (TARGET_REORDER)
+	{
+		reg_alloc_order[0] = 12;
+		reg_alloc_order[1] = 13;
+		reg_alloc_order[2] = 14;
+		reg_alloc_order[3] = 15;
+		for (i = 4; i < 16; i++)
+			reg_alloc_order[i] = 15 - i;
+	}
+	else
+	{
+		for (i = 0; i < 16; i++)
+			reg_alloc_order[i] = 15 - i;
+	}
+
+	return;
+}
+
+/* Output rtx VALUE as .byte to file FILE */
+void
+asm_output_char (file, value)
+FILE *file;
+rtx value;
+{
+	fprintf (file, "\t.byte\t");
+	output_addr_const (file, value);
+	fprintf (file, "\n");
+}
+
+/* Output VALUE as .byte to file FILE */
+void
+asm_output_byte (file, value)
+FILE *file;
+int value;
+{
+	fprintf (file, "\t.byte 0x%x\n", value & 0xff);
+}
+
+/* Output rtx VALUE as .word to file FILE */
+void
+asm_output_short (file, value)
+FILE *file;
+rtx value;
+{
+	fprintf (file, "\t.word ");
+	output_addr_const (file, (value));
+	fprintf (file, "\n");
+}
+
+#if 0
+/* Output real N to file FILE */
+void
+asm_output_float (file, n)
+FILE *file;
+REAL_VALUE_TYPE n;
+{
+	long val;
+	char dstr[100];
+
+	REAL_VALUE_TO_TARGET_SINGLE (n, val);
+	REAL_VALUE_TO_DECIMAL (n, "%g", dstr);
+	fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr);
+}
+#endif
+
+/* Output section name to file FILE
+We make the section read-only and executable for a function decl,
+read-only for a const data decl, and writable for a non-const data decl.  */
+
+void
+asm_output_section_name (file, decl, name, reloc)
+FILE *file;
+tree decl;
+const char *name;
+int reloc ATTRIBUTE_UNUSED;
+{
+	fprintf (file, ".section %s, \"%s\", @progbits\n", name,
+		decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" :
+		decl && TREE_READONLY (decl) ? "a" : "aw");
+}
+
+
+/* The routine used to output NUL terminated strings.  We use a special
+version of this for most svr4 targets because doing so makes the
+generated assembly code more compact (and thus faster to assemble)
+as well as more readable, especially for targets like the i386
+(where the only alternative is to output character sequences as
+comma separated lists of numbers).   */
+
+void
+gas_output_limited_string (file, str)
+FILE *file;
+const char *str;
+{
+	const unsigned char *_limited_str = (unsigned char *) str;
+	unsigned ch;
+	fprintf (file, "%s\"", STRING_ASM_OP);
+	for (; (ch = *_limited_str); _limited_str++)
+	{
+		int escape;
+		switch (escape = ESCAPES[ch])
+		{
+		case 0:
+			putc (ch, file);
+			break;
+		case 1:
+			fprintf (file, "\\%03o", ch);
+			break;
+		default:
+			putc ('\\', file);
+			putc (escape, file);
+			break;
+		}
+	}
+	fprintf (file, "\"\n");
+}
+
+/* The routine used to output sequences of byte values.  We use a special
+version of this for most svr4 targets because doing so makes the
+generated assembly code more compact (and thus faster to assemble)
+as well as more readable.  Note that if we find subparts of the
+character sequence which end with NUL (and which are shorter than
+STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
+
+void
+gas_output_ascii (file, str, length)
+FILE *file;
+const char *str;
+size_t length;
+{
+	const unsigned char *_ascii_bytes = (const unsigned char *) str;
+	const unsigned char *limit = _ascii_bytes + length;
+	unsigned bytes_in_chunk = 0;
+	for (; _ascii_bytes < limit; _ascii_bytes++)
+	{
+		const unsigned char *p;
+		if (bytes_in_chunk >= 60)
+		{
+			fprintf (file, "\"\n");
+			bytes_in_chunk = 0;
+		}
+		for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
+			continue;
+		if (p < limit && (p - _ascii_bytes) <= (signed) STRING_LIMIT)
+		{
+			if (bytes_in_chunk > 0)
+			{
+				fprintf (file, "\"\n");
+				bytes_in_chunk = 0;
+			}
+			gas_output_limited_string (file, (char *) _ascii_bytes);
+			_ascii_bytes = p;
+		}
+		else
+		{
+			int escape;
+			unsigned ch;
+			if (bytes_in_chunk == 0)
+				fprintf (file, "\t.ascii\t\"");
+			switch (escape = ESCAPES[ch = *_ascii_bytes])
+			{
+			case 0:
+				putc (ch, file);
+				bytes_in_chunk++;
+				break;
+			case 1:
+				fprintf (file, "\\%03o", ch);
+				bytes_in_chunk += 4;
+				break;
+			default:
+				putc ('\\', file);
+				putc (escape, file);
+				bytes_in_chunk += 2;
+				break;
+			}
+		}
+	}
+	if (bytes_in_chunk > 0)
+		fprintf (file, "\"\n");
+}
+
+
+
+/* Outputs to the stdio stream FILE some
+appropriate text to go at the start of an assembler file.  */
+
+static void msp430_file_start (void)
+{
+	FILE *file = asm_out_file;
+	output_file_directive (file, main_input_filename);
+	fprintf (file, "\t.arch %s\n\n", msp430_mcu_name);
+
+	if (msp430_has_hwmul)
+	{
+		switch (msp430_get_arch())
+		{
+		case MSP430_ISA_471:
+		case MSP430_ISA_47:
+			fprintf (file, "/* Hardware multiplier registers: */\n"
+				"__MPY=0x130\n"
+				"__MPYS=0x132\n"
+				"__MAC=0x134\n"
+				"__MACS=0x136\n"
+				"__OP2=0x138\n"
+				"__RESLO=0x13a\n"
+				"__RESHI=0x13c\n"
+				"__SUMEXT=0x13e\n"
+				"__MPY32L=0x140\n"
+				"__MPY32H=0x142\n"
+				"__MPYS32L=0x144\n"
+				"__MPYS32H=0x146\n"
+				"__MAC32L=0x148\n"
+				"__MAC32H=0x14a\n"
+				"__MACS32L=0x14c\n"
+				"__MACS32H=0x14e\n"
+				"__OP2L=0x150\n"
+				"__OP2H=0x152\n"
+				"__RES0=0x154\n"
+				"__RES1=0x156\n"
+				"__RES2=0x158\n"
+				"__RES3=0x15a\n"
+				"__MPY32CTL0=0x15c\n"
+				"\n");
+			break;
+		case MSP430_ISA_54:
+			fprintf (file, "/* Hardware multiplier registers: */\n"
+				"__MPY=0x4c0\n"
+				"__MPYS=0x4c2\n"
+				"__MAC=0x4c4\n"
+				"__MACS=0x4c6\n"
+				"__OP2=0x4c8\n"
+				"__RESLO=0x4ca\n"
+				"__RESHI=0x4cc\n"
+				"__SUMEXT=0x4ce\n"
+				"__MPY32L=0x4d0\n"
+				"__MPY32H=0x4d2\n"
+				"__MPYS32L=0x4d4\n"
+				"__MPYS32H=0x4d6\n"
+				"__MAC32L=0x4d8\n"
+				"__MAC32H=0x4da\n"
+				"__MACS32L=0x4dc\n"
+				"__MACS32H=0x4de\n"
+				"__OP2L=0x4e0\n"
+				"__OP2H=0x4e2\n"
+				"__RES0=0x4e4\n"
+				"__RES1=0x4e6\n"
+				"__RES2=0x4e8\n"
+				"__RES3=0x4ea\n"
+				"__MPY32CTL0=0x4ec\n"
+				"\n");
+			break;
+		default:
+			fprintf (file, "/* Hardware multiplier registers: */\n"
+				"__MPY=0x130\n"
+				"__MPYS=0x132\n"
+				"__MAC=0x134\n"
+				"__MACS=0x136\n"
+				"__OP2=0x138\n"
+				"__RESLO=0x13a\n" 
+				"__RESHI=0x13c\n" 
+				"__SUMEXT=0x13e\n" 
+				"\n");
+		}
+
+	}
+
+	msp430_commands_in_file = 0;
+	msp430_commands_in_prologues = 0;
+	msp430_commands_in_epilogues = 0;
+}
+
+/* Outputs to the stdio stream FILE some
+appropriate text to go at the end of an assembler file.  */
+
+static void msp430_file_end (void)
+{
+	fprintf (asm_out_file,
+		"\n"
+		"/*********************************************************************\n"
+		" * File %s: code size: %d words (0x%x)\n * incl. words in prologues: %d, epilogues: %d\n"
+		" *********************************************************************/\n",
+		main_input_filename,
+		msp430_commands_in_file,
+		msp430_commands_in_file, msp430_commands_in_prologues, msp430_commands_in_epilogues);
+}
+
+int
+msp430_hard_regno_mode_ok (regno, mode)
+int regno ATTRIBUTE_UNUSED;
+enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+	return 1;
+}
+
+#if GCC_VERSION_INT >= 0x440
+#define current_function_calls_alloca cfun->calls_alloca
+#endif
+
+int
+frame_pointer_required_p ()
+{
+	return (current_function_calls_alloca
+		/*            || current_function_args_info.nregs == 0 */
+		/*|| current_function_varargs*/);
+
+	/* || get_frame_size () > 0); */
+}
+
+enum reg_class
+preferred_reload_class (x, class)
+rtx x ATTRIBUTE_UNUSED;
+enum reg_class class;
+{
+	return class;
+}
+
+int
+adjust_insn_length (insn, len)
+rtx insn;
+int len;
+{
+
+	rtx patt = PATTERN (insn);
+	rtx set;
+
+	set = single_set (insn);
+
+	if (GET_CODE (patt) == SET)
+	{
+		rtx op[10];
+		op[1] = SET_SRC (patt);
+		op[0] = SET_DEST (patt);
+
+		if (general_operand (op[1], VOIDmode)
+			&& general_operand (op[0], VOIDmode))
+		{
+			op[2] = SET_SRC (patt);
+			switch (GET_MODE (op[0]))
+			{
+			case QImode:
+			case HImode:
+				if (indexed_location (op[1]))
+					len--;
+				break;
+
+			case SImode:
+			case SFmode:
+				/* get length first */
+				msp430_movesi_code (insn, op, &len);
+
+				if (zero_shifted (op[1]) && regsi_ok_safe (op))
+				{
+					rtx reg = XEXP (op[1], 0);
+					if (dead_or_set_p (insn, reg))
+						len -= 1;
+				}
+				else if (!zero_shifted (op[1]) && indexed_location (op[1]))
+				{
+					len -= 1;
+				}
+				break;
+			case DImode:
+				msp430_movedi_code (insn, op, &len);
+				if (zero_shifted (op[1]) && regdi_ok_safe (op))
+				{
+					rtx reg = XEXP (op[1], 0);
+					if (dead_or_set_p (insn, reg))
+						len -= 1;
+				}
+				else if (!zero_shifted (op[1]) && indexed_location (op[1]))
+				{
+					len -= 1;
+				}
+				break;
+
+			default:
+				break;
+			}
+
+			if (GET_CODE (op[2]) == CONST_INT)
+			{
+				if (GET_MODE (op[0]) == DImode)
+				{
+					int x = INTVAL (op[2]);
+					int y = (x & 0xffff0000ul) >> 16;
+					x = x & 0xffff;
+
+					len -= 2;
+
+					if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+						|| x == 0xffff)
+						len--;
+					if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+						|| y == 0xffff)
+						len--;
+				}
+				else if (GET_MODE (op[0]) == SImode)
+				{
+					int x = INTVAL (op[2]);
+					int y = (x & 0xffff0000ul) >> 16;
+					x = x & 0xffff;
+
+					if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+						|| x == 0xffff)
+						len--;
+					if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+						|| y == 0xffff)
+						len--;
+				}
+				else
+				{
+					/* mighr be hi or qi modes */
+					int x = INTVAL (op[2]);
+					x = x & 0xffff;
+					if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+						|| x == 0xffff)
+						len--;
+				}
+			}
+
+			if (GET_CODE (op[2]) == CONST_DOUBLE)
+			{
+				if (GET_MODE (op[0]) == SFmode)
+				{
+					long val;
+					int y, x;
+					REAL_VALUE_TYPE rv;
+					REAL_VALUE_FROM_CONST_DOUBLE (rv, op[2]);
+					REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+
+					y = (val & 0xffff0000ul) >> 16;
+					x = val & 0xffff;
+					if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+						|| x == 0xffff)
+						len--;
+					if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+						|| y == 0xffff)
+						len--;
+				}
+				else
+				{
+					int hi = CONST_DOUBLE_HIGH (op[2]);
+					int lo = CONST_DOUBLE_LOW (op[2]);
+					int x, y, z;
+
+					x = (hi & 0xffff0000ul) >> 16;
+					y = hi & 0xffff;
+					z = (lo & 0xffff0000ul) >> 16;
+					if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+						|| x == 0xffff)
+						len--;
+					if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+						|| y == 0xffff)
+						len--;
+					if (z == 0 || z == 1 || z == 2 || z == 4 || z == 8
+						|| z == 0xffff)
+						len--;
+					z = lo & 0xffff;
+					if (z == 0 || z == 1 || z == 2 || z == 4 || z == 8
+						|| z == 0xffff)
+						len--;
+				}
+			}
+
+			return len;
+		}
+		else if (GET_CODE (op[1]) == MULT)
+		{
+			rtx ops[10];
+			ops[0] = op[0];
+			ops[1] = XEXP (op[1], 0);
+			ops[2] = XEXP (op[1], 1);
+
+			if (GET_MODE (ops[0]) != SImode
+				&& GET_MODE (ops[0]) != SFmode && GET_MODE (ops[0]) != DImode)
+			{
+				if (indexed_location (ops[1]))
+					len--;
+				if (indexed_location (ops[2]))
+					len--;
+			}
+		}
+		else if (GET_CODE (op[1]) == ASHIFT
+			|| GET_CODE (op[1]) == ASHIFTRT || GET_CODE (op[1]) == LSHIFTRT)
+		{
+			rtx ops[10];
+			ops[0] = op[0];
+			ops[1] = XEXP (op[1], 0);
+			ops[2] = XEXP (op[1], 1);
+
+			switch (GET_CODE (op[1]))
+			{
+			case ASHIFT:
+				switch (GET_MODE (op[0]))
+				{
+				case QImode:
+					msp430_emit_ashlqi3 (insn, ops, &len);
+					break;
+				case HImode:
+					msp430_emit_ashlhi3 (insn, ops, &len);
+					break;
+				case SImode:
+					msp430_emit_ashlsi3 (insn, ops, &len);
+					break;
+				case DImode:
+					msp430_emit_ashldi3 (insn, ops, &len);
+					break;
+				default:
+					break;
+				}
+				break;
+
+			case ASHIFTRT:
+				switch (GET_MODE (op[0]))
+				{
+				case QImode:
+					msp430_emit_ashrqi3 (insn, ops, &len);
+					break;
+				case HImode:
+					msp430_emit_ashrhi3 (insn, ops, &len);
+					break;
+				case SImode:
+					msp430_emit_ashrsi3 (insn, ops, &len);
+					break;
+				case DImode:
+					msp430_emit_ashrdi3 (insn, ops, &len);
+					break;
+				default:
+					break;
+				}
+				break;
+
+			case LSHIFTRT:
+				switch (GET_MODE (op[0]))
+				{
+				case QImode:
+					msp430_emit_lshrqi3 (insn, ops, &len);
+					break;
+				case HImode:
+					msp430_emit_lshrhi3 (insn, ops, &len);
+					break;
+				case SImode:
+					msp430_emit_lshrsi3 (insn, ops, &len);
+					break;
+				case DImode:
+					msp430_emit_lshrdi3 (insn, ops, &len);
+					break;
+				default:
+					break;
+				}
+				break;
+
+			default:
+				break;
+			}
+		}
+		else if (GET_CODE (op[1]) == PLUS
+			|| GET_CODE (op[1]) == MINUS
+			|| GET_CODE (op[1]) == AND
+			|| GET_CODE (op[1]) == IOR || GET_CODE (op[1]) == XOR)
+		{
+			rtx ops[10];
+			ops[0] = op[0];
+			ops[1] = XEXP (op[1], 0);
+			ops[2] = XEXP (op[1], 1);
+
+			if (GET_CODE (op[1]) == AND && !general_operand (ops[1], VOIDmode))
+				return len;
+
+			switch (GET_MODE (ops[0]))
+			{
+			case QImode:
+			case HImode:
+				if (indexed_location (ops[2]))
+					len--;
+				break;
+			case SImode:
+			case SFmode:
+
+				if (GET_CODE (op[1]) == PLUS)
+					msp430_addsi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == MINUS)
+					msp430_subsi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == AND)
+					msp430_andsi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == IOR)
+					msp430_iorsi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == XOR)
+					msp430_xorsi_code (insn, ops, &len);
+
+				if (zero_shifted (ops[2]) && regsi_ok_safe (ops))
+				{
+					rtx reg = XEXP (ops[2], 0);
+					if (dead_or_set_p (insn, reg))
+						len -= 1;
+				}
+				else if (!zero_shifted (ops[2]) && indexed_location (ops[2]))
+				{
+					len -= 1;
+				}
+				break;
+			case DImode:
+
+				if (GET_CODE (op[1]) == PLUS)
+					msp430_adddi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == MINUS)
+					msp430_subdi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == AND)
+					msp430_anddi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == IOR)
+					msp430_iordi_code (insn, ops, &len);
+				if (GET_CODE (op[1]) == XOR)
+					msp430_xordi_code (insn, ops, &len);
+
+				if (zero_shifted (ops[2]) && regdi_ok_safe (ops))
+				{
+					rtx reg = XEXP (ops[2], 0);
+					if (dead_or_set_p (insn, reg))
+						len -= 1;
+				}
+				else if (!zero_shifted (ops[2]) && indexed_location (ops[2]))
+				{
+					len -= 1;
+				}
+				break;
+
+			default:
+				break;
+			}
+
+			if (GET_MODE (ops[0]) == SImode)
+			{
+				if (GET_CODE (ops[2]) == CONST_INT)
+				{
+					if (GET_CODE (op[1]) == AND)
+					{
+						msp430_emit_immediate_and2 (insn, ops, &len);
+					}
+					else if (GET_CODE (op[1]) == IOR)
+					{
+						msp430_emit_immediate_ior2 (insn, ops, &len);
+					}
+					else
+					{
+						if (GET_MODE (ops[0]) == SImode)
+						{
+							int x = INTVAL (ops[2]);
+							int y = (x & 0xffff0000ul) >> 16;
+							x = x & 0xffff;
+
+							if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+								|| x == 0xffff)
+								len--;
+							if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+								|| y == 0xffff)
+								len--;
+						}
+					}
+				}
+			}
+
+			if (GET_MODE (ops[0]) == SFmode || GET_MODE (ops[0]) == DImode)
+			{
+				if (GET_CODE (ops[2]) == CONST_DOUBLE)
+				{
+
+					if (GET_CODE (op[1]) == AND)
+					{
+						msp430_emit_immediate_and4 (insn, ops, &len);
+					}
+					else if (GET_CODE (op[1]) == IOR)
+					{
+						msp430_emit_immediate_ior4 (insn, ops, &len);
+					}
+					else if (GET_MODE (ops[0]) == SFmode)
+					{
+						long val;
+						int y, x;
+						REAL_VALUE_TYPE rv;
+						REAL_VALUE_FROM_CONST_DOUBLE (rv, ops[2]);
+						REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+
+						y = (val & 0xffff0000ul) >> 16;
+						x = val & 0xffff;
+						if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+							|| x == 0xffff)
+							len--;
+						if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+							|| y == 0xffff)
+							len--;
+					}
+					else
+					{
+						int hi = CONST_DOUBLE_HIGH (ops[2]);
+						int lo = CONST_DOUBLE_LOW (ops[2]);
+						int x, y, z;
+
+						x = (hi & 0xffff0000ul) >> 16;
+						y = hi & 0xffff;
+						z = (lo & 0xffff0000ul) >> 16;
+						if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8
+							|| x == 0xffff)
+							len--;
+						if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8
+							|| y == 0xffff)
+							len--;
+						if (z == 0 || z == 1 || z == 2 || z == 4 || z == 8
+							|| z == 0xffff)
+							len--;
+					}
+				}
+			}
+
+			return len;
+		}
+		else if (GET_CODE (op[1]) == NOT
+			|| GET_CODE (op[1]) == ABS || GET_CODE (op[1]) == NEG)
+		{
+			if (GET_MODE (op[0]) == HImode || GET_MODE (op[0]) == QImode)
+				if (indexed_location (XEXP (op[1], 0)))
+					len--;
+			/* consts handled by cpp */
+			/* nothing... */
+		}
+		else if (GET_CODE (op[1]) == ZERO_EXTEND)
+		{
+			rtx ops[10];
+			ops[0] = op[0];
+			ops[1] = XEXP (op[1], 0);
+
+			if (GET_MODE (ops[1]) == QImode)
+			{
+				if (GET_MODE (ops[0]) == HImode)
+					zeroextendqihi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == SImode)
+					zeroextendqisi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == DImode)
+					zeroextendqidi (insn, ops, &len);
+			}
+			else if (GET_MODE (ops[1]) == HImode)
+			{
+				if (GET_MODE (ops[0]) == SImode)
+					zeroextendhisi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == DImode)
+					zeroextendhidi (insn, ops, &len);
+			}
+			else if (GET_MODE (ops[1]) == SImode)
+			{
+				if (GET_MODE (ops[1]) == DImode)
+					zeroextendsidi (insn, ops, &len);
+			}
+		}
+		else if (GET_CODE (op[1]) == SIGN_EXTEND)
+		{
+			rtx ops[10];
+			ops[0] = op[0];	/* dest */
+			ops[1] = XEXP (op[1], 0);	/* src */
+
+			if (GET_MODE (ops[1]) == QImode)
+			{
+				if (GET_MODE (ops[0]) == HImode)
+					signextendqihi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == SImode)
+					signextendqisi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == DImode)
+					signextendqidi (insn, ops, &len);
+			}
+			else if (GET_MODE (ops[1]) == HImode)
+			{
+				if (GET_MODE (ops[0]) == SImode)
+					signextendhisi (insn, ops, &len);
+				else if (GET_MODE (ops[0]) == DImode)
+					signextendhidi (insn, ops, &len);
+			}
+			else if (GET_MODE (ops[1]) == SImode)
+			{
+				if (GET_MODE (ops[0]) == DImode)
+					signextendsidi (insn, ops, &len);
+			}
+		}
+		else if (GET_CODE (op[1]) == IF_THEN_ELSE)
+		{
+			if (GET_CODE (op[0]) == PC)
+			{
+				rtx ops[5];
+				ops[0] = XEXP (op[1], 1);
+				ops[1] = XEXP (op[1], 0);
+				ops[2] = XEXP (ops[1], 0);
+				ops[3] = XEXP (ops[1], 1);
+				msp430_cbranch (insn, ops, &len, 0);
+			}
+		}
+		else if (GET_CODE (op[0]) == MEM
+			&& GET_CODE (XEXP (op[0], 0)) == POST_DEC)
+		{
+			rtx ops[4];
+			ops[0] = op[1];
+			if (GET_MODE (op[0]) == QImode)
+				msp430_pushqi (insn, ops, &len);
+			if (GET_MODE (op[0]) == HImode)
+				msp430_pushhi (insn, ops, &len);
+			if (GET_MODE (op[0]) == SImode)
+				msp430_pushsisf (insn, ops, &len);
+			if (GET_MODE (op[0]) == DImode)
+				msp430_pushdi (insn, ops, &len);
+		}
+	}
+
+	if (set)
+	{
+		rtx op[10];
+		op[1] = SET_SRC (set);
+		op[0] = SET_DEST (set);
+
+		if (GET_CODE (patt) == PARALLEL)
+		{
+			if (GET_CODE (op[0]) == PC && GET_CODE (op[1]) == IF_THEN_ELSE)
+			{
+				rtx ops[5];
+				ops[0] = XEXP (op[1], 1);
+				ops[1] = XEXP (op[1], 0);
+				ops[2] = XEXP (ops[1], 0);
+				ops[3] = XEXP (ops[1], 1);
+				msp430_cbranch (insn, ops, &len, 0);
+			}
+
+			if (GET_CODE (op[1]) == ASHIFT
+				|| GET_CODE (op[1]) == ASHIFTRT || GET_CODE (op[1]) == LSHIFTRT)
+			{
+				rtx ops[10];
+				ops[0] = op[0];
+				ops[1] = XEXP (op[1], 0);
+				ops[2] = XEXP (op[1], 1);
+
+				switch (GET_CODE (op[1]))
+				{
+				case ASHIFT:
+					switch (GET_MODE (op[0]))
+					{
+					case QImode:
+						msp430_emit_ashlqi3 (insn, ops, &len);
+						break;
+					case HImode:
+						msp430_emit_ashlhi3 (insn, ops, &len);
+						break;
+					case SImode:
+						msp430_emit_ashlsi3 (insn, ops, &len);
+						break;
+					case DImode:
+						msp430_emit_ashldi3 (insn, ops, &len);
+						break;
+					default:
+						break;
+					}
+					break;
+
+				case ASHIFTRT:
+					switch (GET_MODE (op[0]))
+					{
+					case QImode:
+						msp430_emit_ashrqi3 (insn, ops, &len);
+						break;
+					case HImode:
+						msp430_emit_ashrhi3 (insn, ops, &len);
+						break;
+					case SImode:
+						msp430_emit_ashrsi3 (insn, ops, &len);
+						break;
+					case DImode:
+						msp430_emit_ashrdi3 (insn, ops, &len);
+						break;
+					default:
+						break;
+					}
+					break;
+
+				case LSHIFTRT:
+					switch (GET_MODE (op[0]))
+					{
+					case QImode:
+						msp430_emit_lshrqi3 (insn, ops, &len);
+						break;
+					case HImode:
+						msp430_emit_lshrhi3 (insn, ops, &len);
+						break;
+					case SImode:
+						msp430_emit_lshrsi3 (insn, ops, &len);
+						break;
+					case DImode:
+						msp430_emit_lshrdi3 (insn, ops, &len);
+						break;
+					default:
+						break;
+					}
+					break;
+
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	return len;
+}
+
+void
+machine_dependent_reorg (first_insn)
+rtx first_insn ATTRIBUTE_UNUSED;
+{
+	/* nothing to be done here this time */
+	return;
+}
+
+
+int
+test_hard_reg_class (class, x)
+enum reg_class class;
+rtx x;
+{
+	int regno = true_regnum (x);
+	if (regno < 0)
+		return 0;
+	return TEST_HARD_REG_CLASS (class, regno);
+}
+
+
+/* Returns 1 if SCRATCH are safe to be allocated as a scratch
+registers (for a define_peephole2) in the current function.  */
+/* UNUSED ... yet... */
+int
+msp430_peep2_scratch_safe (scratch)
+rtx scratch;
+{
+	if ((interrupt_function_p (current_function_decl)
+		|| signal_function_p (current_function_decl)) && cfun->machine->is_leaf)
+	{
+		int first_reg = true_regnum (scratch);
+		int last_reg;
+		int size = GET_MODE_SIZE (GET_MODE (scratch));
+		int reg;
+
+		size >>= 1;
+		if (!size)
+			size = 1;
+
+		last_reg = first_reg + size - 1;
+
+		for (reg = first_reg; reg <= last_reg; reg++)
+		{
+			if (!df_regs_ever_live_p(reg))
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+/* Update the condition code in the INSN.
+now mostly unused */
+
+void
+notice_update_cc (body, insn)
+rtx body ATTRIBUTE_UNUSED;
+rtx insn ATTRIBUTE_UNUSED;
+{
+	CC_STATUS_INIT;
+}
+
+
+
+/*********************************************************************/
+
+/*
+Next two return non zero for rtx as
+(set (reg:xx)
+(mem:xx (reg:xx))
+
+*/
+
+int
+regsi_ok_safe (operands)
+rtx operands[];
+{
+	rtx dest = operands[0];
+	rtx areg;
+	int src_reg;
+	int dst_reg;
+
+	if (operands[2])
+		areg = XEXP (operands[2], 0);
+	else
+		areg = XEXP (operands[1], 0);
+
+	if (GET_CODE (dest) == MEM)
+	{
+		dest = XEXP (operands[0], 0);
+		if (GET_CODE (dest) == PLUS && GET_CODE (XEXP (dest, 0)) == REG)
+		{
+			dest = XEXP (dest, 0);
+		}
+		else if (GET_CODE (dest) == REG)
+		{
+			;			/* register */
+		}
+		else
+			return 1;
+	}
+
+	if (REGNO (dest) >= FIRST_PSEUDO_REGISTER
+		|| REGNO (areg) >= FIRST_PSEUDO_REGISTER)
+		return 1;
+
+	dst_reg = true_regnum (dest);
+	src_reg = true_regnum (areg);
+	if (dst_reg > src_reg || dst_reg + 1 < src_reg)
+	{
+		return 1;
+	}
+	return 0;
+}
+
+int
+regsi_ok_clobber (operands)
+rtx operands[];
+{
+	rtx dest = operands[0];
+	rtx areg = XEXP (operands[2], 0);
+	int src_reg;
+	int dst_reg;
+	int regno = REGNO (dest);
+
+
+	if (GET_CODE (dest) == MEM)
+	{
+		dest = XEXP (operands[0], 0);
+		if (GET_CODE (dest) == PLUS && GET_CODE (XEXP (dest, 0)) == REG)
+		{
+			dest = XEXP (dest, 0);
+		}
+		else if (GET_CODE (dest) == REG)
+		{
+			;			/* register */
+		}
+		else
+			return 1;
+	}
+
+	if (regno >= FIRST_PSEUDO_REGISTER || REGNO (areg) >= FIRST_PSEUDO_REGISTER)
+		return 1;
+
+	dst_reg = true_regnum (dest);
+	src_reg = true_regnum (areg);
+	if (dst_reg + 1 == src_reg)
+		return 1;
+	return 0;
+}
+
+int
+regdi_ok_safe (operands)
+rtx operands[];
+{
+	rtx dest = operands[0];
+	rtx areg = XEXP (operands[2], 0);
+	int src_reg;
+	int dst_reg;
+
+
+	if (GET_CODE (dest) == MEM)
+	{
+		dest = XEXP (operands[0], 0);
+		if (GET_CODE (dest) == PLUS && GET_CODE (XEXP (dest, 0)) == REG)
+		{
+			dest = XEXP (dest, 0);
+		}
+		else if (GET_CODE (dest) == REG)
+		{
+			;			/* register */
+		}
+		else
+			return 1;
+	}
+
+	if (REGNO (dest) >= FIRST_PSEUDO_REGISTER
+		|| REGNO (areg) >= FIRST_PSEUDO_REGISTER)
+		return 1;
+
+	dst_reg = true_regnum (dest);
+	src_reg = true_regnum (areg);
+	if (dst_reg > src_reg || dst_reg + 3 < src_reg)
+	{
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+regdi_ok_clobber (operands)
+rtx operands[];
+{
+	rtx dest = operands[0];
+	rtx areg = XEXP (operands[2], 0);
+	int src_reg;
+	int dst_reg;
+	int regno = REGNO (dest);
+
+	if (GET_CODE (dest) == MEM)
+	{
+		dest = XEXP (operands[0], 0);
+		if (GET_CODE (dest) == PLUS && GET_CODE (XEXP (dest, 0)) == REG)
+		{
+			dest = XEXP (dest, 0);
+		}
+		else if (GET_CODE (dest) == REG)
+		{
+			;			/* register */
+		}
+		else
+			return 1;
+	}
+
+	if (regno >= FIRST_PSEUDO_REGISTER || REGNO (areg) >= FIRST_PSEUDO_REGISTER)
+		return 1;
+
+	dst_reg = true_regnum (dest);
+	src_reg = true_regnum (areg);
+	if (dst_reg + 3 == src_reg)
+		return 1;
+	return 0;
+}
+
+
+/***************** ARITHMETIC *******************/
+
+int
+emit_indexed_arith (insn, operands, m, cmd, iscarry)
+rtx insn;
+rtx operands[];
+int m;
+const char *cmd;
+int iscarry;
+{
+	char template[256];
+	register int i = 0;
+	char *p;
+	rtx reg = NULL;
+	int len = m * 2;
+	rtx x = operands[0];
+	int havestop = 0;
+	rtx pattern;
+	rtx next = next_real_insn (insn);
+
+
+	pattern = PATTERN (next);
+
+	if (pattern && GET_CODE (pattern) == PARALLEL)
+	{
+		pattern = XVECEXP (pattern, 0, 0);
+	}
+
+	if (followed_compare_condition (insn) != UNKNOWN
+		|| GET_CODE(insn) == JUMP_INSN
+		|| (pattern
+		&& GET_CODE (pattern) == SET
+		&& SET_DEST (pattern) == cc0_rtx)
+		|| (pattern && GET_CODE (pattern) == SET
+		&& SET_DEST (pattern) == pc_rtx))
+	{
+		/* very exotic case */
+
+		snprintf (template, 255, "%s\t" "%%A%d, %%A0", cmd, operands[2] ? 2 : 1);
+		output_asm_insn (template, operands);
+		snprintf (template, 255, "%s%s\t" "%%B%d, %%B0", cmd, iscarry ? "c" : "",
+			operands[2] ? 2 : 1);
+		output_asm_insn (template, operands);
+
+		if (m == 2)
+			return len;
+
+		snprintf (template, 255, "%s%s\t" "%%C%d, %%C0", cmd, iscarry ? "c" : "",
+			operands[2] ? 2 : 1);
+		output_asm_insn (template, operands);
+		snprintf (template, 255, "%s%s\t" "%%D%d, %%D0", cmd, iscarry ? "c" : "",
+			operands[2] ? 2 : 1);
+		output_asm_insn (template, operands);
+
+		return len;
+	}
+
+	if (operands[2])
+		reg = XEXP (operands[2], 0);
+	else
+		reg = XEXP (operands[1], 0);
+
+	if (GET_CODE (x) == REG)
+	{
+		int src;
+		int dst = REGNO (x);
+
+		if (!reg)
+		{
+			reg = XEXP (operands[1], 0);
+		}
+
+		src = REGNO (reg);
+
+		/* check if registers overlap */
+		if (dst > src || (dst + m - 1) < src)
+		{
+			;			/* fine ! */
+		}
+		else if ((dst + m - 1) == src)
+		{
+			havestop = 1;		/* worse */
+		}
+		else
+		{
+			/* cannot do reverse assigment */
+			while (i < m)
+			{
+				p = (char *) (template + strlen (cmd));
+				p += (i && iscarry) ? 3 : 2;
+				strcpy (template, cmd);
+				strcat (template, (i && iscarry) ? "c\t%" : "\t%");
+				*p = 'A' + i;
+				p++;
+				*p = 0;
+				strcat (template, "0, %");
+				p += 2;
+				*p = 'A' + i;
+				p++;
+				*p = 0;
+				strcat (template, operands[2] ? "2" : "1");
+				output_asm_insn (template, operands);
+				i++;
+			}
+			return m * 3;
+		}
+	}
+
+	while (i < (m - havestop))
+	{
+		p = template + strlen (cmd);
+
+		strcpy (template, cmd);
+
+		if (i && iscarry)
+		{
+			strcat (template, "c\t");
+			p += 2;
+		}
+		else
+		{
+			strcat (template, "\t");
+			p += 1;
+		}
+		strcat (template, operands[2] ? "@%E2+, %" : "@%E1+, %");
+		p += 8;
+		*p = 'A' + i;
+		p++;
+		*p = 0;
+		strcat (template, "0");
+		p++;
+		output_asm_insn (template, operands);
+		i++;
+	}
+
+	if (havestop)
+	{
+		len++;
+		p = template + strlen (cmd);
+		strcpy (template, cmd);
+		if (i && iscarry)
+		{
+			strcat (template, "c\t");
+			p += 2;
+		}
+		else
+		{
+			strcat (template, "\t");
+			p += 1;
+		}
+		strcat (template, operands[2] ? "@%E2, %" : "@%E1, %");
+		p += 8;
+		*p = 'A' + i;
+		p++;
+		*p = 0;
+		strcat (template, "0	;	register won't die");
+		p += 1;
+		output_asm_insn (template, operands);
+	}
+
+	if (!dead_or_set_p (insn, reg) && !havestop)
+	{
+		len++;
+		p = template + 3;
+		strcpy (template, "sub");
+		strcat (template, "\t#");
+		p += 2;
+		*p = '0' + m * 2;
+		p++;
+		*p = 0;
+
+		if (operands[2])
+			strcat (template, ",    %E2	;	restore %E2");
+		else
+			strcat (template, ",    %E1	;	restore %E1");
+		output_asm_insn (template, operands);
+	}
+
+	return len;
+}
+
+static int sameoperand_p PARAMS ((rtx, rtx));
+
+int
+sameoperand (operands, i)
+rtx operands[];
+int i;
+{
+	rtx dst = operands[0];
+	rtx src = operands[i];
+
+	return sameoperand_p (src, dst);
+}
+
+static int
+sameoperand_p (src, dst)
+rtx src;
+rtx dst;
+{
+	enum rtx_code scode = GET_CODE (src);
+	enum rtx_code dcode = GET_CODE (dst);
+	/* cannot use standard functions here 
+	cause operands have different modes:
+	*/
+
+	if (scode != dcode)
+		return 0;
+
+	switch (scode)
+	{
+	case REG:
+		return REGNO (src) == REGNO (dst);
+		break;
+	case MEM:
+		return sameoperand_p (XEXP (src, 0), XEXP (dst, 0));
+		break;
+	case PLUS:
+		return sameoperand_p (XEXP (src, 0), XEXP (dst, 0))
+			&& sameoperand_p (XEXP (src, 1), XEXP (dst, 1));
+		break;
+	case CONST_INT:
+		return INTVAL (src) == INTVAL (dst);
+		break;
+	case SYMBOL_REF:
+		return XSTR (src, 0) == XSTR (dst, 0);
+		break;
+	default:
+		break;
+	}
+	return 0;
+
+}
+
+#define OUT_INSN(x,p,o) \
+	do {                            \
+	if(!x) output_asm_insn (p,o);   \
+	} while(0)
+
+
+
+/************** MOV CODE *********************************/
+
+const char *
+movstrsi_insn (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+
+	/* operands 0 and 1 are registers !!! */
+	/* operand 2 is a cnt and not zero */
+	output_asm_insn ("\n.Lmsn%=:", operands);
+	output_asm_insn ("mov.b\t@%1+,0(%0)", operands);
+	output_asm_insn ("inc\t%0", operands);
+	output_asm_insn ("dec\t%2", operands);
+	output_asm_insn ("jnz\t.Lmsn%=", operands);
+
+	return "";
+}
+
+
+const char *
+clrstrsi_insn (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+
+	/* operand 0 is a register !!! */
+	/* operand 1 is a cnt and not zero */
+	output_asm_insn ("\n.Lcsn%=:", operands);
+	output_asm_insn ("clr.b\t0(%0)	;	clr does not support @rn+",
+		operands);
+	output_asm_insn ("inc\t%0", operands);
+	output_asm_insn ("dec\t%1", operands);
+	output_asm_insn ("jnz\t.Lcsn%=", operands);
+	return "";
+}
+
+const char *
+movstrhi_insn (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+
+	/* operands 0 and 1 are registers !!! */
+	/* operand 2 is a cnt and not zero */
+	output_asm_insn ("\n.Lmsn%=:", operands);
+	output_asm_insn ("mov.b\t@%1+,0(%0)", operands);
+	output_asm_insn ("inc\t%0", operands);
+	output_asm_insn ("dec\t%2", operands);
+	output_asm_insn ("jnz\t.Lmsn%=", operands);
+	return "";
+}
+
+const char *
+clrstrhi_insn (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+
+	/* operand 0 is a register !!! */
+	/* operand 1 is a cnt and not zero */
+	output_asm_insn ("\n.Lcsn%=:", operands);
+	output_asm_insn ("clr.b\t0(%0)", operands);
+	output_asm_insn ("inc\t%0", operands);
+	output_asm_insn ("dec\t%1", operands);
+	output_asm_insn ("jnz\t.Lcsn%=", operands);
+	return "";
+}
+
+int
+msp430_emit_indexed_mov (insn, operands, m, cmd)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int m;
+const char *cmd;
+{
+	char template[256];
+	register int i = 0;
+	char *p;
+	rtx reg = XEXP (operands[1], 0);
+	int len = m * 2;
+	rtx dst = 0;
+	int sreg,dreg = 0;
+
+	if(memory_operand(operands[0], VOIDmode))
+	{
+		if(  REG_P(XEXP(operands[0],0)))
+			dreg = REGNO(XEXP(operands[0],0));
+		else if(GET_CODE(XEXP(operands[0],0)) == PLUS
+			&& REG_P(XEXP(XEXP(operands[0],0),0)) )
+			dreg = REGNO(XEXP(XEXP(operands[0],0),0));
+	}
+
+
+	sreg = REGNO(XEXP(operands[1],0));
+
+	while (i < m)
+	{
+		p = template + strlen (cmd);
+
+		strcpy (template, cmd);
+		strcat (template, "\t");
+		p += 1;
+		strcat (template, "@%E1+, ");
+		p += 7;
+
+		if(dreg==sreg)
+		{
+			*p = '-'; p++;
+			*p = '2'; p++;
+			*p = '+'; p++;
+		}
+
+		*p = '%'; p++;
+		*p = 'A' + ((dreg==sreg)?0:i);
+
+		p++;
+		*p = 0;
+		strcat (template, "0");
+		p += 1;
+		output_asm_insn (template, operands);
+		i++;
+	}
+
+	if (!dead_or_set_p (insn, reg))
+	{
+		len++;
+		p = template + 3;
+		strcpy (template, "sub");
+		strcat (template, "\t#");
+		p += 2;
+		*p = '0' + m * 2;
+		p++;
+		*p = 0;
+		strcat (template, ",    %E1	;	restore %E1");
+		output_asm_insn (template, operands);
+	}
+
+	return len;
+}
+
+const char *
+msp430_emit_indexed_mov2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	msp430_emit_indexed_mov (insn, operands, 2, "mov");
+	return "";
+}
+
+const char *
+msp430_emit_indexed_mov4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	msp430_emit_indexed_mov (insn, operands, 4, "mov");
+	return "";
+}
+
+const char *
+movsisf_regmode (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	rtx dest = operands[0];
+	rtx src = operands[1];
+	rtx areg = XEXP (src, 0);
+	int src_reg = true_regnum (areg);
+	int dst_reg = true_regnum (dest);
+
+
+	if (dst_reg > src_reg || dst_reg + 1 < src_reg)
+	{
+		output_asm_insn ("mov\t@%E1+, %A0", operands);
+		output_asm_insn ("mov\t@%E1+, %B0", operands);
+		if (!dead_or_set_p (insn, areg))
+		{
+			output_asm_insn ("sub\t#4, %E1\t;\trestore %E1", operands);
+		}
+		return "";
+	}
+	else if (dst_reg + 1 == src_reg)
+	{
+		output_asm_insn ("mov\t@%E1+, %A0", operands);
+		output_asm_insn ("mov\t@%E1, %B0", operands);
+		return "";
+	}
+	else
+	{
+		/* destination overlaps with source.
+		so, update destination in reverse way */
+		output_asm_insn ("mov\t%B1, %B0", operands);
+		output_asm_insn ("mov\t@%E1, %A0", operands);
+	}
+
+	return "";			/* make compiler happy */
+}
+
+
+/* From Max Behensky <maxb@twinlanes.com>  
+This function tells you what the index register in an operand is.  It
+returns the register number, or -1 if it is not an indexed operand */
+static int get_indexed_reg PARAMS ((rtx));
+static int
+get_indexed_reg (x)
+rtx x;
+{
+	int code;
+
+	code = GET_CODE (x);
+
+	if (code != MEM)
+		return (-1);
+
+	x = XEXP (x, 0);
+	code = GET_CODE (x);
+	if (code == REG)
+		return (REGNO (x));
+
+	if (code != PLUS)
+		return (-1);
+
+	x = XEXP (x, 0);
+	code = GET_CODE (x);
+	if (code != REG)
+		return (-1);
+
+	return (REGNO (x));
+}
+
+
+const char *
+msp430_movesi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op1 = operands[1];
+
+
+	if (memory_operand (op0, VOIDmode)
+		&& memory_operand (op1, VOIDmode) && zero_shifted (op1))
+	{
+		if (!len)
+			msp430_emit_indexed_mov2 (insn, operands, NULL);
+		else
+			*len = 5;
+		return "";
+	}	
+	else if (register_operand (op0, VOIDmode)
+		&& memory_operand (op1, VOIDmode) && zero_shifted (op1))
+	{
+		if (!len)
+			movsisf_regmode (insn, operands, NULL);
+		else
+			*len = 3;
+		return "";
+	}
+
+	if (!len)
+	{
+		if ((register_operand (op0, VOIDmode)
+			&& register_operand (op1, VOIDmode)
+			&& REGNO (op1) + 1 == REGNO (op0))
+			|| (register_operand (op0, VOIDmode)
+			&& memory_operand (op1, VOIDmode)
+			&& get_indexed_reg (op1) == true_regnum (op0)))
+		{
+			output_asm_insn ("mov\t%B1, %B0", operands);
+			output_asm_insn ("mov\t%A1, %A0", operands);
+		}
+		else
+		{
+			output_asm_insn ("mov\t%A1, %A0", operands);
+			output_asm_insn ("mov\t%B1, %B0", operands);
+		}
+	}
+	else
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (op0, VOIDmode))
+			*len += 0;
+		else if (memory_operand (op0, VOIDmode))
+			*len += 2;
+
+		if (register_operand (op1, VOIDmode))
+			*len += 0;
+		else if (memory_operand (op1, VOIDmode))
+			*len += 2;
+		else if (immediate_operand (op1, VOIDmode))
+			*len += 2;
+	}
+
+	return "";
+}
+
+const char *
+movdidf_regmode (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	rtx dest = operands[0];
+	rtx src = operands[1];
+	rtx areg = XEXP (src, 0);
+
+	int src_reg = true_regnum (areg);
+	int dst_reg = true_regnum (dest);
+
+
+	if (dst_reg > src_reg || dst_reg + 3 < src_reg)
+	{
+		output_asm_insn ("mov\t@%E1+, %A0", operands);
+		output_asm_insn ("mov\t@%E1+, %B0", operands);
+		output_asm_insn ("mov\t@%E1+, %C0", operands);
+		output_asm_insn ("mov\t@%E1+, %D0", operands);
+		if (!dead_or_set_p (insn, areg))
+		{
+			output_asm_insn ("sub\t#8, %E1\t;\trestore %E1", operands);
+		}
+	}
+	else if (dst_reg + 3 == src_reg)
+	{
+		output_asm_insn ("mov\t@%E1+, %A0", operands);
+		output_asm_insn ("mov\t@%E1+, %B0", operands);
+		output_asm_insn ("mov\t@%E1+, %C0", operands);
+		output_asm_insn ("mov\t@%E1,  %D0	;	%E1 == %D0", operands);
+	}
+	else
+	{
+		/* destination overlaps source.
+		so, update destination in reverse way */
+		output_asm_insn ("mov\t%D1, %D0	; %E1 overlaps wit one of %A0 - %D0",
+			operands);
+		output_asm_insn ("mov\t%C1, %C0", operands);
+		output_asm_insn ("mov\t%B1, %B0", operands);
+		output_asm_insn ("mov\t@%E1, %A0", operands);
+	}
+
+	return "";
+}
+
+const char *
+msp430_movedi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op1 = operands[1];
+
+	if (memory_operand (op0, DImode)
+		&& memory_operand (op1, DImode) && zero_shifted (op1))
+	{
+		if (!len)
+			msp430_emit_indexed_mov4 (insn, operands, NULL);
+		else
+			*len = 9;
+		return "";
+	}
+	else if (register_operand (op0, DImode)
+		&& memory_operand (op1, DImode) && zero_shifted (op1))
+	{
+		if (!len)
+			movdidf_regmode (insn, operands, NULL);
+		else
+			*len = 5;
+		return "";
+	}
+
+	if (!len)
+	{
+		if (register_operand (op0, SImode)
+			&& register_operand (op1, SImode) && REGNO (op1) + 3 == REGNO (op0))
+		{
+			output_asm_insn ("mov\t%D1, %D0", operands);
+			output_asm_insn ("mov\t%C1, %C0", operands);
+			output_asm_insn ("mov\t%B1, %B0", operands);
+			output_asm_insn ("mov\t%A1, %A0", operands);
+		}
+		else
+		{
+			output_asm_insn ("mov\t%A1, %A0", operands);
+			output_asm_insn ("mov\t%B1, %B0", operands);
+			output_asm_insn ("mov\t%C1, %C0", operands);
+			output_asm_insn ("mov\t%D1, %D0", operands);
+		}
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op1, DImode))
+			*len += 0;
+		else if (memory_operand (op1, DImode))
+			*len += 4;
+		else if (immediate_operand (op1, DImode))
+			*len += 4;
+	}
+
+	return "";
+}
+
+
+
+
+/**************	ADD CODE *********************************/
+
+
+const char *
+msp430_emit_indexed_add2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 2, "add", 1);
+	return "";
+}
+
+const char *
+msp430_emit_indexed_add4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 4, "add", 1);
+	return "";
+}
+
+const char *
+msp430_addsi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+	rtx ops[4];
+
+	if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_add2 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, SImode))
+				*len = 5;
+			else if (register_operand (op0, SImode))
+				*len = 3;
+		}
+		return "";
+	}
+	else if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("add\t@%E2+, %A0", operands);
+			output_asm_insn ("addc\t@%E2+, %B0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, SImode))
+				*len = 2;
+			else if (memory_operand (op0, SImode))
+				*len = 4;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	ops[0] = operands[0];
+	ops[2] = operands[2];
+
+	if (!len)
+	{
+		output_asm_insn ("add\t%A2, %A0", ops);
+		output_asm_insn ("addc\t%B2, %B0", ops);
+	}
+
+	if (len)
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (ops[0], SImode))
+			*len += 0;
+		else if (memory_operand (ops[0], SImode))
+			*len += 2;
+
+		if (register_operand (ops[2], SImode))
+			*len += 0;
+		else if (memory_operand (ops[2], SImode))
+			*len += 2;
+		else if (immediate_operand (ops[2], SImode))
+		{
+			int x = INTVAL (ops[2]);
+			if (x == -2 || x == -4 || x == -8)
+			{
+				*len += 1;
+			}
+			else
+				*len += 2;
+		}
+	}
+	return "";
+}
+
+const char *
+msp430_adddi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_add4 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, DImode))
+				*len = 9;
+			else if (register_operand (op0, DImode))
+				*len = 5;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("add\t@%E2+, %A0", operands);
+			output_asm_insn ("addc\t@%E2+, %B0", operands);
+			output_asm_insn ("addc\t@%E2+, %C0", operands);
+			output_asm_insn ("addc\t@%E2+, %D0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, DImode))
+				*len = 4;
+			else if (memory_operand (op0, DImode))
+				*len = 8;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("add\t%A2, %A0", operands);
+		output_asm_insn ("addc\t%B2, %B0", operands);
+		output_asm_insn ("addc\t%C2, %C0", operands);
+		output_asm_insn ("addc\t%D2, %D0", operands);
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op2, DImode))
+			*len += 0;
+		else if (memory_operand (op2, DImode))
+			*len += 4;
+		else if (immediate_operand (op2, DImode))
+		{
+			int x = INTVAL (op2);
+
+			if (x == -2 || x == -4 || x == -8)
+				*len += 0;
+			else
+				*len += 4;
+		}
+		else
+			abort ();
+	}
+
+	return "";
+}
+
+
+/**************	SUB CODE *********************************/
+
+const char *
+msp430_emit_indexed_sub2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 2, "sub", 1);
+	return "";
+}
+
+const char *
+msp430_emit_indexed_sub4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 4, "sub", 1);
+	return "";
+}
+
+const char *
+msp430_subsi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_sub2 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, SImode))
+				*len = 5;
+			else if (register_operand (op0, SImode))
+				*len = 3;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("sub\t@%E2+, %A0", operands);
+			output_asm_insn ("subc\t@%E2+, %B0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, SImode))
+				*len = 2;
+			else if (memory_operand (op0, SImode))
+				*len = 4;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("sub\t%A2, %A0", operands);
+		output_asm_insn ("subc\t%B2, %B0", operands);
+	}
+	else
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (op0, SImode))
+			*len += 0;
+		else if (memory_operand (op0, SImode))
+			*len += 2;
+
+		if (register_operand (op2, SImode))
+			*len += 0;
+		else if (memory_operand (op2, SImode))
+			*len += 2;
+		else if (immediate_operand (op2, SImode))
+			*len += 2;
+	}
+
+	return "";
+}
+
+
+const char *
+msp430_subdi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_sub4 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, DImode))
+				*len = 9;
+			else if (register_operand (op0, DImode))
+				*len = 5;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("sub\t@%E2+, %A0", operands);
+			output_asm_insn ("subc\t@%E2+, %B0", operands);
+			output_asm_insn ("subc\t@%E2+, %C0", operands);
+			output_asm_insn ("subc\t@%E2+, %D0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, DImode))
+				*len = 4;
+			else if (memory_operand (op0, DImode))
+				*len = 8;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("sub\t%A2, %A0", operands);
+		output_asm_insn ("subc\t%B2, %B0", operands);
+		output_asm_insn ("subc\t%C2, %C0", operands);
+		output_asm_insn ("subc\t%D2, %D0", operands);
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op2, DImode))
+			*len += 0;
+		else if (memory_operand (op2, DImode))
+			*len += 4;
+		else if (immediate_operand (op2, DImode))
+			*len += 4;
+		else
+			abort ();
+	}
+
+	return "";
+}
+
+
+/**************	AND CODE *********************************/
+
+const char *
+msp430_emit_indexed_and2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 2, "and", 0);
+	return "";
+}
+
+const char *
+msp430_emit_indexed_and4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 4, "and", 0);
+	return "";
+}
+
+const char *
+msp430_emit_immediate_and2 (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int v;
+	int l = INTVAL (operands[2]);
+	int r = REG_P (operands[0]);
+	int list1 = ((~1) & 0xffff);
+	int list2 = ((~2) & 0xffff);
+	int list4 = ((~4) & 0xffff);
+	int list8 = ((~8) & 0xffff);
+
+	rtx op[4];
+
+	op[0] = operands[0];
+	op[1] = operands[1];
+	op[2] = operands[2];
+
+	/* check nibbles */
+
+	v = (l) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %A0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %A0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	v = (l >> 16) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %B0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %B0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+const char *
+msp430_emit_immediate_and4 (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int v;
+	int l = CONST_DOUBLE_LOW (operands[2]);
+	int h = CONST_DOUBLE_HIGH (operands[2]);
+	int r = REG_P (operands[0]);
+	int list1 = ((~1) & 0xffff);
+	int list2 = ((~2) & 0xffff);
+	int list4 = ((~4) & 0xffff);
+	int list8 = ((~8) & 0xffff);
+	rtx op[4];
+
+	op[0] = operands[0];
+	op[1] = operands[1];
+	op[2] = operands[2];
+
+	/* check if operand 2 is really const_double */
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		l = INTVAL (operands[2]);
+		h = 0;
+	}
+
+	/* check nibbles */
+	v = (l) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %A0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %A0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	v = (l >> 16) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %B0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %B0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	v = (h) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %C0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %C0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	v = (h >> 16) & 0xffff;
+	if (v != 0xffff)
+	{
+		if (v == list1 || v == list2 || v == list4 || v == list8)
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, ~v);
+			OUT_INSN (len, "bic\t%A2, %D0", op);
+			dummy++;
+			if (!r)
+				dummy++;
+		}
+		else
+		{
+			op[2] = gen_rtx_CONST_INT (SImode, v);
+			OUT_INSN (len, "and\t%A2, %D0", op);
+			dummy++;
+			dummy++;
+			if (!r)
+				dummy++;
+			if (v == 0 || v == 1 || v == 2 || v == 4 || v == 8)
+				dummy--;
+		}
+	}
+
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+const char *
+msp430_andsi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (nonimmediate_operand (op0, SImode) && immediate_operand (op2, SImode))
+	{
+		if (!len)
+			msp430_emit_immediate_and2 (insn, operands, NULL);
+		return "";
+	}
+
+	if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_and2 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, SImode))
+				*len = 5;
+			else if (register_operand (op0, SImode))
+				*len = 3;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("and\t@%E2+, %A0", operands);
+			output_asm_insn ("and\t@%E2+, %B0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, SImode))
+				*len = 2;
+			else if (memory_operand (op0, SImode))
+				*len = 4;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("and\t%A2, %A0", operands);
+		output_asm_insn ("and\t%B2, %B0", operands);
+	}
+	else
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (op0, SImode))
+			*len += 0;
+		else if (memory_operand (op0, SImode))
+			*len += 2;
+
+		if (register_operand (op2, SImode))
+			*len += 0;
+		else if (memory_operand (op2, SImode))
+			*len += 2;
+		else if (immediate_operand (op2, SImode))
+			*len += 2;
+	}
+
+	return "";
+}
+
+
+const char *
+msp430_anddi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (nonimmediate_operand (op0, DImode) && immediate_operand (op2, DImode))
+	{
+		if (!len)
+			msp430_emit_immediate_and4 (insn, operands, NULL);
+		return "";
+	}
+
+	if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_and4 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, DImode))
+				*len = 9;
+			else if (register_operand (op0, DImode))
+				*len = 5;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("and\t@%E2+, %A0", operands);
+			output_asm_insn ("and\t@%E2+, %B0", operands);
+			output_asm_insn ("and\t@%E2+, %C0", operands);
+			output_asm_insn ("and\t@%E2+, %D0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, DImode))
+				*len = 4;
+			else if (memory_operand (op0, DImode))
+				*len = 8;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("and\t%A2, %A0", operands);
+		output_asm_insn ("and\t%B2, %B0", operands);
+		output_asm_insn ("and\t%C2, %C0", operands);
+		output_asm_insn ("and\t%D2, %D0", operands);
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op2, DImode))
+			*len += 0;
+		else if (memory_operand (op2, DImode))
+			*len += 4;
+		else if (immediate_operand (op2, DImode))
+			*len += 4;
+		else
+			abort ();
+	}
+
+	return "";
+}
+
+/**************	IOR CODE *********************************/
+
+const char *
+msp430_emit_indexed_ior2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 2, "bis", 0);
+	return "";
+}
+
+const char *
+msp430_emit_indexed_ior4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	emit_indexed_arith (insn, operands, 4, "bis", 0);
+	return "";
+}
+
+const char *
+msp430_emit_immediate_ior2 (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int l = INTVAL (operands[2]);
+	int r = REG_P (operands[0]);
+	int v;
+
+
+	v = l & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%A2,%A0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	v = (l >> 16) & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%B2,%B0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+const char *
+msp430_emit_immediate_ior4 (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int l = CONST_DOUBLE_LOW (operands[2]);
+	int h = CONST_DOUBLE_HIGH (operands[2]);
+	int r = REG_P (operands[0]);
+	int v;
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		l = INTVAL (operands[2]);
+		h = 0;
+	}
+
+	v = l & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%A2,%A0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	v = (l >> 16) & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%B2,%B0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	l = h;
+	v = l & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%C2,%C0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	v = (l >> 16) & 0xffff;
+
+	if (v)
+	{
+		OUT_INSN (len, "bis\t%D2,%D0", operands);
+		dummy++;
+		dummy++;
+		if (v == 0xffff || v == 1 || v == 2 || v == 4 || v == 8)
+			dummy--;
+		if (!r)
+			dummy++;
+	}
+
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+const char *
+msp430_iorsi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (nonimmediate_operand (op0, SImode) && immediate_operand (op2, SImode))
+	{
+		if (!len)
+			msp430_emit_immediate_ior2 (insn, operands, NULL);
+		return "";
+	}
+
+	if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_ior2 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, SImode))
+				*len = 5;
+			else if (register_operand (op0, SImode))
+				*len = 3;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("bis\t@%E2+, %A0", operands);
+			output_asm_insn ("bis\t@%E2+, %B0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, SImode))
+				*len = 2;
+			else if (memory_operand (op0, SImode))
+				*len = 4;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("bis\t%A2, %A0", operands);
+		output_asm_insn ("bis\t%B2, %B0", operands);
+	}
+	else
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (op0, SImode))
+			*len += 0;
+		else if (memory_operand (op0, SImode))
+			*len += 2;
+
+		if (register_operand (op2, SImode))
+			*len += 0;
+		else if (memory_operand (op2, SImode))
+			*len += 2;
+		else if (immediate_operand (op2, SImode))
+			*len += 2;
+	}
+
+	return "";
+}
+
+const char *
+msp430_iordi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (nonimmediate_operand (op0, DImode) && immediate_operand (op2, DImode))
+	{
+		if (!len)
+			msp430_emit_immediate_ior4 (insn, operands, NULL);
+		return "";
+	}
+
+	if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_ior4 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, DImode))
+				*len = 9;
+			else if (register_operand (op0, DImode))
+				*len = 5;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("bis\t@%E2+, %A0", operands);
+			output_asm_insn ("bis\t@%E2+, %B0", operands);
+			output_asm_insn ("bis\t@%E2+, %C0", operands);
+			output_asm_insn ("bis\t@%E2+, %D0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, DImode))
+				*len = 4;
+			else if (memory_operand (op0, DImode))
+				*len = 8;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("bis\t%A2, %A0", operands);
+		output_asm_insn ("bis\t%B2, %B0", operands);
+		output_asm_insn ("bis\t%C2, %C0", operands);
+		output_asm_insn ("bis\t%D2, %D0", operands);
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op2, DImode))
+			*len += 0;
+		else if (memory_operand (op2, DImode))
+			*len += 4;
+		else if (immediate_operand (op2, DImode))
+			*len += 4;
+		else
+			abort ();
+	}
+
+	return "";
+}
+
+
+/************************* XOR CODE *****************/
+
+const char *
+msp430_emit_indexed_xor2 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l;
+{
+	int dummy = emit_indexed_arith (insn, operands, 2, "xor", 0);
+	if (!l)
+		l = &dummy;
+	*l = dummy;
+	return "";
+}
+
+const char *
+msp430_emit_indexed_xor4 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l;
+{
+	int dummy = emit_indexed_arith (insn, operands, 4, "xor", 0);
+	if (!l)
+		l = &dummy;
+	*l = dummy;
+	return "";
+}
+
+
+const char *
+msp430_emit_indexed_xor2_3 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l;
+{
+	int dummy;
+	rtx x = operands[2];
+	if (zero_shifted (x))
+	{
+		dummy = emit_indexed_arith (insn, operands, 2, "xor", 0);
+	}
+	else
+	{
+		dummy = 6;
+		output_asm_insn ("xor\t%A2, %A0", operands);
+		output_asm_insn ("xor\t%B2, %B0", operands);
+	}
+
+	if (!l)
+		l = &dummy;
+	*l = dummy;
+	return "";
+}
+
+const char *
+msp430_emit_indexed_xor4_3 (insn, operands, l)
+rtx insn;
+rtx operands[];
+int *l;
+{
+
+	int dummy;
+	rtx x = operands[2];
+	if (zero_shifted (x))
+	{
+		dummy = emit_indexed_arith (insn, operands, 4, "xor", 0);
+	}
+	else
+	{
+		dummy = 8;
+		output_asm_insn ("xor\t%A2, %A0", operands);
+		output_asm_insn ("xor\t%B2, %B0", operands);
+		output_asm_insn ("xor\t%C2, %C0", operands);
+		output_asm_insn ("xor\t%D2, %D0", operands);
+	}
+
+	if (!l)
+		l = &dummy;
+	*l = dummy;
+	return "";
+}
+
+const char *
+msp430_xorsi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_xor2 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, SImode))
+				*len = 5;
+			else if (register_operand (op0, SImode))
+				*len = 3;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, SImode)
+		&& zero_shifted (operands[2]) && regsi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("xor\t@%E2+, %A0", operands);
+			output_asm_insn ("xor\t@%E2+, %B0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, SImode))
+				*len = 2;
+			else if (memory_operand (op0, SImode))
+				*len = 4;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+
+		if (immediate_operand (op2, SImode))
+		{
+			if (INTVAL (op2) & 0xfffful)
+				output_asm_insn ("xor\t%A2, %A0", operands);
+
+			if (INTVAL (op2) & 0xffff0000ul)
+				output_asm_insn ("xor\t%B2, %B0", operands);
+		}
+		else
+		{
+			output_asm_insn ("xor\t%A2, %A0", operands);
+			output_asm_insn ("xor\t%B2, %B0", operands);
+		}
+
+	}
+	else
+	{
+		*len = 2;			/* base length */
+
+		if (register_operand (op0, SImode))
+			*len += 0;
+		else if (memory_operand (op0, SImode))
+			*len += 2;
+
+		if (register_operand (op2, SImode))
+			*len += 0;
+		else if (memory_operand (op2, SImode))
+			*len += 2;
+		else if (immediate_operand (op2, SImode))
+		{
+			if (INTVAL (op2) & 0xfffful)
+				*len += 1;
+			if (INTVAL (op2) & 0xffff0000ul)
+				*len += 1;
+		}
+	}
+
+	return "";
+}
+
+const char *
+msp430_xordi_code (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	rtx op0 = operands[0];
+	rtx op2 = operands[2];
+
+	if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_safe (operands))
+	{
+		if (!len)
+			msp430_emit_indexed_xor4 (insn, operands, NULL);
+		else
+		{
+			if (memory_operand (op0, DImode))
+				*len = 9;
+			else if (register_operand (op0, DImode))
+				*len = 5;
+		}
+
+		return "";
+	}
+	else if (memory_operand (op2, DImode)
+		&& zero_shifted (operands[2]) && regdi_ok_clobber (operands))
+	{
+		if (!len)
+		{
+			output_asm_insn ("xor\t@%E2+, %A0", operands);
+			output_asm_insn ("xor\t@%E2+, %B0", operands);
+			output_asm_insn ("xor\t@%E2+, %C0", operands);
+			output_asm_insn ("xor\t@%E2+, %D0", operands);
+		}
+		else
+		{
+			if (register_operand (op0, DImode))
+				*len = 4;
+			else if (memory_operand (op0, DImode))
+				*len = 8;
+			else
+				abort ();
+		}
+		return "";
+	}
+
+	if (!len)
+	{
+		output_asm_insn ("xor\t%A2, %A0", operands);
+		output_asm_insn ("xor\t%B2, %B0", operands);
+		output_asm_insn ("xor\t%C2, %C0", operands);
+		output_asm_insn ("xor\t%D2, %D0", operands);
+	}
+	else
+	{
+		*len = 4;			/* base length */
+
+		if (register_operand (op0, DImode))
+			*len += 0;
+		else if (memory_operand (op0, DImode))
+			*len += 4;
+
+		if (register_operand (op2, DImode))
+			*len += 0;
+		else if (memory_operand (op2, DImode))
+			*len += 4;
+		else if (immediate_operand (op2, DImode))
+			*len += 4;
+		else
+			abort ();
+	}
+
+	return "";
+}
+
+
+/********* ABS CODE ***************************************/
+const char *
+msp430_emit_abssi (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	output_asm_insn ("tst\t%B0", operands);
+	output_asm_insn ("jge\t.Lae%=", operands);
+	output_asm_insn ("inv\t%A0", operands);
+	output_asm_insn ("inv\t%B0", operands);
+	output_asm_insn ("inc\t%A0", operands);
+	output_asm_insn ("adc\t%B0", operands);
+	output_asm_insn (".Lae%=:", operands);
+	return "";
+}
+
+const char *
+msp430_emit_absdi (insn, operands, l)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *l ATTRIBUTE_UNUSED;
+{
+	output_asm_insn ("tst\t%D0", operands);
+	output_asm_insn ("jge\t.Lae%=", operands);
+	output_asm_insn ("inv\t%A0", operands);
+	output_asm_insn ("inv\t%B0", operands);
+	output_asm_insn ("inv\t%C0", operands);
+	output_asm_insn ("inv\t%D0", operands);
+	output_asm_insn ("inc\t%A0", operands);
+	output_asm_insn ("adc\t%B0", operands);
+	output_asm_insn ("adc\t%C0", operands);
+	output_asm_insn ("adc\t%D0", operands);
+	output_asm_insn (".Lae%=:", operands);
+	return "";
+}
+
+
+/***** SIGN EXTEND *********/
+const char *
+signextendqihi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (indexed_location (operands[1]))
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "sxt\t%A0", operands);
+	dummy += 2;
+
+	if (zs || GET_CODE (operands[0]) == REG)
+		dummy -= 1;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+signextendqisi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (indexed_location (operands[1]))
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "sxt\t%A0", operands);
+	OUT_INSN (len, "mov\t%A0, %B0", operands);
+	OUT_INSN (len, "rla\t%B0", operands);
+	OUT_INSN (len, "subc\t%B0, %B0", operands);
+	OUT_INSN (len, "inv\t%B0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy += 5;
+	else if (zs)
+		dummy += 10;
+	else
+		dummy += 12;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+signextendqidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (indexed_location (operands[1]))
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "sxt\t%A0", operands);
+	OUT_INSN (len, "mov\t%A0, %B0", operands);
+	OUT_INSN (len, "rla\t%B0", operands);
+	OUT_INSN (len, "subc\t%B0, %B0", operands);
+	OUT_INSN (len, "inv\t%B0", operands);
+	OUT_INSN (len, "mov\t%B0, %C0", operands);
+	OUT_INSN (len, "mov\t%C0, %D0", operands);
+
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy += 7;
+	else if (zs)
+		dummy += 16;
+	else
+		dummy += 18;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+signextendhisi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov\t%A1, %A0", operands);
+		dummy = 3;
+		if (indexed_location (operands[1]))
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "mov\t%A0, %B0", operands);
+	OUT_INSN (len, "rla\t%B0", operands);
+	OUT_INSN (len, "subc\t%B0, %B0", operands);
+	OUT_INSN (len, "inv\t%B0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy += 4;
+	else if (zs)
+		dummy += 9;
+	else
+		dummy += 11;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+signextendhidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov\t%A1, %A0", operands);
+		dummy = 3;
+		if (indexed_location (operands[1]))
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "mov\t%A0, %B0", operands);
+	OUT_INSN (len, "rla\t%B0", operands);
+	OUT_INSN (len, "subc\t%B0, %B0", operands);
+	OUT_INSN (len, "inv\t%B0", operands);
+	OUT_INSN (len, "mov\t%B0, %C0", operands);
+	OUT_INSN (len, "mov\t%C0, %D0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy += 6;
+	else if (zs)
+		dummy += 13;
+	else
+		dummy += 14;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+signextendsidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov\t%A1, %A0", operands);
+		OUT_INSN (len, "mov\t%B1, %B0", operands);
+		dummy = 6;
+		if (indexed_location (operands[1]))
+			dummy = 4;
+		if (GET_CODE (operands[0]) == REG)
+			dummy -= 2;
+		if (GET_CODE (operands[1]) == REG)
+			dummy -= 2;
+	}
+
+	OUT_INSN (len, "mov\t%B0, %C0", operands);
+	OUT_INSN (len, "rla\t%C0", operands);
+	OUT_INSN (len, "subc\t%C0, %C0", operands);
+	OUT_INSN (len, "inv\t%C0", operands);
+	OUT_INSN (len, "mov\t%C0, %D0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy += 5;
+	else
+		dummy += 13;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+
+/**** ZERO EXTEND *****/
+
+const char *
+zeroextendqihi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[1]) || indexed_location (operands[1]);
+
+	if(operands[0] == op2_rtx)
+	{
+		OUT_INSN (len, "and	#0xff00, %0",operands);
+		dummy = 3;
+		return "";
+	}
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (zs)
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	if (!REG_P (operands[0]))
+	{
+		OUT_INSN (len, "clr.b\t%J0", operands);
+		dummy += 2;
+	}
+	else if (sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "and.b\t#-1,%0", operands);
+		dummy++;
+	}
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+zeroextendqisi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[1]) || indexed_location (operands[1]);
+
+	if (!sameoperand (operands, 1) || REG_P (operands[0]))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (zs)
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+
+	if (!REG_P (operands[0]))
+	{
+		OUT_INSN (len, "clr.b\t%J0", operands);
+	}
+	else if (sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "and.b\t#-1,%0", operands);
+		dummy++;
+	}
+	OUT_INSN (len, "clr\t%B0", operands);
+	dummy += 2;
+	if (GET_CODE (operands[0]) == REG)
+		dummy--;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+
+const char *
+zeroextendqidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[1]) || indexed_location (operands[1]);
+
+	if (!sameoperand (operands, 1) || REG_P (operands[0]))
+	{
+		OUT_INSN (len, "mov.b\t%A1, %A0", operands);
+		dummy = 3;
+		if (zs)
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	if (!REG_P (operands[0]))
+	{
+		OUT_INSN (len, "clr.b\t%J0", operands);
+		dummy += 2;
+	}
+	else if (sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "and.b\t#-1,%0", operands);
+		dummy++;
+	}
+	dummy += 6;
+	OUT_INSN (len, "clr\t%B0", operands);
+	OUT_INSN (len, "clr\t%C0", operands);
+	OUT_INSN (len, "clr\t%D0", operands);
+
+	if (GET_CODE (operands[0]) == REG && len)
+		*len -= 3;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+zeroextendhisi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[1]) || indexed_location (operands[1]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov\t%A1, %A0", operands);
+		dummy = 3;
+		if (zs)
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	OUT_INSN (len, "clr\t%B0", operands);
+	dummy += 2;
+	if (GET_CODE (operands[0]) == REG)
+		dummy--;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+
+}
+
+const char *
+zeroextendhidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[1]) || indexed_location (operands[1]);
+
+	if (!sameoperand (operands, 1))
+	{
+		OUT_INSN (len, "mov\t%A1, %A0", operands);
+		dummy = 3;
+		if (zs)
+			dummy = 2;
+		if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		if (GET_CODE (operands[1]) == REG)
+			dummy--;
+	}
+
+	dummy += 6;
+	OUT_INSN (len, "clr\t%B0", operands);
+	OUT_INSN (len, "clr\t%C0", operands);
+	OUT_INSN (len, "clr\t%D0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy -= 3;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+const char *
+zeroextendsidi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+
+	if (!sameoperand (operands, 1))
+	{
+		if (zero_shifted (operands[1]))
+		{
+			rtx reg = XEXP (operands[1], 0);
+
+			OUT_INSN (len, "mov\t@%E1+, %A0", operands);
+			OUT_INSN (len, "mov\t@%E1+, %B0", operands);
+			dummy = 4;
+			if (GET_CODE (operands[0]) == REG)
+				dummy -= 2;
+
+			if (!dead_or_set_p (insn, reg))
+			{
+				OUT_INSN (len, "sub\t#4, %E1", operands);
+				dummy += 1;
+			}
+		}
+		else
+		{
+			OUT_INSN (len, "mov\t%A1, %A0", operands);
+			OUT_INSN (len, "mov\t%B1, %B0", operands);
+			dummy = 6;
+			if (GET_CODE (operands[0]) == REG)
+				dummy -= 2;
+			if (GET_CODE (operands[1]) == REG)
+				dummy -= 2;
+			if (indexed_location (operands[1]))
+				dummy--;
+		}
+	}
+
+	dummy += 4;
+	OUT_INSN (len, "clr\t%C0", operands);
+	OUT_INSN (len, "clr\t%D0", operands);
+
+	if (GET_CODE (operands[0]) == REG)
+		dummy -= 2;
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+/******************* TESTS AND JUMPS *********************/
+
+
+/*****************  AUXES FOR TESTS *********************/
+
+RTX_CODE
+followed_compare_condition (insn)
+rtx insn;
+{
+	rtx next = next_real_insn (insn);
+	RTX_CODE cond = UNKNOWN;
+
+	if (next && GET_CODE (next) == JUMP_INSN)
+	{
+		rtx pat = PATTERN (next);
+		rtx src, t;
+
+		if (pat && GET_CODE (pat) == PARALLEL)
+			pat = XVECEXP (pat, 0, 0);
+
+		if (!pat || GET_CODE (pat) != SET)
+			return UNKNOWN;
+
+		src = SET_SRC (pat);
+		t = XEXP (src, 0);
+		cond = GET_CODE (t);
+	}
+	else if (next && GET_CODE (next) == INSN)
+	{
+		/* here, two possible : sgeu ans sltu */
+
+		rtx pat = PATTERN (next);
+		rtx src;
+
+		if (!pat || GET_CODE (pat) != SET)
+			return UNKNOWN;
+
+		src = SET_SRC (pat);
+		cond = GET_CODE (src);	/* this must be IF_THEN_ELSE */
+		if (cond != IF_THEN_ELSE)
+			return UNKNOWN;
+	}
+	return cond;
+}
+
+
+/* SHIFT GUARDS */
+int
+msp430_ashlhi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx set, shift;
+	rtx dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (HImode, operands[0]);
+		op1 = force_reg (HImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_ashlhi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+
+	if (x > 15 || x < 0)
+	{
+		emit_move_insn (operands[0], const0_rtx);
+		return 1;
+	}
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (x < 3)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_ASHIFT (HImode, dst, const1_rtx);
+		set = gen_rtx_SET (HImode, dst, shift);
+		while (x--)
+			emit_insn (set);
+		return 1;
+	}
+
+	if (x == 15)
+	{
+		shift = gen_rtx_ASHIFT (HImode, operands[1], GEN_INT (15));
+		set = gen_rtx_SET (HImode, operands[0], shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (HImode, operands[1]);
+	else
+		dst = operands[1];
+	if (x > 7)
+	{
+		emit_insn (gen_andhi3 (dst, dst, GEN_INT (0xff)));
+		emit_insn (gen_swpb (dst, dst));
+		x -= 8;
+	}
+
+	shift = gen_rtx_ASHIFT (HImode, dst, const1_rtx);
+	set = gen_rtx_SET (HImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+	return 1;
+}
+
+int
+msp430_ashlsi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx shift, set, dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (SImode, operands[0]);
+		op1 = force_reg (SImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_ashlsi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+
+	if (x >= 32 || x < 0)
+	{
+		emit_move_insn (operands[0], const0_rtx);
+		return 1;
+	}
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (x == 1)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_ASHIFT (SImode, dst, operands[2]);
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (SImode, operands[1]);
+	else
+		dst = operands[1];
+
+	if (x == 31)
+	{
+		shift = gen_rtx_ASHIFT (SImode, operands[1], GEN_INT (31));
+		set = gen_rtx_SET (SImode, operands[0], shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (x >= 16)
+	{
+		rtx dhi = gen_highpart (HImode, operands[0]);
+		rtx dlo = gen_lowpart (HImode, operands[0]);
+		rtx shi = gen_highpart (HImode, operands[1]);
+		rtx slo = gen_lowpart (HImode, operands[1]);
+
+		emit_move_insn (dhi, slo);
+		emit_move_insn (dlo, const0_rtx); 
+		x -= 16;
+		if (x)
+		{
+			rtx ops[3];
+			ops[0] = dhi;
+			ops[1] = dhi;
+			ops[2] = GEN_INT (x);
+			msp430_ashlhi3 (ops);
+		}
+		return 1;
+	}
+
+	if (x >= 8)
+	{
+		shift = gen_rtx_ASHIFT (SImode, dst, GEN_INT (8));
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		x -= 8;
+	}
+
+	shift = gen_rtx_ASHIFT (SImode, dst, GEN_INT (1));
+	set = gen_rtx_SET (SImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+	return 1;
+}
+
+/* arithmetic right */
+int
+msp430_ashrhi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx shift, set, dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (HImode, operands[0]);
+		op1 = force_reg (HImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_ashrhi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+	if (x >= 15 || x < 0)
+	{
+		dst = gen_lowpart (QImode, operands[0]);
+		emit_move_insn (operands[0], operands[1]);
+		emit_insn (gen_swpb (operands[0], operands[0]));
+		emit_insn (gen_extendqihi2 (operands[0], dst));
+		emit_insn (gen_swpb (operands[0], operands[0]));
+		emit_insn (gen_extendqihi2 (operands[0], dst));
+		return 1;
+	}
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (x < 3)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx);
+		set = gen_rtx_SET (HImode, dst, shift);
+
+		while (x--)
+			emit_insn (set);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (HImode, operands[1]);
+	else
+		dst = operands[1];
+
+	if (x >= 8)
+	{
+		rtx dlo = gen_lowpart (QImode, dst);
+		emit_insn (gen_swpb (dst, dst));
+		emit_insn (gen_extendqihi2 (dst, dlo));
+		x -= 8;
+	}
+
+	shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx);
+	set = gen_rtx_SET (HImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+
+	return 1;
+}
+
+int
+msp430_ashrsi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx shift, set, dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (SImode, operands[0]);
+		op1 = force_reg (SImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_ashrsi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (SImode, operands[1]);
+	else
+		dst = operands[1];
+
+	if (x >= 31 || x < 0)
+	{
+
+		shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (31));
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+
+		if (dst != operands[0])
+			emit_move_insn (operands[0], dst);
+		return 1;
+	}
+
+	if (x == 1)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_ASHIFTRT (SImode, dst, operands[2]);
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (x >= 16)
+	{
+		rtx dlo = gen_lowpart (HImode, operands[0]);
+		rtx shi = gen_highpart (HImode, dst);
+
+		emit_move_insn (gen_highpart (HImode, operands[0]), const0_rtx);
+		emit_insn (gen_extendhisi2 (operands[0], shi));
+		x -= 16;
+		if (x)
+		{
+			rtx ops[3];
+			ops[0] = dlo;
+			ops[1] = dlo;
+			ops[2] = GEN_INT (x);
+			msp430_ashrhi3 (ops);
+		}
+		return 1;
+	}
+
+	if (x >= 8)
+	{
+		shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (8));
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		x -= 8;
+	}
+
+	shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (1));
+	set = gen_rtx_SET (SImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+	return 1;
+}
+
+/* logical right */
+int
+msp430_lshrhi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx shift, set, dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (HImode, operands[0]);
+		op1 = force_reg (HImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_lshrhi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+	if (x > 15 || x < 0)
+	{
+		emit_move_insn (operands[0], const0_rtx);
+		return 1;
+	}
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (x < 3)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_LSHIFTRT (HImode, dst, const1_rtx);
+		set = gen_rtx_SET (HImode, dst, shift);
+		emit_insn (set);
+		x--;
+
+		if (x)
+		{
+			shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx);
+			set = gen_rtx_SET (HImode, dst, shift);
+			emit_insn (set);
+		}
+		return 1;
+	}
+
+	if (x == 15)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_LSHIFTRT (HImode, dst, GEN_INT (15));
+		set = gen_rtx_SET (HImode, dst, shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (HImode, operands[1]);
+	else
+		dst = operands[1];
+
+	if (x >= 8)
+	{
+		rtx dlo = gen_lowpart (QImode, dst);
+		emit_insn (gen_swpb (dst, dst));
+		emit_insn (gen_zero_extendqihi2 (dst, dlo));
+		x -= 8;
+	}
+
+	if (x)
+	{
+		shift = gen_rtx_LSHIFTRT (HImode, dst, const1_rtx);
+		set = gen_rtx_SET (HImode, dst, shift);
+		x--;
+		emit_insn (set);
+	}
+	shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx);
+	set = gen_rtx_SET (HImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+
+	return 1;
+}
+
+int
+msp430_lshrsi3 (operands)
+rtx operands[];
+{
+	int x;
+	rtx shift, set, dst;
+
+	if (!const_int_operand (operands[2], VOIDmode))
+	{
+		rtx op0, op1;
+
+		op0 = force_reg (SImode, operands[0]);
+		op1 = force_reg (SImode, operands[1]);
+		operands[2] = copy_to_mode_reg (HImode, operands[2]);
+		emit_insn (gen_lshrsi3_cnt (op0, op1, operands[2]));
+		emit_move_insn (operands[0], op0);
+		return 1;
+	}
+
+	x = INTVAL (operands[2]);
+
+	if (x == 0)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		return 1;
+	}
+
+	if (x == 1)
+	{
+		emit_move_insn (operands[0], operands[1]);
+		dst = operands[0];
+		shift = gen_rtx_LSHIFTRT (SImode, dst, operands[2]);
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		return 1;
+	}
+
+	if (x > 31 || x < 0)
+	{
+		emit_move_insn (operands[0], const0_rtx);
+		return 1;
+	}
+
+	if (operands[0] != operands[1])
+		dst = copy_to_mode_reg (SImode, operands[1]);
+	else
+		dst = operands[1];
+
+	if (x >= 16)
+	{
+		rtx dlo = gen_lowpart (HImode, operands[0]);
+		rtx shi = gen_highpart (HImode, dst);
+
+		emit_move_insn (gen_highpart (HImode, operands[0]), const0_rtx);
+		emit_insn (gen_zero_extendhisi2 (operands[0], shi));
+		x -= 16;
+		if (x)
+		{
+			rtx ops[3];
+			ops[0] = dlo;
+			ops[1] = dlo;
+			ops[2] = GEN_INT (x);
+			msp430_lshrhi3 (ops);
+		}
+		return 1;
+	}
+
+	if (x >= 8)
+	{
+		shift = gen_rtx_LSHIFTRT (SImode, dst, GEN_INT (8));
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		x -= 8;
+	}
+
+	if (x)
+	{
+		shift = gen_rtx_LSHIFTRT (SImode, dst, const1_rtx);
+		set = gen_rtx_SET (SImode, dst, shift);
+		emit_insn (set);
+		x--;
+	}
+
+	shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (1));
+	set = gen_rtx_SET (SImode, dst, shift);
+
+	while (x--)
+		emit_insn (set);
+	if (dst != operands[0])
+		emit_move_insn (operands[0], dst);
+	return 1;
+}
+
+/******* COMMON SHIFT CODE ***************/
+int
+is_shift_better_in_reg (operands)
+rtx operands[];
+{
+	rtx x = operands[0];
+	rtx cnt = operands[2];
+	int size = GET_MODE_SIZE (x->mode);
+	int icnt = -1;
+	int r = 0;
+
+	if (!optimize)
+		return 0;
+
+	if (GET_CODE (cnt) == CONST_INT)
+		icnt = INTVAL (cnt);
+	else
+		return 1;
+
+	switch (size)
+	{
+	case 1:
+		if (icnt != 1 && icnt != 2 && icnt != 7)
+			r = 1;
+		break;
+	case 2:
+		if (icnt != 1 && icnt != 2 && icnt != 8 && icnt != 15)
+			r = 2;
+		break;
+	case 4:
+		if (icnt != 1
+			&& icnt != 2 && icnt != 8 && icnt != 16 && icnt != 24 && icnt != 31)
+			r = 4;
+		break;
+	case 8:
+		if (icnt != 1
+			&& icnt != 2 && icnt != 16 && icnt != 32 && icnt != 48 && icnt != 63)
+			r = 8;
+		break;
+	}
+
+	return r;
+}
+
+
+static int set_len PARAMS ((rtx, int, int));
+/* for const operand2 and for SI, DI modes.*/
+static int
+set_len (x, bl, sc)
+rtx x;			/* operand0 */
+int bl;			/* base length in assumption of memory operand */
+int sc;			/* shift count */
+{
+	int dummy;
+	int zs = zero_shifted (x);
+	int size = GET_MODE_SIZE (x->mode);
+	int sshi = 0;
+
+	if (size == 4)
+		sshi = 1;
+	else if (size == 8)
+		sshi = 2;
+
+	if (size == 1)
+		size++;
+
+	if (GET_CODE (x) == REG)
+		dummy = (bl >> 1) - sshi;	/* bl / 2 is not fully correct */
+	else if (zs)
+		dummy = bl - (size >> 1) + 1;
+	else if (indexed_location (x))
+		dummy = bl - 1;
+	else
+		dummy = bl;
+
+	return dummy * sc;
+}
+
+static int set_ren PARAMS ((rtx, int, int));
+/* for const operand2 and for SI, DI modes.*/
+static int
+set_ren (x, bl, sc)
+rtx x;			/* operand0 */
+int bl;			/* base length in assumption of memory operand */
+int sc;			/* shift count */
+{
+	int dummy;
+
+	bl *= sc;
+	if (GET_CODE (x) == REG)
+		dummy = bl / 2;
+	else if (indexed_location (x))
+		dummy = bl - sc;
+	else
+		dummy = bl;
+	return dummy;
+}
+
+static int set_rel PARAMS ((rtx, int, int));
+/* for const operand2 and for SI, DI modes.*/
+static int
+set_rel (x, bl, sc)
+rtx x;			/* operand0 */
+int bl;			/* base length in assumption of memory operand */
+int sc;			/* shift count */
+{
+	int dummy;
+
+	bl *= sc;
+	if (GET_CODE (x) == REG)
+		dummy = bl / 2;
+	else if (indexed_location (x))
+		dummy = bl - sc;
+	else
+		dummy = bl;
+	dummy += sc;
+	return dummy;
+}
+
+
+
+#define INST_THRESHOLD  16
+
+int
+msp430_emit_shift_cnt (set_len_fun, pattern, insn, operands, len, lsc)
+int (*set_len_fun) (rtx, int, int);
+const char *pattern;
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+int lsc;
+{
+	rtx op[10];
+	int dummy = 0;
+
+	op[0] = operands[0];
+	op[1] = operands[1];
+	op[2] = operands[2];
+	op[3] = operands[3];
+
+
+	OUT_INSN (len, "tst\t%2", op);
+	OUT_INSN (len, "jz\t.Lsend%=\n.Lsst%=:", op);
+	OUT_INSN (len, pattern, op);
+	OUT_INSN (len, "dec\t%2", op);
+	OUT_INSN (len, "jnz\t.Lsst%=\n.Lsend%=:", op);
+	dummy = (set_len_fun) (op[0], lsc, 1) + 4;
+	if (!REG_P (op[2]) && !indexed_location (op[2]))
+		dummy += 2;
+
+
+	if (len)
+		*len = dummy;
+	return 0;
+}
+
+
+/* <<<<<<<<<<<<< SHIFT LEFT CODE <<<<<<<<<<<<<<<<<     */
+
+const char *
+msp430_emit_ashlqi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *pattern;
+	int shiftpos;
+
+	if (zs)
+		pattern = "rla.b\t@%E0";
+	else
+		pattern = "rla.b\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		default:
+			if (zs)
+				OUT_INSN (len, "clr.b\t@%E0", operands);
+			else
+				OUT_INSN (len, "clr.b\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy >>= 1;
+			break;
+
+		case 0:		/* paranoia setting */
+			dummy = 0;
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 3, 1);
+			}
+			break;
+
+		case 7:
+			if (zs)
+			{
+				OUT_INSN (len, "rra.b\t%0", operands);
+				OUT_INSN (len, "clr.b\t%0", operands);
+				OUT_INSN (len, "rrc.b\t%0", operands);
+				dummy = 5;
+			}
+			else
+			{
+				OUT_INSN (len, "rra.b\t%0", operands);
+				OUT_INSN (len, "clr.b\t%0", operands);
+				OUT_INSN (len, "rrc.b\t%0", operands);
+				dummy = 6;
+				if (REG_P (operands[0]))
+					dummy = 3;
+			}
+
+			break;
+		}
+
+		if (len)
+			*len = dummy;
+		return "";
+
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 3);
+	}
+
+	return "";
+}
+
+
+const char *
+msp430_emit_ashlhi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs;
+	const char *pattern;
+	int shiftpos;
+
+	zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+
+	if (zs)
+		pattern = "rla\t@%E0";
+	else
+		pattern = "rla\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:		/* paranoia setting */
+			dummy = 0;
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 3, 1);
+			}
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+			if (zs)
+			{
+				dummy = 3;
+				OUT_INSN (len, "and.b\t#0xffff, %A0", operands);
+				OUT_INSN (len, "swpb\t@%E0", operands);
+			}
+			else
+			{
+				dummy = 4;
+				OUT_INSN (len, "and.b\t#0xffff, %A0", operands);
+				OUT_INSN (len, "swpb\t%A0", operands);
+				if (REG_P (operands[0]))
+					dummy = 2;
+			}
+
+
+			shiftpos -= 8;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 3, 1);
+			}
+			break;
+
+		case 15:
+			if (zs)
+			{
+				OUT_INSN (len, "rra\t%0", operands);
+				OUT_INSN (len, "clr\t%0", operands);
+				OUT_INSN (len, "rrc\t%0", operands);
+				dummy = 5;
+			}
+			else
+			{
+				OUT_INSN (len, "rra\t%0", operands);
+				OUT_INSN (len, "clr\t%0", operands);
+				OUT_INSN (len, "rrc\t%0", operands);
+				dummy = 6;
+				if (REG_P (operands[0]))
+					dummy = 3;
+			}
+
+			break;
+
+
+		default:
+
+			OUT_INSN (len, "clr\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy = 1;
+			break;
+		}
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 3);
+	}
+
+	return "";
+}
+
+
+const char *
+msp430_emit_ashlsi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+
+	int dummy = 0;
+	int zs;
+	const char *pattern;
+
+	zs = zero_shifted (operands[0]);
+
+	if (zs)
+		pattern = "add\t@%E0+, -2(%E0)\n\taddc\t@%E0+, -2(%E0)\n\tsub\t#4, %E0";
+	else
+		pattern = "rla\t%A0\n\trlc\t%B0";
+
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+
+		case 0:
+			dummy = 0;
+			break;
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 6, 1);
+			}
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+
+			if (zs || indexed_location (operands[0]))
+			{
+				OUT_INSN (len, "xor.b\t@%E0, %B0", operands);
+				OUT_INSN (len, "xor\t@%E0, %B0", operands);
+				OUT_INSN (len, "swpb\t%B0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				dummy = 9;
+			}
+			else
+			{
+				OUT_INSN (len, "xor.b\t%A0, %B0", operands);
+				OUT_INSN (len, "xor\t%A0, %B0", operands);
+				OUT_INSN (len, "swpb\t%B0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				OUT_INSN (len, "swpb\t%A0", operands);
+				dummy = 12;
+				if (REG_P (operands[0]))
+					dummy = 5;
+			}
+
+			shiftpos -= 8;
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 6, 1);
+			}
+
+			if (len)
+				*len = dummy;
+			return "";
+
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+
+			if (zs || indexed_location (operands[0]))
+			{
+				OUT_INSN (len, "mov\t@%E0, %B0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				dummy = 4;
+			}
+			else
+			{
+				OUT_INSN (len, "mov\t%A0, %B0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				dummy = 5;
+				if (REG_P (operands[0]))
+					dummy = 3;
+			}
+
+			shiftpos -= 16;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 6, 1);
+			}
+
+			if (len)
+				*len = dummy;
+			return "";
+			break;
+
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+			if (zs || indexed_location (operands[0]))
+			{
+				OUT_INSN (len, "mov.b\t@%E0,%B0", operands);
+				OUT_INSN (len, "swpb\t%B0", operands);
+				OUT_INSN (len, "clr\t@%E0", operands);
+				dummy = 6;
+			}
+			else
+			{
+				OUT_INSN (len, "mov.b\t%A0,%B0", operands);
+				OUT_INSN (len, "swpb\t%B0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				dummy = 8;
+				if (GET_CODE (operands[0]) == REG)
+					dummy = 3;
+			}
+
+			shiftpos -= 24;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 6, 1);
+			}
+
+			if (len)
+				*len = dummy;
+			return "";
+
+			break;
+
+		case 31:
+			if (zs || indexed_location (operands[0]))
+			{
+				OUT_INSN (len, "rra\t@%E0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "rrc\t%B0", operands);
+				dummy = 9;
+
+			}
+			else
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "rrc\t%B0", operands);
+				dummy = 10;
+				if (REG_P (operands[0]))
+					dummy = 4;
+			}
+
+			if (len)
+				*len = dummy;
+			return "";
+			break;
+
+		default:
+			OUT_INSN (len, "clr\t%A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			if (len)
+				*len = set_len (operands[0], 6, 1);
+			return "";
+			break;
+
+		}			/* switch */
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+		msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 6);
+
+	return "";
+
+}
+
+const char *
+msp430_emit_ashldi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+
+	int dummy = 0;
+	int zs;
+	const char *pattern;
+
+	zs = zero_shifted (operands[0]);
+
+	if (zs)
+		pattern =
+		"add\t@%E0+,-2(%E0)\n\taddc\t@%E0+,-2(%E0)\n\taddc\t@%E0+,-2(%E0)\n\taddc\t@%E0+,-2(%E0)\n\tsub\t#8,%E0";
+	else
+		pattern = "rla\t%A0\n\trlc\t%B0\n\trlc\t%C0\n\trlc\t%D0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:
+			dummy = 0;
+			if (len)
+				*len = dummy;
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 12, 1);
+			}
+			if (len)
+				*len = dummy;
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+			if (zs || indexed_location (operands[0]))
+			{
+				dummy = 10;
+				OUT_INSN (len, "mov\t%C0, %D0", operands);
+				OUT_INSN (len, "mov\t%B0, %C0", operands);
+				OUT_INSN (len, "mov\t@%E0, %B0", operands);
+				OUT_INSN (len, "clr\t@%E0", operands);
+			}
+			else
+			{
+				dummy = 11;
+				OUT_INSN (len, "mov\t%C0, %D0", operands);
+				OUT_INSN (len, "mov\t%B0, %C0", operands);
+				OUT_INSN (len, "mov\t%A0, %B0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+
+			}
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+			shiftpos -= 16;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 12, 1);
+			}
+			if (len)
+				*len = dummy;
+			break;
+
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+		case 31:
+			if (zs)
+			{
+				dummy = 8;
+				OUT_INSN (len, "mov\t@%E0, %D0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+
+			}
+			else
+			{
+				dummy = 9;
+				OUT_INSN (len, "mov\t%A0, %D0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+			}
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+
+			shiftpos -= 16;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 12, 1);
+			}
+
+			if (len)
+				*len = dummy;
+			break;
+
+		case 32:
+		case 33:
+		case 34:
+		case 35:
+		case 36:
+		case 37:
+		case 38:
+		case 39:
+		case 40:
+		case 41:
+		case 42:
+		case 43:
+		case 44:
+		case 45:
+		case 46:
+		case 47:
+
+			if (zs)
+			{
+				OUT_INSN (len, "mov\t@%E0+, %C0", operands);
+				OUT_INSN (len, "mov\t@%E0+, %D0", operands);
+				OUT_INSN (len, "sub\t#4, %E0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				dummy = 9;
+			}
+			else
+			{
+				dummy = 10;
+				OUT_INSN (len, "mov\t%A0, %C0", operands);
+				OUT_INSN (len, "mov\t%B0, %D0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+			}
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+
+			shiftpos -= 32;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 12, 1);
+			}
+
+			if (len)
+				*len = dummy;
+			break;
+
+		case 48:
+		case 49:
+		case 50:
+		case 51:
+		case 52:
+		case 53:
+		case 54:
+		case 55:
+		case 56:
+		case 57:
+		case 58:
+		case 59:
+		case 60:
+		case 61:
+		case 62:
+			if (zs)
+			{
+				dummy = 8;
+				OUT_INSN (len, "mov\t@%E0, %D0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+			}
+			else
+			{
+				dummy = 9;
+				OUT_INSN (len, "mov\t%A0, %D0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+			}
+
+			shiftpos -= 48;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_len (operands[0], 12, 1);
+			}
+
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+			if (len)
+				*len = dummy;
+
+			break;
+
+		case 63:
+			if (zs || indexed_location (operands[0]))
+			{
+				OUT_INSN (len, "rra\t@%E0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+				OUT_INSN (len, "clr\t%D0", operands);
+				OUT_INSN (len, "rrc\t%D0", operands);
+				dummy = 11;
+			}
+			else
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "clr\t%B0", operands);
+				OUT_INSN (len, "clr\t%C0", operands);
+				OUT_INSN (len, "clr\t%D0", operands);
+				OUT_INSN (len, "rrc\t%D0", operands);
+				dummy = 12;
+				if (REG_P (operands[0]))
+					dummy = 6;
+			}
+
+			if (len)
+				*len = dummy;
+
+			break;		/* make compiler happy */
+
+		default:
+			OUT_INSN (len, "clr\t%A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "clr\t%C0", operands);
+			OUT_INSN (len, "clr\t%D0", operands);
+			dummy = 8;
+			if (zs)
+				dummy--;
+			if (REG_P (operands[0]))
+				dummy = 4;
+
+			if (len)
+				*len = dummy;
+
+		}			/* switch */
+
+		return "";
+	}
+	else
+		msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 12);
+
+	return "";			/* make compiler happy */
+}
+
+/********* SHIFT RIGHT CODE ***************************************/
+const char *
+msp430_emit_ashrqi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *pattern;
+	int shiftpos;
+
+	if (zs)
+		pattern = "rra.b\t@%E0";
+	else
+		pattern = "rra.b\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+
+		shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:		/* paranoia setting */
+			dummy = 0;
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += 2;
+			}
+			break;
+
+		case 7:
+			if (zs)
+			{
+				OUT_INSN (len, "sxt\t@%E0", operands);
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				dummy = 4;
+			}
+			else
+			{
+				OUT_INSN (len, "sxt\t%A0", operands);
+				OUT_INSN (len, "swpb\t%A0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				dummy = 6;
+			}
+			if (REG_P (operands[0]))
+				dummy = 3;
+			if (len)
+				*len = dummy;
+			return "";
+
+			break;
+
+		default:
+			OUT_INSN (len, "clr.b\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy = 1;
+		}
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 2);
+	}
+
+	return "";
+}
+
+const char *
+msp430_emit_ashrhi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *pattern;
+	int shiftpos;
+
+	if (zs)
+		pattern = "rra\t@%E0";
+	else
+		pattern = "rra\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:		/* paranoia setting */
+			dummy = 0;
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += 2;
+			}
+			if (zs || REG_P (operands[0]))
+				dummy >>= 1;
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+			if (zs)
+			{
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				OUT_INSN (len, "sxt\t@%E0", operands);
+				dummy = 2;
+			}
+			else
+			{
+				OUT_INSN (len, "swpb\t%A0", operands);
+				OUT_INSN (len, "sxt\t%A0", operands);
+				dummy = 4;
+				if (REG_P (operands[0]))
+					dummy = 2;
+			}
+			shiftpos -= 8;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += (zs || REG_P (operands[0])) ? 1 : 2;
+			}
+			break;
+
+		case 15:
+			if (zs)
+			{
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				OUT_INSN (len, "sxt\t@%E0", operands);
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				dummy = 4;
+			}
+			else
+			{
+				OUT_INSN (len, "swpb\t%A0", operands);
+				OUT_INSN (len, "sxt\t%A0", operands);
+				OUT_INSN (len, "swpb\t%A0", operands);
+				OUT_INSN (len, "sxt\t%A0", operands);
+				dummy = 8;
+			}
+			if (REG_P (operands[0]))
+				dummy = 4;
+			break;
+
+		default:
+			OUT_INSN (len, "clr\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy = 1;
+		}
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 2);
+	}
+
+	return "";
+}
+
+const char *
+msp430_emit_ashrsi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+
+	int dummy = 0;
+	const char *pattern;
+	int zs = zero_shifted (operands[0]);
+
+	pattern = "rra\t%B0\n\trrc\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:
+			dummy = 0;
+			break;
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_ren (operands[0], 4, 1);
+			}
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+			OUT_INSN (len, "swpb\t%A0", operands);
+			OUT_INSN (len, "swpb\t%B0", operands);
+			OUT_INSN (len, "xor.b\t%B0, %A0", operands);
+			OUT_INSN (len, "xor\t%B0, %A0", operands);
+			OUT_INSN (len, "sxt\t%B0", operands);
+			dummy = 12;
+
+			if (REG_P (operands[0]))
+				dummy = 5;
+			shiftpos -= 8;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_ren (operands[0], 4, 1);
+			}
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "bit\t#0x8000, %B0", operands);
+			OUT_INSN (len, "jz\t.Lsrc%=", operands);
+			OUT_INSN (len, "bis\t#0xffff, %B0", operands);
+			OUT_INSN (len, "jmp\t.Lsre%=\n.Lsrc%=:", operands);
+			OUT_INSN (len, "clr\t%B0\n.Lsre%=:", operands);
+			dummy = 12;
+
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 7;
+
+			shiftpos -= 16;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				dummy += 2;
+				if (GET_CODE (operands[0]) == REG || zs)
+					dummy--;
+			}
+
+			break;
+
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+			OUT_INSN (len, "swpb\t%B0", operands);
+			OUT_INSN (len, "sxt\t%B0", operands);
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "swpb\t%B0", operands);
+			OUT_INSN (len, "sxt\t%B0", operands);
+			dummy = 11;
+
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 5;
+
+			shiftpos -= 24;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				dummy += 2;
+				if (GET_CODE (operands[0]) == REG || zs)
+					dummy--;
+			}
+			break;
+
+		case 31:
+			OUT_INSN (len, "tst\t%B0", operands);
+			OUT_INSN (len, "mov\t#-1,%B0", operands);
+			OUT_INSN (len, "mov\t#-1,%A0", operands);
+			if (GET_CODE (operands[0]) == REG)
+				OUT_INSN (len, "jn\t+4", operands);
+			else
+				OUT_INSN (len, "jn\t+8", operands);
+			OUT_INSN (len, "clr\t%A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			dummy = 11;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 6;
+			break;
+
+		default:
+			dummy = 0;		/* leave it alone!!! */
+			break;
+
+		}			/* switch */
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+		msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 4);
+
+	return "";
+
+}
+
+const char *
+msp430_emit_ashrdi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+
+	int dummy = 0;
+	const char *pattern;
+
+	pattern = "rra\t%D0\n\trrc\t%C0\n\trrc\t%B0\n\trrc\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		switch (shiftpos)
+		{
+		case 0:
+			dummy = 0;
+			break;
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, pattern, operands);
+				dummy += set_ren (operands[0], 8, 1);
+			}
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+		case 31:
+
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "mov\t%C0, %B0", operands);
+			OUT_INSN (len, "mov\t%D0, %C0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+
+			dummy = 17;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 7;
+			shiftpos -= 16;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%C0\n\trrc\t%B0\n\trrc\t%A0", operands);
+				dummy += set_ren (operands[0], 6, 1);
+			}
+
+			break;
+
+		case 32:
+		case 33:
+		case 34:
+		case 35:
+		case 36:
+		case 37:
+		case 38:
+		case 39:
+		case 40:
+		case 41:
+		case 42:
+		case 43:
+		case 44:
+		case 45:
+		case 46:
+		case 47:
+			OUT_INSN (len, "mov\t%C0, %A0", operands);
+			OUT_INSN (len, "mov\t%D0, %B0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "mov\t%D0, %C0", operands);
+			dummy = 17;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 8;
+			shiftpos -= 32;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%B0\n\trrc\t%A0", operands);
+				dummy += set_ren (operands[0], 4, 1);
+			}
+			break;
+
+		case 48:
+		case 49:
+		case 50:
+		case 51:
+		case 52:
+		case 53:
+		case 54:
+		case 55:
+		case 56:
+		case 57:
+		case 58:
+		case 59:
+		case 60:
+		case 61:
+		case 62:
+			OUT_INSN (len, "mov\t%D0, %A0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "mov\t%D0, %C0", operands);
+			OUT_INSN (len, "mov\t%D0, %B0", operands);
+			dummy = 17;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 7;
+			shiftpos -= 48;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				dummy += set_ren (operands[0], 2, 1);
+			}
+			break;
+
+		case 63:
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "swpb\t%D0", operands);
+			OUT_INSN (len, "sxt\t%D0", operands);
+			OUT_INSN (len, "mov\t%D0, %C0", operands);
+			OUT_INSN (len, "mov\t%D0, %B0", operands);
+			OUT_INSN (len, "mov\t%D0, %A0", operands);
+			dummy = 17;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 7;
+			break;
+
+		default:
+			dummy = 0;
+
+		}			/* case */
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+		msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 8);
+	return "";
+}
+
+/********* LOGICAL SHIFT RIGHT CODE ***************************************/
+const char *
+msp430_emit_lshrqi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *pattern;
+	const char *second_pat;
+	int shiftpos;
+
+	if (zs)
+	{
+		pattern = "clrc\n\trrc.b\t@%E0";
+		second_pat = "rra.b\t@%E0";
+	}
+	else
+	{
+		pattern = "clrc\n\trrc.b\t%A0";
+		second_pat = "rra.b\t%A0";
+	}
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+
+		shiftpos = INTVAL (operands[2]);
+
+		if (shiftpos != 7 && shiftpos)
+		{
+			OUT_INSN (len, pattern, operands);
+			dummy += set_rel (operands[0], 2, 1);
+			shiftpos--;
+		}
+
+		switch (shiftpos)
+		{
+		case 0:
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, second_pat, operands);
+				dummy += set_rel (operands[0], 2, 1) - 1;
+			}
+
+			break;
+
+		case 7:
+			if (zs)
+			{
+				OUT_INSN (len, "rla.b\t@%E0", operands);
+				OUT_INSN (len, "clr.b\t%A0", operands);
+				OUT_INSN (len, "rlc.b\t@%E0", operands);
+				dummy = 4;
+			}
+			else
+			{
+				OUT_INSN (len, "rla.b\t%A0", operands);
+				OUT_INSN (len, "clr.b\t%A0", operands);
+				OUT_INSN (len, "rlc.b\t%A0", operands);
+				dummy = 6;
+			}
+			if (REG_P (operands[0]))
+				dummy = 3;
+			break;
+
+		default:
+			OUT_INSN (len, "clr.b\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy = 1;
+			break;
+		}
+
+		if (len)
+			*len = dummy;
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 2);
+	}
+
+	return "";
+}
+
+const char *
+msp430_emit_lshrhi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *pattern;
+	const char *second_pat;
+	int shiftpos;
+
+	if (zs)
+	{
+		pattern = "clrc\n\trrc\t@%E0";
+		second_pat = "rra\t@%E0";
+	}
+	else
+	{
+		pattern = "clrc\n\trrc\t%A0";
+		second_pat = "rra\t%A0";
+	}
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		shiftpos = INTVAL (operands[2]);
+
+		if (shiftpos < 8 && shiftpos)
+		{
+			OUT_INSN (len, pattern, operands);
+			dummy += set_rel (operands[0], 2, 1);
+			shiftpos--;
+		}
+
+		switch (shiftpos)
+		{
+		case 0:
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, second_pat, operands);
+				dummy += set_rel (operands[0], 2, 1) - 1;
+			}
+
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+
+			if (zs)
+			{
+				OUT_INSN (len, "swpb\t@%E0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				dummy = 3;
+			}
+			else
+			{
+				OUT_INSN (len, "swpb\t%A0", operands);
+				OUT_INSN (len, "and.b\t#-1, %A0", operands);
+				dummy = 4;
+			}
+			if (REG_P (operands[0]))
+				dummy = 2;
+			shiftpos -= 8;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, second_pat, operands);
+				dummy += set_rel (operands[0], 2, 1) - 1;
+			}
+			break;
+
+		case 15:
+
+			if (zs)
+			{
+				OUT_INSN (len, "rla\t@%E0", operands);
+				OUT_INSN (len, "clr\t@%E0", operands);
+				OUT_INSN (len, "rlc\t@%E0", operands);
+				dummy = 3;
+			}
+			else
+			{
+				OUT_INSN (len, "rla\t%A0", operands);
+				OUT_INSN (len, "clr\t%A0", operands);
+				OUT_INSN (len, "rlc\t%A0", operands);
+				dummy = 6;
+			}
+			if (REG_P (operands[0]))
+				dummy = 3;
+			break;
+
+		default:
+			OUT_INSN (len, "clr\t%A0", operands);
+			dummy = 2;
+			if (REG_P (operands[0]))
+				dummy = 1;
+			break;
+		}
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+	{
+		msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 2);
+	}
+
+	return "";
+
+}
+
+const char *
+msp430_emit_lshrsi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	const char *pattern;
+	int dummy = 0;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *second_pat = "rra\t%B0\n\trrc\t%A0";
+
+	pattern = "clrc\n\trrc\t%B0\n\trrc\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		if (shiftpos < 8 && shiftpos)
+		{
+			OUT_INSN (len, pattern, operands);
+			/* This function was underestimating the length by 1 for shifts from
+			1 to 7.  I added one here - Max */
+			dummy += set_rel (operands[0], 2, 1) + 1;
+			shiftpos--;
+		}
+
+		switch (shiftpos)
+		{
+		case 0:
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, second_pat, operands);
+				dummy += set_rel (operands[0], 4, 1) - 1;
+			}
+
+			break;
+
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+			OUT_INSN (len, "swpb\t%A0", operands);
+			OUT_INSN (len, "swpb\t%B0", operands);
+			OUT_INSN (len, "xor.b\t%B0, %A0", operands);
+			OUT_INSN (len, "xor\t%B0, %A0", operands);
+			OUT_INSN (len, "and.b\t#-1, %B0", operands);
+			dummy = 12;
+
+			if (REG_P (operands[0]))
+				dummy = 5;
+			shiftpos -= 8;
+			while (shiftpos--)
+			{
+				OUT_INSN (len, second_pat, operands);
+				dummy += set_rel (operands[0], 4, 1) - 1;
+			}
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			dummy = 5;
+			if (REG_P (operands[0]))
+				dummy = 2;
+
+			shiftpos -= 16;
+			if (shiftpos)
+			{
+				OUT_INSN (len, "clrc\n\trrc\t%A0", operands);
+				dummy += 2;
+				if (!zs && !REG_P (operands[0]))
+					dummy++;
+				shiftpos--;
+			}
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				dummy += 1;
+				if (!zs && !REG_P (operands[0]))
+					dummy++;
+			}
+			break;
+
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "swpb\t%A0", operands);
+			OUT_INSN (len, "and.b\t#-1, %A0", operands);
+			dummy = 9;
+			if (REG_P (operands[0]))
+				dummy = 4;
+			if (indexed_location (operands[0]))
+				dummy -= 1;
+			shiftpos -= 24;
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				dummy += 1;
+				if (!zs && !REG_P (operands[0]))
+					dummy++;
+			}
+			break;
+
+		case 31:
+			OUT_INSN (len, "rla\r%B0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "clr\t%A0", operands);
+			OUT_INSN (len, "rlc\t%A0", operands);
+			dummy = 8;
+			if (REG_P (operands[0]))
+				dummy = 4;
+			if (indexed_location (operands[0]))
+				dummy -= 1;
+			break;
+
+		default:
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "clr\t%A0", operands);
+			dummy = 4;
+			if (REG_P (operands[0]))
+				dummy = 2;
+			break;
+
+		}			/* switch */
+
+		if (len)
+			*len = dummy;
+		return "";
+	}
+	else
+		msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 4);
+
+	return "";
+}
+
+const char *
+msp430_emit_lshrdi3 (insn, operands, len)
+rtx insn;
+rtx operands[];
+int *len;
+{
+	int dummy = 0;
+	const char *pattern;
+	int zs = zero_shifted (operands[0]) || indexed_location (operands[0]);
+	const char *secondary_pat = "rra\t%D0\n\trrc\t%C0\n\trrc\t%B0\n\trrc\t%A0";
+
+	pattern = "clrc\n\trrc\t%D0\n\trrc\t%C0\n\trrc\t%B0\n\trrc\t%A0";
+
+	if (GET_CODE (operands[2]) == CONST_INT)
+	{
+		int shiftpos = INTVAL (operands[2]);
+
+		if (shiftpos < 16 && shiftpos)
+		{
+			OUT_INSN (len, pattern, operands);
+			dummy += set_rel (operands[0], 2, 1);
+			shiftpos--;
+		}
+
+		switch (shiftpos)
+		{
+		case 0:
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+			while (shiftpos--)
+			{
+				OUT_INSN (len, secondary_pat, operands);
+				dummy += set_rel (operands[0], 8, 1) - 1;
+			}
+
+			break;
+
+		case 16:
+		case 17:
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+		case 30:
+		case 31:
+			OUT_INSN (len, "mov\t%B0, %A0", operands);
+			OUT_INSN (len, "mov\t%C0, %B0", operands);
+			OUT_INSN (len, "mov\t%D0, %C0", operands);
+			OUT_INSN (len, "clr\t%D0", operands);
+			dummy = 11;
+			if (REG_P (operands[0]))
+				dummy = 4;
+			shiftpos -= 16;
+
+			if (shiftpos)
+			{
+				OUT_INSN (len, secondary_pat, operands);
+				dummy += set_rel (operands[0], 8, 1) - 1;
+				shiftpos--;
+			}
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%C0\n\trrc\t%B0\n\trrc\t%A0", operands);
+				if (REG_P (operands[0]))
+					dummy = 3;
+				else
+					dummy += 6;
+				if (zs)
+					dummy--;
+			}
+
+			break;
+
+		case 32:
+		case 33:
+		case 34:
+		case 35:
+		case 36:
+		case 37:
+		case 38:
+		case 39:
+		case 40:
+		case 41:
+		case 42:
+		case 43:
+		case 44:
+		case 45:
+		case 46:
+		case 47:
+			OUT_INSN (len, "mov\t%C0, %A0", operands);
+			OUT_INSN (len, "mov\t%D0, %B0", operands);
+			OUT_INSN (len, "clr\t%C0", operands);
+			OUT_INSN (len, "clr\t%D0", operands);
+
+			dummy = 10;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+
+			shiftpos -= 32;
+
+			if (shiftpos)
+			{
+				OUT_INSN (len, "clrc\n\trrc\t%B0,rrc\t%A0", operands);
+				if (REG_P (operands[0]))
+					dummy += 3;
+				else
+					dummy += 5;
+				if (zs)
+					dummy--;
+				shiftpos--;
+			}
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%B0,rrc\t%A0", operands);
+				if (REG_P (operands[0]))
+					dummy += 2;
+				else
+					dummy += 4;
+				if (zs)
+					dummy--;
+			}
+			break;
+
+		case 48:
+		case 49:
+		case 50:
+		case 51:
+		case 52:
+		case 53:
+		case 54:
+		case 55:
+		case 56:
+		case 57:
+		case 58:
+		case 59:
+		case 60:
+		case 61:
+		case 62:
+			OUT_INSN (len, "mov\t%D0, %A0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "clr\t%C0", operands);
+			OUT_INSN (len, "clr\t%D0", operands);
+			dummy = 9;
+			if (GET_CODE (operands[0]) == REG)
+				dummy = 4;
+			shiftpos -= 48;
+
+			if (shiftpos)
+			{
+				OUT_INSN (len, "clrc\n\trrc\t%A0", operands);
+				if (REG_P (operands[0]) || zs)
+					dummy += 2;
+				else
+					dummy += 3;
+
+				shiftpos--;
+			}
+
+			while (shiftpos--)
+			{
+				OUT_INSN (len, "rra\t%A0", operands);
+				if (REG_P (operands[0]) || zs)
+					dummy++;
+				else
+					dummy += 2;
+			}
+			break;
+
+		case 63:
+
+			OUT_INSN (len, "rla\t%D0", operands);
+			OUT_INSN (len, "clr\t%D0", operands);
+			OUT_INSN (len, "clr\t%C0", operands);
+			OUT_INSN (len, "clr\t%B0", operands);
+			OUT_INSN (len, "clr\t%A0", operands);
+			OUT_INSN (len, "rlc\t%A0", operands);
+			if (REG_P (operands[0]))
+				dummy += 6;
+			else
+				dummy += 13;
+
+			if (zs)
+				dummy--;
+			break;
+
+		default:
+			break;
+		}			/* case */
+
+		if (len)
+			*len = dummy;
+	}
+	else
+		msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 8);
+
+	return "";
+}
+
+/*
+*	Multiplication helpers
+*	1. As shifts, 2. the rest 
+*/
+
+#define SOME_SHIFT_THRESHOLD_VAL 	10
+
+int
+msp430_easy_mul (operands, sext)
+rtx operands[];
+int sext;
+{
+	enum machine_mode op0mode = GET_MODE (operands[0]);
+	enum machine_mode op1mode = GET_MODE (operands[1]);
+	rtx op0 = operands[0];
+	rtx op1 = operands[1];
+	rtx insn;
+	int m = INTVAL (operands[2]);
+	int sign = (m < 0);
+	int val = (m > 0 ? m : -m);
+	int shift1 = 0, shift0 = 0;
+	int add1 = 0, sub1 = 0;
+	int t0, t1;
+	int ops = 0;
+
+	m = val;
+	/* 
+	we can do: 
+	const == single bit const +- N that (shift0 + add1/sub1 < 8 instructions) 
+	*/
+	shift0 = 1;
+	shift1 = 0;
+
+	for (t0 = 2;
+		t0 <= val * 2 && shift0 < GET_MODE_SIZE (op0mode) * BITS_PER_UNIT;
+		t0 <<= 1)
+	{
+		if (t0 == val)
+			goto done;
+
+		for (t1 = 1; t1 < t0 && shift1 < GET_MODE_SIZE (op1mode) * BITS_PER_UNIT;
+			t1 <<= 1)
+		{
+			add1 = 0;
+			sub1 = 0;
+			if (t0 + t1 == m)
+			{
+				add1 = 1;
+				goto done;
+			}
+			if (t0 - t1 == m)
+			{
+				sub1 = 1;
+				goto done;
+			}
+
+			if (t0 + t1 * 3 == m)
+			{
+				add1 = 3;
+				goto done;
+			}
+
+			if (t0 - t1 * 3 == m)
+			{
+				sub1 = 3;
+				goto done;
+			}
+
+			add1 = 0;
+			sub1 = 0;
+			shift1++;
+
+		}
+		shift1 = 0;
+		shift0++;
+	}
+
+	return 0;
+done:
+
+	ops = shift0 * (op0mode == SImode ? 2 : 1);
+	ops += shift1 + add1 + sub1;
+	if (op0mode != op1mode)
+	{
+		ops += (op0mode == SImode ? 2 : 1) * ((add1 || sub1) ? 2 : 1);
+	}
+
+	if (ops > SOME_SHIFT_THRESHOLD_VAL)
+		return 0;
+
+	if (op0mode != op1mode)
+	{
+		rtx extend;
+		if (sext)
+			extend = gen_rtx_SIGN_EXTEND (op0mode, op1);
+		else
+			extend = gen_rtx_ZERO_EXTEND (op0mode, op1);
+		insn = gen_rtx_SET (VOIDmode, op0, extend);
+		emit_insn (insn);
+	}
+	else
+	{
+		emit_move_insn (op0, op1);
+	}
+
+	/* shift0 */
+	switch (op0mode)
+	{
+	case QImode:
+		emit_insn (gen_ashlqi3 (op0, op0, GEN_INT (shift0)));
+		break;
+	case HImode:
+		emit_insn (gen_ashlhi3 (op0, op0, GEN_INT (shift0)));
+		break;
+	case SImode:
+		emit_insn (gen_ashlsi3 (op0, op0, GEN_INT (shift0)));
+		break;
+	case DImode:
+		emit_insn (gen_ashldi3 (op0, op0, GEN_INT (shift0)));
+		break;
+	default:
+		abort ();
+	}
+
+	if (op0mode != op1mode && (add1 || sub1 || shift1))
+	{
+		/* equalize operands modes */
+		rtx extend;
+		rtx treg = gen_reg_rtx (op0mode);
+
+		if (sext)
+			extend = gen_rtx_SIGN_EXTEND (op0mode, op1);
+		else
+			extend = gen_rtx_ZERO_EXTEND (op0mode, op1);
+		insn = gen_rtx_SET (VOIDmode, treg, extend);
+		emit_insn (insn);
+		op1 = treg;
+		op1mode = GET_MODE (treg);
+	}
+	else if (add1 || sub1 || shift1)
+	{
+		rtx treg = gen_reg_rtx (op0mode);
+		emit_move_insn (treg, op1);
+		op1 = treg;
+	}
+
+	if (shift1 && (add1 || sub1))
+	{
+		switch (op1mode)
+		{
+		case QImode:
+			emit_insn (gen_ashlqi3 (op1, op1, GEN_INT (shift1)));
+			break;
+		case HImode:
+			emit_insn (gen_ashlhi3 (op1, op1, GEN_INT (shift1)));
+			break;
+		case SImode:
+			emit_insn (gen_ashlsi3 (op1, op1, GEN_INT (shift1)));
+			break;
+		case DImode:
+			emit_insn (gen_ashldi3 (op1, op1, GEN_INT (shift1)));
+			break;
+		default:
+			abort ();
+		}
+	}
+	else if (shift1)
+		abort ();			/* paranoia */
+
+	while (add1--)
+	{
+		insn =
+			gen_rtx_SET (VOIDmode, op0, gen_rtx_PLUS (GET_MODE (op0), op0, op1));
+		emit_insn (insn);
+	}
+
+	while (sub1--)
+	{
+		insn =
+			gen_rtx_SET (VOIDmode, op0,
+			gen_rtx_MINUS (GET_MODE (op0), op0, op1));
+		emit_insn (insn);
+	}
+
+	if (sign)
+	{
+		switch (op0mode)
+		{
+		case QImode:
+			emit_insn (gen_negqi2 (op0, op0));
+			break;
+		case HImode:
+			emit_insn (gen_neghi2 (op0, op0));
+			break;
+		case SImode:
+			emit_insn (gen_negsi2 (op0, op0));
+			break;
+		case DImode:
+			emit_insn (gen_negdi2 (op0, op0));
+			break;
+		default:
+			abort ();
+		}
+	}
+
+	return 1;
+}
+
+/* multiplication guards */
+#define LOAD_MPY(x)	\
+	do{ \
+	if(GET_MODE(x) == QImode)		\
+	emit_insn(gen_load_mpyq(x));	\
+  else					\
+  emit_insn(gen_load_mpy(x));	\
+	}while(0)
+
+#define LOAD_MPYS(x)	\
+	do{ \
+	if(GET_MODE(x) == QImode)		\
+	emit_insn(gen_load_mpysq(x));	\
+  else					\
+  emit_insn(gen_load_mpys(x));	\
+	}while(0)
+
+#define LOAD_OP2(x)	\
+	do{ \
+	if(GET_MODE(x) == QImode)		\
+	emit_insn(gen_load_op2q(x));	\
+  else					\
+  emit_insn(gen_load_op2(x));	\
+	}while(0)
+
+int
+msp430_mul3_guard (operands, sext)
+rtx operands[];
+int sext;
+{
+	rtx m_mpys = mpys_rtx;
+	rtx m_op2 = op2_rtx;
+	rtx m_reslo = reslo_rtx;
+	enum machine_mode op0mode = GET_MODE (operands[0]);
+	enum machine_mode op1mode = GET_MODE (operands[1]);
+	rtx r12 = gen_rtx_REG (op1mode, 12);
+	rtx r10 = gen_rtx_REG (op1mode, 10);
+	rtx r14 = gen_rtx_REG (op0mode, 14);
+
+	if (const_int_operand (operands[2], VOIDmode) &&
+		msp430_easy_mul (operands, sext))
+		return 1;
+
+	if (!msp430_has_hwmul)
+	{
+		rtx clob1 = gen_rtx_CLOBBER (VOIDmode, r10);
+		rtx clob2 = gen_rtx_CLOBBER (VOIDmode, r12);
+		rtx set;
+		rtx mult, op1, op2;
+		rtvec vec;
+		/* prepare 'call' pattern */
+		if (sext==1)
+		{
+			op1 = gen_rtx_SIGN_EXTEND (op0mode, r10);
+			op2 = gen_rtx_SIGN_EXTEND (op0mode, r12);
+		}
+		else
+		{
+			op1 = r10;
+			op2 = r12;
+		}
+		mult = gen_rtx_MULT (op0mode, op1, op2);
+		set = gen_rtx_SET (op0mode, r14, mult);
+		vec = gen_rtvec (3, set, clob1, clob2);
+
+		emit_move_insn (r10, operands[1]);
+		emit_move_insn (r12, operands[2]);
+		emit (gen_rtx_PARALLEL (VOIDmode, vec));
+		emit_move_insn (operands[0], r14);
+		return 1;
+	}
+	if (op1mode == QImode)
+	{
+		m_mpys = gen_lowpart (QImode, mpys_rtx);
+		m_op2 = gen_lowpart (QImode, op2_rtx);
+	}
+
+	if (op0mode == QImode)
+		m_reslo = gen_lowpart (QImode, reslo_rtx);
+
+	if (!MSP430_NOINT_HWMUL)
+		emit_insn (gen_reent_in ());
+
+	LOAD_MPYS (operands[1]);
+	if (sext)
+		emit_insn (gen_extendqihi2 (mpys_rtx, m_mpys));
+	LOAD_OP2 (operands[2]);
+	if (sext)
+		emit_insn (gen_extendqihi2 (op2_rtx, m_op2));
+
+	if (MSP430_NOINT_HWMUL)
+	{
+		if (op0mode == HImode)
+			emit_insn (gen_fetch_result_hi_nint (operands[0]));
+		else
+			emit_insn (gen_fetch_result_qi_nint (operands[0]));
+	}
+	else
+	{
+		if (op0mode == HImode)
+			emit_insn (gen_fetch_result_hi (operands[0]));
+		else
+			emit_insn (gen_fetch_result_qi (operands[0]));
+	}
+
+	return 1;
+}
+
+
+int
+msp430_umul3_guard (operands, sext)
+rtx operands[];
+int sext ATTRIBUTE_UNUSED;
+{
+	rtx m_mpy = mpy_rtx;
+	rtx m_op2 = op2_rtx;
+	enum machine_mode op0mode = GET_MODE (operands[0]);
+	enum machine_mode op1mode = GET_MODE (operands[1]);
+	rtx r12 = gen_rtx_REG (op1mode, 12);
+	rtx r10 = gen_rtx_REG (op1mode, 10);
+	rtx r14 = gen_rtx_REG (op0mode, 14);
+
+	if (const_int_operand (operands[2], VOIDmode) &&
+		msp430_easy_mul (operands, 0))
+		return 1;
+
+	if (!msp430_has_hwmul)
+	{
+		rtx clob1 = gen_rtx_CLOBBER (VOIDmode, r10);
+		rtx clob2 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (op1mode, 12));
+		rtx set;
+		rtx mult, op1, op2;
+		rtvec vec;
+		/* prepare 'call' pattern */
+		op1 = gen_rtx_ZERO_EXTEND (op0mode, r10);
+		op2 = gen_rtx_ZERO_EXTEND (op0mode, r12);
+
+		mult = gen_rtx_MULT (op0mode, op1, op2);
+		set = gen_rtx_SET (op0mode, r14, mult);
+		vec = gen_rtvec (3, set, clob1, clob2);
+
+		emit_move_insn (r10, operands[1]);
+		emit_move_insn (r12, operands[2]);
+		emit (gen_rtx_PARALLEL (VOIDmode, vec));
+		emit_move_insn (operands[0], r14);
+		return 1;
+	}
+
+	m_mpy = gen_lowpart (QImode, mpy_rtx);
+	m_op2 = gen_lowpart (QImode, op2_rtx);
+
+	if (!MSP430_NOINT_HWMUL)
+		emit_insn (gen_reent_in ());
+
+	/*  LOAD_MPY (gen_lowpart (QImode,operands[1]));
+	//emit_insn (gen_zero_extendqihi2 (mpy_rtx, m_mpy));
+	//LOAD_OP2 (gen_lowpart (QImode,operands[2]));
+	//emit_insn (gen_zero_extendqihi2 (op2_rtx, m_op2));
+	emit_move_insn(m_op2, gen_lowpart (QImode,operands[2]));*/
+
+	//The code above does not work on GCC v4, as the optimizer removes the move INSN
+	LOAD_MPY (operands[1]);
+	//emit_insn (gen_zero_extendqihi2 (mpy_rtx, m_mpy)); // No need for extension, as the HWMUL recognizes the operand width
+	LOAD_OP2 (operands[2]);
+	//emit_insn (gen_zero_extendqihi2 (op2_rtx, m_op2));
+
+
+	if (MSP430_NOINT_HWMUL)
+		emit_insn (gen_fetch_result_hi_nint (operands[0]));
+	else
+		emit_insn (gen_fetch_result_hi (operands[0]));
+
+	return 1;
+}
+
+
+int
+msp430_mulhisi_guard (operands)
+rtx operands[];
+{
+	enum machine_mode op0mode = GET_MODE (operands[0]);
+	enum machine_mode op1mode = GET_MODE (operands[1]);
+	rtx r12 = gen_rtx_REG (op1mode, 12);
+	rtx r10 = gen_rtx_REG (op1mode, 10);
+	rtx r14 = gen_rtx_REG (op0mode, 14);
+	rtx r11 = gen_rtx_REG (op1mode, 11);
+	rtx r13 = gen_rtx_REG (op1mode, 13);
+
+	if (const_int_operand (operands[2], VOIDmode) &&
+		msp430_easy_mul (operands, 1))
+		return 1;
+
+	if (!msp430_has_hwmul)
+	{
+		rtx clob1 = gen_rtx_CLOBBER (VOIDmode, r10);
+		rtx clob2 = gen_rtx_CLOBBER (VOIDmode, r11);
+		rtx clob3 = gen_rtx_CLOBBER (VOIDmode, r12);
+		rtx clob4 = gen_rtx_CLOBBER (VOIDmode, r13);
+
+		rtx set;
+		rtx mult, op1, op2;
+		rtvec vec;
+		/* prepare 'call' pattern */
+		op1 = gen_rtx_SIGN_EXTEND (op0mode, r10);
+		op2 = gen_rtx_SIGN_EXTEND (op0mode, r12);
+
+		mult = gen_rtx_MULT (op0mode, op1, op2);
+		set = gen_rtx_SET (op0mode, r14, mult);
+		vec = gen_rtvec (5, set, clob1, clob2, clob3, clob4);
+
+		emit_move_insn (r10, operands[1]);
+		emit_move_insn (r12, operands[2]);
+		emit (gen_rtx_PARALLEL (VOIDmode, vec));
+		emit_move_insn (operands[0], r14);
+		return 1;
+	}
+	if (!MSP430_NOINT_HWMUL)
+		emit_insn (gen_reent_in ());
+
+	LOAD_MPYS (operands[1]);
+	LOAD_OP2 (operands[2]);
+
+	if (MSP430_NOINT_HWMUL)
+	{
+		emit_insn (gen_fetch_result_si_nint (operands[0]));
+	}
+	else
+		emit_insn (gen_fetch_result_si (operands[0]));
+
+	return 1;
+}
+
+
+int
+msp430_umulhisi_guard (operands)
+rtx operands[];
+{
+	enum machine_mode op0mode = GET_MODE (operands[0]);
+	enum machine_mode op1mode = GET_MODE (operands[1]);
+	rtx r12 = gen_rtx_REG (op1mode, 12);
+	rtx r10 = gen_rtx_REG (op1mode, 10);
+	rtx r14 = gen_rtx_REG (op0mode, 14);
+	rtx r11 = gen_rtx_REG (op1mode, 11);
+	rtx r13 = gen_rtx_REG (op1mode, 13);
+
+	if (const_int_operand (operands[2], VOIDmode) &&
+		msp430_easy_mul (operands, 0))
+		return 1;
+
+	if (!msp430_has_hwmul)
+	{
+		rtx clob1 = gen_rtx_CLOBBER (VOIDmode, r10);
+		rtx clob2 = gen_rtx_CLOBBER (VOIDmode, r11);
+		rtx clob3 = gen_rtx_CLOBBER (VOIDmode, r12);
+		rtx clob4 = gen_rtx_CLOBBER (VOIDmode, r13);
+
+		rtx set;
+		rtx mult, op1, op2;
+		rtvec vec;
+		/* prepare 'call' pattern */
+		op1 = gen_rtx_ZERO_EXTEND (op0mode, r10);
+		op2 = gen_rtx_ZERO_EXTEND (op0mode, r12);
+
+		mult = gen_rtx_MULT (op0mode, op1, op2);
+		set = gen_rtx_SET (op0mode, r14, mult);
+		vec = gen_rtvec (5, set, clob1, clob2, clob3, clob4);
+
+		emit_move_insn (r10, operands[1]);
+		emit_move_insn (r12, operands[2]);
+		emit (gen_rtx_PARALLEL (VOIDmode, vec));
+		emit_move_insn (operands[0], r14);
+		return 1;
+	}
+
+	if (!MSP430_NOINT_HWMUL)
+		emit_insn (gen_reent_in ());
+
+	LOAD_MPY (operands[1]);
+	LOAD_OP2 (operands[2]);
+
+	if (MSP430_NOINT_HWMUL)
+	{
+		emit_insn (gen_fetch_result_si_nint (operands[0]));
+	}
+	else
+		emit_insn (gen_fetch_result_si (operands[0]));
+
+	return 1;
+}
+
+
+/* something like 'push x(r1)' or 'push @r1' */
+int self_push (rtx x)
+{
+	rtx c;
+	rtx r;
+
+	if (GET_CODE (x) != MEM)
+		return 0;
+
+	c = XEXP (x, 0);
+
+	if (REG_P (c) && REGNO (c) == 1)
+		return 1;
+
+	if (GET_CODE (c) == PLUS)
+	{
+		r = XEXP (c, 0);
+		if (REG_P (r) && REGNO (r) == 1)
+			return 1;
+	}
+	return 0;
+}
+
+const char * msp430_emit_call (rtx operands[])
+{
+	rtx x = operands[0];
+	rtx c;
+	rtx r;
+
+	if (GET_CODE (x) == MEM)
+	{
+		c = XEXP (x, 0);
+
+		if (REG_P (c) && REGNO (c) == 1)
+		{
+			OUT_INSN (NULL, "call\t2(%E0)", operands);
+			return "";
+		}
+
+		if (GET_CODE (c) == PLUS)
+		{
+			r = XEXP (c, 0);
+			if (REG_P (r) && REGNO (r) == 1)
+			{
+				OUT_INSN (NULL, "call\t2+%A0", operands);
+				return "";
+			}
+		}
+	}
+
+	OUT_INSN(NULL, "call\t%0", operands);
+	return "";
+}
+
+/* difficult pushes.
+if planets are not aligned, the combiner does not allocate
+r4 as a frame pointer. Instead, it uses stack pointer for frame.
+If there is a va_arg call and non-register local var has to be passed 
+as a function parameter, the push X(r1) in SI, SF and DI modes will
+corrupt passed var. The following minds this fact */
+
+const char *
+msp430_pushqi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int sp = self_push (operands[0]);
+	int dummy = 0;
+
+	if (sp)
+	{
+		rtx c;
+		c = XEXP (operands[0], 0);
+		if (REG_P (c))
+			OUT_INSN (len, "push.b\t2(%E0)", operands);
+		else
+			OUT_INSN (len, "push.b\t2+%A0", operands);
+		dummy = 2;
+	}
+	else
+	{
+		OUT_INSN (len, "push.b\t%A0", operands);
+		dummy = 2;
+
+		if (GET_CODE (operands[0]) == CONST_INT)
+		{
+			int cval = INTVAL (operands[0]);
+			int x = (cval) & 0x0fffful;
+			if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff)
+				dummy--;
+
+		}
+		else if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		else if (GET_CODE (operands[0]) == MEM && REG_P (XEXP (operands[0], 0)))
+			dummy--;
+	}
+
+	return "";
+}
+
+const char *
+msp430_pushhi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int sp = self_push (operands[0]);
+	int dummy = 0;
+
+	if (sp)
+	{
+		rtx c;
+		c = XEXP (operands[0], 0);
+		if (REG_P (c))
+			OUT_INSN (len, "push\t2(%E0)", operands);
+		else
+			OUT_INSN (len, "push\t2+%A0", operands);
+		dummy = 2;
+	}
+	else
+	{
+		OUT_INSN (len, "push\t%A0", operands);
+		dummy = 2;
+
+		if (GET_CODE (operands[0]) == CONST_INT)
+		{
+			int cval = INTVAL (operands[0]);
+			int x = (cval) & 0x0fffful;
+
+			if (cval == 99999999)
+			{
+				if (len)
+					*len = 3;
+				return "";
+			}
+
+			if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff)
+				dummy--;
+
+		}
+		else if (GET_CODE (operands[0]) == REG)
+			dummy--;
+		else if (GET_CODE (operands[0]) == MEM && REG_P (XEXP (operands[0], 0)))
+			dummy--;
+	}
+	if (len)
+		*len = dummy;
+	return "";
+}
+
+const char *
+msp430_pushsisf (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int sp = self_push (operands[0]);
+	int dummy = 0;
+
+	if (!sp)
+	{
+		OUT_INSN (len, "push\t%B0", operands);
+		OUT_INSN (len, "push\t%A0", operands);
+		dummy = 4;
+		if (indexed_location (operands[0]))
+			dummy--;
+		if (REG_P (operands[0]))
+			dummy -= 2;
+		if (GET_CODE (operands[0]) == CONST_INT)
+		{
+			int cval = INTVAL (operands[0]);
+			int x = (cval) & 0x0fffful;
+			int y = (((unsigned long) (cval)) & 0xffff0000ul >> 16);
+			if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff)
+				dummy--;
+			if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8 || y == 0xffff)
+				dummy--;
+		}
+		else if (GET_CODE (operands[0]) == CONST_DOUBLE
+			&& GET_MODE (operands[0]) == SFmode)
+		{
+			long val;
+			int y, x;
+			REAL_VALUE_TYPE rv;
+			REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[0]);
+			REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+
+			y = (val & 0xffff0000ul) >> 16;
+			x = val & 0xffff;
+			if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff)
+				dummy--;
+			if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8 || y == 0xffff)
+				dummy--;
+		}
+	}
+	else
+	{
+		OUT_INSN (len, "push\t2+%B0", operands);
+		OUT_INSN (len, "push\t2+%B0", operands);
+		dummy = 4;
+	}
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+
+const char *
+msp430_pushdi (insn, operands, len)
+rtx insn ATTRIBUTE_UNUSED;
+rtx operands[];
+int *len;
+{
+	int sp = self_push (operands[0]);
+	int dummy = 0;
+
+	if (!sp)
+	{
+		OUT_INSN (len, "push\t%D0", operands);
+		OUT_INSN (len, "push\t%C0", operands);
+		OUT_INSN (len, "push\t%B0", operands);
+		OUT_INSN (len, "push\t%A0", operands);
+
+		dummy = 8;
+		if (indexed_location (operands[0]))
+			dummy--;
+		if (REG_P (operands[0]))
+			dummy -= 4;
+		if (GET_CODE (operands[0]) == CONST_DOUBLE)
+		{
+			int hi = CONST_DOUBLE_HIGH (operands[0]);
+			int lo = CONST_DOUBLE_LOW (operands[0]);
+			int x, y, z;
+
+			x = (hi & 0xffff0000ul) >> 16;
+			y = hi & 0xffff;
+			z = (lo & 0xffff0000ul) >> 16;
+			if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff)
+				dummy--;
+			if (y == 0 || y == 1 || y == 2 || y == 4 || y == 8 || y == 0xffff)
+				dummy--;
+			if (z == 0 || z == 1 || z == 2 || z == 4 || z == 8 || z == 0xffff)
+				dummy--;
+			z = lo & 0xffff;
+			if (z == 0 || z == 1 || z == 2 || z == 4 || z == 8 || z == 0xffff)
+				dummy--;
+		}
+	}
+	else
+	{
+		OUT_INSN (len, "push\t2+%D0", operands);
+		OUT_INSN (len, "push\t2+%D0", operands);
+		OUT_INSN (len, "push\t2+%D0", operands);
+		OUT_INSN (len, "push\t2+%D0", operands);
+		dummy = 8;
+	}
+
+	if (len)
+		*len = dummy;
+
+	return "";
+}
+
+int dead_or_set_in_peep (int which, rtx insn ATTRIBUTE_UNUSED, rtx x)
+{
+	extern int peep2_current_count;
+	rtx r;
+	rtx next;
+
+	if (which > peep2_current_count)
+		return 0;
+
+	next = peep2_next_insn (which);
+	if (!next)
+		return 0;
+	if (!REG_P (x))
+		return 0;
+	r = find_regno_note (next, REG_DEAD, REGNO (x));
+
+	if (!r)
+		return 0;
+
+	r = XEXP (r, 0);
+	return GET_MODE (r) == GET_MODE (x);
+}
+
+void
+msp430_trampoline_template (FILE * fd)
+{
+	fprintf (fd, "; TRAMPOLINE HERE\n"
+		"; move context (either r1 or r4) to r6\n"
+		"; call function (0xf0f0 will be changed)\n");
+	fprintf (fd, "\tmov	#0xf0f0, r6\n");
+	fprintf (fd, "\tbr	#0xf0f0\n");
+	fprintf (fd, "; END OF TRAMPOLINE\n\n");
+}
+
+void
+msp430_initialize_trampoline (tramp, fn, ctx)
+rtx tramp;
+rtx fn;
+rtx ctx;
+{
+	emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), ctx);
+	emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 6)), fn);
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------------
+
+static bool
+msp430_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+	int cst;
+	rtx op0, op1;
+	/***
+	[(outer:mode1 (inner:mode (op1) (op2))]
+
+
+	inner		outer	mode1	op1   op2
+	--------------------------
+	CONST_INT	UNKNOWN	VOID
+	PLUS		SET	HI	reg + reg
+	ASHIFT	SET	HI	reg << 1
+	ASHIFT	SET	HI	reg << 15
+	NEG		SET	HI	reg
+	DIV		SET	HI	reg / 32
+	MOD		SET	HI	reg % 32
+	UDIV		SET	QI	reg / reg
+	MULT		SET	QI	reg * reg
+	MULT		SET	HI	0<-reg * 0<-reg
+	TRUNCATE	SET	QI	HI -> QI
+	UDIV		SET	HI	reg / reg
+	MULT		SET	HI	reg * reg
+	MULT		SET	SI	0<-reg * 0<-reg
+	TRUNCATE	SET	HI	SI -> HI
+	UDIV		SET	SI	reg / reg
+	MULT		SET	SI	reg * reg
+	MULT		SET	DI	0<-reg * 0<-reg
+	TRUNCATE	SET	SI	DI -> SI
+	UDIV		SET	DI	reg / reg
+	MULT		SET	DI	reg * reg
+	MULT		SET	TI	0<-reg * 0<-reg
+	TRUNCATE	SET	DI	TI -> DI
+	UDIV		SET	TI	reg / reg
+	MULT		SET	TI	reg * reg
+	MULT		SET	OI	reg * reg
+	TRUNCATE	SET	TI	OI -> TI
+	UDIV		SET	OI	reg / reg
+	MULT		SET	OI	reg * reg
+	CONST_INT	COMPARE	VOID	
+	...
+	CONST_INT	PLUS	HI	reg + const
+	PLUS		MEM	HI	X(rn)
+	PLUS		CONST_INT	???????? ?????
+	MEM		SET	any
+	PLUS		MEM	HI	reg + const
+
+	***/
+	cst = COSTS_N_INSNS (5);
+	if (outer_code == SET)
+	{
+		op0 = XEXP (x, 0);
+		op1 = XEXP (x, 1);
+		switch (code)
+		{
+		case CONST_INT:	/* source only !!! */
+			{
+				int i = INTVAL (x);
+				if (i == -1 || i == 0 || i == 2 || i == 4 || i == 8)
+					cst = COSTS_N_INSNS (1);
+				else
+					cst = COSTS_N_INSNS (2);
+			}
+			break;
+		case PLUS:
+		case MINUS:
+		case AND:
+		case IOR:
+		case XOR:
+		case UNSPEC:
+		case UNSPEC_VOLATILE:
+			cst = COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			break;
+		case ASHIFT:
+		case LSHIFTRT:
+		case ASHIFTRT:
+			/* cst = COSTS_N_INSNS(10);
+			break; */
+			if (CONSTANT_P (op1) && INTVAL (op1) == 1)
+				cst =
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			else if (CONSTANT_P (op1) && INTVAL (op1) == 15)
+				cst =
+				3 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			else if (CONSTANT_P (op1) && INTVAL (op1) == 8)
+				cst =
+				2 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			else if (CONSTANT_P (op1) && INTVAL (op1) == 16)
+				cst =
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			else if (CONSTANT_P (op1) && INTVAL (op1) == 24)
+				cst =
+				4 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			else if (CONSTANT_P (op1) && INTVAL (op1) == 31)
+				cst =
+				3 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			if (code == ASHIFTRT)
+				cst += COSTS_N_INSNS (1);
+			break;
+
+		case NEG:
+			cst =
+				2 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			break;
+		case DIV:
+		case MOD:
+		case MULT:
+		case UDIV:
+			cst = COSTS_N_INSNS (64);
+			break;
+		case TRUNCATE:
+			cst = COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			break;
+		case ZERO_EXTEND:
+			cst =
+				2 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			break;
+		case SIGN_EXTEND:
+		case ABS:
+			cst =
+				2 *
+				COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+			cst += COSTS_N_INSNS (2);
+			break;
+		default:
+			cst = 0;
+		}
+	}
+	else if (outer_code == COMPARE)
+	{
+		cst = COSTS_N_INSNS (((GET_MODE_SIZE (GET_MODE (x)) + 1) & ~1) >> 1);
+		cst += COSTS_N_INSNS (2);
+	}
+	else if (outer_code == JUMP_INSN)
+	{
+		cst = COSTS_N_INSNS (2);
+	}
+	else if (outer_code == CALL_INSN)
+	{
+		cst = COSTS_N_INSNS (4);
+	}
+	else
+		return false;
+
+	*total = cst;
+	if (cst)
+		return true;
+	return false;
+}
+
+int
+default_rtx_costs (rtx X ATTRIBUTE_UNUSED, enum rtx_code code, enum rtx_code outer_code ATTRIBUTE_UNUSED)
+{
+	int cost = 4;
+
+	switch (code)
+	{
+	case SYMBOL_REF:
+		cost += 2;
+		break;
+	case LABEL_REF:
+		cost += 2;
+		break;
+	case MEM:
+		cost += 2;
+		break;
+	case CONST_INT:
+		cost += 2;
+		break;
+	case SIGN_EXTEND:
+	case ZERO_EXTEND:
+		cost += 2;
+		break;
+	default:
+		break;
+	}
+	return cost;
+}
+
+
+static void 
+msp430_globalize_label(FILE *stream, const char *name)
+{
+	if(*name == '*' || *name == '@') name++;
+	if(*name >='0' && *name <='9') return;
+	fputs (GLOBAL_ASM_OP, stream);
+	assemble_name (stream, name);
+	putc ('\n', stream);
+}
+
+static bool msp430_function_ok_for_sibcall(tree decl ATTRIBUTE_UNUSED, tree exp ATTRIBUTE_UNUSED)
+{
+	int cfp = msp430_critical_function_p (current_function_decl);
+	int ree = msp430_reentrant_function_p (current_function_decl);
+	int nfp = msp430_naked_function_p (current_function_decl);
+	int ifp = interrupt_function_p (current_function_decl);
+	int wup = wakeup_function_p (current_function_decl);
+	int fee = msp430_empty_epilogue ();
+
+	/*
+	function must be:
+	- not critical
+	- not reentrant
+	- not naked
+	- not interrupt
+	- nor wakeup
+	- must have empty epilogue
+	*/
+
+	if(nfp || ifp || wup || ree || cfp || !fee)
+		return false;
+	return true;
+}
+
+int
+msp430_address_costs (rtx x)
+{
+	enum rtx_code code = GET_CODE (x);
+	rtx op0, op1;
+
+	switch (code)
+	{
+	case PLUS:			/* X(rn), addr + X */
+		op0 = XEXP (x, 0);
+		op1 = XEXP (x, 1);
+		if (REG_P (op0))
+		{
+			if (INTVAL (op1) == 0)
+				return COSTS_N_INSNS (2);
+			else
+				return COSTS_N_INSNS (3);
+		}
+		break;
+	case REG:
+		return COSTS_N_INSNS (2);
+		break;
+	default:
+		break;
+	}
+	return COSTS_N_INSNS (3);
+}
+
+void msp430_expand_mov_intptr (rtx dest, rtx src)
+{
+  if (push_operand (dest, HImode) && ! general_no_elim_operand (src, HImode))
+	src = copy_to_mode_reg (HImode, src);
+
+  emit_insn (gen_rtx_SET (VOIDmode, dest, src));
+}
diff -ruNp gcc-4.x/gcc/config/msp430/msp430.h gcc-4.4.5/gcc/config/msp430/msp430.h
--- gcc-4.x/gcc/config/msp430/msp430.h	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430.h	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,3198 @@
+/* This work is partially financed by the European Commission under the
+ * Framework 6 Information Society Technologies Project
+ * "Wirelessly Accessible Sensor Populations (WASP)".
+ */
+
+/* Definitions of target machine for GNU compiler,
+   for Texas Instruments MSP430 microcontrollers.
+   Copyright (C) 2001-2009 Free Software Foundation, Inc.
+   Contributed by Dmitry Diky <diwil@mail.ru>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* This declaration should be present. */
+/*
+#include <stdio.h>
+*/
+
+#include "_gccver.h"
+
+#define TARGET_CPU_CPP_BUILTINS()                       \
+do{							\
+  builtin_define_std ("MSP430");			\
+  builtin_define_std ("__MSP430__");			\
+  if(msp430_has_hwmul)					\
+    builtin_define ("MSP430_HAS_HWMUL");		\
+  else							\
+    builtin_define ("MSP430_NO_HWMUL");		        \
+}while(0)
+
+
+extern int target_flags;
+
+extern const char *msp430_endup;
+extern const char *msp430_init_stack;
+extern const char *msp430_mcu_name;
+extern int msp430_has_hwmul;
+
+
+#define MSP430_HAS_HWMUL_INTERNAL (msp430_has_hwmul)
+
+int msp430_current_function_noint_hwmul_function_p(void);
+#define MSP430_NOINT_HWMUL (msp430_current_function_noint_hwmul_function_p())
+
+
+#define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)");
+
+#define OVERRIDE_OPTIONS msp430_override_options()
+
+/*#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0*/
+#define CAN_DEBUG_WITHOUT_FP
+/* Define this macro if debugging can be performed even without a
+   frame pointer.  If this macro is defined, GNU CC will turn on the
+   `-fomit-frame-pointer' option whenever `-O' is specified.  */
+
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN 0
+#define WORDS_BIG_ENDIAN 0
+#define BITS_PER_UNIT 8
+#define BITS_PER_WORD 16
+
+#ifdef IN_LIBGCC2
+/* This is to get correct SI and DI modes in libgcc2.c (32 and 64 bits).  */
+#define UNITS_PER_WORD 4
+#else
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 2
+#endif
+
+/* Width in bits of a pointer.
+   See also the macro `Pmode' defined below.  */
+#define POINTER_SIZE 16
+
+
+/* Maximum sized of reasonable data type
+   DImode or Dfmode ...  */
+#define MAX_FIXED_MODE_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 16
+
+/* Every structure's size must be a multiple of this.  */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Define this if move instructions will actually fail to work
+   when given unaligned data.  */
+#define STRICT_ALIGNMENT 1
+
+/* A C expression for the size in bits of the type `int' on the
+     target machine.  If you don't define this, the default is one word.  */
+#define INT_TYPE_SIZE ( 16)
+
+
+/* A C expression for the size in bits of the type `short' on the
+   target machine.  If you don't define this, the default is half a
+   word.  (If this would be less than one storage unit, it is rounded
+   up to one unit.)  */
+#define SHORT_TYPE_SIZE (INT_TYPE_SIZE == 8 ? INT_TYPE_SIZE : 16)
+
+/* A C expression for the size in bits of the type `long' on the
+   target machine.  If you don't define this, the default is one word.  */
+#define LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 16 : 32)
+
+#define LONG_LONG_TYPE_SIZE 64
+/* A C expression for the size in bits of the type `long long' on the
+   target machine.  If you don't define this, the default is two
+   words.  If you want to support GNU Ada on your machine, the value
+   of macro must be at least 64.  */
+
+
+#define  CHAR_TYPE_SIZE 8
+/* A C expression for the size in bits of the type `char' on the
+   target machine.  If you don't define this, the default is one
+   quarter of a word.  (If this would be less than one storage unit,
+   it is rounded up to one unit.)  */
+
+#define FLOAT_TYPE_SIZE 32
+/* A C expression for the size in bits of the type `float' on the
+   target machine.  If you don't define this, the default is one word.  */
+
+#define DOUBLE_TYPE_SIZE 32
+/* A C expression for the size in bits of the type `double' on the
+   target machine.  If you don't define this, the default is two
+   words. */
+
+
+#define LONG_DOUBLE_TYPE_SIZE 32
+/* A C expression for the size in bits of the type `long double' on
+   the target machine.  If you don't define this, the default is two
+   words.  */
+
+#define DEFAULT_SIGNED_CHAR 1
+/* An expression whose value is 1 or 0, according to whether the type
+   `char' should be signed or unsigned by default.  The user can
+   always override this default with the options `-fsigned-char' and
+   `-funsigned-char'.  */
+
+/* `DEFAULT_SHORT_ENUMS'
+   A C expression to determine whether to give an `enum' type only as
+   many bytes as it takes to represent the range of possible values
+   of that type.  A nonzero value means to do that; a zero value
+   means all `enum' types should be allocated like `int'.
+
+   If you don't define the macro, the default is 0.  */
+
+#define SIZE_TYPE (INT_TYPE_SIZE == 8 ? "long unsigned int" : "unsigned int")
+/* A C expression for a string describing the name of the data type
+   to use for size values.  The typedef name `size_t' is defined
+   using the contents of the string.
+   
+   The string can contain more than one keyword.  If so, separate
+   them with spaces, and write first any length keyword, then
+   `unsigned' if appropriate, and finally `int'.  The string must
+   exactly match one of the data type names defined in the function
+   `init_decl_processing' in the file `c-decl.c'.  You may not omit
+   `int' or change the order--that would cause the compiler to crash
+   on startup.
+   
+   If you don't define this macro, the default is `"long unsigned
+   int"'.  */
+
+#define PTRDIFF_TYPE (INT_TYPE_SIZE == 8 ? "long int" :"int")
+/* A C expression for a string describing the name of the data type
+   to use for the result of subtracting two pointers.  The typedef
+   name `ptrdiff_t' is defined using the contents of the string.  See
+   `SIZE_TYPE' above for more information.
+   
+   If you don't define this macro, the default is `"long int"'.  */
+
+
+#define WCHAR_TYPE_SIZE 16
+/* A C expression for the size in bits of the data type for wide
+   characters.  This is used in `cpp', which cannot make use of
+   `WCHAR_TYPE'.  */
+
+#define FIRST_PSEUDO_REGISTER 17
+/* Number of hardware registers known to the compiler.  They receive
+   numbers 0 through `FIRST_PSEUDO_REGISTER-1'; thus, the first
+   pseudo register's number really is assigned the number
+   `FIRST_PSEUDO_REGISTER'.  */
+
+/*#define DWARF_FRAME_REGISTERS 16*/
+
+#define FIXED_REGISTERS {\
+  1,1,/* r0 r1 == PC  SP */\
+  1,1,/* r2 r3 == CG1(SR) CG2*/\
+  0,0,/* r4 r5 */\
+  0,0,/* r6 r7 */\
+  0,0,/* r8 r9 */\
+  0,0,/* r10 r11 */\
+  0,0,/* r12 r13 */\
+  0,0,/* r14 r15 */\
+  1, /* argp register */\
+}
+/* An initializer that says which registers are used for fixed
+   purposes all throughout the compiled code and are therefore not
+   available for general allocation.  These would include the stack
+   pointer, the frame pointer (except on machines where that can be
+   used as a general register when no frame pointer is needed), the
+   program counter on machines where that is considered one of the
+   addressable registers, and any other numbered register with a
+   standard use.
+
+   This information is expressed as a sequence of numbers, separated
+   by commas and surrounded by braces.  The Nth number is 1 if
+   register N is fixed, 0 otherwise.
+
+   The table initialized from this macro, and the table initialized by
+   the following one, may be overridden at run time either
+   automatically, by the actions of the macro
+   `CONDITIONAL_REGISTER_USAGE', or by the user with the command
+   options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'.  */
+
+#define CALL_USED_REGISTERS {			\
+    1,1,/* r0 r1 */				\
+    1,1,/* r2 r3 */				\
+    0,0,/* r4 r5 */				\
+    0,0,/* r6 r7 */				\
+    0,0,/* r8 r9 */				\
+    0,0,/* r10 r11 */				\
+    1,1,/* r12 r13 */				\
+    1,1,/* r14 r15 */				\
+	1, \
+}
+/* Like `FIXED_REGISTERS' but has 1 for each register that is
+   clobbered (in general) by function calls as well as for fixed
+   registers.  This macro therefore identifies the registers that are
+   not available for general allocation of values that must live
+   across function calls.
+
+   If a register has 0 in `CALL_USED_REGISTERS', the compiler
+   automatically saves it on function entry and restores it on
+   function exit, if the register is used within the function.  */
+
+#define REG_ALLOC_ORDER { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }
+
+/* If defined, an initializer for a vector of integers, containing the
+   numbers of hard registers in the order in which GNU CC should
+   prefer to use them (from most preferred to least).
+   
+   If this macro is not defined, registers are used lowest numbered
+   first (all else being equal).
+   
+   One use of this macro is on machines where the highest numbered
+   registers must always be saved and the save-multiple-registers
+   instruction supports only sequences of consetionve registers.  On
+   such machines, define `REG_ALLOC_ORDER' to be an initializer that
+   lists the highest numbered allocatable register first. */
+
+#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
+/* ORDER_REGS_FOR_LOCAL_ALLOC'
+   A C statement (sans semicolon) to choose the order in which to
+   allocate hard registers for pseudo-registers local to a basic
+   block.
+
+   Store the desired register order in the array `reg_alloc_order'.
+   Element 0 should be the register to allocate first; element 1, the
+   next register; and so on.
+
+   The macro body should not assume anything about the contents of
+   `reg_alloc_order' before execution of the macro.
+
+   On most machines, it is not necessary to define this macro.  */
+
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* A C expression for the number of consecutive hard registers,
+   starting at register number REGNO, required to hold a value of mode
+   MODE.
+
+   On a machine where all registers are exactly one word, a suitable
+   definition of this macro is
+
+   #define HARD_REGNO_NREGS(REGNO, MODE)            \
+   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
+   / UNITS_PER_WORD))  */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+/*
+msp430_hard_regno_mode_ok(REGNO, MODE)
+*/
+/* A C expression that is nonzero if it is permissible to store a
+   value of mode MODE in hard register number REGNO (or in several
+   registers starting with that one).  For a machine where all
+   registers are equivalent, a suitable definition is
+
+   #define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+   It is not necessary for this macro to check for the numbers of
+   fixed registers, because the allocation mechanism considers them
+   to be always occupied.
+
+   On some machines, double-precision values must be kept in even/odd
+   register pairs.  The way to implement that is to define this macro
+   to reject odd register numbers for such modes.
+
+   The minimum requirement for a mode to be OK in a register is that
+   the `movMODE' instruction pattern support moves between the
+   register and any other hard register for which the mode is OK; and
+   that moving a value into the register and back out not alter it.
+
+   Since the same instruction used to move `SImode' will work for all
+   narrower integer modes, it is not necessary on any machine for
+   `HARD_REGNO_MODE_OK' to distinguish between these modes, provided
+   you define patterns `movhi', etc., to take advantage of this.  This
+   is useful because of the interaction between `HARD_REGNO_MODE_OK'
+   and `MODES_TIEABLE_P'; it is very desirable for all integer modes
+   to be tieable.
+
+   Many machines have special registers for floating point arithmetic.
+   Often people assume that floating point machine modes are allowed
+   only in floating point registers.  This is not true.  Any
+   registers that can hold integers can safely *hold* a floating
+   point machine mode, whether or not floating arithmetic can be done
+   on it in those registers.  Integer move instructions can be used
+   to move the values.
+
+   On some machines, though, the converse is true: fixed-point machine
+   modes may not go in floating registers.  This is true if the
+   floating registers normalize any value stored in them, because
+   storing a non-floating value there would garble it.  In this case,
+   `HARD_REGNO_MODE_OK' should reject fixed-point machine modes in
+   floating registers.  But if the floating registers do not
+   automatically normalize, if you can store any bit pattern in one
+   and retrieve it unchanged without a trap, then any machine mode
+   may go in a floating register, so you can define this macro to say
+   so.
+
+   The primary significance of special floating registers is rather
+   that they are the registers acceptable in floating point arithmetic
+   instructions.  However, this is of no concern to
+   `HARD_REGNO_MODE_OK'.  You handle it by writing the proper
+   constraints for those instructions.
+
+   On some machines, the floating registers are especially slow to
+   access, so that it is better to store a value in a stack frame
+   than in such a register if floating point arithmetic is not being
+   done.  As long as the floating registers are not in class
+   `GENERAL_REGS', they will not be used unless some pattern's
+   constraint asks for one.  */
+
+#define MODES_TIEABLE_P(MODE1, MODE2)           	\
+0
+/*
+  ((MODE1) == (MODE2)                           	\
+     || ((MODE1) == QImode && (MODE2) == HImode)	\
+     || ((MODE1) == HImode && (MODE2) == QImode))
+*/       
+/* A C expression that is nonzero if it is desirable to choose
+   register allocation so as to avoid move instructions between a
+   value of mode MODE1 and a value of mode MODE2.
+
+   If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R,
+   MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1,
+   MODE2)' must be zero.  */
+
+
+enum reg_class {
+  NO_REGS,
+  PC_REG,			/* r0  - PC	*/
+  SP_REG,			/* r1  - SP	*/
+  STACK_REGS,			/* r2  - SR	*/
+  CG1_REG,			/* r2  - CG1	*/
+  CG2_REG,			/* r3  - CG2	*/
+  CG_REGS,			/* r2, r3	*/
+  GENERAL_REGS,			/* r4 - r15 	*/
+  POINTER_REGS,
+  FFOUR_REG,
+  ALL_REGS, LIM_REG_CLASSES
+};
+  
+/* An enumeral type that must be defined with all the register class
+   names as enumeral values.  `NO_REGS' must be first.  `ALL_REGS'
+   must be the last register class, followed by one more enumeral
+   value, `LIM_REG_CLASSES', which is not a register class but rather
+   tells how many classes there are.
+
+   Each register class has a number, which is the value of casting
+   the class name to type `int'.  The number serves as an index in
+   many of the tables described below.  */
+
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+/* The number of distinct register classes, defined as follows:
+   #define N_REG_CLASSES (int) LIM_REG_CLASSES  */
+
+#define REG_CLASS_NAMES {		\
+		"NO_REGS",		\
+		"PC_REG",		\
+		"SP_REG",		\
+		"STACK_REGS",		\
+		"CG1_REG",		\
+		"CG2_REG",		\
+		"CG_REGS",		\
+		"GENERAL_REGS",		\
+		"POINTER_REGS",		\
+		"FFOUR_REG",		\
+		"ALL_REGS" 		\
+}
+
+/* An initializer containing the names of the register classes as C
+   string constants.  These names are used in writing some of the
+   debugging dumps.  */
+
+#define REG_CLASS_CONTENTS {				\
+  {0x00000000ul},	/* NO_REGS	*/	\
+  {0x00000001ul},	/* PC_REG 	*/	\
+  {0x00000002ul},	/* SP_REG 	*/	\
+  {0x00000004ul},	/* r2		*/	\
+  {0x00000004ul},	/* r2		*/	\
+  {0x00000008ul},	/* r3		*/	\
+  {0x0000000cul},	/* r2,r3	*/	\
+  {0x0001fff2ul}, /* r4 - r15,r1  */      \
+  {0x0001fff2ul}, /* r4 - r15,r1  */      \
+  {0x0001fff0ul},	/* r4 - r15	*/	\
+  {0x0001fffful}	/* ALL_REGS */		\
+}
+/* An initializer containing the contents of the register classes, as
+   integers which are bit masks.  The Nth integer specifies the
+   contents of class N.  The way the integer MASK is interpreted is
+   that register R is in the class if `MASK & (1 << R)' is 1.
+
+   When the machine has more than 32 registers, an integer does not
+   suffice.  Then the integers are replaced by sub-initializers,
+   braced groupings containing several integers.  Each
+   sub-initializer must be suitable as an initializer for the type
+   `HARD_REG_SET' which is defined in `hard-reg-set.h'.  */
+
+
+enum reg_class msp430_regno_reg_class PARAMS ((int));
+#define REGNO_REG_CLASS(R) msp430_regno_reg_class(R)
+/* A C expression whose value is a register class containing hard
+   register REGNO.  In general there is more than one such class;
+   choose a class which is "minimal", meaning that no smaller class
+   also contains the register.  */
+
+#define BASE_REG_CLASS POINTER_REGS
+/* A macro whose definition is the name of the class to which a valid
+   base register must belong.  A base register is one used in an
+   address which is the register value plus a displacement.  */
+
+#define INDEX_REG_CLASS NO_REGS
+/* A macro whose definition is the name of the class to which a valid
+   index register must belong.  An index register is one used in an
+   address where its value is either multiplied by a scale factor or
+   added to another register (as well as added to a displacement).  */
+
+#define REG_CLASS_FROM_LETTER(C) msp430_reg_class_from_letter(C)
+/* A C expression which defines the machine-dependent operand
+   constraint letters for register classes.  If CHAR is such a
+   letter, the value should be the register class corresponding to
+   it.  Otherwise, the value should be `NO_REGS'.  The register
+   letter `r', corresponding to class `GENERAL_REGS', will not be
+   passed to this macro; you do not need to handle it.  */
+
+#define REGNO_OK_FOR_BASE_P(r) msp430_regno_ok_for_base_p(r) 
+					
+/* A C expression which is nonzero if register number NUM is suitable
+   for use as a base register in operand addresses.  It may be either
+   a suitable hard register or a pseudo register that has been
+   allocated such a hard register.  */
+
+/* #define REGNO_MODE_OK_FOR_BASE_P(r, m) 
+   A C expression that is just like `REGNO_OK_FOR_BASE_P', except that
+   that expression may examine the mode of the memory reference in
+   MODE.  You should define this macro if the mode of the memory
+   reference affects whether a register may be used as a base
+   register.  If you define this macro, the compiler will use it
+   instead of `REGNO_OK_FOR_BASE_P'.  */
+
+#define REGNO_OK_FOR_INDEX_P(NUM) 0
+/* A C expression which is nonzero if register number NUM is suitable
+   for use as an index register in operand addresses.  It may be
+   either a suitable hard register or a pseudo register that has been
+   allocated such a hard register.
+
+   The difference between an index register and a base register is
+   that the index register may be scaled.  If an address involves the
+   sum of two registers, neither one of them scaled, then either one
+   may be labeled the "base" and the other the "index"; but whichever
+   labeling is used must fit the machine's constraints of which
+   registers may serve in each capacity.  The compiler will try both
+   labelings, looking for one that is valid, and will reload one or
+   both registers only if neither labeling works.  */
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) FFOUR_REG
+
+/*
+referred_reload_class(X,CLASS)
+ A C expression that places additional restrictions on the register
+   class to use when it is necessary to copy value X into a register
+   in class CLASS.  The value is a register class; perhaps CLASS, or
+   perhaps another, smaller class.  On many machines, the following
+   definition is safe:
+
+   #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
+
+   Sometimes returning a more restrictive class makes better code.
+   For example, on the 68000, when X is an integer constant that is
+   in range for a `moveq' instruction, the value of this macro is
+   always `DATA_REGS' as long as CLASS includes the data registers.
+   Requiring a data register guarantees that a `moveq' will be used.
+
+   If X is a `const_double', by returning `NO_REGS' you can force X
+   into a memory constant.  This is useful on certain machines where
+   immediate floating values cannot be loaded into certain kinds of
+   registers.  */
+/* `PREFERRED_OUTPUT_RELOAD_CLASS (X, CLASS)'
+   Like `PREFERRED_RELOAD_CLASS', but for output reloads instead of
+   input reloads.  If you don't define this macro, the default is to
+   use CLASS, unchanged.  */
+
+/* `LIMIT_RELOAD_CLASS (MODE, CLASS)'
+   A C expression that places additional restrictions on the register
+   class to use when it is necessary to be able to hold a value of
+   mode MODE in a reload register for which class CLASS would
+   ordinarily be used.
+
+   Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when
+   there are certain modes that simply can't go in certain reload
+   classes.
+
+   The value is a register class; perhaps CLASS, or perhaps another,
+   smaller class.
+
+   Don't define this macro unless the target machine has limitations
+   which require the macro to do something nontrivial.  */
+
+/*
+#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) GENERAL_REGS
+
+
+#define  SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) GENERAL_REGS
+
+
+   `SECONDARY_RELOAD_CLASS (CLASS, MODE, X)'
+   `SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X)'
+   Many machines have some registers that cannot be copied directly
+   to or from memory or even from other types of registers.  An
+   example is the `MQ' register, which on most machines, can only be
+   copied to or from general registers, but not memory.  Some
+   machines allow copying all registers to and from memory, but
+   require a scratch register for stores to some memory locations
+   (e.g., those with symbolic address on the RT, and those with
+   certain symbolic address on the Sparc when compiling PIC).  In
+   some cases, both an intermediate and a scratch register are
+   required.
+
+   You should define these macros to indicate to the reload phase
+   that it may need to allocate at least one register for a reload in
+   addition to the register to contain the data.  Specifically, if
+   copying X to a register CLASS in MODE requires an intermediate
+   register, you should define `SECONDARY_INPUT_RELOAD_CLASS' to
+   return the largest register class all of whose registers can be
+   used as intermediate registers or scratch registers.
+
+   If copying a register CLASS in MODE to X requires an intermediate
+   or scratch register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be
+   defined to return the largest register class required.  If the
+   requirements for input and output reloads are the same, the macro
+   `SECONDARY_RELOAD_CLASS' should be used instead of defining both
+   macros identically.
+
+   The values returned by these macros are often `GENERAL_REGS'.
+   Return `NO_REGS' if no spare register is needed; i.e., if X can be
+   directly copied to or from a register of CLASS in MODE without
+   requiring a scratch register.  Do not define this macro if it
+   would always return `NO_REGS'.
+
+   If a scratch register is required (either with or without an
+   intermediate register), you should define patterns for
+   `reload_inM' or `reload_outM', as required (*note Standard
+   Names::..  These patterns, which will normally be implemented with
+   a `define_expand', should be similar to the `movM' patterns,
+   except that operand 2 is the scratch register.
+
+   Define constraints for the reload register and scratch register
+   that contain a single register class.  If the original reload
+   register (whose class is CLASS) can meet the constraint given in
+   the pattern, the value returned by these macros is used for the
+   class of the scratch register.  Otherwise, two additional reload
+   registers are required.  Their classes are obtained from the
+   constraints in the insn pattern.
+
+   X might be a pseudo-register or a `subreg' of a pseudo-register,
+   which could either be in a hard register or in memory.  Use
+   `true_regnum' to find out; it will return -1 if the pseudo is in
+   memory and the hard register number if it is in a register.
+
+   These macros should not be used in the case where a particular
+   class of registers can only be copied to memory and not to another
+   class of registers.  In that case, secondary reload registers are
+   not needed and would not be helpful.  Instead, a stack location
+   must be used to perform the copy and the `movM' pattern should use
+   memory as a intermediate storage.  This case often occurs between
+   floating-point and general registers.  */
+
+/* `SECONDARY_MEMORY_NEEDED (CLASS1, CLASS2, M)'
+   Certain machines have the property that some registers cannot be
+   copied to some other registers without using memory.  Define this
+   macro on those machines to be a C expression that is non-zero if
+   objects of mode M in registers of CLASS1 can only be copied to
+   registers of class CLASS2 by storing a register of CLASS1 into
+   memory and loading that memory location into a register of CLASS2.
+
+   Do not define this macro if its value would always be zero.
+
+   `SECONDARY_MEMORY_NEEDED_RTX (MODE)'
+   Normally when `SECONDARY_MEMORY_NEEDED' is defined, the compiler
+   allocates a stack slot for a memory location needed for register
+   copies.  If this macro is defined, the compiler instead uses the
+   memory location defined by this macro.
+
+   Do not define this macro if you do not define
+   `SECONDARY_MEMORY_NEEDED'.  */
+
+#define SMALL_REGISTER_CLASSES 1
+/* Normally the compiler avoids choosing registers that have been
+   explicitly mentioned in the rtl as spill registers (these
+   registers are normally those used to pass parameters and return
+   values).  However, some machines have so few registers of certain
+   classes that there would not be enough registers to use as spill
+   registers if this were done.
+
+   Define `SMALL_REGISTER_CLASSES' to be an expression with a non-zero
+   value on these machines.  When this macro has a non-zero value, the
+   compiler allows registers explicitly used in the rtl to be used as
+   spill registers but avoids extending the lifetime of these
+   registers.
+
+   It is always safe to define this macro with a non-zero value, but
+   if you unnecessarily define it, you will reduce the amount of
+   optimizations that can be performed in some cases.  If you do not
+   define this macro with a non-zero value when it is required, the
+   compiler will run out of spill registers and print a fatal error
+   message.  For most machines, you should not define this macro at
+   all.  */
+
+/*
+#define CLASS_LIKELY_SPILLED_P(CLASS) \
+	( (CLASS) != ALL_REGS && (CLASS) != GENERAL_REGS)
+ A C expression whose value is nonzero if pseudos that have been
+   assigned to registers of class CLASS would likely be spilled
+   because registers of CLASS are needed for spill registers.
+
+   The default value of this macro returns 1 if CLASS has exactly one
+   register and zero otherwise.  On most machines, this default
+   should be used.  Only define this macro to some other expression
+   if pseudo allocated by `local-alloc.c' end up in memory because
+   their hard registers were needed for spill registers.  If this
+   macro returns nonzero for those classes, those pseudos will only
+   be allocated by `global.c', which knows how to reallocate the
+   pseudo to another register.  If there would not be another
+   register available for reallocation, you should not change the
+   definition of this macro since the only effect of such a
+   definition would be to slow down register allocation.  */
+
+#define CLASS_MAX_NREGS(CLASS, MODE)	\
+	((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+/* A C expression for the maximum number of consecutive registers of
+   class CLASS needed to hold a value of mode MODE.
+
+   This is closely related to the macro `HARD_REGNO_NREGS'.  In fact,
+   the value of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be
+   the maximum value of `HARD_REGNO_NREGS (REGNO, MODE)' for all
+   REGNO values in the class CLASS.
+
+   This macro helps control the handling of multiple-word values in
+   the reload pass.  */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C)				\
+  ((C) == 'I' ? (VALUE) >= -32767 && (VALUE) <= 32767 :		\
+   (C) == 'J' ? (VALUE) <= 0 && (VALUE) >= -32767:		\
+   (C) == 'K' ? (VALUE) >= 0 && (VALUE) <= 32767 :		\
+   (C) == 'L' ? (VALUE) >= 0 && (VALUE) <= 0xff	 :		\
+   (C) == 'M' ? (VALUE) >= 0x10 && (VALUE) <= 0xff :		\
+   (C) == 'N' ? (VALUE) >= 0x100 && (VALUE) <= 0x1ff :		\
+   (C) == 'O' ? (VALUE)&1:					\
+   (C) == 'P' ? ((VALUE)==-1||(VALUE)==1||(VALUE)==2||(VALUE)==4||(VALUE)==8 ||(VALUE)==0) : 0)
+/* A C expression that defines the machine-dependent operand
+   constraint letters (`I', `J', `K', ... `P') that specify
+   particular ranges of integer values.  If C is one of those
+   letters, the expression should check that VALUE, an integer, is in
+   the appropriate range and return 1 if so, 0 otherwise.  If C is
+   not one of those letters, the value should be 0 regardless of
+   VALUE.  */
+
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+  ((C) == 'G' ? (VALUE) == CONST0_RTX (SFmode)	\
+   : 0)
+/* `CONST_DOUBLE_OK_FOR_LETTER_P (VALUE, C)'
+   A C expression that defines the machine-dependent operand
+   constraint letters that specify particular ranges of
+   `const_double' values (`G' or `H').
+
+   If C is one of those letters, the expression should check that
+   VALUE, an RTX of code `const_double', is in the appropriate range
+   and return 1 if so, 0 otherwise.  If C is not one of those
+   letters, the value should be 0 regardless of VALUE.
+
+   `const_double' is used for all floating-point constants and for
+   `DImode' fixed-point constants.  A given letter can accept either
+   or both kinds of values.  It can use `GET_MODE' to distinguish
+   between these kinds.  */
+
+#define EXTRA_CONSTRAINT(x, c) extra_constraint(x, c)
+/* A C expression that defines the optional machine-dependent
+   constraint letters (``Q', `R', `S', `T', `U') that can'
+   be used to segregate specific types of operands, usually memory
+   references, for the target machine.  Normally this macro will not
+   be defined.  If it is required for a particular target machine, it
+   should return 1 if VALUE corresponds to the operand type
+   represented by the constraint letter C.  If C is not defined as an
+   extra constraint, the value returned should be 0 regardless of
+   VALUE.
+
+   For example, on the ROMP, load instructions cannot have their
+   output in r0 if the memory reference contains a symbolic address.
+   Constraint letter `Q' is defined as representing a memory address
+   that does *not* contain a symbolic address.  An alternative is
+   specified with a `Q' constraint on the input and `r' on the
+   output.  The next alternative specifies `m' on the input and a
+   register class that does not include r0 on the output.  */
+
+/*  This is an undocumented variable which describes
+    how GCC will push a data */
+#define STACK_PUSH_CODE PRE_DEC
+
+#define PUSH_ARGS !TARGET_ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS TARGET_ACCUMULATE_OUTGOING_ARGS
+
+#define STACK_GROWS_DOWNWARD
+/* Define this macro if pushing a word onto the stack moves the stack
+   pointer to a smaller address.
+
+   When we say, "define this macro if ...," it means that the
+   compiler checks this macro only with `#ifdef' so the precise
+   definition used does not matter.  */
+
+#define STARTING_FRAME_OFFSET 0
+/* Offset from the frame pointer to the first local variable slot to
+   be allocated.
+
+   If `FRAME_GROWS_DOWNWARD', find the next slot's offset by
+   subtracting the first slot's length from `STARTING_FRAME_OFFSET'.
+   Otherwise, it is found by adding the length of the first slot to
+   the value `STARTING_FRAME_OFFSET'.  */
+
+#define STACK_POINTER_OFFSET 0
+/* Offset from the stack pointer register to the first location at
+   which outgoing arguments are placed.  If not specified, the
+   default value of zero is used.  This is the proper value for most
+   machines.
+
+   If `ARGS_GROW_DOWNWARD', this is the offset to the location above
+   the first location at which outgoing arguments are placed.  */
+
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+/* Offset from the argument pointer register to the first argument's
+   address.  On some machines it may depend on the data type of the
+   function.
+
+   If `ARGS_GROW_DOWNWARD', this is the offset to the location above
+   the first argument's address.  */
+
+/* `STACK_DYNAMIC_OFFSET (FUNDECL)'
+   Offset from the stack pointer register to an item dynamically
+   allocated on the stack, e.g., by `alloca'.
+
+   The default value for this macro is `STACK_POINTER_OFFSET' plus the
+   length of the outgoing arguments.  The default is correct for most
+   machines.  See `function.c' for details.  */
+
+#define STACK_BOUNDARY 16
+/* Define this macro if there is a guaranteed alignment for the stack
+   pointer on this machine.  The definition is a C expression for the
+   desired alignment (measured in bits).  This value is used as a
+   default if PREFERRED_STACK_BOUNDARY is not defined.  */
+
+#define STACK_POINTER_REGNUM 1
+/* The register number of the stack pointer register, which must also
+   be a fixed register according to `FIXED_REGISTERS'.  On most
+   machines, the hardware determines which register this is.  */
+
+#define FRAME_POINTER_REGNUM 4
+/* The register number of the frame pointer register, which is used to
+   access automatic variables in the stack frame.  On some machines,
+   the hardware determines which register this is.  On other
+   machines, you can choose any register you wish for this purpose.  */
+
+/* We use a pseudo-register called "argp" to represent argument pointer.
+	As the register is marked as fixed, it will always be eliminated
+	(replaced by sp + offset).*/
+#define ARG_POINTER_REGNUM 16
+/* The register number of the arg pointer register, which is used to
+   access the function's argument list.  On some machines, this is
+   the same as the frame pointer register.  On some machines, the
+   hardware determines which register this is.  On other machines,
+   you can choose any register you wish for this purpose.  If this is
+   not the same register as the frame pointer register, then you must
+   mark it as a fixed register according to `FIXED_REGISTERS', or
+   arrange to be able to eliminate it (*note Elimination::.).  */
+
+#define STATIC_CHAIN_REGNUM 6
+/* Register numbers used for passing a function's static chain
+   pointer.  If register windows are used, the register number as
+   seen by the called function is `STATIC_CHAIN_INCOMING_REGNUM',
+   while the register number as seen by the calling function is
+   `STATIC_CHAIN_REGNUM'.  If these registers are the same,
+   `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
+
+   The static chain register need not be a fixed register.
+
+   If the static chain is passed in memory, these macros should not be
+   defined; instead, the next two macros should be defined.  */
+
+#define FRAME_POINTER_REQUIRED   frame_pointer_required_p()
+
+/*
+ A C expression which is nonzero if a function must have and use a
+   frame pointer.  This expression is evaluated  in the reload pass.
+   If its value is nonzero the function will have a frame pointer.
+
+   The expression can in principle examine the current function and
+   decide according to the facts, but on most machines the constant 0
+   or the constant 1 suffices.  Use 0 when the machine allows code to
+   be generated with no frame pointer, and doing so saves some time
+   or space.  Use 1 when there is no possible advantage to avoiding a
+   frame pointer.
+
+   In certain cases, the compiler does not know how to produce valid
+   code without a frame pointer.  The compiler recognizes those cases
+   and automatically gives the function a frame pointer regardless of
+   what `FRAME_POINTER_REQUIRED' says.  You don't need to worry about
+   them.
+
+   In a function that does not require a frame pointer, the frame
+   pointer register can be allocated for ordinary usage, unless you
+   mark it as a fixed register.  See `FIXED_REGISTERS' for more
+   information.  */
+
+#define ELIMINABLE_REGS {			\
+   {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+   {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+}
+/* If defined, this macro specifies a table of register pairs used to
+   eliminate unneeded registers that point into the stack frame.  If
+   it is not defined, the only elimination attempted by the compiler
+   is to replace references to the frame pointer with references to
+   the stack pointer.
+
+   The definition of this macro is a list of structure
+   initializations, each of which specifies an original and
+   replacement register.
+
+   On some machines, the position of the argument pointer is not
+   known until the compilation is completed.  In such a case, a
+   separate hard register must be used for the argument pointer.
+   This register can be eliminated by replacing it with either the
+   frame pointer or the argument pointer, depending on whether or not
+   the frame pointer has been eliminated.
+
+   In this case, you might specify:
+   #define ELIMINABLE_REGS  \
+   {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+   {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+
+   Note that the elimination of the argument pointer with the stack
+   pointer is specified first since that is the preferred elimination.  */
+
+#define CAN_ELIMINATE(FROM, TO) 1
+/*#define CAN_ELIMINATE(FROM, TO) (((FROM) == ARG_POINTER_REGNUM		   \
+				  && (TO) == FRAME_POINTER_REGNUM)	   \
+				 || (((FROM) == FRAME_POINTER_REGNUM)	   \
+				     && ! FRAME_POINTER_REQUIRED	   \
+				     ))*/
+/* A C expression that returns non-zero if the compiler is allowed to
+   try to replace register number FROM-REG with register number
+   TO-REG.  This macro need only be defined if `ELIMINABLE_REGS' is
+   defined, and will usually be the constant 1, since most of the
+   cases preventing register elimination are things that the compiler
+   already knows about.  */
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)			\
+     OFFSET = initial_elimination_offset (FROM, TO)
+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It
+   specifies the initial difference between the specified pair of
+   registers.  This macro must be defined if `ELIMINABLE_REGS' is
+   defined.  */
+/*
+#define RETURN_ADDR_RTX(count, x) \
+  gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (tem, 1)))
+*/
+#define PUSH_ROUNDING(NPUSHED) ((NPUSHED+1) & ~1)
+/* A C expression that is the number of bytes actually pushed onto the
+   stack when an instruction attempts to push NPUSHED bytes.
+
+   If the target machine does not have a push instruction, do not
+   define this macro.  That directs GNU CC to use an alternate
+   strategy: to allocate the entire argument block and then store the
+   arguments into it.
+
+   On some machines, the definition
+
+   #define PUSH_ROUNDING(BYTES) (BYTES)
+
+   will suffice.  But on other machines, instructions that appear to
+   push one byte actually push two bytes in an attempt to maintain
+   alignment.  Then the definition should be
+
+   #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)  */
+
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
+/* A C expression that should indicate the number of bytes of its own
+   arguments that a function pops on returning, or 0 if the function
+   pops no arguments and the caller must therefore pop them all after
+   the function returns.
+
+   FUNDECL is a C variable whose value is a tree node that describes
+   the function in question.  Normally it is a node of type
+   `FUNCTION_DECL' that describes the declaration of the function.
+   From this you can obtain the DECL_MACHINE_ATTRIBUTES of the
+   function.
+
+   FUNTYPE is a C variable whose value is a tree node that describes
+   the function in question.  Normally it is a node of type
+   `FUNCTION_TYPE' that describes the data type of the function.
+   From this it is possible to obtain the data types of the value and
+   arguments (if known).
+
+   When a call to a library function is being considered, FUNDECL
+   will contain an identifier node for the library function.  Thus, if
+   you need to distinguish among various library functions, you can
+   do so by their names.  Note that "library function" in this
+   context means a function used to perform arithmetic, whose name is
+   known specially in the compiler and was not mentioned in the C
+   code being compiled.
+
+   STACK-SIZE is the number of bytes of arguments passed on the
+   stack.  If a variable number of bytes is passed, it is zero, and
+   argument popping will always be the responsibility of the calling
+   function.
+
+   On the Vax, all functions always pop their arguments, so the
+   definition of this macro is STACK-SIZE.  On the 68000, using the
+   standard calling convention, no functions pop their arguments, so
+   the value of the macro is always 0 in this case.  But an
+   alternative calling convention is available in which functions
+   that take a fixed number of arguments pop them but other functions
+   (such as `printf') pop nothing (the caller pops all).  When this
+   convention is in use, FUNTYPE is examined to determine whether a
+   function takes a fixed number of arguments.  */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+(function_arg (&(CUM), MODE, TYPE, NAMED))
+
+/*
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+(function_incoming_arg (&(CUM), MODE, TYPE, NAMED))
+*/
+/* A C expression that controls whether a function argument is passed
+   in a register, and which register.
+
+   The arguments are CUM, which summarizes all the previous
+   arguments; MODE, the machine mode of the argument; TYPE, the data
+   type of the argument as a tree node or 0 if that is not known
+   (which happens for C support library functions); and NAMED, which
+   is 1 for an ordinary argument and 0 for nameless arguments that
+   correspond to `...' in the called function's prototype.
+
+   The value of the expression is usually either a `reg' RTX for the
+   hard register in which to pass the argument, or zero to pass the
+   argument on the stack.
+
+   For machines like the Vax and 68000, where normally all arguments
+   are pushed, zero suffices as a definition.
+
+   The value of the expression can also be a `parallel' RTX.  This is
+   used when an argument is passed in multiple locations.  The mode
+   of the of the `parallel' should be the mode of the entire
+   argument.  The `parallel' holds any number of `expr_list' pairs;
+   each one describes where part of the argument is passed.  In each
+   `expr_list', the first operand can be either a `reg' RTX for the
+   hard register in which to pass this part of the argument, or zero
+   to pass the argument on the stack.  If this operand is a `reg',
+   then the mode indicates how large this part of the argument is.
+   The second operand of the `expr_list' is a `const_int' which gives
+   the offset in bytes into the entire argument where this part
+   starts.
+
+   The usual way to make the ANSI library `stdarg.h' work on a machine
+   where some arguments are usually passed in registers, is to cause
+   nameless arguments to be passed on the stack instead.  This is done
+   by making `FUNCTION_ARG' return 0 whenever NAMED is 0.
+
+   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
+   definition of this macro to determine if this argument is of a
+   type that must be passed in the stack.  If `REG_PARM_STACK_SPACE'
+   is not defined and `FUNCTION_ARG' returns non-zero for such an
+   argument, the compiler will abort.  If `REG_PARM_STACK_SPACE' is
+   defined, the argument will be computed in the stack and then
+   loaded into a register.  */
+
+typedef struct msp430_args {
+  int nregs;			/* # registers available for passing */
+  int regno;			/* next available register number */
+} CUMULATIVE_ARGS;
+/* A C type for declaring a variable that is used as the first
+   argument of `FUNCTION_ARG' and other related values.  For some
+   target machines, the type `int' suffices and can hold the number
+   of bytes of argument so far.
+
+   There is no need to record in `CUMULATIVE_ARGS' anything about the
+   arguments that have been passed on the stack.  The compiler has
+   other variables to keep track of that.  For target machines on
+   which all arguments are passed on the stack, there is no need to
+   store anything in `CUMULATIVE_ARGS'; however, the data structure
+   must exist and should not be empty, so use `int'.  */
+
+
+/*
+	Correct DWARF2 unwind info generation requires prologue and epilogue
+	to be expanded into series of INSNs, so that DWARF2 info generator
+	can analyze those INSNs. Currently, prologue and epilogue are printed
+	to the output file as raw text, so, unwind info cannot be generated.
+*/
+
+#define DWARF2_UNWIND_INFO 1
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
+
+#define INCOMING_FRAME_SP_OFFSET ((cfun && cfun->machine->is_interrupt) ? 4 : 2)
+
+#define EPILOGUE_USES(REGNO) msp430_epilogue_uses(REGNO)
+   
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS ) \
+init_cumulative_args (&(CUM), FNTYPE, LIBNAME, FNDECL)
+
+#define  INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
+init_cumulative_incoming_args(&(CUM), FNTYPE, LIBNAME)
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
+  (function_arg_advance (&CUM, MODE, TYPE, NAMED))
+
+#define FUNCTION_ARG_REGNO_P(r) (r >= 12 && r <= 15)
+
+/* A C statement (sans semicolon) for initializing the variable CUM
+   for the state at the beginning of the argument list.  The variable
+   has type `CUMULATIVE_ARGS'.  The value of FNTYPE is the tree node
+   for the data type of the function which will receive the args, or 0
+   if the args are to a compiler support library function.  The value
+   of INDIRECT is nonzero when processing an indirect call, for
+   example a call through a function pointer.  The value of INDIRECT
+   is zero for a call to an explicitly named function, a library
+   function call, or when `INIT_CUMULATIVE_ARGS' is used to find
+   arguments for the function being compiled.
+   
+   When processing a call to a compiler support library function,
+   LIBNAME identifies which one.  It is a `symbol_ref' rtx which
+   contains the name of the function, as a string.  LIBNAME is 0 when
+   an ordinary C function call is being processed.  Thus, each time
+   this macro is called, either LIBNAME or FNTYPE is nonzero, but
+   never both of them at once.   */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
+  (function_arg_advance (&CUM, MODE, TYPE, NAMED))
+
+/* A C statement (sans semicolon) to update the summarizer variable
+   CUM to advance past an argument in the argument list.  The values
+   MODE, TYPE and NAMED describe that argument.  Once this is done,
+   the variable CUM is suitable for analyzing the *following*
+   argument with `FUNCTION_ARG', etc.
+   
+   This macro need not do anything if the argument in question was
+   passed on the stack.  The compiler knows how to track the amount
+   of stack space used for arguments without any special help. */
+
+#define FUNCTION_ARG_REGNO_P(r) (r >= 12 && r <= 15)
+/* A C expression that is nonzero if REGNO is the number of a hard
+   register in which function arguments are sometimes passed.  This
+   does *not* include implicit arguments such as the static chain and
+   the structure-value address.  On many machines, no registers can be
+   used for this purpose since all function arguments are pushed on
+   the stack.  */
+
+extern int msp430_reg_order[];
+
+#define RET_REGISTER  15 /* msp430_ret_register ()*/
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) msp430_function_value (VALTYPE, FUNC)
+/* A C expression to create an RTX representing the place where a
+   function returns a value of data type VALTYPE.  VALTYPE is a tree
+   node representing a data type.  Write `TYPE_MODE (VALTYPE)' to get
+   the machine mode used to represent that type.  On many machines,
+   only the mode is relevant.  (Actually, on most machines, scalar
+   values are returned in the same place regardless of mode).
+
+   The value of the expression is usually a `reg' RTX for the hard
+   register where the return value is stored.  The value can also be a
+   `parallel' RTX, if the return value is in multiple places.  See
+   `FUNCTION_ARG' for an explanation of the `parallel' form.
+
+   If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same
+   promotion rules specified in `PROMOTE_MODE' if VALTYPE is a scalar
+   type.
+
+   If the precise function being called is known, FUNC is a tree node
+   (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This
+   makes it possible to use a different value-returning convention
+   for specific functions when all their calls are known.
+
+   `FUNCTION_VALUE' is not used for return vales with aggregate data
+   types, because these are returned in another way.  See
+   `STRUCT_VALUE_REGNUM' and related macros, below.  */
+
+#define LIBCALL_VALUE(MODE)  msp430_libcall_value (MODE)
+/* A C expression to create an RTX representing the place where a
+   library function returns a value of mode MODE.  If the precise
+   function being called is known, FUNC is a tree node
+   (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This
+   makes it possible to use a different value-returning convention
+   for specific functions when all their calls are known.
+
+   Note that "library function" in this context means a compiler
+   support routine, used to perform arithmetic, whose name is known
+   specially by the compiler and was not mentioned in the C code being
+   compiled.
+
+   The definition of `LIBRARY_VALUE' need not be concerned aggregate
+   data types, because none of the library functions returns such
+   types.  */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == RET_REGISTER)
+/* A C expression that is nonzero if REGNO is the number of a hard
+   register in which the values of called function may come back.
+
+   A register whose use for returning values is limited to serving as
+   the second of a pair (for a value of type `double', say) need not
+   be recognized by this macro.  So for most machines, this definition
+   suffices:
+
+   #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+   If the machine has register windows, so that the caller and the
+   called function use different registers for the return value, this
+   macro should recognize only the caller's register numbers.  */
+
+#define RETURN_IN_MEMORY(TYPE) ((TYPE_MODE (TYPE) == BLKmode)	\
+				? int_size_in_bytes (TYPE) > 8	\
+				: 0)
+/* A C expression which can inhibit the returning of certain function
+   values in registers, based on the type of value.  A nonzero value
+   says to return the function value in memory, just as large
+   structures are always returned.  Here TYPE will be a C expression
+   of type `tree', representing the data type of the value.
+
+   Note that values of mode `BLKmode' must be explicitly handled by
+   this macro.  Also, the option `-fpcc-struct-return' takes effect
+   regardless of this macro.  On most systems, it is possible to
+   leave the macro undefined; this causes a default definition to be
+   used, whose value is the constant 1 for `BLKmode' values, and 0
+   otherwise.
+
+   Do not use this macro to indicate that structures and unions
+   should always be returned in memory.  You should instead use
+   `DEFAULT_PCC_STRUCT_RETURN' to indicate this.  */
+
+#define DEFAULT_PCC_STRUCT_RETURN 0
+/* Define this macro to be 1 if all structure and union return values
+   must be in memory.  Since this results in slower code, this should
+   be defined only if needed for compatibility with other compilers
+   or with an ABI.  If you define this macro to be 0, then the
+   conventions used for structure and union return values are decided
+   by the `RETURN_IN_MEMORY' macro.
+
+   If not defined, this defaults to the value 1.  */
+
+#define STRUCT_VALUE 0
+/* If the structure value address is not passed in a register, define
+   `STRUCT_VALUE' as an expression returning an RTX for the place
+   where the address is passed.  If it returns 0, the address is
+   passed as an "invisible" first argument.  */
+
+/*
+#define HAVE_PRE_INCREMENT 	1
+*/
+
+#define HAVE_POST_INCREMENT 	1
+
+/*
+#define HAVE_PRE_DECREMENT 	1
+#define HAVE_PRE_INCREMENT 	1
+#define HAVE_POST_DECREMENT 	1  
+*/
+/* Similar for other kinds of addressing.  */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/*
+(GET_CODE (X) == LABEL_REF 	\
+|| GET_CODE (X) == SYMBOL_REF   \
+|| GET_CODE (X) == CONST_INT    \
+|| GET_CODE (X) == CONST)
+*/
+
+/*
+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+do{CODE = msp430_canonicalize_comparison(CODE, &OP0, &OP1); }while(0)
+*/
+
+/* A C expression that is 1 if the RTX X is a constant which is a
+   valid address.  On most machines, this can be defined as
+   `CONSTANT_P (X)', but a few machines are more restrictive in which
+   constant addresses are supported.
+
+   `CONSTANT_P' accepts integer-values expressions whose values are
+   not explicitly known, such as `symbol_ref', `label_ref', and
+   `high' expressions and `const' arithmetic expressions, in addition
+   to `const_int' and `const_double' expressions.  */
+
+#define MAX_REGS_PER_ADDRESS 1
+/* A number, the maximum number of registers that can appear in a
+   valid memory address.  Note that it is up to you to specify a
+   value equal to the maximum number that `GO_IF_LEGITIMATE_ADDRESS'
+   would ever accept.  */
+
+#ifdef REG_OK_STRICT
+#  define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR)	\
+{							\
+  if (legitimate_address_p (mode, operand, 1))		\
+    goto ADDR;						\
+}
+#  else
+#  define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR)	\
+{							\
+  if (legitimate_address_p (mode, operand, 0))		\
+    goto ADDR;						\
+}
+#endif
+/* A C compound statement with a conditional `goto LABEL;' executed
+   if X (an RTX) is a legitimate memory address on the target machine
+   for a memory operand of mode MODE.
+
+   It usually pays to define several simpler macros to serve as
+   subroutines for this one.  Otherwise it may be too complicated to
+   understand.
+
+   This macro must exist in two variants: a strict variant and a
+   non-strict one.  The strict variant is used in the reload pass.  It
+   must be defined so that any pseudo-register that has not been
+   allocated a hard register is considered a memory reference.  In
+   contexts where some kind of register is required, a pseudo-register
+   with no hard register must be rejected.
+
+   The non-strict variant is used in other passes.  It must be
+   defined to accept all pseudo-registers in every context where some
+   kind of register is required.
+
+   Compiler source files that want to use the strict variant of this
+   macro define the macro `REG_OK_STRICT'.  You should use an `#ifdef
+   REG_OK_STRICT' conditional to define the strict variant in that
+   case and the non-strict variant otherwise.
+
+   Subroutines to check for acceptable registers for various purposes
+   (one for base registers, one for index registers, and so on) are
+   typically among the subroutines used to define
+   `GO_IF_LEGITIMATE_ADDRESS'.  Then only these subroutine macros
+   need have two variants; the higher levels of macros may be the
+   same whether strict or not.
+
+   Normally, constant addresses which are the sum of a `symbol_ref'
+   and an integer are stored inside a `const' RTX to mark them as
+   constant.  Therefore, there is no need to recognize such sums
+   specifically as legitimate addresses.  Normally you would simply
+   recognize any `const' as legitimate.
+
+   Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant
+   sums that are not marked with  `const'.  It assumes that a naked
+   `plus' indicates indexing.  If so, then you *must* reject such
+   naked constant sums as illegitimate addresses, so that none of
+   them will be given to `PRINT_OPERAND_ADDRESS'.
+
+   On some machines, whether a symbolic address is legitimate depends
+   on the section that the address refers to.  On these machines,
+   define the macro `ENCODE_SECTION_INFO' to store the information
+   into the `symbol_ref', and then check for it here.  When you see a
+   `const', you will have to look inside it to find the `symbol_ref'
+   in order to determine the section.  *Note Assembler Format::.
+
+   The best way to modify the name string is by adding text to the
+   beginning, with suitable punctuation to prevent any ambiguity.
+   Allocate the new name in `saveable_obstack'.  You will have to
+   modify `ASM_OUTPUT_LABELREF' to remove and decode the added text
+   and output the name accordingly, and define `STRIP_NAME_ENCODING'
+   to access the original name string.
+
+   You can check the information stored here into the `symbol_ref' in
+   the definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
+   `PRINT_OPERAND_ADDRESS'. */
+
+/* `REG_OK_FOR_BASE_P (X)'
+   A C expression that is nonzero if X (assumed to be a `reg' RTX) is
+   valid for use as a base register.  For hard registers, it should
+   always accept those which the hardware permits and reject the
+   others.  Whether the macro accepts or rejects pseudo registers
+   must be controlled by `REG_OK_STRICT' as described above.  This
+   usually requires two variant definitions, of which `REG_OK_STRICT'
+   controls the one actually used.  */
+
+#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
+  (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
+
+#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#ifdef REG_OK_STRICT
+#  define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X)
+#else
+#  define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NOSTRICT_P (X)
+#endif
+
+/* A C expression that is just like `REG_OK_FOR_BASE_P', except that
+   that expression may examine the mode of the memory reference in
+   MODE.  You should define this macro if the mode of the memory
+   reference affects whether a register may be used as a base
+   register.  If you define this macro, the compiler will use it
+   instead of `REG_OK_FOR_BASE_P'.  */
+
+
+#define REG_OK_FOR_INDEX_P(X) 0 /*( REGNO(X)!=3 && REGNO(X)!=2 &&REGNO(X)<=15) */
+/*   A C expression that is nonzero if X (assumed to be a `reg' RTX) is
+   valid for use as an index register.
+
+   The difference between an index register and a base register is
+   that the index register may be scaled.  If an address involves the
+   sum of two registers, neither one of them scaled, then either one
+   may be labeled the "base" and the other the "index"; but whichever
+   labeling is used must fit the machine's constraints of which
+   registers may serve in each capacity.  The compiler will try both
+   labelings, looking for one that is valid, and will reload one or
+   both registers only if neither labeling works.  */
+
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)				\
+GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
+
+/*{									\
+									\
+  (X) = legitimize_address (X, OLDX, MODE);				\
+  if (memory_address_p (MODE, X))					\
+    goto WIN;								\
+									\
+} */
+
+/* A C compound statement that attempts to replace X with a valid
+   memory address for an operand of mode MODE.  WIN will be a C
+   statement label elsewhere in the code; the macro definition may use
+
+   GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN);
+
+   to avoid further processing if the address has become legitimate.
+
+   X will always be the result of a call to `break_out_memory_refs',
+   and OLDX will be the operand that was given to that function to
+   produce X.
+
+   The code generated by this macro should not alter the substructure
+   of X.  If it transforms X into a more legitimate form, it should
+   assign X (which will always be a C variable) a new value.
+
+   It is not necessary for this macro to come up with a legitimate
+   address.  The compiler has standard ways of doing so in all cases.
+   In fact, it is safe for this macro to do nothing.  But often a
+   machine-dependent strategy can generate better code.  */
+
+/* A C compound statement that attempts to replace X, which is an
+   address that needs reloading, with a valid memory address for an
+   operand of mode MODE.  WIN will be a C statement label elsewhere
+   in the code.  It is not necessary to define this macro, but it
+   might be useful for performance reasons.
+
+   For example, on the i386, it is sometimes possible to use a single
+   reload register instead of two by reloading a sum of two pseudo
+   registers into a register.  On the other hand, for number of RISC
+   processors offsets are limited so that often an intermediate
+   address needs to be generated in order to address a stack slot.
+   By defining LEGITIMIZE_RELOAD_ADDRESS appropriately, the
+   intermediate addresses generated for adjacent some stack slots can
+   be made identical, and thus be shared.
+
+   *Note*: This macro should be used with caution.  It is necessary
+   to know something of how reload works in order to effectively use
+   this, and it is quite easy to produce macros that build in too
+   much knowledge of reload internals.
+
+   *Note*: This macro must be able to reload an address created by a
+   previous invocation of this macro.  If it fails to handle such
+   addresses then the compiler may generate incorrect code or abort.
+
+   The macro definition should use `push_reload' to indicate parts
+   that need reloading; OPNUM, TYPE and IND_LEVELS are usually
+   suitable to be passed unaltered to `push_reload'.
+
+   The code generated by this macro must not alter the substructure of
+   X.  If it transforms X into a more legitimate form, it should
+   assign X (which will always be a C variable) a new value.  This
+   also applies to parts that you change indirectly by calling
+   `push_reload'.
+
+   The macro definition may use `strict_memory_address_p' to test if
+   the address has become legitimate.
+
+   If you want to change only a part of X, one standard way of doing
+   this is to use `copy_rtx'.  Note, however, that is unshares only a
+   single level of rtl.  Thus, if the part to be changed is not at the
+   top level, you'll need to replace first the top leve It is not
+   necessary for this macro to come up with a legitimate address;
+   but often a machine-dependent strategy can generate better code.  */
+	
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)			\
+{}
+/* A C statement or compound statement with a conditional `goto
+   LABEL;' executed if memory address X (an RTX) can have different
+   meanings depending on the machine mode of the memory reference it
+   is used for or if the address is valid for some modes but not
+   others.
+
+   Autoincrement and autodecrement addresses typically have
+   mode-dependent effects because the amount of the increment or
+   decrement is the size of the operand being addressed.  Some
+   machines have other mode-dependent addresses.  Many RISC machines
+   have no mode-dependent addresses.
+
+   You may assume that ADDR is a valid address for the machine.  */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+/* A C expression that is nonzero if X is a legitimate constant for
+   an immediate operand on the target machine.  You can assume that X
+   satisfies `CONSTANT_P', so you need not check this.  In fact, `1'
+   is a suitable definition for this macro on machines where anything
+   `CONSTANT_P' is valid.  */
+
+/*#define CONST_COSTS(x,CODE,OUTER_CODE)		\
+    case CONST_INT:				\
+      if (OUTER_CODE == PLUS			\
+	  || OUTER_CODE == IOR			\
+	  || OUTER_CODE == AND			\
+	  || OUTER_CODE == MINUS		\
+	  || OUTER_CODE == SET			\
+	  || INTVAL (x) == 0			\
+          || INTVAL (x) == 1			\
+          || INTVAL (x) == 2			\
+          || INTVAL (x) == 4			\
+          || INTVAL (x) == 8			\
+          || INTVAL (x) == -1)			\
+        return 0;				\
+    case CONST:					\
+      return 0;					\
+    case LABEL_REF:				\
+      return 1;					\
+    case SYMBOL_REF:				\
+      return 2;					\
+    case CONST_DOUBLE:				\
+      return 4;*/
+
+/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
+   This can be used, for example, to indicate how costly a multiply
+   instruction is.  In writing this macro, you can use the construct
+   `COSTS_N_INSNS (N)' to specify a cost equal to N fast
+   instructions.  OUTER_CODE is the code of the expression in which X
+   is contained.
+
+   This macro is optional; do not define it if the default cost
+   assumptions are adequate for the target machine.  */
+
+#define REGISTER_MOVE_COST(MODE, FROM, TO) ((MODE)==QImode ? 1 :   \
+					    (MODE)==HImode ? 1 :   \
+					    (MODE)==SImode ? 2 :   \
+					    (MODE)==SFmode ? 2 : 4)
+
+/* A C expression for the cost of moving data from a register in class
+   FROM to one in class TO.  The classes are expressed using the
+   enumeration values such as `GENERAL_REGS'.  A value of 2 is the
+   default; other values are interpreted relative to that.
+
+   It is not required that the cost always equal 2 when FROM is the
+   same as TO; on some machines it is expensive to move between
+   registers if they are not general registers.
+
+   If reload sees an insn consisting of a single `set' between two
+   hard registers, and if `REGISTER_MOVE_COST' applied to their
+   classes returns a value of 2, reload does not check to ensure that
+   the constraints of the insn are met.  Setting a cost of other than
+   2 will allow reload to verify that the constraints are met.  You
+   should do this if the `movM' pattern's constraints do not allow
+   such copying.  */
+
+#define MEMORY_MOVE_COST(MODE,CLASS,IN) ((MODE)==QImode ? 2 :	\
+					 (MODE)==HImode ? 2 :	\
+					 (MODE)==SImode ? 4 :	\
+					 (MODE)==SFmode ? 4 : 8)
+/* A C expression for the cost of moving data of mode M between a
+   register and memory.  A value of 4 is the default; this cost is
+   relative to those in `REGISTER_MOVE_COST'.
+
+   If moving between registers and memory is more expensive than
+   between two registers, you should define this macro to express the
+   relative cost.  */
+
+#if GCC_VERSION_INT >= 0x440
+#define BRANCH_COST(a,b) 0
+#else
+#define BRANCH_COST 0
+#endif
+
+/* A C expression for the cost of a branch instruction.  A value of 1
+   is the default; other values are interpreted relative to that.
+
+   Here are additional macros which do not specify precise relative
+   costs, but only that certain actions are more expensive than GCC would
+   ordinarily expect.  */
+
+#define SLOW_BYTE_ACCESS 0
+/* Define this macro as a C expression which is nonzero if accessing
+   less than a word of memory (i.e. a `char' or a `short') is no
+   faster than accessing a word of memory, i.e., if such access
+   require more than one instruction or if there is no difference in
+   cost between byte and (aligned) word loads.
+
+   When this macro is not defined, the compiler will access a field by
+   finding the smallest containing object; when it is defined, a
+   fullword load will be used if alignment permits.  Unless bytes
+   accesses are faster than word accesses, using word accesses is
+   preferable since it may eliminate subsequent memory access if
+   subsequent accesses occur to other fields in the same word of the
+   structure, but to different bytes.
+
+   `SLOW_ZERO_EXTEND'
+   Define this macro if zero-extension (of a `char' or `short' to an
+   `int') can be done faster if the destination is a register that is
+   known to be zero.
+
+   If you define this macro, you must have instruction patterns that
+   recognize RTL structures like this:
+
+   (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...)
+
+   and likewise for `HImode'.
+
+   `SLOW_UNALIGNED_ACCESS'
+   Define this macro to be the value 1 if unaligned accesses have a
+   cost many times greater than aligned accesses, for example if they
+   are emulated in a trap handler.
+
+   When this macro is non-zero, the compiler will act as if
+   `STRICT_ALIGNMENT' were non-zero when generating code for block
+   moves.  This can cause significantly more instructions to be
+   produced.  Therefore, do not set this macro non-zero if unaligned
+   accesses only add a cycle or two to the time for a memory access.
+
+   If the value of this macro is always zero, it need not be defined.
+
+   `DONT_REDUCE_ADDR'
+   Define this macro to inhibit strength reduction of memory
+   addresses.  (On some machines, such strength reduction seems to do
+   harm rather than good.)
+
+   `MOVE_RATIO'
+   The number of scalar move insns which should be generated instead
+   of a string move insn or a library call.  Increasing the value
+   will always make code faster, but eventually incurs high cost in
+   increased code size.
+
+   If you don't define this, a reasonable default is used.  */
+
+#define NO_FUNCTION_CSE
+/* Define this macro if it is as good or better to call a constant
+   function address than to call an address kept in a register.  */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+/* A C expression whose value is a string containing the assembler
+   operation that should precede instructions and read-only data.
+   Normally `"\t.text"' is right.  */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+/* A C expression whose value is a string containing the assembler
+   operation to identify the following data as writable initialized
+   data.  Normally `"\t.data"' is right.  */
+
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
+
+/*#define EXTRA_SECTIONS in_bootloader, in_infomem*/
+/* A list of names for sections other than the standard two, which are
+   `in_text' and `in_data'.  You need not define this macro on a
+   system with no other sections (that GCC needs to use).  */
+
+#if 0
+#define EXTRA_SECTION_FUNCTIONS						      \
+									      \
+void									      \
+bootloader_section (void)							\
+{									      \
+  if (in_section != in_bootloader)						\
+    {									      \
+      fprintf (asm_out_file,						      \
+	       "\t.section .bootloader, \"ax\", @progbits\n");	      		\
+      /* Should already be aligned, this is just to be safe if it isn't.  */  \
+      fprintf (asm_out_file, "\t.p2align 1\n");				      \
+      in_section = in_bootloader;						\
+    }									      \
+}										\
+									      \
+void									      \
+infomem_section (void)							      \
+{									      \
+  if (in_section != in_infomem)						      \
+    {									      \
+      fprintf (asm_out_file,						      \
+	       "\t.section .infomem, \"a\", @progbits\n");	      		\
+      /* Should already be aligned, this is just to be safe if it isn't.  */  \
+      fprintf (asm_out_file, "\t.p2align 1\n");				      \
+      in_section = in_infomem;						      \
+    }									      \
+}
+#endif
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+   There are no shared libraries on this target, and these sections are
+   placed in the read-only program memory, so they are not writable.  */
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\t.global\t__do_global_ctors\n\t.section .ctors,\"a\",@progbits"
+
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\t.global\t__do_global_dtors\n\t.section .dtors,\"a\",@progbits"
+
+#define TARGET_ASM_CONSTRUCTOR default_ctor_section_asm_out_constructor
+
+#define TARGET_ASM_DESTRUCTOR default_dtor_section_asm_out_destructor
+
+/* `EXTRA_SECTION_FUNCTIONS'
+   One or more functions to be defined in `varasm.c'.  These
+   functions should do jobs analogous to those of `text_section' and
+   `data_section', for your additional sections.  Do not define this
+   macro if you do not define `EXTRA_SECTIONS'.  */
+
+/*
+#define READONLY_DATA_SECTION data_section
+   On most machines, read-only variables, constants, and jump tables
+   are placed in the text section.  If this is not the case on your
+   machine, this macro should be defined to be the name of a function
+   (either `data_section' or a function defined in `EXTRA_SECTIONS')
+   that switches to the section to be used for read-only items.
+
+   If these items should be placed in the text section, this macro
+   should not be defined.  */
+
+/* `SELECT_SECTION (EXP, RELOC)'
+   A C statement or statements to switch to the appropriate section
+   for output of EXP.  You can assume that EXP is either a `VAR_DECL'
+   node or a constant of some sort.  RELOC indicates whether the
+   initial value of EXP requires link-time relocations.  Select the
+   section by calling `text_section' or one of the alternatives for
+   other sections.
+
+   Do not define this macro if you put all read-only variables and
+   constants in the read-only data section (usually the text section).  */
+
+/* `SELECT_RTX_SECTION (MODE, RTX)'
+   A C statement or statements to switch to the appropriate section
+   for output of RTX in mode MODE.  You can assume that RTX is some
+   kind of constant in RTL.  The argument MODE is redundant except in
+   the case of a `const_int' rtx.  Select the section by calling
+   `text_section' or one of the alternatives for other sections.
+
+   Do not define this macro if you put all constants in the read-only
+   data section.  */
+
+#define JUMP_TABLES_IN_TEXT_SECTION 0
+/* Define this macro if jump tables (for `tablejump' insns) should be
+   output in the text section, along with the assembler instructions.
+   Otherwise, the readonly data section is used.
+
+   This macro is irrelevant if there is no separate readonly data
+   section.  */
+
+/* ???? 
+#define ENCODE_SECTION_INFO(DECL)  encode_section_info(DECL)
+   Define this macro if references to a symbol must be treated
+   differently depending on something about the variable or function
+   named by the symbol (such as what section it is in).
+
+   The macro definition, if any, is executed immediately after the
+   rtl for DECL has been created and stored in `DECL_RTL (DECL)'.
+   The value of the rtl will be a `mem' whose address is a
+   `symbol_ref'.
+
+   The usual thing for this macro to do is to record a flag in the
+   `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified
+   name string in the `symbol_ref' (if one bit is not enough
+   information).  */
+
+
+/* `UNIQUE_SECTION_P (DECL)'
+   A C expression which evaluates to true if DECL should be placed
+   into a unique section for some target-specific reason.  If you do
+   not define this macro, the default is `0'.  Note that the flag
+   `-ffunction-sections' will also cause functions to be placed into
+   unique sections.  */
+
+#define ASM_COMMENT_START " ; "
+/* A C string constant describing how to begin a comment in the target
+   assembler language.  The compiler assumes that the comment will
+   end at the end of the line.  */
+
+#define ASM_APP_ON "/* #APP */\n"
+/* A C string constant for text to be output before each `asm'
+   statement or group of consecutive ones.  Normally this is
+   `"#APP"', which is a comment that has no effect on most assemblers
+   but tells the GNU assembler that it must check the lines that
+   follow for all valid assembler constructs.  */
+
+#define ASM_APP_OFF "/* #NOAPP */\n"
+/* A C string constant for text to be output after each `asm'
+   statement or group of consecutive ones.  Normally this is
+   `"#NO_APP"', which tells the GNU assembler to resume making the
+   time-saving assumptions that are valid for ordinary compiler
+   output.  */
+
+#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) fprintf (STREAM, "no double float %.20e\n", VALUE)
+#define ASM_OUTPUT_FLOAT(STREAM, VALUE) asm_output_float (STREAM, VALUE)
+/* `ASM_OUTPUT_LONG_DOUBLE (STREAM, VALUE)'
+   `ASM_OUTPUT_THREE_QUARTER_FLOAT (STREAM, VALUE)'
+   `ASM_OUTPUT_SHORT_FLOAT (STREAM, VALUE)'
+   `ASM_OUTPUT_BYTE_FLOAT (STREAM, VALUE)'
+   A C statement to output to the stdio stream STREAM an assembler
+   instruction to assemble a floating-point constant of `TFmode',
+   `DFmode', `SFmode', `TQFmode', `HFmode', or `QFmode',
+   respectively, whose value is VALUE.  VALUE will be a C expression
+   of type `REAL_VALUE_TYPE'.  Macros such as
+   `REAL_VALUE_TO_TARGET_DOUBLE' are useful for writing these
+   definitions.  */
+
+
+#define ASM_OUTPUT_INT(FILE, VALUE)			\
+ ( fprintf (FILE, "\t.long "),				\
+   output_addr_const (FILE, (VALUE)),			\
+   fputs ("\n", FILE))
+
+ /* Likewise for `short' and `char' constants.   */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) asm_output_short(FILE,VALUE)
+#define ASM_OUTPUT_CHAR(FILE,VALUE) asm_output_char(FILE,VALUE)
+
+/* `ASM_OUTPUT_QUADRUPLE_INT (STREAM, EXP)'
+   A C statement to output to the stdio stream STREAM an assembler
+   instruction to assemble an integer of 16, 8, 4, 2 or 1 bytes,
+   respectively, whose value is VALUE.  The argument EXP will be an
+   RTL expression which represents a constant value.  Use
+   `output_addr_const (STREAM, EXP)' to output this value as an
+   assembler expression.
+
+   For sizes larger than `UNITS_PER_WORD', if the action of a macro
+   would be identical to repeatedly calling the macro corresponding to
+   a size of `UNITS_PER_WORD', once for each word, you need not define
+   the macro.  */
+
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) asm_output_byte (FILE,VALUE)
+/* A C statement to output to the stdio stream STREAM an assembler
+   instruction to assemble a single byte containing the number VALUE.  */
+
+#define ASM_BYTE_OP "\t.byte "
+/* A C string constant giving the pseudo-op to use for a sequence of
+   single-byte constants.  If this macro is not defined, the default
+   is `"\t.byte\t"'.  */
+
+#define ASM_OUTPUT_ASCII(FILE, P, SIZE)	 gas_output_ascii (FILE,P,SIZE)
+/* `ASM_OUTPUT_ASCII (STREAM, PTR, LEN)'
+   output_ascii (FILE, P, SIZE)
+   A C statement to output to the stdio stream STREAM an assembler
+   instruction to assemble a string constant containing the LEN bytes
+   at PTR.  PTR will be a C expression of type `char *' and LEN a C
+   expression of type `int'.
+
+   If the assembler has a `.ascii' pseudo-op as found in the Berkeley
+   Unix assembler, do not define the macro `ASM_OUTPUT_ASCII'.  */
+
+#if GCC_VERSION_INT >= 0x430
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n')
+#else
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
+#endif
+/* Define this macro as a C expression which is nonzero if C is used
+   as a logical line separator by the assembler.
+
+   If you do not define this macro, the default is that only the
+   character `;' is treated as a logical line separator.  */
+
+/*
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+ These macros are defined as C string constant, describing the
+   syntax in the assembler for grouping arithmetic expressions.  The
+   following definitions are correct for most assemblers:
+
+   #define ASM_OPEN_PAREN "("
+   #define ASM_CLOSE_PAREN ")"
+
+   These macros are provided by `real.h' for writing the definitions of
+   `ASM_OUTPUT_DOUBLE' and the like:  */
+
+/* Here we much catch r0 - r15  variable names */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) 			\
+do{							\
+	char *p = NAME;					\
+	while(*p == '_') p++;				\
+	if(*p == 'r' || *p == 'R')			\
+	{						\
+	    int val;					\
+	    char *endptr;				\
+	    p++;					\
+	    val = strtol (p, &endptr, 10);		\
+	    if(val >= 0 && val <= 15 &&			\
+	    	*endptr == 0 )				\
+	    {						\
+	    	asm_fprintf ((FILE), "_%U%s", (NAME));	\
+	    }						\
+	    else					\
+	    	asm_fprintf ((FILE), "%U%s", (NAME));   \
+	}						\
+	else						\
+		asm_fprintf ((FILE), "%U%s", (NAME));	\
+} while(0)
+
+
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)	\
+do {							\
+     const char *p = NAME;					\
+     if(*p == '*' || *p == '@' ) p++;			\
+     if(*p >= '0' && *p <= '9' ) break;			\
+     fputs ("\t.comm ", (STREAM));			\
+     assemble_name ((STREAM), (NAME));			\
+     fprintf ((STREAM), ",%d%s", (SIZE), (SIZE)>1?",2\n":"\n");\
+} while (0)
+
+#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED)	\
+do {							\
+     const char *p = NAME;					\
+     if(*p == '*' || *p == '@' ) p++;			\
+     if(*p >= '0' && *p <= '9' ) break;			\
+     fputs ("\t.local ", (STREAM));			\
+     assemble_name ((STREAM), (NAME));			\
+     fputs ("\n",(STREAM));				\
+     fputs ("\t.comm ", (STREAM));                     	\
+     assemble_name ((STREAM), (NAME));			\
+     fprintf ((STREAM), ",%d%s", (SIZE),(SIZE)>1?",2\n":"\n");\
+} while (0)
+
+#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED)                 \
+do { \
+  const char *p = (NAME); \
+  if(*p == '*' || *p == '@' ) p++; \
+  if(*p >= '0' && *p <= '9' ) break; \
+  asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)); \
+} while(0)
+
+/* macros to output uninitialized variable definitions */
+
+/* Return a non-zero value if DECL has a section attribute.  */
+#define IN_NAMED_SECTION(DECL)                                           \
+  ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL)    \
+   && DECL_SECTION_NAME (DECL) != NULL_TREE)
+
+#define BSS_SECTION_ASM_OP	"\t.section\t.bss"
+/* If defined, a C expression whose value is a string containing the
+   assembler operation to identify the following data as
+   uninitialized global data.  If not defined, and neither
+   'ASM_OUTPUT_BSS' nor 'ASM_OUTPUT_ALIGNED_BSS' are defined,
+   uninitialized global data will be output in the data section if
+   -fno-common' is passed, otherwise 'ASM_OUTPUT_COMMON' will be
+   used.
+*/
+
+
+#define ASM_OUTPUT_LABEL(STREAM, NAME)		\
+{						\
+  int __msp430_data_name_workaround = (((NAME)[0] == '*') && ((NAME)[1] == '0'));  \
+  if (__msp430_data_name_workaround) \
+  { \
+    static int repeatable_pseudolabels_resolver = 0;\
+	fprintf (STREAM, "__");			\
+    assemble_name (STREAM, NAME);			\
+	fprintf (STREAM, "_%d", ++repeatable_pseudolabels_resolver);			\
+  } \
+  else \
+    assemble_name (STREAM, NAME);			\
+  fprintf (STREAM, ":\n");			\
+}
+/* A C statement (sans semicolon) to output to the stdio stream
+   STREAM the assembler definition of a label named NAME.  Use the
+   expression `assemble_name (STREAM, NAME)' to output the name
+   itself; before and after that, output the additional assembler
+   syntax for defining the name, and a newline.  */
+
+#undef TYPE_ASM_OP
+#undef SIZE_ASM_OP
+#undef WEAK_ASM_OP
+#define TYPE_ASM_OP	"\t.type\t"
+#define SIZE_ASM_OP	"\t.size\t"
+#define WEAK_ASM_OP	"\t.weak\t"
+/* Define the strings used for the special svr4 .type and .size directives.
+   These strings generally do not vary from one system running svr4 to
+   another, but if a given system (e.g. m88k running svr) needs to use
+   different pseudo-op names for these, they may be overridden in the
+   file which includes this one.  */
+
+
+#undef TYPE_OPERAND_FMT
+#define TYPE_OPERAND_FMT	"@%s"
+/* The following macro defines the format used to output the second
+   operand of the .type assembler directive.  Different svr4 assemblers
+   expect various different forms for this operand.  The one given here
+   is just a default.  You may need to override it in your machine-
+   specific tm.h file (depending upon the particulars of your assembler).  */
+
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+asm_declare_function_name (FILE, NAME, DECL)
+
+
+/* A C statement (sans semicolon) to output to the stdio stream
+   STREAM any text necessary for declaring the name NAME of a
+   function which is being defined.  This macro is responsible for
+   outputting the label definition (perhaps using
+   `ASM_OUTPUT_LABEL').  The argument DECL is the `FUNCTION_DECL'
+   tree node representing the function.
+
+   If this macro is not defined, then the function name is defined in
+   the usual manner as a label (by means of `ASM_OUTPUT_LABEL').  */
+
+
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)			\
+  do {									\
+    if (!flag_inhibit_size_directive)					\
+      {									\
+        char label[256];						\
+	static int labelno;						\
+	labelno++;							\
+	ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno);		\
+	fprintf(FILE, ".%s%d:\n", "Lfe", labelno) ;		\
+	fprintf (FILE, "%s", SIZE_ASM_OP);				\
+	assemble_name (FILE, (FNAME));					\
+        fprintf (FILE, ",");						\
+	assemble_name (FILE, label);					\
+        fprintf (FILE, "-");						\
+	assemble_name (FILE, (FNAME));					\
+	fprintf (FILE,"\n;; End of function \n\n");	\
+      }									\
+  } while (0)
+
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)			  \
+do {									  \
+      int __msp430_data_name_workaround = (((NAME)[0] == '*') && ((NAME)[1] == '0'));  \
+	  if (__msp430_data_name_workaround) \
+	    fprintf (FILE, "#"); \
+      fprintf (FILE, "%s", TYPE_ASM_OP);				  \
+      assemble_name (FILE, NAME);					  \
+      putc (',', FILE);							  \
+      fprintf (FILE, TYPE_OPERAND_FMT, "object");			  \
+      putc ('\n', FILE);						  \
+      size_directive_output = 0;					  \
+      if (!flag_inhibit_size_directive && DECL_SIZE (DECL))		  \
+	{								  \
+	  size_directive_output = 1;					  \
+	  if (__msp430_data_name_workaround) \
+	    fprintf (FILE, "#"); \
+	  fprintf (FILE, "%s", SIZE_ASM_OP);				  \
+	  assemble_name (FILE, NAME);					  \
+	  fprintf (FILE, ",%ld\n",  int_size_in_bytes (TREE_TYPE (DECL))); \
+    }									  \
+  ASM_OUTPUT_LABEL(FILE, NAME);						  \
+} while (0)
+
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END)	 \
+do {									 \
+     const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0);		 \
+     if (!flag_inhibit_size_directive && DECL_SIZE (DECL)		 \
+         && ! AT_END && TOP_LEVEL					 \
+	 && DECL_INITIAL (DECL) == error_mark_node			 \
+	 && !size_directive_output)					 \
+       {								 \
+	 size_directive_output = 1;					 \
+	 fprintf (FILE, "%s", SIZE_ASM_OP);				 \
+	 assemble_name (FILE, name);					 \
+	 fprintf (FILE, ",%d\n",  int_size_in_bytes (TREE_TYPE (DECL))); \
+       }								 \
+   } while (0)
+
+
+#define ESCAPES \
+"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
+/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
+   ASM_OUTPUT_LIMITED_STRING macros.  Each byte in the table
+   corresponds to a particular byte value [0..255].  For any
+   given byte value, if the value in the corresponding table
+   position is zero, the given character can be output directly.
+   If the table value is 1, the byte must be output as a \ooo
+   octal escape.  If the tables value is anything else, then the
+   byte value should be output as a \ followed by the value
+   in the table.  Note that we can use standard UN*X escape
+   sequences for many control characters, but we don't use
+   \a to represent BEL because some svr4 assemblers (e.g. on
+   the i386) don't know about that.  Also, we don't use \v
+   since some versions of gas, such as 2.2 did not accept it.  */
+
+#define STRING_LIMIT	((unsigned) 64)
+#define STRING_ASM_OP	"\t.string\t"
+/* Some svr4 assemblers have a limit on the number of characters which
+   can appear in the operand of a .string directive.  If your assembler
+   has such a limitation, you should define STRING_LIMIT to reflect that
+   limit.  Note that at least some svr4 assemblers have a limit on the
+   actual number of bytes in the double-quoted string, and that they
+   count each character in an escape sequence as one byte.  Thus, an
+   escape sequence like \377 would count as four bytes.
+
+   If your target assembler doesn't support the .string directive, you
+   should define this to zero.  */
+
+#define GLOBAL_ASM_OP ".global\t"
+     
+#define ASM_WEAKEN_LABEL(FILE, NAME) 	\
+  do					\
+    {					\
+      fputs ("\t.weak\t", (FILE));	\
+      assemble_name ((FILE), (NAME)); 	\
+      fputc ('\n', (FILE));		\
+    }					\
+  while (0)
+
+/* A C statement (sans semicolon) to output to the stdio stream
+   STREAM some commands that will make the label NAME weak; that is,
+   available for reference from other files but only used if no other
+   definition is available.  Use the expression `assemble_name
+   (STREAM, NAME)' to output the name itself; before and after that,
+   output the additional assembler syntax for making that name weak,
+   and a newline.
+
+   If you don't define this macro, GNU CC will not support weak
+   symbols and you should not define the `SUPPORTS_WEAK' macro.
+*/
+
+#define SUPPORTS_WEAK 1
+/* A C expression which evaluates to true if the target supports weak
+   symbols.
+
+   If you don't define this macro, `defaults.h' provides a default
+   definition.  If `ASM_WEAKEN_LABEL' is defined, the default
+   definition is `1'; otherwise, it is `0'.  Define this macro if you
+   want to control weak symbol support with a compiler flag such as
+   `-melf'.
+
+   `MAKE_DECL_ONE_ONLY'
+   A C statement (sans semicolon) to mark DECL to be emitted as a
+   public symbol such that extra copies in multiple translation units
+   will be discarded by the linker.  Define this macro if your object
+   file format provides support for this concept, such as the `COMDAT'
+   section flags in the Microsoft Windows PE/COFF format, and this
+   support requires changes to DECL, such as putting it in a separate
+   section.
+
+   `SUPPORTS_WEAK'
+   A C expression which evaluates to true if the target supports
+   one-only semantics.
+
+   If you don't define this macro, `varasm.c' provides a default
+   definition.  If `MAKE_DECL_ONE_ONLY' is defined, the default
+   definition is `1'; otherwise, it is `0'.  Define this macro if you
+   want to control weak symbol support with a compiler flag, or if
+   setting the `DECL_ONE_ONLY' flag is enough to mark a declaration to
+   be emitted as one-only.  */
+
+/* A C statement to output to the stdio stream STREAM a label whose
+   name is made from the string PREFIX and the number NUM.
+
+   It is absolutely essential that these labels be distinct from the
+   labels used for user-level functions and variables.  Otherwise,
+   certain programs will have name conflicts with internal labels.
+
+   It is desirable to exclude internal labels from the symbol table
+   of the object file.  Most assemblers have a naming convention for
+   labels that should be excluded; on many systems, the letter `L' at
+   the beginning of a label has this effect.  You should find out what
+   convention your system uses, and follow it.
+
+   The usual definition of this macro is as follows:
+
+   fprintf (STREAM, "L%s%d:\n", PREFIX, NUM)  */
+
+#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)	\
+sprintf (STRING, "*.%s%d", PREFIX, NUM)
+/* A C statement to store into the string STRING a label whose name
+   is made from the string PREFIX and the number NUM.
+
+   This string, when output subsequently by `assemble_name', should
+   produce the output that `ASM_OUTPUT_INTERNAL_LABEL' would produce
+   with the same PREFIX and NUM.
+
+   If the string begins with `*', then `assemble_name' will output
+   the rest of the string unchanged.  It is often convenient for
+   `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way.  If the
+   string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to
+   output the string, and may change it.  (Of course,
+   `ASM_OUTPUT_LABELREF' is also part of your machine description, so
+   you should know what it does on your machine.)  */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)	\
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),	\
+  sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* A C expression to assign to OUTVAR (which is a variable of type
+   `char *') a newly allocated string made from the string NAME and
+   the number NUMBER, with some suitable punctuation added.  Use
+   `alloca' to get space for the string.
+
+   The string will be used as an argument to `ASM_OUTPUT_LABELREF' to
+   produce an assembler label for an internal static variable whose
+   name is NAME.  Therefore, the string must be such as to result in
+   valid assembler code.  The argument NUMBER is different each time
+   this macro is executed; it prevents conflicts between
+   similarly-named internal static variables in different scopes.
+
+   Ideally this string should not be a valid C identifier, to prevent
+   any conflict with the user's own symbols.  Most assemblers allow
+   periods or percent signs in assembler symbols; putting at least
+   one of these between the name and the number will suffice.  */
+
+/* `ASM_OUTPUT_WEAK_ALIAS (STREAM, NAME, VALUE)'
+   A C statement to output to the stdio stream STREAM assembler code
+   which defines (equates) the weak symbol NAME to have the value
+   VALUE.
+
+   Define this macro if the target only supports weak aliases; define
+   ASM_OUTPUT_DEF instead if possible.  */
+
+#define HAS_INIT_SECTION 1
+/* If defined, `main' will not call `__main' as described above.
+   This macro should be defined for systems that control the contents
+   of the init section on a symbol-by-symbol basis, such as OSF/1,
+   and should not be defined explicitly for systems that support
+   `INIT_SECTION_ASM_OP'.  */
+
+#define REGISTER_NAMES {				\
+  "r0","r1","r2","r3","r4","r5","r6","r7",		\
+  "r8","r9","r10","r11","r12","r13","r14","r15","argp"		\
+}
+/* A C initializer containing the assembler's names for the machine
+   registers, each one as a C string constant.  This is what
+   translates register numbers in the compiler into assembler
+   language.  */
+
+#define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)
+/* If defined, a C statement to be executed just prior to the output
+   of assembler code for INSN, to modify the extracted operands so
+   they will be output differently.
+
+   Here the argument OPVEC is the vector containing the operands
+   extracted from INSN, and NOPERANDS is the number of elements of
+   the vector which contain meaningful data for this insn.  The
+   contents of this vector are what will be used to convert the insn
+   template into assembler code, so you can change the assembler
+   output by changing the contents of the vector.
+
+   This macro is useful when various assembler syntaxes share a single
+   file of instruction patterns; by defining this macro differently,
+   you can cause a large class of instructions to be output
+   differently (such as with rearranged operands).  Naturally,
+   variations in assembler syntax affecting individual insn patterns
+   ought to be handled by writing conditional output routines in
+   those patterns.
+
+   If this macro is not defined, it is equivalent to a null statement.  */
+
+#define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE)
+/* A C compound statement to output to stdio stream STREAM the
+   assembler syntax for an instruction operand X.  X is an RTL
+   expression.
+
+   CODE is a value that can be used to specify one of several ways of
+   printing the operand.  It is used when identical operands must be
+   printed differently depending on the context.  CODE comes from the
+   `%' specification that was used to request printing of the
+   operand.  If the specification was just `%DIGIT' then CODE is 0;
+   if the specification was `%LTR DIGIT' then CODE is the ASCII code
+   for LTR.
+
+   If X is a register, this macro should print the register's name.
+   The names can be found in an array `reg_names' whose type is `char
+   *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
+
+   When the machine description has a specification `%PUNCT' (a `%'
+   followed by a punctuation character), this macro is called with a
+   null pointer for X and the punctuation character for CODE.  */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~')
+/* A C expression which evaluates to true if CODE is a valid
+   punctuation character for use in the `PRINT_OPERAND' macro.  If
+   `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no
+   punctuation characters (except for the standard one, `%') are used
+   in this way.  */
+
+#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
+/* A C compound statement to output to stdio stream STREAM the
+   assembler syntax for an instruction operand that is a memory
+   reference whose address is X.  X is an RTL expression.
+
+   On some machines, the syntax for a symbolic address depends on the
+   section that the address refers to.  On these machines, define the
+   macro `ENCODE_SECTION_INFO' to store the information into the
+   `symbol_ref', and then check for it here.  *Note Assembler
+   Format::.  */
+
+#define USER_LABEL_PREFIX ""
+/* `LOCAL_LABEL_PREFIX'
+   `REGISTER_PREFIX'
+   `IMMEDIATE_PREFIX'
+   If defined, C string expressions to be used for the `%R', `%L',
+   `%U', and `%I' options of `asm_fprintf' (see `final.c').  These
+   are useful when a single `md' file must support multiple assembler
+   formats.  In that case, the various `tm.h' files can define these
+   macros differently.  */
+
+#define ASSEMBLER_DIALECT MSP430_HAS_HWMUL_INTERNAL
+/* If your target supports multiple dialects of assembler language
+  (such as different opcodes), define this macro as a C expression
+  that gives the numeric index of the assembler language dialect to
+  use, with zero as the first variant.
+
+  If this macro is defined, you may use constructs of the form
+  `{option0|option1|option2...}' in the output templates of patterns
+  (*note Output Template::.) or in the first argument of
+  `asm_fprintf'.  This construct outputs `option0', `option1' or
+  `option2', etc., if the value of `ASSEMBLER_DIALECT' is zero, one
+  or two, etc.  Any special characters within these strings retain
+  their usual meaning.
+
+  If you do not define this macro, the characters `{', `|' and `}'
+  do not have any special meaning when used in templates or operands
+  to `asm_fprintf'.
+
+  Define the macros `REGISTER_PREFIX', `LOCAL_LABEL_PREFIX',
+  `USER_LABEL_PREFIX' and `IMMEDIATE_PREFIX' if you can express the
+  variations in assembler language syntax with that mechanism.
+  Define `ASSEMBLER_DIALECT' and use the `{option0|option1}' syntax
+  if the syntax variant are larger and involve such things as
+  different opcodes or operand order.  */
+
+#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO)	\
+{						\
+  if (REGNO > 15)				\
+    abort ();					\
+  fprintf (STREAM, "\tpush\tr%d", REGNO);	\
+}
+/* A C expression to output to STREAM some assembler code which will
+   push hard register number REGNO onto the stack.  The code need not
+   be optimal, since this macro is used only when profiling.  */
+
+#define ASM_OUTPUT_REG_POP(STREAM, REGNO)	\
+{						\
+  if (REGNO > 15)				\
+    abort ();					\
+  fprintf (STREAM, "\tpop\tr%d", REGNO);	\
+}
+/* A C expression to output to STREAM some assembler code which will
+   pop hard register number REGNO off of the stack.  The code need
+   not be optimal, since this macro is used only when profiling.  */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE)		\
+  msp430_output_addr_vec_elt(STREAM, VALUE)
+/* This macro should be provided on machines where the addresses in a
+   dispatch table are absolute.
+
+   The definition should be a C statement to output to the stdio
+   stream STREAM an assembler pseudo-instruction to generate a
+   reference to a label.  VALUE is the number of an internal label
+   whose definition is output using `ASM_OUTPUT_INTERNAL_LABEL'.  For
+   example,
+
+   fprintf (STREAM, "\t.word L%d\n", VALUE)  */
+
+/*
+#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \
+   progmem_section (), ASM_OUTPUT_INTERNAL_LABEL (STREAM, PREFIX, NUM)
+
+   `ASM_OUTPUT_CASE_LABEL (STREAM, PREFIX, NUM, TABLE)'
+   Define this if the label before a jump-table needs to be output
+   specially.  The first three arguments are the same as for
+   `ASM_OUTPUT_INTERNAL_LABEL'; the fourth argument is the jump-table
+   which follows (a `jump_insn' containing an `addr_vec' or
+   `addr_diff_vec').
+
+   This feature is used on system V to output a `swbeg' statement for
+   the table.
+
+   If this macro is not defined, these labels are output with
+   `ASM_OUTPUT_INTERNAL_LABEL'.  */
+
+/* `ASM_OUTPUT_CASE_END (STREAM, NUM, TABLE)'
+   Define this if something special must be output at the end of a
+   jump-table.  The definition should be a C statement to be executed
+   after the assembler code for the table is written.  It should write
+   the appropriate code to stdio stream STREAM.  The argument TABLE
+   is the jump-table insn, and NUM is the label-number of the
+   preceding label.
+
+   If this macro is not defined, nothing special is output at the end
+   of the jump-table.  */
+
+#ifndef SET_ASM_OP
+#define SET_ASM_OP "\t.set\t"
+#endif
+  
+#define ASM_OUTPUT_SKIP(STREAM, N)		\
+fprintf (STREAM, "\t.skip %d,0\n", N)
+/* A C statement to output to the stdio stream STREAM an assembler
+   instruction to advance the location counter by NBYTES bytes.
+   Those bytes should be zero when loaded.  NBYTES will be a C
+   expression of type `int'.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+fprintf (STREAM, "\t.p2align %d,0\n", POWER)
+/* A C statement to output to the stdio stream STREAM an assembler
+   command to advance the location counter to a multiple of 2 to the
+   POWER bytes.  POWER will be a C expression of type `int'.  */
+
+#define CASE_VECTOR_MODE HImode
+/* An alias for a machine mode name.  This is the machine mode that
+   elements of a jump-table should have.  */
+
+extern struct rtx_def *msp430_compare_op0, *msp430_compare_op1;
+
+
+extern int msp430_case_values_threshold;
+
+#define CASE_VALUES_THRESHOLD msp430_case_values_threshold
+/* `CASE_VALUES_THRESHOLD'
+   Define this to be the smallest number of different values for
+   which it is best to use a jump-table instead of a tree of
+   conditional branches.  The default is four for machines with a
+   `casesi' instruction and five otherwise.  This is best for most
+   machines.  */
+
+#undef WORD_REGISTER_OPERATIONS
+/* Define this macro if operations between registers with integral
+   mode smaller than a word are always performed on the entire
+   register.  Most RISC machines have this property and most CISC
+   machines do not.  */
+
+/*
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+ An alias for a tree code that is the easiest kind of division to
+   compile code for in the general case.  It may be `TRUNC_DIV_EXPR',
+   `FLOOR_DIV_EXPR', `CEIL_DIV_EXPR' or `ROUND_DIV_EXPR'.  These four
+   division operators differ in how they round the result to an
+   integer.  `EASY_DIV_EXPR' is used when it is permissible to use
+   any of those kinds of division and the choice should be made on
+   the basis of efficiency.  */
+
+#define MOVE_MAX 2
+/* The maximum number of bytes that a single instruction can move
+   quickly between memory and registers or between two memory
+   locations.  */
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+/* A C expression which is nonzero if on this machine it is safe to
+   "convert" an integer of INPREC bits to one of OUTPREC bits (where
+   OUTPREC is smaller than INPREC) by merely operating on it as if it
+   had only OUTPREC bits.
+
+   On many machines, this expression can be 1.
+
+   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for
+   modes for which `MODES_TIEABLE_P' is 0, suboptimal code can result.
+   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in
+   such cases may improve things.  */
+
+#define Pmode HImode
+/* An alias for the machine mode for pointers.  On most machines,
+   define this to be the integer mode corresponding to the width of a
+   hardware pointer; `SImode' on 32-bit machine or `DImode' on 64-bit
+   machines.  On some machines you must define this to be one of the
+   partial integer modes, such as `PSImode'.
+
+   The width of `Pmode' must be at least as large as the value of
+   `POINTER_SIZE'.  If it is not equal, you must define the macro
+   `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to
+   `Pmode'.  */
+
+#define FUNCTION_MODE HImode
+/* An alias for the machine mode used for memory references to
+   functions being called, in `call' RTL expressions.  On most
+   machines this should be `QImode'.  */
+     /*                            1        3 */
+/*
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+ `VALID_MACHINE_DECL_ATTRIBUTE (DECL, ATTRIBUTES, IDENTIFIER, ARGS)'
+   If defined, a C expression whose value is nonzero if IDENTIFIER
+   with arguments ARGS is a valid machine specific attribute for DECL.
+   The attributes in ATTRIBUTES have previously been assigned to DECL.  */
+
+/*
+#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
+     valid_machine_type_attribute(TYPE, ATTRIBUTES, IDENTIFIER, ARGS)
+   `VALID_MACHINE_TYPE_ATTRIBUTE (TYPE, ATTRIBUTES, IDENTIFIER, ARGS)'
+   If defined, a C expression whose value is nonzero if IDENTIFIER
+   with arguments ARGS is a valid machine specific attribute for TYPE.
+   The attributes in ATTRIBUTES have previously been assigned to TYPE.  */
+
+#define DOLLARS_IN_IDENTIFIERS 0
+/* Define this macro to control use of the character `$' in identifier
+   names.  0 means `$' is not allowed by default; 1 means it is
+   allowed.  1 is the default; there is no need to define this macro
+   in that case.  This macro controls the compiler proper; it does
+   not affect the preprocessor.  */
+
+#define NO_DOLLAR_IN_LABEL 1
+/* Define this macro if the assembler does not accept the character
+   `$' in label names.  By default constructors and destructors in
+   G++ have `$' in the identifiers.  If this macro is defined, `.' is
+   used instead.  */
+
+#define TRAMPOLINE_TEMPLATE(FILE) msp430_trampoline_template((FILE))
+
+#define TRAMPOLINE_SIZE 8
+#define TRAMPOLINE_ALIGNMENT 16
+
+
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)	\
+	msp430_initialize_trampoline (TRAMP, FNADDR, CXT)
+
+
+/* Store in cc_status the expressions
+   that the condition codes will describe
+   after execution of an instruction whose pattern is EXP.
+   Do not alter them if the instruction would not alter the cc's.  */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
+
+/* The add insns don't set overflow in a usable way.  */
+#define CC_OVERFLOW_UNUSABLE 01000
+/* The mov,and,or,xor insns don't set carry.  That's ok though as the
+   Z bit is all we need when doing unsigned comparisons on the result of
+   these insns (since they're always with 0).  However, conditions.h has
+   CC_NO_OVERFLOW defined for this purpose.  Rename it to something more
+   understandable.  */
+#define CC_NO_CARRY CC_NO_OVERFLOW
+
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+   for profiling a function entry.  */
+
+#define FUNCTION_PROFILER(FILE, LABELNO)  \
+  fprintf (FILE, "/* profiler %d */", (LABELNO))
+
+/* `FIRST_INSN_ADDRESS'
+   When the `length' insn attribute is used, this macro specifies the
+   value to be assigned to the address of the first insn in a
+   function.  If not specified, 0 is used.  */
+
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) (LENGTH =\
+					  adjust_insn_length (INSN, LENGTH))
+/* If defined, modifies the length assigned to instruction INSN as a
+   function of the context in which it is used.  LENGTH is an lvalue
+   that contains the initially computed length of the insn and should
+   be updated with the correct length of the insn.  If updating is
+   required, INSN must not be a varying-length insn.
+
+   This macro will normally not be required.  A case in which it is
+   required is the ROMP.  On this machine, the size of an `addr_vec'
+   insn must be increased by two to compensate for the fact that
+   alignment may be required.  */
+
+#define CPP_SPEC "\
+%{!mmcu*|mmcu=msp1:%(cpp_msp1)} \
+%{mmcu=msp2:%(cpp_msp2)} \
+%{mmcu=msp3:%(cpp_msp3)} \
+%{mmcu=msp4:%(cpp_msp4)} \
+%{mmcu=msp5:%(cpp_msp5)} \
+%{mmcu=msp6:%(cpp_msp6)} \
+%{mmcu=msp430x110:%(cpp_msp1) -D__MSP430_110__} \
+%{mmcu=msp430x112:%(cpp_msp1) -D__MSP430_112__} \
+%{mmcu=msp430x1101:%(cpp_msp1) -D__MSP430_1101__} \
+%{mmcu=msp430x1111:%(cpp_msp1) -D__MSP430_1111__} \
+%{mmcu=msp430x1121:%(cpp_msp1) -D__MSP430_1121__} \
+%{mmcu=msp430x1122:%(cpp_msp1) -D__MSP430_1122__} \
+%{mmcu=msp430x1132:%(cpp_msp1) -D__MSP430_1132__} \
+%{mmcu=msp430x122:%(cpp_msp1) -D__MSP430_122__} \
+%{mmcu=msp430x123:%(cpp_msp1) -D__MSP430_123__} \
+%{mmcu=msp430x1222:%(cpp_msp1) -D__MSP430_1222__} \
+%{mmcu=msp430x1232:%(cpp_msp1) -D__MSP430_1232__} \
+%{mmcu=msp430x133:%(cpp_msp1) -D__MSP430_133__} \
+%{mmcu=msp430x135:%(cpp_msp1) -D__MSP430_135__} \
+%{mmcu=msp430x1331:%(cpp_msp1) -D__MSP430_1331__} \
+%{mmcu=msp430x1351:%(cpp_msp1) -D__MSP430_1351__} \
+%{mmcu=msp430x147:%(cpp_msp2) -D__MSP430_147__} \
+%{mmcu=msp430x148:%(cpp_msp2) -D__MSP430_148__} \
+%{mmcu=msp430x149:%(cpp_msp2) -D__MSP430_149__} \
+%{mmcu=msp430x1471:%(cpp_msp2) -D__MSP430_1471__} \
+%{mmcu=msp430x1481:%(cpp_msp2) -D__MSP430_1481__} \
+%{mmcu=msp430x1491:%(cpp_msp2) -D__MSP430_1491__} \
+%{mmcu=msp430x155:%(cpp_msp1) -D__MSP430_155__} \
+%{mmcu=msp430x156:%(cpp_msp1) -D__MSP430_156__} \
+%{mmcu=msp430x157:%(cpp_msp1) -D__MSP430_157__} \
+%{mmcu=msp430x167:%(cpp_msp2) -D__MSP430_167__} \
+%{mmcu=msp430x168:%(cpp_msp2) -D__MSP430_168__} \
+%{mmcu=msp430x169:%(cpp_msp2) -D__MSP430_169__} \
+%{mmcu=msp430x1610:%(cpp_msp2) -D__MSP430_1610__} \
+%{mmcu=msp430x1611:%(cpp_msp2) -D__MSP430_1611__} \
+%{mmcu=msp430x1612:%(cpp_msp2) -D__MSP430_1612__} \
+%{mmcu=msp430x2001:%(cpp_msp1) -D__MSP430_2001__} \
+%{mmcu=msp430x2011:%(cpp_msp1) -D__MSP430_2011__} \
+%{mmcu=msp430x2002:%(cpp_msp1) -D__MSP430_2002__} \
+%{mmcu=msp430x2012:%(cpp_msp1) -D__MSP430_2012__} \
+%{mmcu=msp430x2003:%(cpp_msp1) -D__MSP430_2003__} \
+%{mmcu=msp430x2013:%(cpp_msp1) -D__MSP430_2013__} \
+%{mmcu=msp430x2101:%(cpp_msp1) -D__MSP430_2101__} \
+%{mmcu=msp430x2111:%(cpp_msp1) -D__MSP430_2111__} \
+%{mmcu=msp430x2121:%(cpp_msp1) -D__MSP430_2121__} \
+%{mmcu=msp430x2131:%(cpp_msp1) -D__MSP430_2131__} \
+%{mmcu=msp430x2112:%(cpp_msp1) -D__MSP430_2112__} \
+%{mmcu=msp430x2122:%(cpp_msp1) -D__MSP430_2122__} \
+%{mmcu=msp430x2132:%(cpp_msp1) -D__MSP430_2132__} \
+%{mmcu=msp430x2201:%(cpp_msp1) -D__MSP430_2201__} \
+%{mmcu=msp430x2211:%(cpp_msp1) -D__MSP430_2211__} \
+%{mmcu=msp430x2221:%(cpp_msp1) -D__MSP430_2221__} \
+%{mmcu=msp430x2231:%(cpp_msp1) -D__MSP430_2231__} \
+%{mmcu=msp430x2232:%(cpp_msp1) -D__MSP430_2232__} \
+%{mmcu=msp430x2252:%(cpp_msp1) -D__MSP430_2252__} \
+%{mmcu=msp430x2272:%(cpp_msp1) -D__MSP430_2272__} \
+%{mmcu=msp430x2234:%(cpp_msp1) -D__MSP430_2234__} \
+%{mmcu=msp430x2254:%(cpp_msp1) -D__MSP430_2254__} \
+%{mmcu=msp430x2274:%(cpp_msp1) -D__MSP430_2274__} \
+%{mmcu=msp430x233:%(cpp_msp2) -D__MSP430_233__} \
+%{mmcu=msp430x235:%(cpp_msp2) -D__MSP430_235__} \
+%{mmcu=msp430x2330:%(cpp_msp2) -D__MSP430_2330__} \
+%{mmcu=msp430x2350:%(cpp_msp2) -D__MSP430_2350__} \
+%{mmcu=msp430x2370:%(cpp_msp2) -D__MSP430_2370__} \
+%{mmcu=msp430x247:%(cpp_msp2) -D__MSP430_247__} \
+%{mmcu=msp430x248:%(cpp_msp2) -D__MSP430_248__} \
+%{mmcu=msp430x249:%(cpp_msp2) -D__MSP430_249__} \
+%{mmcu=msp430x2410:%(cpp_msp2) -D__MSP430_2410__} \
+%{mmcu=msp430x2471:%(cpp_msp2) -D__MSP430_2471__} \
+%{mmcu=msp430x2481:%(cpp_msp2) -D__MSP430_2481__} \
+%{mmcu=msp430x2491:%(cpp_msp2) -D__MSP430_2491__} \
+%{mmcu=msp430x2416:%(cpp_msp3) -D__MSP430_2416__} \
+%{mmcu=msp430x2417:%(cpp_msp3) -D__MSP430_2417__} \
+%{mmcu=msp430x2418:%(cpp_msp3) -D__MSP430_2418__} \
+%{mmcu=msp430x2419:%(cpp_msp3) -D__MSP430_2419__} \
+%{mmcu=msp430x2616:%(cpp_msp3) -D__MSP430_2616__} \
+%{mmcu=msp430x2617:%(cpp_msp3) -D__MSP430_2617__} \
+%{mmcu=msp430x2618:%(cpp_msp3) -D__MSP430_2618__} \
+%{mmcu=msp430x2619:%(cpp_msp3) -D__MSP430_2619__} \
+%{mmcu=msp430x311:%(cpp_msp1) -D__MSP430_311__} \
+%{mmcu=msp430x312:%(cpp_msp1) -D__MSP430_312__} \
+%{mmcu=msp430x313:%(cpp_msp1) -D__MSP430_313__} \
+%{mmcu=msp430x314:%(cpp_msp1) -D__MSP430_314__} \
+%{mmcu=msp430x315:%(cpp_msp1) -D__MSP430_315__} \
+%{mmcu=msp430x323:%(cpp_msp1) -D__MSP430_323__} \
+%{mmcu=msp430x325:%(cpp_msp1) -D__MSP430_325__} \
+%{mmcu=msp430x336:%(cpp_msp2) -D__MSP430_336__} \
+%{mmcu=msp430x337:%(cpp_msp2) -D__MSP430_337__} \
+%{mmcu=msp430x412:%(cpp_msp1) -D__MSP430_412__} \
+%{mmcu=msp430x413:%(cpp_msp1) -D__MSP430_413__} \
+%{mmcu=msp430x415:%(cpp_msp1) -D__MSP430_415__} \
+%{mmcu=msp430x417:%(cpp_msp1) -D__MSP430_417__} \
+%{mmcu=msp430x423:%(cpp_msp2) -D__MSP430_423__} \
+%{mmcu=msp430x425:%(cpp_msp2) -D__MSP430_425__} \
+%{mmcu=msp430x427:%(cpp_msp2) -D__MSP430_427__} \
+%{mmcu=msp430x4250:%(cpp_msp1) -D__MSP430_4250__} \
+%{mmcu=msp430x4260:%(cpp_msp1) -D__MSP430_4260__} \
+%{mmcu=msp430x4270:%(cpp_msp1) -D__MSP430_4270__} \
+%{mmcu=msp430xG4250:%(cpp_msp1) -D__MSP430_G4250__} \
+%{mmcu=msp430xG4260:%(cpp_msp1) -D__MSP430_G4260__} \
+%{mmcu=msp430xG4270:%(cpp_msp1) -D__MSP430_G4270__} \
+%{mmcu=msp430xE423:%(cpp_msp2) -D__MSP430_E423__} \
+%{mmcu=msp430xE425:%(cpp_msp2) -D__MSP430_E425__} \
+%{mmcu=msp430xE427:%(cpp_msp2) -D__MSP430_E427__} \
+%{mmcu=msp430xE4232:%(cpp_msp2) -D__MSP430_E4232__} \
+%{mmcu=msp430xE4242:%(cpp_msp2) -D__MSP430_E4242__} \
+%{mmcu=msp430xE4252:%(cpp_msp2) -D__MSP430_E4252__} \
+%{mmcu=msp430xE4272:%(cpp_msp2) -D__MSP430_E4272__} \
+%{mmcu=msp430xW423:%(cpp_msp1) -D__MSP430_W423__} \
+%{mmcu=msp430xW425:%(cpp_msp1) -D__MSP430_W425__} \
+%{mmcu=msp430xW427:%(cpp_msp1) -D__MSP430_W427__} \
+%{mmcu=msp430xG437:%(cpp_msp1) -D__MSP430_G437__} \
+%{mmcu=msp430xG438:%(cpp_msp1) -D__MSP430_G438__} \
+%{mmcu=msp430xG439:%(cpp_msp1) -D__MSP430_G439__} \
+%{mmcu=msp430x435:%(cpp_msp1) -D__MSP430_435__} \
+%{mmcu=msp430x436:%(cpp_msp1) -D__MSP430_436__} \
+%{mmcu=msp430x437:%(cpp_msp1) -D__MSP430_437__} \
+%{mmcu=msp430x4351:%(cpp_msp1) -D__MSP430_4351__} \
+%{mmcu=msp430x4361:%(cpp_msp1) -D__MSP430_4361__} \
+%{mmcu=msp430x4371:%(cpp_msp1) -D__MSP430_4371__} \
+%{mmcu=msp430x447:%(cpp_msp2) -D__MSP430_447__} \
+%{mmcu=msp430x448:%(cpp_msp2) -D__MSP430_448__} \
+%{mmcu=msp430x449:%(cpp_msp2) -D__MSP430_449__} \
+%{mmcu=msp430xG4616:%(cpp_msp3) -D__MSP430_G4616__} \
+%{mmcu=msp430xG4617:%(cpp_msp3) -D__MSP430_G4617__} \
+%{mmcu=msp430xG4618:%(cpp_msp3) -D__MSP430_G4618__} \
+%{mmcu=msp430xG4619:%(cpp_msp3) -D__MSP430_G4619__} \
+%{mmcu=msp430x4783:%(cpp_msp4) -D__MSP430_4783__} \
+%{mmcu=msp430x4784:%(cpp_msp4) -D__MSP430_4784__} \
+%{mmcu=msp430x4793:%(cpp_msp4) -D__MSP430_4793__} \
+%{mmcu=msp430x4794:%(cpp_msp4) -D__MSP430_4794__} \
+%{mmcu=msp430x47166:%(cpp_msp5) -D__MSP430_47166__} \
+%{mmcu=msp430x47176:%(cpp_msp5) -D__MSP430_47176__} \
+%{mmcu=msp430x47186:%(cpp_msp5) -D__MSP430_47186__} \
+%{mmcu=msp430x47196:%(cpp_msp5) -D__MSP430_47196__} \
+%{mmcu=msp430x47167:%(cpp_msp5) -D__MSP430_47167__} \
+%{mmcu=msp430x47177:%(cpp_msp5) -D__MSP430_47177__} \
+%{mmcu=msp430x47187:%(cpp_msp5) -D__MSP430_47187__} \
+%{mmcu=msp430x47197:%(cpp_msp5) -D__MSP430_47197__} \
+%{mmcu=msp430x5418:%(cpp_msp6) -D__MSP430_5418__} \
+%{mmcu=msp430x5419:%(cpp_msp6) -D__MSP430_5419__} \
+%{mmcu=msp430x5435:%(cpp_msp6) -D__MSP430_5435__} \
+%{mmcu=msp430x5436:%(cpp_msp6) -D__MSP430_5436__} \
+%{mmcu=msp430x5437:%(cpp_msp6) -D__MSP430_5437__} \
+%{mmcu=msp430x5438:%(cpp_msp6) -D__MSP430_5438__} \
+%{mmcu=msp430x5510:%(cpp_msp6) -D__MSP430_5510__} \
+%{mmcu=msp430x5513:%(cpp_msp6) -D__MSP430_5513__} \
+%{mmcu=msp430x5514:%(cpp_msp6) -D__MSP430_5514__} \
+%{mmcu=msp430x5515:%(cpp_msp6) -D__MSP430_5515__} \
+%{mmcu=msp430x5517:%(cpp_msp6) -D__MSP430_5517__} \
+%{mmcu=msp430x5519:%(cpp_msp6) -D__MSP430_5519__} \
+%{mmcu=msp430x5521:%(cpp_msp6) -D__MSP430_5521__} \
+%{mmcu=msp430x5522:%(cpp_msp6) -D__MSP430_5522__} \
+%{mmcu=msp430x5524:%(cpp_msp6) -D__MSP430_5524__} \
+%{mmcu=msp430x5525:%(cpp_msp6) -D__MSP430_5525__} \
+%{mmcu=msp430x5526:%(cpp_msp6) -D__MSP430_5526__} \
+%{mmcu=msp430x5527:%(cpp_msp6) -D__MSP430_5527__} \
+%{mmcu=msp430x5528:%(cpp_msp6) -D__MSP430_5528__} \
+%{mmcu=msp430x5529:%(cpp_msp6) -D__MSP430_5529__} \
+%{mmcu=msp430x6638:%(cpp_msp6) -D__MSP430_6638__} \
+%{mmcu=cc430x5133:%(cpp_msp6) -D__CC430_5133__} \
+%{mmcu=cc430x5125:%(cpp_msp6) -D__CC430_5125__} \
+%{mmcu=cc430x6125:%(cpp_msp6) -D__CC430_6125__} \
+%{mmcu=cc430x6135:%(cpp_msp6) -D__CC430_6135__} \
+%{mmcu=cc430x6126:%(cpp_msp6) -D__CC430_6126__} \
+%{mmcu=cc430x5137:%(cpp_msp6) -D__CC430_5137__} \
+%{mmcu=cc430x6127:%(cpp_msp6) -D__CC430_6127__} \
+%{mmcu=cc430x6137:%(cpp_msp6) -D__CC430_6137__} \
+%{posix:-D_POSIX_SOURCE} %{mIAR:-D_IAR_ASSEMBLER_}"
+
+/* A C string constant that tells the GNU CC driver program options to
+   pass to CPP.  It can also specify how to translate options you
+   give to GNU CC into options for GNU CC to pass to the CPP.
+
+   Do not define this macro if it does not need to do anything.  */
+
+#define CC1_SPEC "%{profile:-p}"
+
+#define CC1PLUS_SPEC "-fno-rtti -fno-exceptions"
+
+/* A C string constant that tells the GNU CC driver program options to
+   pass to `cc1'.  It can also specify how to translate options you
+   give to GNU CC into options for GNU CC to pass to the `cc1'.
+
+   Do not define this macro if it does not need to do anything.  */
+
+#define ASM_SPEC "%{mmcu=*:-mmcu=%*}"
+/* A C string constant that tells the GNU CC driver program options to
+   pass to the assembler.  It can also specify how to translate
+   options you give to GNU CC into options for GNU CC to pass to the
+   assembler.  See the file `sun3.h' for an example of this.
+
+   Do not define this macro if it does not need to do anything.  */
+
+#define ASM_FINAL_SPEC ""
+/* A C string constant that tells the GNU CC driver program how to
+   run any programs which cleanup after the normal assembler.
+   Normally, this is not needed.  See the file `mips.h' for an
+   example of this.
+
+   Do not define this macro if it does not need to do anything.  */
+
+#define LINK_SPEC "\
+%{!mmcu*:-m msp430x110} \
+%{mmcu=msp1:-m msp430x110} \
+%{mmcu=msp2:-m msp430x147} \
+%{mmcu=msp3:-m msp430xG4616} \
+%{mmcu=msp4:-m msp430x4783} \
+%{mmcu=msp5:-m msp430x47166} \
+%{mmcu=msp6:-m msp430x5418} \
+%{mmcu=msp430x110:-m msp430x110 } \
+%{mmcu=msp430x112:-m msp430x112 } \
+%{mmcu=msp430x1101:-m msp430x1101 } \
+%{mmcu=msp430x1111:-m msp430x1111 } \
+%{mmcu=msp430x1121:-m msp430x1121 } \
+%{mmcu=msp430x1122:-m msp430x1122 } \
+%{mmcu=msp430x1132:-m msp430x1132 } \
+%{mmcu=msp430x122:-m msp430x122 } \
+%{mmcu=msp430x123:-m msp430x123 } \
+%{mmcu=msp430x1222:-m msp430x1222 } \
+%{mmcu=msp430x1232:-m msp430x1232 } \
+%{mmcu=msp430x133:-m msp430x133 } \
+%{mmcu=msp430x135:-m msp430x135 } \
+%{mmcu=msp430x1331:-m msp430x1331 } \
+%{mmcu=msp430x1351:-m msp430x1351 } \
+%{mmcu=msp430x147:-m msp430x147 } \
+%{mmcu=msp430x148:-m msp430x148 } \
+%{mmcu=msp430x149:-m msp430x149 } \
+%{mmcu=msp430x1471:-m msp430x1471 } \
+%{mmcu=msp430x1481:-m msp430x1481 } \
+%{mmcu=msp430x1491:-m msp430x1491 } \
+%{mmcu=msp430x155:-m msp430x155 } \
+%{mmcu=msp430x156:-m msp430x156 } \
+%{mmcu=msp430x157:-m msp430x157 } \
+%{mmcu=msp430x167:-m msp430x167 } \
+%{mmcu=msp430x168:-m msp430x168 } \
+%{mmcu=msp430x169:-m msp430x169 } \
+%{mmcu=msp430x1610:-m msp430x1610 } \
+%{mmcu=msp430x1611:-m msp430x1611 } \
+%{mmcu=msp430x1612:-m msp430x1612 } \
+%{mmcu=msp430x2001:-m msp430x2001 } \
+%{mmcu=msp430x2011:-m msp430x2011 } \
+%{mmcu=msp430x2002:-m msp430x2002 } \
+%{mmcu=msp430x2012:-m msp430x2012 } \
+%{mmcu=msp430x2003:-m msp430x2003 } \
+%{mmcu=msp430x2013:-m msp430x2013 } \
+%{mmcu=msp430x2101:-m msp430x2101 } \
+%{mmcu=msp430x2111:-m msp430x2111 } \
+%{mmcu=msp430x2121:-m msp430x2121 } \
+%{mmcu=msp430x2131:-m msp430x2131 } \
+%{mmcu=msp430x2112:-m msp430x2112 } \
+%{mmcu=msp430x2122:-m msp430x2122 } \
+%{mmcu=msp430x2132:-m msp430x2132 } \
+%{mmcu=msp430x2201:-m msp430x2201 } \
+%{mmcu=msp430x2211:-m msp430x2211 } \
+%{mmcu=msp430x2221:-m msp430x2221 } \
+%{mmcu=msp430x2231:-m msp430x2231 } \
+%{mmcu=msp430x2232:-m msp430x2232 } \
+%{mmcu=msp430x2252:-m msp430x2252 } \
+%{mmcu=msp430x2272:-m msp430x2272 } \
+%{mmcu=msp430x2234:-m msp430x2234 } \
+%{mmcu=msp430x2254:-m msp430x2254 } \
+%{mmcu=msp430x2274:-m msp430x2274 } \
+%{mmcu=msp430x233:-m msp430x233 } \
+%{mmcu=msp430x235:-m msp430x235 } \
+%{mmcu=msp430x2330:-m msp430x2330 } \
+%{mmcu=msp430x2350:-m msp430x2350 } \
+%{mmcu=msp430x2370:-m msp430x2370 } \
+%{mmcu=msp430x247:-m msp430x247 } \
+%{mmcu=msp430x248:-m msp430x248 } \
+%{mmcu=msp430x249:-m msp430x249 } \
+%{mmcu=msp430x2410:-m msp430x2410 } \
+%{mmcu=msp430x2471:-m msp430x2471 } \
+%{mmcu=msp430x2481:-m msp430x2481 } \
+%{mmcu=msp430x2491:-m msp430x2491 } \
+%{mmcu=msp430x2416:-m msp430x2416 } \
+%{mmcu=msp430x2417:-m msp430x2417 } \
+%{mmcu=msp430x2418:-m msp430x2418 } \
+%{mmcu=msp430x2419:-m msp430x2419 } \
+%{mmcu=msp430x2616:-m msp430x2616 } \
+%{mmcu=msp430x2617:-m msp430x2617 } \
+%{mmcu=msp430x2618:-m msp430x2618 } \
+%{mmcu=msp430x2619:-m msp430x2619 } \
+%{mmcu=msp430x311:-m msp430x311 } \
+%{mmcu=msp430x312:-m msp430x312 } \
+%{mmcu=msp430x313:-m msp430x313 } \
+%{mmcu=msp430x314:-m msp430x314 } \
+%{mmcu=msp430x315:-m msp430x315 } \
+%{mmcu=msp430x323:-m msp430x323 } \
+%{mmcu=msp430x325:-m msp430x325 } \
+%{mmcu=msp430x336:-m msp430x336 } \
+%{mmcu=msp430x337:-m msp430x337 } \
+%{mmcu=msp430x412:-m msp430x412 } \
+%{mmcu=msp430x413:-m msp430x413 } \
+%{mmcu=msp430x415:-m msp430x415 } \
+%{mmcu=msp430x417:-m msp430x417 } \
+%{mmcu=msp430x423:-m msp430x423 } \
+%{mmcu=msp430x425:-m msp430x425 } \
+%{mmcu=msp430x427:-m msp430x427 } \
+%{mmcu=msp430x4250:-m msp430x4250 } \
+%{mmcu=msp430x4260:-m msp430x4260 } \
+%{mmcu=msp430x4270:-m msp430x4270 } \
+%{mmcu=msp430xG4250:-m msp430xG4250 } \
+%{mmcu=msp430xG4260:-m msp430xG4260 } \
+%{mmcu=msp430xG4270:-m msp430xG4270 } \
+%{mmcu=msp430xE423:-m msp430xE423 } \
+%{mmcu=msp430xE425:-m msp430xE425 } \
+%{mmcu=msp430xE427:-m msp430xE427 } \
+%{mmcu=msp430xE4232:-m msp430xE4232 } \
+%{mmcu=msp430xE4242:-m msp430xE4242 } \
+%{mmcu=msp430xE4252:-m msp430xE4252 } \
+%{mmcu=msp430xE4272:-m msp430xE4272 } \
+%{mmcu=msp430xW423:-m msp430xW423 } \
+%{mmcu=msp430xW425:-m msp430xW425 } \
+%{mmcu=msp430xW427:-m msp430xW427 } \
+%{mmcu=msp430xG437:-m msp430xG437 } \
+%{mmcu=msp430xG438:-m msp430xG438 } \
+%{mmcu=msp430xG439:-m msp430xG439 } \
+%{mmcu=msp430x435:-m msp430x435 } \
+%{mmcu=msp430x436:-m msp430x436 } \
+%{mmcu=msp430x437:-m msp430x437 } \
+%{mmcu=msp430x4351:-m msp430x4351 } \
+%{mmcu=msp430x4361:-m msp430x4361 } \
+%{mmcu=msp430x4371:-m msp430x4371 } \
+%{mmcu=msp430x447:-m msp430x447 } \
+%{mmcu=msp430x448:-m msp430x448 } \
+%{mmcu=msp430x449:-m msp430x449 } \
+%{mmcu=msp430xG4616:-m msp430xG4616 } \
+%{mmcu=msp430xG4617:-m msp430xG4617 } \
+%{mmcu=msp430xG4618:-m msp430xG4618 } \
+%{mmcu=msp430xG4619:-m msp430xG4619 } \
+%{mmcu=msp430x4783:-m msp430x4783 } \
+%{mmcu=msp430x4784:-m msp430x4784 } \
+%{mmcu=msp430x4793:-m msp430x4793 } \
+%{mmcu=msp430x4794:-m msp430x4794 } \
+%{mmcu=msp430x47166:-m msp430x47166 } \
+%{mmcu=msp430x47176:-m msp430x47176 } \
+%{mmcu=msp430x47186:-m msp430x47186 } \
+%{mmcu=msp430x47196:-m msp430x47196 } \
+%{mmcu=msp430x47167:-m msp430x47167 } \
+%{mmcu=msp430x47177:-m msp430x47177 } \
+%{mmcu=msp430x47187:-m msp430x47187 } \
+%{mmcu=msp430x47197:-m msp430x47197 } \
+%{mmcu=msp430x5418:-m msp430x5418 } \
+%{mmcu=msp430x5419:-m msp430x5419 } \
+%{mmcu=msp430x5435:-m msp430x5435 } \
+%{mmcu=msp430x5436:-m msp430x5436 } \
+%{mmcu=msp430x5437:-m msp430x5437 } \
+%{mmcu=msp430x5438:-m msp430x5438 } \
+%{mmcu=msp430x5510:-m msp430x5510 } \
+%{mmcu=msp430x5513:-m msp430x5513 } \
+%{mmcu=msp430x5514:-m msp430x5514 } \
+%{mmcu=msp430x5515:-m msp430x5515 } \
+%{mmcu=msp430x5517:-m msp430x5517 } \
+%{mmcu=msp430x5519:-m msp430x5519 } \
+%{mmcu=msp430x5521:-m msp430x5521 } \
+%{mmcu=msp430x5522:-m msp430x5522 } \
+%{mmcu=msp430x5524:-m msp430x5524 } \
+%{mmcu=msp430x5525:-m msp430x5525 } \
+%{mmcu=msp430x5526:-m msp430x5526 } \
+%{mmcu=msp430x5527:-m msp430x5527 } \
+%{mmcu=msp430x5528:-m msp430x5528 } \
+%{mmcu=msp430x5529:-m msp430x5529 } \
+%{mmcu=msp430x6638:-m msp430x6638 } \
+%{mmcu=cc430x5133:-m cc430x5133 } \
+%{mmcu=cc430x5125:-m cc430x5125 } \
+%{mmcu=cc430x6125:-m cc430x6125 } \
+%{mmcu=cc430x6135:-m cc430x6135 } \
+%{mmcu=cc430x6126:-m cc430x6126 } \
+%{mmcu=cc430x5137:-m cc430x5137 } \
+%{mmcu=cc430x6127:-m cc430x6127 } \
+%{mmcu=cc430x6137:-m cc430x6137 }"
+
+#define LIB_SPEC "-lc"
+#define LIBGCC_SPEC "-lgcc"
+#define LIBSTDCXX "-lgcc"
+
+#define STARTFILE_SPEC "%(crt_binutils)"
+/* Another C string constant used much like `LINK_SPEC'.  The
+   difference between the two is that `STARTFILE_SPEC' is used at the
+   very beginning of the command given to the linker.
+
+   If this macro is not defined, a default is provided that loads the
+   standard C startup file from the usual place.  See `gcc.c'.  */
+
+#define ENDFILE_SPEC ""
+/* Another C string constant used much like `LINK_SPEC'.  The
+   difference between the two is that `ENDFILE_SPEC' is used at the
+   very end of the command given to the linker.
+
+   Do not define this macro if it does not need to do anything.  */
+
+#define CRT_BINUTILS_SPECS "\
+%{!mmcu=*|mmcu=msp430x110|mmcu=msp1:crt430x110.o%s} \
+%{mmcu=msp430x112:crt430x112.o%s} \
+%{mmcu=msp430x1101:crt430x1101.o%s} \
+%{mmcu=msp430x1111:crt430x1111.o%s} \
+%{mmcu=msp430x1121:crt430x1121.o%s} \
+%{mmcu=msp430x1122:crt430x1122.o%s} \
+%{mmcu=msp430x1132:crt430x1132.o%s} \
+%{mmcu=msp430x122:crt430x122.o%s} \
+%{mmcu=msp430x123:crt430x123.o%s} \
+%{mmcu=msp430x1222:crt430x1222.o%s} \
+%{mmcu=msp430x1232:crt430x1232.o%s} \
+%{mmcu=msp430x133:crt430x133.o%s} \
+%{mmcu=msp430x135:crt430x135.o%s} \
+%{mmcu=msp430x1331:crt430x1331.o%s} \
+%{mmcu=msp430x1351:crt430x1351.o%s} \
+%{mmcu=msp430x147:crt430x147.o%s} \
+%{mmcu=msp430x148:crt430x148.o%s} \
+%{mmcu=msp430x149:crt430x149.o%s} \
+%{mmcu=msp430x1471:crt430x1471.o%s} \
+%{mmcu=msp430x1481:crt430x1481.o%s} \
+%{mmcu=msp430x1491:crt430x1491.o%s} \
+%{mmcu=msp430x155:crt430x155.o%s} \
+%{mmcu=msp430x156:crt430x156.o%s} \
+%{mmcu=msp430x157:crt430x157.o%s} \
+%{mmcu=msp430x167:crt430x167.o%s} \
+%{mmcu=msp430x168:crt430x168.o%s} \
+%{mmcu=msp430x169:crt430x169.o%s} \
+%{mmcu=msp430x1610:crt430x1610.o%s} \
+%{mmcu=msp430x1611:crt430x1611.o%s} \
+%{mmcu=msp430x1612:crt430x1612.o%s} \
+%{mmcu=msp430x2001:crt430x2001.o%s} \
+%{mmcu=msp430x2011:crt430x2011.o%s} \
+%{mmcu=msp430x2002:crt430x2002.o%s} \
+%{mmcu=msp430x2012:crt430x2012.o%s} \
+%{mmcu=msp430x2003:crt430x2003.o%s} \
+%{mmcu=msp430x2013:crt430x2013.o%s} \
+%{mmcu=msp430x2101:crt430x2101.o%s} \
+%{mmcu=msp430x2111:crt430x2111.o%s} \
+%{mmcu=msp430x2121:crt430x2121.o%s} \
+%{mmcu=msp430x2131:crt430x2131.o%s} \
+%{mmcu=msp430x2112:crt430x2112.o%s} \
+%{mmcu=msp430x2122:crt430x2122.o%s} \
+%{mmcu=msp430x2132:crt430x2132.o%s} \
+%{mmcu=msp430x2201:crt430x2201.o%s} \
+%{mmcu=msp430x2211:crt430x2211.o%s} \
+%{mmcu=msp430x2221:crt430x2221.o%s} \
+%{mmcu=msp430x2231:crt430x2231.o%s} \
+%{mmcu=msp430x2232:crt430x2232.o%s} \
+%{mmcu=msp430x2252:crt430x2252.o%s} \
+%{mmcu=msp430x2272:crt430x2272.o%s} \
+%{mmcu=msp430x2234:crt430x2234.o%s} \
+%{mmcu=msp430x2254:crt430x2254.o%s} \
+%{mmcu=msp430x2274:crt430x2274.o%s} \
+%{mmcu=msp430x233:crt430x233.o%s} \
+%{mmcu=msp430x235:crt430x235.o%s} \
+%{mmcu=msp430x2330:crt430x2330.o%s} \
+%{mmcu=msp430x2350:crt430x2350.o%s} \
+%{mmcu=msp430x2370:crt430x2370.o%s} \
+%{mmcu=msp430x247:crt430x247.o%s} \
+%{mmcu=msp430x248:crt430x248.o%s} \
+%{mmcu=msp430x249:crt430x249.o%s} \
+%{mmcu=msp430x2410:crt430x2410.o%s} \
+%{mmcu=msp430x2471:crt430x2471.o%s} \
+%{mmcu=msp430x2481:crt430x2481.o%s} \
+%{mmcu=msp430x2491:crt430x2491.o%s} \
+%{mmcu=msp430x2416:crt430x2416.o%s} \
+%{mmcu=msp430x2417:crt430x2417.o%s} \
+%{mmcu=msp430x2418:crt430x2418.o%s} \
+%{mmcu=msp430x2419:crt430x2419.o%s} \
+%{mmcu=msp430x2616:crt430x2616.o%s} \
+%{mmcu=msp430x2617:crt430x2617.o%s} \
+%{mmcu=msp430x2618:crt430x2618.o%s} \
+%{mmcu=msp430x2619:crt430x2619.o%s} \
+%{mmcu=msp430x311:crt430x311.o%s} \
+%{mmcu=msp430x312:crt430x312.o%s} \
+%{mmcu=msp430x313:crt430x313.o%s} \
+%{mmcu=msp430x314:crt430x314.o%s} \
+%{mmcu=msp430x315:crt430x315.o%s} \
+%{mmcu=msp430x323:crt430x323.o%s} \
+%{mmcu=msp430x325:crt430x325.o%s} \
+%{mmcu=msp430x336|mmcu=msp2:crt430x336.o%s} \
+%{mmcu=msp430x337:crt430x337.o%s} \
+%{mmcu=msp430x412:crt430x412.o%s} \
+%{mmcu=msp430x413:crt430x413.o%s} \
+%{mmcu=msp430x415:crt430x415.o%s} \
+%{mmcu=msp430x417:crt430x417.o%s} \
+%{mmcu=msp430x423:crt430x423.o%s} \
+%{mmcu=msp430x425:crt430x425.o%s} \
+%{mmcu=msp430x427:crt430x427.o%s} \
+%{mmcu=msp430x4250:crt430x4250.o%s} \
+%{mmcu=msp430x4260:crt430x4260.o%s} \
+%{mmcu=msp430x4270:crt430x4270.o%s} \
+%{mmcu=msp430xG4250:crt430xG4250.o%s} \
+%{mmcu=msp430xG4260:crt430xG4260.o%s} \
+%{mmcu=msp430xG4270:crt430xG4270.o%s} \
+%{mmcu=msp430xE423:crt430xE423.o%s} \
+%{mmcu=msp430xE425:crt430xE425.o%s} \
+%{mmcu=msp430xE427:crt430xE427.o%s} \
+%{mmcu=msp430xE4232:crt430xE4232.o%s} \
+%{mmcu=msp430xE4242:crt430xE4242.o%s} \
+%{mmcu=msp430xE4252:crt430xE4252.o%s} \
+%{mmcu=msp430xE4272:crt430xE4272.o%s} \
+%{mmcu=msp430xW423:crt430xW423.o%s} \
+%{mmcu=msp430xW425:crt430xW425.o%s} \
+%{mmcu=msp430xW427:crt430xW427.o%s} \
+%{mmcu=msp430xG437:crt430xG437.o%s} \
+%{mmcu=msp430xG438:crt430xG438.o%s} \
+%{mmcu=msp430xG439:crt430xG439.o%s} \
+%{mmcu=msp430x435:crt430x435.o%s} \
+%{mmcu=msp430x436:crt430x436.o%s} \
+%{mmcu=msp430x437:crt430x437.o%s} \
+%{mmcu=msp430x4351:crt430x4351.o%s} \
+%{mmcu=msp430x4361:crt430x4361.o%s} \
+%{mmcu=msp430x4371:crt430x4371.o%s} \
+%{mmcu=msp430x447:crt430x447.o%s} \
+%{mmcu=msp430x448:crt430x448.o%s} \
+%{mmcu=msp430x449:crt430x449.o%s} \
+%{mmcu=msp430xG4616|mmcu=msp3:crt430xG4616.o%s} \
+%{mmcu=msp430xG4617:crt430xG4617.o%s} \
+%{mmcu=msp430xG4618:crt430xG4618.o%s} \
+%{mmcu=msp430xG4619:crt430xG4619.o%s} \
+%{mmcu=msp430x4783|mmcu=msp4:crt430x4783.o%s} \
+%{mmcu=msp430x4784:crt430x4784.o%s} \
+%{mmcu=msp430x4793:crt430x4793.o%s} \
+%{mmcu=msp430x4794:crt430x4794.o%s} \
+%{mmcu=msp430x47166|mmcu=msp5:crt430x47166.o%s} \
+%{mmcu=msp430x47176:crt430x47176.o%s} \
+%{mmcu=msp430x47186:crt430x47186.o%s} \
+%{mmcu=msp430x47196:crt430x47196.o%s} \
+%{mmcu=msp430x47167:crt430x47167.o%s} \
+%{mmcu=msp430x47177:crt430x47177.o%s} \
+%{mmcu=msp430x47187:crt430x47187.o%s} \
+%{mmcu=msp430x47197:crt430x47197.o%s} \
+%{mmcu=msp430x5418|mmcu=msp6:crt430x5418.o%s} \
+%{mmcu=msp430x5419:crt430x5419.o%s} \
+%{mmcu=msp430x5435:crt430x5435.o%s} \
+%{mmcu=msp430x5436:crt430x5436.o%s} \
+%{mmcu=msp430x5437:crt430x5437.o%s} \
+%{mmcu=msp430x5438:crt430x5438.o%s} \
+%{mmcu=msp430x5510:crt430x5510.o%s} \
+%{mmcu=msp430x5513:crt430x5513.o%s} \
+%{mmcu=msp430x5514:crt430x5514.o%s} \
+%{mmcu=msp430x5515:crt430x5515.o%s} \
+%{mmcu=msp430x5517:crt430x5517.o%s} \
+%{mmcu=msp430x5519:crt430x5519.o%s} \
+%{mmcu=msp430x5521:crt430x5521.o%s} \
+%{mmcu=msp430x5522:crt430x5522.o%s} \
+%{mmcu=msp430x5524:crt430x5524.o%s} \
+%{mmcu=msp430x5525:crt430x5525.o%s} \
+%{mmcu=msp430x5526:crt430x5526.o%s} \
+%{mmcu=msp430x5527:crt430x5527.o%s} \
+%{mmcu=msp430x5528:crt430x5528.o%s} \
+%{mmcu=msp430x5529:crt430x5529.o%s} \
+%{mmcu=msp430x6638:crt430x6638.o%s} \
+%{mmcu=cc430x5133:crtcc430x5133.o%s} \
+%{mmcu=cc430x5125:crtcc430x5125.o%s} \
+%{mmcu=cc430x6125:crtcc430x6125.o%s} \
+%{mmcu=cc430x6135:crtcc430x6135.o%s} \
+%{mmcu=cc430x6126:crtcc430x6126.o%s} \
+%{mmcu=cc430x5137:crtcc430x5137.o%s} \
+%{mmcu=cc430x6127:crtcc430x6127.o%s} \
+%{mmcu=cc430x6137:crtcc430x6137.o%s}"
+
+#define CPP_MSP1_SPEC " -DMSP430_NO_HW_MUL "
+#define CPP_MSP2_SPEC " -DMSP430_HAS_HW_MUL -DMSP430_HAS_HWMUL "
+#define CPP_MSP3_SPEC " -DMSP430_HAS_HW_MUL -DMSP430_HAS_HWMUL -D__MSP430X__"
+#define CPP_MSP4_SPEC " -DMSP430_HAS_HW_MUL -DMSP430_HAS_HWMUL"
+#define CPP_MSP5_SPEC " -DMSP430_HAS_HW_MUL -DMSP430_HAS_HWMUL -D__MSP430X__"
+#define CPP_MSP6_SPEC " -DMSP430_HAS_HW_MUL -DMSP430_HAS_HWMUL -D__MSP430X2__"
+
+#define EXTRA_SPECS                           	\
+{"cpp_msp1",CPP_MSP1_SPEC},			\
+{"cpp_msp2",CPP_MSP2_SPEC},			\
+{"cpp_msp3",CPP_MSP3_SPEC},			\
+{"cpp_msp4",CPP_MSP4_SPEC},			\
+{"cpp_msp5",CPP_MSP5_SPEC},			\
+{"cpp_msp6",CPP_MSP6_SPEC},			\
+{"crt_binutils", CRT_BINUTILS_SPECS},
+
+/* Define this macro to provide additional specifications to put in
+   the `specs' file that can be used in various specifications like
+   `CC1_SPEC'.
+
+   The definition should be an initializer for an array of structures,
+   containing a string constant, that defines the specification name,
+   and a string constant that provides the specification.
+
+   Do not define this macro if it does not need to do anything.
+
+   `EXTRA_SPECS' is useful when an architecture contains several
+   related targets, which have various `..._SPECS' which are similar
+   to each other, and the maintainer would like one central place to
+   keep these definitions.
+
+   For example, the PowerPC System V.4 targets use `EXTRA_SPECS' to
+   define either `_CALL_SYSV' when the System V calling sequence is
+   used or `_CALL_AIX' when the older AIX-based calling sequence is
+   used.
+
+   The `config/rs6000/rs6000.h' target file defines:
+
+   #define EXTRA_SPECS \
+   { "cpp_sysv_default", CPP_SYSV_DEFAULT },
+
+   #define CPP_SYS_DEFAULT ""
+
+   The `config/rs6000/sysv.h' target file defines:
+   #undef CPP_SPEC
+   #define CPP_SPEC \
+   "%{posix: -D_POSIX_SOURCE } \
+   %{mcall-sysv: -D_CALL_SYSV } %{mcall-aix: -D_CALL_AIX } \
+   %{!mcall-sysv: %{!mcall-aix: %(cpp_sysv_default) }} \
+   %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT}"
+
+   #undef CPP_SYSV_DEFAULT
+   #define CPP_SYSV_DEFAULT "-D_CALL_SYSV"
+
+   while the `config/rs6000/eabiaix.h' target file defines
+   `CPP_SYSV_DEFAULT' as:
+
+   #undef CPP_SYSV_DEFAULT
+   #define CPP_SYSV_DEFAULT "-D_CALL_AIX"  */
+
+
+#define MULTILIB_DEFAULTS { "mmcu=msp430x110" }
+
+#define TEST_HARD_REG_CLASS(CLASS, REGNO) \
+  TEST_HARD_REG_BIT (reg_class_contents[ (int) (CLASS)], REGNO)
+
+/* Note that the other files fail to use these
+   in some of the places where they should.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+#define AS2(a,b,c) #a " " #b "," #c
+#define AS2C(b,c) " " #b "," #c
+#define AS3(a,b,c,d) #a " " #b "," #c "," #d
+#define AS1(a,b) #a " " #b
+#else
+#define AS1(a,b) "a	b"
+#define AS2(a,b,c) "a	b,c"
+#define AS2C(b,c) " b,c"
+#define AS3(a,b,c,d) "a	b,c,d"
+#endif
+#define OUT_AS1(a,b) output_asm_insn (AS1(a,b), operands)
+#define OUT_AS2(a,b,c) output_asm_insn (AS2(a,b,c), operands)
+#define CR_TAB "\n\t"
+
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#define DWARF2_DEBUGGING_INFO 1
+#define OBJECT_FORMAT_ELF
+
+#define DBX_REGISTER_NUMBER(r) (r)
+
+/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+
+struct machine_function GTY(())
+{
+  /* 'true' - if the current function is a leaf function.  */
+  int is_leaf;
+
+  /* 'true' - if current function is a naked function.  */
+  int is_naked;
+
+  /* 'true' - if current function is an interrupt function 
+     as specified by the "interrupt" attribute.  */
+  int is_interrupt;
+
+  /* 'true' - if current function is a 'task' function 
+     as specified by the "OS_task" attribute.  */
+  int is_OS_task;
+ 
+  int is_noint_hwmul;
+  
+  int is_critical;
+  
+  int is_reenterant;
+  
+  int is_wakeup;
+  
+  int is_signal;
+};
+
+#ifdef RTX_CODE
+extern int default_rtx_costs (rtx X ATTRIBUTE_UNUSED, enum rtx_code code, enum rtx_code outer_code ATTRIBUTE_UNUSED);
+#endif
diff -ruNp gcc-4.x/gcc/config/msp430/msp430.md gcc-4.4.5/gcc/config/msp430/msp430.md
--- gcc-4.x/gcc/config/msp430/msp430.md	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430.md	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,4281 @@
+;; -*- Mode: Scheme -*-
+;;   Machine description for GNU compiler,
+;;   for Texas Instruments msp430 MCUs
+;;   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+;;   Contributed by Dmitry Diky <diwil@mail.ru>
+;;	 GCC 4.x port by Ivan Shcherbakov <mspgcc@sysprogs.org>
+
+;; This work is partially financed by the European Commission under the
+;; Framework 6 Information Society Technologies Project
+;; "Wirelessly Accessible Sensor Populations (WASP)".
+
+;
+
+; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(include "predicates.md")
+
+;; Special characters after '%':
+;;  A  No effect (add 0).
+;;  B  Add 1 to REG number, 2 to MEM address or CONST_INT.
+;;  C	   2		    4
+;;  D	   3		    6
+;;  E  adds nothing to reg but used only with (mem:hi (reg:hi))
+;;  F  no trim array
+;;  M  Add 0 to address if using stack pointer
+;;  N  Add 2 to address if using stack pointer
+;;  Extra constarains:
+;;  P  hardware constants: -1,0,+1,+2,+4,+8
+;;  Q  Indexed destination register as X(Rn)
+;;  R  Indexed source register as @Rn+
+;;  S  Symbol reference for 'C' like: a = *b;
+;;
+
+;; Unspec usage:
+;; 3 - strlen
+;; 0  - addc_reg
+;; 5  - addc_any
+;; 1  - bittest_lo
+;; 2  - bittest_hi
+;; 6  - bittest
+;; 4  - swpb
+;; 7  - bittest_b
+;; 8  - move SF to SI with no conversion
+
+(define_constants
+  [(REG_PC			0)
+   (REG_SP			1)
+   (UNSPEC_EINT		100)
+   (UNSPEC_DINT		101)
+   (UNSPEC_EXPLICIT_BR 102)
+   (UNSPEC_PUSH_SREG 103)
+   (UNSPEC_SAVE_PC_TO_REG 104)
+   (UNSPEC_LOAD_SP	105)
+   (UNSPEC_PROLOGUE_PUSH 106)
+   (UNSPEC_POP_R2	107)
+   ]
+)
+
+;; Condition code settings.
+
+
+(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,further,oper,cbranch"
+  (const_string "none"))
+
+(define_attr "type" "branch,branch1,arith"
+  (const_string "arith"))
+
+(define_attr "msp430_has_hwmul" "yes,no"
+  (const (if_then_else (symbol_ref "MSP430_HAS_HWMUL_INTERNAL")
+		       (const_string "yes")
+		       (const_string "no"))))
+
+(define_attr "msp430_noint_hwmul" "" (symbol_ref "MSP430_NOINT_HWMUL"))
+
+;; The size of instructions in bytes.
+;; XXX may depend from "cc"
+
+;; for confitional branches
+(define_attr "length" ""
+  (cond [(eq_attr "type" "branch")
+         (if_then_else  (and (ge (minus (pc) (match_dup 0)) 
+	 				(const_int -508))
+                             (le (minus (pc) (match_dup 0)) 
+			     		(const_int  508)))
+                        (const_int 1)
+			(const_int 2))]
+	(const_int 2)
+))
+
+
+;;========================================================================
+;;  PUSH/POP helper functions
+;;
+
+
+(define_insn "*pushqi_pre_mod"
+[(set (mem:QI (pre_modify:HI (reg:HI 1)
+                (plus:HI (reg:HI 1) (const_int -2))))
+	(match_operand:QI 0 "general_operand" "rim"))]
+""
+"* return msp430_pushqi(insn, operands, NULL);"
+[(set_attr "length" "2")])
+
+(define_insn "*pushqi"
+  [(set (match_operand:QI 1 "push_operand" "=<")
+;;  [(set (mem:QI (post_dec (reg:HI 1)))	;PRE_DEC!
+        (match_operand:QI 0 "general_operand" "rim"))]
+  ""
+  "* return msp430_pushqi(insn, operands, NULL);"
+  [(set_attr "length" "2")])
+
+(define_insn "*pushhi"
+  [(set (match_operand:HI 1 "push_operand" "=<")
+        (match_operand:HI 0 "general_no_elim_operand" "rim"))]
+  ""
+  "* return msp430_pushhi(insn, operands, NULL);"
+  [(set_attr "length" "2")])
+
+(define_insn "pushhi_prologue"
+  [(set (match_operand:HI 1 "push_operand" "=<")
+        (match_operand:HI 0 "general_operand" "rim"))
+	(unspec_volatile:HI [(const_int 0)] UNSPEC_PROLOGUE_PUSH)]
+  ""
+  "* return msp430_pushhi(insn, operands, NULL);"
+  [(set_attr "length" "2")])
+
+  
+;(define_insn_and_split "*pushhi"
+;  [(set (match_operand:HI 1 "push_operand" "=<")
+;        (match_operand:HI 0 "general_operand" "rim"))]
+;  ""
+;  "* return msp430_pushhi(insn, operands, NULL);"
+;  "(GET_CODE(operands[0]) == REG) && ((REGNO(operands[0]) == REG_SP) || (operands[0] == arg_pointer_rtx) || (operands[0] == frame_pointer_rtx) || IN_RANGE (REGNO (operands[0]), FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER))"
+;  [
+;	(set (match_dup 2) (match_dup 0))
+;	(set (match_dup 1) (match_dup 2))
+;  ]
+;  "operands[2] = gen_rtx_reg(SImode);"
+;  [(set_attr "length" "2")]
+; )
+
+ 
+
+(define_insn "*pushsi"
+  [(set (match_operand:SI 1 "push_operand" "=<")
+;;  [(set (mem:SI (post_dec (reg:HI 1))) ;PRE_DEC!
+        (match_operand:SI 0 "general_operand" "rmi"))]
+  ""
+  "* return msp430_pushsisf(insn, operands, NULL);"
+  [(set_attr "length" "4")])
+
+
+(define_insn "*pushdi"
+  [(set (match_operand:DI 1 "push_operand" "=<")
+;;  [(set (mem:DI (post_dec (reg:HI 1)))	;PRE_DEC!
+        (match_operand:DI 0 "general_operand" "rmi"))]
+  ""
+  "* return msp430_pushdi(insn, operands, NULL);"
+  [(set_attr "length" "8")])
+
+
+(define_insn "*pushsf"
+  [(set (match_operand:SF 1 "push_operand" "=<")
+;;  [(set (mem:SF (post_dec (reg:HI 1)))	;PRE+DEC
+        (match_operand:SF 0 "general_operand" "rmi"))]
+  ""
+  "* return msp430_pushsisf(insn, operands, NULL);"
+  [(set_attr "length" "4")])
+  
+(define_insn "push_sreg"
+  [(unspec_volatile:HI [(const_int 0)] UNSPEC_PUSH_SREG)
+   (set (reg:HI REG_SP) (minus:HI 
+                           (reg:HI REG_SP)
+                           (const_int 2)))]
+  ""
+  "push r2"
+  [(set_attr "length" "2")])
+
+
+;; =========================================== POP register instruction ====================================
+
+;; The POP instruction is used only by expand_epilogue() function.
+;; As present implementation of DWARF2 CFA generator (gcc 4.4.2) does
+;; not recognize pop_operand-based or post_inc-based operations,
+;; the short and neat definition (first one) cannot be used.
+;; Instead, we use a longer PARALLEL format to define the action of
+;; "pop", so the DWARF2 generator will be happy.
+
+;;(define_insn "pophi_reg"
+;;  [(set (match_operand:HI 0 "register_operand" "=r")
+;;		(match_operand:HI 1 "pop_operand" ">"))]
+;;  ""
+;;  "pop %0"
+;;  [(set_attr "length" "1")])
+
+(define_insn "pophi_reg"
+  [(parallel [
+    (set (reg:HI REG_SP) (plus:HI (reg:HI REG_SP) (const_int 2)))				;;This goes first, so the DWARF2 generator can recognize it
+	(set (match_operand:HI 0 "register_operand" "=r") (mem:HI (reg:HI REG_SP)))	;;This goes second with RTX_FRAME_RELATED_P() set to 0
+	]
+	)]
+  ""
+  "pop\t%0"
+  [(set_attr "length" "1")])
+
+(define_insn "pop_r2"
+  [(set (reg:HI REG_SP) (plus:HI (reg:HI REG_SP) (const_int 2)))
+	(unspec_volatile:HI [(const_int 0)] UNSPEC_POP_R2)]
+  ""
+  "pop\tr2"
+  [(set_attr "length" "2")])
+
+(define_insn "save_pc_to_reg"
+  [(unspec_volatile:HI [(const_int 0)] UNSPEC_SAVE_PC_TO_REG)
+   (set (match_operand:HI 0 "register_operand" "=r") (reg:HI REG_PC))]
+  ""
+  "mov\tr0, %0"
+  [(set_attr "length" "2")])
+  
+;; =================================================================================================
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "general_operand" ""))
+   (set (mem:HI (post_dec (reg:HI 1)))
+	(match_dup 0))]
+"dead_or_set_in_peep(1, insn, operands[0])"
+  [(set (mem:HI (post_dec (reg:HI 1)))
+	(match_dup 1))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "general_operand" ""))
+   (set (mem:SI (post_dec (reg:HI 1)))
+	(match_dup 0))]
+"dead_or_set_in_peep(1, insn, operands[0])"
+  [(set (mem:SI (post_dec (reg:HI 1)))
+	(match_dup 1))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SF 0 "register_operand" "") 
+	(match_operand:SF 1 "general_operand" ""))
+   (set (mem:SF (post_dec (reg:HI 1)))
+	(match_dup 0))]
+"dead_or_set_in_peep(1, insn, operands[0])"
+  [(set (mem:SF (post_dec (reg:HI 1)))
+	(match_dup 1))]
+"")
+
+
+;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;; This instructin sets Z flag
+
+(define_insn "sez"
+  [(set (cc0) (const_int 0))]
+""
+"setz"
+  [(set_attr "length" "1")
+   (set_attr "cc" "compare")])
+
+
+
+;;========================================================================
+;; compare
+
+(define_expand "cmpqi"
+  [(set (cc0)
+        (compare:QI (match_operand:QI 0 "nonimmediate_operand_msp430" "rm")   
+                    (match_operand:QI 1 "general_operand_msp430" "rmi")))]
+ ""
+"
+  msp430_compare_op0 = operands[0];
+  msp430_compare_op1 = operands[1];
+  DONE;
+")
+
+
+(define_expand "cmphi"
+  [(set (cc0)
+        (compare:HI (match_operand:HI 0 "nonimmediate_operand_msp430" "rm")   
+                    (match_operand:HI 1 "general_operand_msp430" "rmi")))]
+ ""
+"
+  msp430_compare_op0 = operands[0];
+  msp430_compare_op1 = operands[1];
+  DONE;
+")
+
+
+(define_expand "cmpsi"
+   [(set (cc0)
+         (compare:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+                     (match_operand:SI 1 "general_operand" "rmi")))]
+   ""
+"
+  msp430_compare_op0 = operands[0];
+  msp430_compare_op1 = operands[1];
+  DONE;
+")
+
+
+(define_expand "beq"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (EQ, operands[0]); DONE; }")
+
+(define_expand "bne"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (NE, operands[0]); DONE; }")
+
+(define_expand "bge"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (GE, operands[0]); DONE; }")
+
+(define_expand "bgt"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (GT, operands[0]); DONE; }")
+
+(define_expand "ble"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (LE, operands[0]); DONE; }")
+
+(define_expand "blt"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (LT, operands[0]); DONE; }")
+
+(define_expand "bgeu"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (GEU, operands[0]); DONE; }")
+
+(define_expand "bgtu"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (GTU, operands[0]); DONE; }")
+
+(define_expand "bleu"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (LEU, operands[0]); DONE; }")
+
+(define_expand "bltu"
+   [(use (match_operand 0 "" ""))]
+""
+"{ msp430_emit_cbranch (LTU, operands[0]); DONE; }")
+
+
+(define_insn "*cbranchqi"
+  [(set (pc)
+     (if_then_else (match_operator:QI 1 "comparison_operator"
+		    [(match_operand:QI 2 "nonimmediate_operand_msp430" "rm")
+		     (match_operand:QI 3 "general_operand" "rmi")])
+      (label_ref (match_operand 0 "" ""))
+      (pc)))]
+""
+"* return msp430_cbranch(insn, operands, NULL, 0);"
+ [(set_attr "length" "9") 
+ (set_attr "cc" "cbranch")])
+
+
+
+(define_insn "*cbranchhi"
+  [(set (pc)
+     (if_then_else (match_operator:HI 1 "comparison_operator"
+		    [(match_operand:HI 2 "nonimmediate_operand_msp430" "rm")
+		     (match_operand:HI 3 "general_operand" "rmi")])
+      (label_ref (match_operand 0 "" ""))
+      (pc)))]
+""
+"* return msp430_cbranch(insn, operands, NULL, 0);"
+ [(set_attr "length" "9")
+ (set_attr "cc" "cbranch")])
+
+
+(define_insn "*cbranchsi_eqne"
+  [(set (pc)
+     (if_then_else (match_operator:SI 1 "equality_operator"
+		    [(match_operand:SI 2 "nonimmediate_operand" "rm")
+		     (match_operand:SI 3 "general_operand" "rmi")])
+      (label_ref (match_operand 0 "" ""))
+      (pc)))]
+""
+"* return msp430_cbranch(insn, operands, NULL, 0);"
+[(set_attr "length" "9")
+ (set_attr "cc" "cbranch")])
+
+
+(define_insn "*cbranchsi_others"
+  [(parallel [(set (pc)
+     (if_then_else (match_operator:SI 1 "inequality_operator"
+		    [(match_operand:SI 2 "register_operand" "r")
+		     (match_operand:SI 3 "general_operand" "rmi")])
+      (label_ref (match_operand 0 "" ""))
+      (pc)))
+  (clobber (match_dup 2))])]
+""
+"* return msp430_cbranch(insn, operands, NULL, 0);"
+[(set_attr "length" "9")
+ (set_attr "cc" "cbranch")])
+
+
+(define_insn "*cbranch_uncoded"
+  [(set (pc)
+     (if_then_else (match_operator 1 "comparison_operator"
+		    [(cc0)
+		     (const_int 0)])
+      (label_ref (match_operand 0 "" ""))
+      (pc)))]
+""
+"* return msp430_cbranch(insn, operands, NULL, 1);"
+[(set_attr "length" "9")
+(set_attr "cc" "cbranch")])
+
+
+;;========================================================================
+;; noop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop"
+  [(set_attr "cc" "none")
+   (set_attr "length" "1")])
+
+
+;;============================================================================
+;; call
+;;
+
+(define_expand "call"
+  [(call (match_operand:HI 0 "general_operand" "")
+         (match_operand:HI 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn "*call_insn"
+  [(call (mem:HI (match_operand:HI 0 "general_operand" "r,P,mi"))
+         (match_operand:HI 1 "general_operand" "X,X,X"))]
+""
+"* return msp430_emit_call(operands);"
+[ (set_attr "length" "1,1,2")
+   (set_attr "cc" "clobber")])
+
+
+(define_expand "call_value"
+  [(set (match_operand 0 "register_operand" "")
+        (call (match_operand:HI 1 "general_operand" "")
+              (match_operand:HI 2 "general_operand" "")))]
+  ""
+  "")
+
+(define_insn "*call_value_insn"
+  [( set (match_operand 0 "register_operand" "=r,r,r")
+   (call (mem:HI (match_operand:HI 1 "general_operand" "r,P,mi"))
+	 (match_operand:HI 2 "general_operand" "X,X,X")))]
+""
+ "call\\t%N1"
+[ (set_attr "length" "1,1,2")
+   (set_attr "cc" "clobber")])
+
+
+
+
+
+;;========================================================================
+;;========================================================================
+;; mult helpers
+
+(define_insn "reent_in"
+  [(set (mem:HI (post_dec (reg:HI 1))) 
+        (unspec_volatile:HI [(const_int 99999999)] 10))]
+  ""
+  "push\\tr2
+\\tdint
+\\tnop"
+  [(set_attr "length" "4")
+   (set_attr "cc" "clobber")])
+
+;;
+;; Next three help to make sure, that
+;; all instructions are 'in order'
+
+(define_insn "fetch_result_qi"
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:QI [(const_int 0)] 12))
+  (set (mem:HI (post_inc (reg:HI 1)))
+	(unspec_volatile:HI [(const_int 99999999)] 11))]
+ ""
+ "mov.b\\t&__RESLO, %0
+\\tpop\\tr2"
+ [(set_attr "length" "3,4")
+  (set_attr "cc" "none")])
+ 
+(define_insn "fetch_result_hi"
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:HI [(const_int 0)] 13))
+  (set (mem:HI (post_inc (reg:HI 1)))
+	(unspec_volatile:HI [(const_int 99999999)] 11))]
+ ""
+ "mov\\t&__RESLO, %0
+\\tpop\\tr2"
+ [(set_attr "length" "3,4")
+  (set_attr "cc" "none")])
+
+(define_insn "fetch_result_si"
+ [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:SI [(const_int 0)] 14))
+  (set (mem:HI (post_inc (reg:HI 1)))
+	(unspec_volatile:HI [(const_int 99999999)] 11))]
+ ""
+ "mov\\t&__RESLO, %A0
+\\tmov\\t&__RESHI, %B0
+\\tpop\\tr2"
+ [(set_attr "length" "5,7")
+  (set_attr "cc" "none")])
+
+;; ===the same with no int
+
+(define_insn "fetch_result_qi_nint"
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:QI [(const_int 0)] 121))]
+ ""
+ "mov.b\\t&__RESLO, %0"
+ [(set_attr "length" "2,3")
+  (set_attr "cc" "none")])
+ 
+(define_insn "fetch_result_hi_nint"
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:HI [(const_int 0)] 131))]
+ ""
+ "mov\\t&__RESLO, %0"
+ [(set_attr "length" "2,3")
+  (set_attr "cc" "none")])
+
+(define_insn "fetch_result_si_nint"
+ [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "=r,m") 
+       (unspec_volatile:SI [(const_int 0)] 141))]
+ ""
+ "mov\\t&__RESLO, %A0
+\\tmov\\t&__RESHI, %B0"
+ [(set_attr "length" "4,6")
+  (set_attr "cc" "none")])
+
+(define_insn "addc_zero"
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m")
+   (unspec_volatile:HI [(const_int 0 )] 15))]
+ ""
+ "addc\\t#0, %0"
+[(set_attr "length" "1,2")
+ (set_attr "cc" "none")])
+
+(define_insn "subc_zero"
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m")
+   (unspec:HI [(const_int 0 )] 16))]
+ ""
+ "subc\\t#0, %0"
+[(set_attr "length" "1,2")
+ (set_attr "cc" "none")])
+
+(define_insn "load_mpy"
+ [(unspec_volatile:HI [(const_int 0)] 17)
+  (use (match_operand:HI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov\\t%0, &__MPY"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+
+
+(define_insn "load_mpys"
+  [(unspec_volatile:HI [(const_int 0)] 18)
+   (use (match_operand:HI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov\\t%0, &__MPYS"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+ 
+ 
+(define_insn "load_op2"
+  [(unspec_volatile:HI [(const_int 0)] 19)
+   (use (match_operand:HI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov\\t%0, &__OP2"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+ 
+
+(define_insn "load_mpyq"
+  [(unspec_volatile:QI [(const_int 0 )] 20)
+   (use (match_operand:QI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov.b\\t%0, &__MPY"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+
+
+(define_insn "load_mpysq"
+  [(unspec_volatile:QI [(const_int 0 )] 21)
+   (use (match_operand:QI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov.b\\t%0, &__MPYS"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+ 
+(define_insn "load_op2q"
+  [(unspec_volatile:QI [(const_int 0 )] 22)
+  (use (match_operand:QI 0 "general_operand_msp430" "rRP,mi"))]
+""
+"mov.b\\t%0, &__OP2"
+[(set_attr "length" "2,3")
+ (set_attr "cc" "none")])
+
+
+
+
+ 
+
+;;========================================================================
+;;========================================================================
+;;========================================================================
+;;
+;;  Multiplication 
+
+;;========================================================================
+;; 8 = 8x8 and 16 = 8x8
+
+(define_expand "mulqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (mult:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")
+                 (match_operand:QI 2 "general_operand_msp430" "")))]  
+  ""             
+"{ msp430_mul3_guard(operands,0); DONE; }")
+
+(define_insn "*mulqi3_call"
+  [(set (reg:QI 14) (mult:QI (reg:QI 10) (reg:QI 12)))
+	(clobber (reg:QI 10))
+	(clobber (reg:QI 12))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "call	#__mulqi3"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+;; ============= qi -> hi =======================================================
+(define_expand "mulqihi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand_msp430" ""))
+                 (sign_extend:HI (match_operand:QI 2 "general_operand_msp430" ""))))]
+""
+"{ msp430_mul3_guard(operands,1); DONE; }")
+
+(define_insn "*mulqihi3_call"
+  [(set (reg:HI 14) (mult:HI (sign_extend:HI (reg:QI 10))
+			     (sign_extend:HI (reg:QI 12))))
+        (clobber (reg:QI 10))
+        (clobber (reg:QI 12))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "call	#__mulqihi3"   
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+;; ============ unsigned ones ===================================================
+(define_expand "umulqihi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand_msp430" ""))
+                 (zero_extend:HI (match_operand:QI 2 "general_operand_msp430" ""))))]
+  ""
+  "{ msp430_umul3_guard(operands,0); DONE; }")  
+
+(define_insn "*umulqihi3_call"
+  [(set (reg:HI 14) (mult:HI (zero_extend:HI (reg:QI 10))
+                	     (zero_extend:HI (reg:QI 12))))
+        (clobber (reg:QI 10))
+        (clobber (reg:QI 12))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "call	#__umulqihi3" 
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+;;========================================================================
+;; 16 = 16x16 and 32 = 16x16
+
+(define_expand "mulhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (mult:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "")
+                 (match_operand:HI 2 "general_operand_msp430" "")))]  
+  ""
+"{msp430_mul3_guard(operands,0); DONE; } ")
+
+(define_insn "*mulhi3_call"
+  [(set (reg:HI 14) (mult:HI (reg:HI 10) (reg:HI 12)))
+	(clobber (reg:HI 10))
+	(clobber (reg:HI 12))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "call	#__mulhi3"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+;; ========================== hi -> si =============================
+(define_expand "mulhisi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "")
+        (mult:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand_msp430" ""))
+                 (sign_extend:SI (match_operand:HI 2 "general_operand_msp430" ""))))]
+""
+  "{msp430_mulhisi_guard(operands); DONE;}"
+)
+
+(define_insn "*mulhisi3_call"
+  [(set (reg:SI 14) (mult:SI (sign_extend:SI (reg:HI 10))
+			     (sign_extend:SI (reg:HI 12))))
+        (clobber (reg:HI 10))
+        (clobber (reg:HI 11))
+	(clobber (reg:HI 12))  
+	(clobber (reg:HI 13))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "mov	#0, r11
+	tst	r10
+	jge	+2
+	mov	#-1, r11
+	mov	#0, r13
+	tst	r12
+	jge	+2
+	mov	#-1, r13
+	call	#__mulhisi3"
+  [(set_attr "length" "10")
+   (set_attr "cc" "clobber")])
+
+;; ================== unsigned  hi -> si =============================
+(define_expand "umulhisi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "")
+        (mult:SI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand_msp430" ""))
+                 (zero_extend:SI (match_operand:HI 2 "general_operand_msp430" ""))))]
+  ""
+  "{msp430_umulhisi_guard(operands); DONE;}")
+
+(define_insn "*umulhisi3_call"
+  [(set (reg:SI 14) (mult:SI (zero_extend:SI (reg:HI 10))
+                	     (zero_extend:SI (reg:HI 12))))
+        (clobber (reg:HI 10))
+        (clobber (reg:HI 11))
+	(clobber (reg:HI 12))  
+	(clobber (reg:HI 13))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "clr	r11
+	clr	r13
+	call	#__umulhisi3" 
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+;;========================================================================
+;; 32 = 32x32.      64 = 32x32 <- via library calls only
+
+(define_expand "mulsi3"
+  [(set (reg:SI 10) (match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+   (set (reg:SI 12) (match_operand:SI 2 "general_operand_msp430" ""))
+   (set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))
+   (set (match_operand:SI 0 "nonimmediate_operand_msp430" "") (reg:SI 14))]
+""
+"{
+  if (!MSP430_HAS_HWMUL_INTERNAL)
+    {
+      emit_insn (gen_mulsi3_call (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
+
+(define_insn "*mulsi3hw_call_ni"
+  [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))]
+  "(!TARGET_INLINESIHWMUL) && MSP430_NOINT_HWMUL"
+  "call	#__umulsi3hw"
+[(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*mulsi3hw_call_ie"
+  [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))]
+  "(!TARGET_INLINESIHWMUL) && !MSP430_NOINT_HWMUL"
+  "push	r2
+	dint
+	call	#__umulsi3hw
+	pop	r2"
+[(set_attr "length" "5")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*mulsi3hw_inline_ni"
+  [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))]
+  "TARGET_INLINESIHWMUL && MSP430_HAS_HWMUL_INTERNAL && MSP430_NOINT_HWMUL"
+  "mov	r12, &__MPY
+	mov	r10, &__OP2
+	mov	r12, &__MAC
+	mov	&__RESLO, r14
+	mov	&__RESHI, &__RESLO
+	mov	r11, &__OP2
+	mov	r13, &__MAC
+	mov	r10, &__OP2
+	mov	&__RESLO, r15"
+[(set_attr "length" "19")  
+   (set_attr "cc" "none")])
+
+(define_insn "*mulsi3hw_inline_ie"
+  [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))]
+  "TARGET_INLINESIHWMUL && MSP430_HAS_HWMUL_INTERNAL && !MSP430_NOINT_HWMUL"
+  "push	r2
+	dint
+	nop
+	mov	r12, &__MPY
+	mov	r10, &__OP2
+	mov	r12, &__MAC
+	mov	&__RESLO, r14
+	mov	&__RESHI, &__RESLO
+	mov	r11, &__OP2
+	mov	r13, &__MAC
+	mov	r10, &__OP2
+	mov	&__RESLO, r15
+	pop	r2"
+[(set_attr "length" "23")  
+   (set_attr "cc" "none")])
+
+(define_expand "mulsi3_call"
+  [(set (reg:SI 10) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 12) (match_operand:SI 2 "register_operand" "")) 
+   (parallel [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))
+        (clobber (reg:SI 10))
+        (clobber (reg:SI 12))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 14))]
+"!MSP430_HAS_HWMUL_INTERNAL"
+"")
+
+(define_insn "*mulsi3_call"
+  [(set (reg:SI 14) (mult:SI (reg:SI 10) (reg:SI 12)))
+	(clobber (reg:SI 10))
+	(clobber (reg:SI 12))]
+  "!MSP430_HAS_HWMUL_INTERNAL"
+  "call	#__mulsi3"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+;; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % /
+;; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % /
+;; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % /
+;; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % /
+
+(define_expand "divmodqi4"
+  [(set (reg:QI 12) (match_operand:QI 1 "register_operand" ""))
+   (set (reg:QI 10) (match_operand:QI 2 "register_operand" ""))
+   (parallel [(set (reg:QI 12) (div:QI (reg:QI 12) (reg:QI 10)))
+              (set (reg:QI 14) (mod:QI (reg:QI 12) (reg:QI 10)))
+              (clobber (reg:QI 10))
+              (clobber (reg:QI 11))
+	      (clobber (reg:QI 13))])
+   (set (match_operand:QI 0 "register_operand" "") (reg:QI 12))
+   (set (match_operand:QI 3 "register_operand" "") (reg:QI 14))]
+  ""
+  "")
+
+(define_insn "*divmodqi4_call"
+  [(set (reg:QI 12) (div:QI (reg:QI 12) (reg:QI 10)))
+   (set (reg:QI 14) (mod:QI (reg:QI 12) (reg:QI 10)))
+   (clobber (reg:QI 10))
+   (clobber (reg:QI 11))
+   (clobber (reg:QI 13))]
+  ""
+  "call	#__divmodqi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodqi4"
+  [(set (reg:QI 12) (match_operand:QI 1 "register_operand" ""))
+   (set (reg:QI 10) (match_operand:QI 2 "register_operand" ""))
+   (parallel [(set (reg:QI 12) (udiv:QI (reg:QI 12) (reg:QI 10)))
+              (set (reg:QI 14) (umod:QI (reg:QI 12) (reg:QI 10)))
+              (clobber (reg:QI 10))
+              (clobber (reg:QI 11)) 
+              (clobber (reg:QI 13))])
+   (set (match_operand:QI 0 "register_operand" "") (reg:QI 12))
+   (set (match_operand:QI 3 "register_operand" "") (reg:QI 14))]
+  ""
+  "")
+
+(define_insn "*udivmodqi4_call"
+  [(set (reg:QI 12) (udiv:QI (reg:QI 12) (reg:QI 10)))
+   (set (reg:QI 14) (umod:QI (reg:QI 12) (reg:QI 10)))
+   (clobber (reg:QI 10))
+   (clobber (reg:QI 11)) 
+   (clobber (reg:QI 13))]
+  ""
+  "call	#__udivmodqi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+(define_expand "divmodhi4"
+  [(set (reg:HI 12) (match_operand:HI 1 "register_operand" ""))
+   (set (reg:HI 10) (match_operand:HI 2 "register_operand" ""))
+   (parallel [(set (reg:HI 12) (div:HI (reg:HI 12) (reg:HI 10)))
+              (set (reg:HI 14) (mod:HI (reg:HI 12) (reg:HI 10)))
+              (clobber (reg:HI 10))
+              (clobber (reg:HI 11))
+	      (clobber (reg:HI 13))])
+   (set (match_operand:HI 0 "register_operand" "") (reg:HI 12))
+   (set (match_operand:HI 3 "register_operand" "") (reg:HI 14))]
+  ""
+  "")
+
+(define_insn "*divmodhi4_call"
+  [(set (reg:HI 12) (div:HI (reg:HI 12) (reg:HI 10)))
+   (set (reg:HI 14) (mod:HI (reg:HI 12) (reg:HI 10)))
+   (clobber (reg:HI 10))
+   (clobber (reg:HI 11))
+   (clobber (reg:HI 13))]
+  ""
+  "call	#__divmodhi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodhi4"
+  [(set (reg:HI 12) (match_operand:HI 1 "register_operand" ""))
+   (set (reg:HI 10) (match_operand:HI 2 "register_operand" ""))
+   (parallel [(set (reg:HI 12) (udiv:HI (reg:HI 12) (reg:HI 10)))
+              (set (reg:HI 14) (umod:HI (reg:HI 12) (reg:HI 10)))
+              (clobber (reg:HI 10))
+              (clobber (reg:HI 11)) 
+              (clobber (reg:HI 13))])
+   (set (match_operand:HI 0 "register_operand" "") (reg:HI 12))
+   (set (match_operand:HI 3 "register_operand" "") (reg:HI 14))]
+  ""
+  "")
+
+(define_insn "*udivmodhi4_call"
+  [(set (reg:HI 12) (udiv:HI (reg:HI 12) (reg:HI 10)))
+   (set (reg:HI 14) (umod:HI (reg:HI 12) (reg:HI 10)))
+   (clobber (reg:HI 10))
+   (clobber (reg:HI 11)) 
+   (clobber (reg:HI 13))]
+  ""
+  "call	#__udivmodhi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+;; ///////////////// SINGLE INTEGER %%%%%%%%%%%%%%%%%
+
+(define_expand "divmodsi4"
+  [(set (reg:SI 12) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 10) (match_operand:SI 2 "register_operand" ""))
+   (parallel [(set (reg:SI 12) (div:SI (reg:SI 12) (reg:SI 10)))
+              (set (reg:SI 14) (mod:SI (reg:SI 12) (reg:SI 10)))
+              (clobber (reg:SI 10))
+              (clobber (reg:HI 9))
+	      (clobber (reg:HI 8))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 12))
+   (set (match_operand:SI 3 "register_operand" "") (reg:SI 14))]
+  ""
+  "")
+
+(define_insn "*divmodsi4_call"
+  [(set (reg:SI 12) (div:SI (reg:SI 12) (reg:SI 10)))
+   (set (reg:SI 14) (mod:SI (reg:SI 12) (reg:SI 10)))
+   (clobber (reg:SI 10))
+   (clobber (reg:HI 9))
+   (clobber (reg:HI 8))]
+  ""
+  "call	#__divmodsi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodsi4"
+  [(set (reg:SI 12) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 10) (match_operand:SI 2 "register_operand" ""))
+   (parallel [(set (reg:SI 12) (udiv:SI (reg:SI 12) (reg:SI 10)))
+              (set (reg:SI 14) (umod:SI (reg:SI 12) (reg:SI 10)))
+              (clobber (reg:SI 10))
+              (clobber (reg:HI 9)) 
+              (clobber (reg:HI 8))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 12))
+   (set (match_operand:SI 3 "register_operand" "") (reg:SI 14))]
+  ""
+  "")
+
+(define_insn "*udivmodsi4_call"
+  [(set (reg:SI 12) (udiv:SI (reg:SI 12) (reg:SI 10)))
+   (set (reg:SI 14) (umod:SI (reg:SI 12) (reg:SI 10)))
+   (clobber (reg:SI 10))
+   (clobber (reg:HI 9)) 
+   (clobber (reg:HI 8))]
+  ""
+  "call	#__udivmodsi4"
+   [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+
+
+;;========================================================================
+;; MOV STRING
+;;   structures and stuff are word aligned.
+;;   so, QI mode only defined (as HI actually)
+;;
+
+(define_expand "movstrhi"
+  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
+                   (match_operand:BLK 1 "memory_operand" ""))
+              (use (match_operand 2 "const_int_operand" ""))
+              (use (match_operand 3 "const_int_operand" ""))
+              (clobber (match_dup 4))
+              (clobber (match_dup 5))
+              (clobber (match_dup 6))])]
+  ""
+  " 
+{   
+  rtx addr0, addr1;
+  rtx a0, a1;
+  
+  if (GET_CODE (operands[2]) != CONST_INT) FAIL;
+
+  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+  
+  a0 = operands[0];
+  a1 = operands[1];
+  
+  operands[5] = addr0;
+  operands[6] = addr1;
+
+  operands[0] = gen_rtx_MEM (BLKmode, addr0);
+  operands[1] = gen_rtx_MEM (BLKmode, addr1);
+
+  if(INTVAL (operands[2]) <= 10 && !(INTVAL(operands[3])&1))
+  {
+    int x = INTVAL (operands[2]);
+    int y = (x&~1) >> 1;
+    int i = 0;
+     
+    while(y--)
+    {
+      rtx dest = gen_rtx_MEM (HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(i)));
+      emit_insn(gen_movstrhi5(dest,addr1));
+      i+= 2;
+    }
+
+    if(x & 1)
+    {
+      rtx real_dst = gen_rtx_MEM (HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(x-1)));
+      emit_insn(gen_movstrqi5(real_dst,addr1));
+    }
+    DONE;
+  }
+  else if(INTVAL (operands[2]) <= 6 && (INTVAL(operands[3])&1))
+  {
+    int x = INTVAL (operands[2]);
+    int i = 0;
+    
+    while(x--)
+    {
+      rtx dst = gen_rtx_MEM (HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(i)));
+      emit_insn(gen_movstrqi5(dst,addr1));
+      i++;
+    }
+    DONE;
+  }
+  else
+  {
+  	operands[2] = copy_to_mode_reg (HImode, operands[2]);
+  	operands[4] = operands[2];
+  }
+}
+")
+
+(define_insn "movstrqi5"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=m")
+	(mem:HI (match_operand:HI 1 "register_operand" "+r")))
+	(set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
+  ""
+  "mov.b	@%1+, %0"
+[(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
+(define_insn "movstrhi5"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=m")
+	(mem:HI (match_operand:HI 1 "register_operand" "+r")))
+	(set (match_dup 1) (plus:HI (match_dup 1) (const_int 2)))]
+ ""
+ "mov	@%1+, %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*movstrhi_insn"
+  [(set (mem:BLK (match_operand:HI 0 "register_operand" "r"))
+        (mem:BLK (match_operand:HI 1 "register_operand" "r")))
+   (use (match_operand:HI 2 "register_operand" "r"))
+   (use (match_operand 3 "const_int_operand" "i"))
+   (clobber (match_dup 2))
+   (clobber (match_dup 0))
+   (clobber (match_dup 1))]
+  ""
+  "* return movstrhi_insn(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*movstrqi_insn"
+  [(set (mem:BLK (match_operand:HI 0 "register_operand" "r"))
+        (mem:BLK (match_operand:HI 1 "register_operand" "r")))
+   (use (match_operand:QI 2 "register_operand" "r"))
+   (use (match_operand 3 "const_int_operand" "i"))
+   (clobber (match_dup 2))
+   (clobber (match_dup 0))
+   (clobber (match_dup 1))]
+  ""
+  "* return movstrhi_insn(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+
+
+;;========================================================================
+;; CLEAR STRING
+
+(define_expand "clrstrhi"
+  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
+                   (const_int 0))
+              (use (match_operand 1 "const_int_operand" ""))
+              (use (match_operand 2 "const_int_operand" "i"))
+              (clobber (match_dup 3))
+              (clobber (match_dup 4))])]
+  ""
+  " 
+{
+  rtx addr0;
+
+  if (GET_CODE (operands[1]) != CONST_INT) FAIL;
+  operands[1] = copy_to_mode_reg (HImode, operands[1]);
+  operands[3] = operands[1];
+  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+  operands[4] = addr0;
+  operands[0] = gen_rtx_MEM (BLKmode, addr0);
+}")
+
+
+(define_insn "*clrstrhi_insn"
+  [(set (mem:BLK (match_operand:HI 0 "register_operand" "r"))
+        (const_int 0))
+   (use (match_operand:HI 1 "register_operand" "r")) 
+   (use (match_operand 2 "const_int_operand" "i"))
+   (clobber (match_dup 1)) 
+   (clobber (match_dup 0))]
+  ""
+  "* return clrstrhi_insn(insn, operands, NULL);"
+[(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+
+;;========================================================================
+;; %0 = strchr(%1,%2) - %1
+
+(define_expand "strlenhi"
+  [(set (match_dup 4)
+            (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
+                        (match_operand 2 "const_int_operand" "")
+                        (match_operand:HI 3 "immediate_operand" "")] 3))
+     (set (match_operand:HI 0 "register_operand" "")
+          (minus:HI (match_dup 4)
+                    (match_dup 5)))]
+
+   ""
+   "
+{
+  rtx addr;
+
+  if (! (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0))
+	FAIL;
+  addr = copy_to_mode_reg (Pmode, XEXP (operands[1],0));
+  operands[1] = gen_rtx_MEM (BLKmode, addr); 
+  operands[5] = addr;
+  operands[4] = gen_reg_rtx (HImode);
+
+}")
+
+
+(define_insn "*strlenhi"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+        (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0"))
+                    (const_int 0)
+		    (match_operand:HI 2 "immediate_operand" "i") ] 3))]
+  ""
+"dec	%0
+.L__strlenhi__%=:
+	inc	%0
+	tst.b	0(%0)
+        jne	.L__strlenhi__%="
+[(set_attr "length" "5")
+   (set_attr "cc" "clobber")])
+
+
+;;========================================================================
+;; MOV code
+;;
+;;
+
+
+;;========================================================================
+;; move byte
+;; nothing much special
+;; all addressing modes allowed
+;; fits perfectly into a single instruction 
+
+(define_expand "movqi" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (match_operand:QI 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn "*movqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand"	"=m,m,m,m,r,r,r,r")
+	(match_operand:QI 1 "general_operand_msp430"	" m,r,P,i,m,r,P,i"))]
+  ""
+  "mov.b\\t%1, %0"
+  [(set_attr "length" "3,2,3,3,2,1,2,2")
+   (set_attr "cc" "none,none,none,none,none,none,none,none")])
+
+
+(define_insn "movqipi"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,m")
+	(mem:QI (post_inc:QI (match_operand:HI 1 "register_operand" "r,r"))))]
+  ""
+  "mov.b	@%1+, %0"
+[(set_attr "length" "1,2")
+   (set_attr "cc" "none,none")])
+
+
+
+;;============================================================================
+;; move word (16 bit)
+;; the same as above
+
+(define_expand "movhi" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (match_operand:HI 1 "general_operand_msp430" ""))]
+  ""
+  "msp430_expand_mov_intptr (operands[0], operands[1]); DONE;")
+
+(define_insn "*movhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"	"=m,m,m,m,r,r,r,r")
+	(match_operand:HI 1 "general_operand_msp430"		" r,m,P,i,r,m,P,i"))]
+  ""
+  "mov\\t%1, %0 "
+  [(set_attr "length" "2,3,3,3,1,2,2,2")
+   (set_attr "cc" "none")])
+
+(define_insn "movhipi"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m")
+	(mem:HI (post_inc:HI (match_operand:HI 1 "register_operand" "r,r"))))]
+  ""
+  "mov	@%1+, %0"
+[(set_attr "length" "1,2")
+   (set_attr "cc" "none,none")])
+
+;;============================================================================
+;; move long (32 bit)
+;; the same as above
+
+(define_expand "movsi" 
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (match_operand:SI 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn "*movsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"	"=rm")
+	(match_operand:SI 1 "general_operand"		" rmi"))]
+""
+"* return msp430_movesi_code(insn,operands,NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "none")])
+
+(define_insn "movsipi"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "=r,m")
+	(mem:SI (post_inc (match_operand:HI 1 "register_operand" "r,r"))))]
+  ""
+  "mov	@%1+, %A0
+	mov	@%1+, %B0"
+[(set_attr "length" "2,4")
+   (set_attr "cc" "none,none")])
+
+
+
+;;============================================================================
+;; floats are the SI
+
+(define_expand "movsf" 
+  [(set (match_operand:SF 0 "nonimmediate_operand" "")
+        (match_operand:SF 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn "*movsf3"
+  [(set (match_operand:SF 0 "nonimmediate_operand"	"=rm")
+	(match_operand:SF 1 "general_operand"		"rmi"))]
+""
+"* return msp430_movesi_code(insn,operands,NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "none")])
+
+
+(define_insn "movsfpi"
+  [(set (match_operand:SF 0 "nonimmediate_operand_msp430" "=r,m")
+	(mem:SF (post_inc (match_operand:HI 1 "register_operand" "r,r"))))]
+  ""
+  "mov	@%1+, %A0
+	mov	@%1+, %B0"
+[(set_attr "length" "2,4")
+   (set_attr "cc" "none,none")])
+
+;;============================================================================
+;; move long long (64 bit)
+;; the same as above
+(define_expand "movdi" 
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (match_operand:DI 1 "general_operand" ""))]
+  ""
+  "")
+
+(define_insn "*movdi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" 	"=rm")
+	(match_operand:DI 1 "general_operand"		"rmi"))]
+""
+"* return msp430_movedi_code(insn,operands,NULL);"
+  [(set_attr "length" "12")
+   (set_attr "cc" "none")])
+
+
+(define_insn "movdipi"
+  [(set (match_operand:DI 0 "nonimmediate_operand_msp430" "=r,m")
+	(mem:DI (post_inc (match_operand:HI 1 "register_operand" "r,r"))))]
+  ""
+  "mov	@%1+, %A0
+	mov	@%1+, %B0
+	mov	@%1+, %C0
+	mov	@%1+, %D0"
+[(set_attr "length" "4,8")
+   (set_attr "cc" "none,none")])
+
+
+;;============================================================================
+;;  ARITHMETIC CODE
+;;
+
+
+;;  random operations:
+
+(define_insn "*opqi3_pi"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"          "=r,m")
+	(match_operator:QI 3 "three_operands_msp430"
+	 [(match_operand:QI 1 "nonimmediate_operand_msp430" "%0,0")
+	 (mem:QI (post_inc (match_operand:HI 2 "register_operand" "r,r")))]))]
+""
+"%3.b	@%2+, %0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "oper,oper")])
+
+(define_insn "*ophi3_pi"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"          "=r,m")
+	(match_operator:HI 3 "three_operands_msp430"
+	 [(match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0")
+	  (mem:HI (post_inc (match_operand:HI 2 "register_operand" "r,r")))]))]
+""
+"%3	@%2+, %0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "oper,oper")])
+
+(define_insn "*opsi3_pi"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"          "=r,m")
+	(match_operator:SI 3 "three_operands_msp430"
+	 [(match_operand:SI 1 "nonimmediate_operand_msp430" "%0,0")
+	  (mem:SI (post_inc (match_operand:HI 2 "register_operand" "r,r")))]))]
+""
+"%A3\\t@%2+, %A0
+\\t%B3\\t@%2+, %B0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "oper,oper")])
+
+(define_insn "*opdi3_pi"
+  [(set (match_operand:DI 0 "nonimmediate_operand_msp430"          "=r,m")
+	(match_operator:DI 3 "three_operands_msp430"
+	 [(match_operand:DI 1 "nonimmediate_operand_msp430" "%0,0")
+	  (mem:DI (post_inc (match_operand:HI 2 "register_operand" "r,r")))]))]
+""
+"%A3\\t@%2+, %A0
+\\t%B3\\t@%2+, %B0
+\\t%C3\\t@%2+, %C0
+\\t%D3\\t@%2+, %D0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "oper,oper")])
+
+
+
+
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;; add 1 byte 
+
+
+(define_expand "addqi3" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (plus:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:QI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+(define_insn "*addqi3_cg"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=m,r")
+        (plus:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "%0,0")
+		 (match_operand:QI 2 "const_int_operand"      "i,i")))]
+"(INTVAL(operands[2]) == -2
+  || INTVAL(operands[2]) == -4
+  || INTVAL(operands[2]) == -8 )"
+"* {
+      operands[2] = gen_rtx_CONST_INT(QImode, -INTVAL(operands[2]));
+      return \"sub.b\\t%2, %0\";
+}"
+[(set_attr "length" "2,1")
+ (set_attr "cc" "set_czn,set_czn")])
+
+
+(define_insn "*addqi3_3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"          "=m,m,m,m,r,r,r,r")  
+        (plus:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "%0,0,0,0,0,0,0,0")  
+                 (match_operand:QI 2 "general_operand_msp430"      " m,r,P,i,m,r,P,i")))]  
+""
+  "add.b	%2, %0"
+  [(set_attr "length" "3,2,2,3,2,1,1,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+;;============================================================================
+;; add 1 word (16 bits)
+;; same as above
+
+
+(define_expand "addhi3" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (plus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "")
+                 (match_operand:HI 2 "general_operand_msp430" "")))]
+  ""
+  "")
+
+(define_insn "*addhi3_cg"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=m,r")
+	(plus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0")
+		 (match_operand:HI 2 "const_int_operand"      "i,i")))]
+"(INTVAL(operands[2]) == -2
+  || INTVAL(operands[2]) == -4
+  || INTVAL(operands[2]) == -8 )"
+"* {
+      operands[2] = gen_rtx_CONST_INT(HImode, -INTVAL(operands[2]));
+      return \"sub\\t%2, %0\" ;
+}"
+[(set_attr "length" "2,1")
+ (set_attr "cc" "set_czn,set_czn")])
+
+(define_insn "*addhi3_3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"          "=m,m,m,m,r,r,r,r")
+        (plus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0,0,0,0,0,0,0")
+                 (match_operand:HI 2 "general_operand_msp430"      " m,r,P,i,m,r,P,i")))]
+""
+  "add	%2, %0"
+  [(set_attr "length" "3,2,2,3,2,1,1,2")
+   (set_attr "cc"
+"set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+;;============================================================================
+;; add 2 words (32 bits)
+;; same as above
+
+(define_expand "addsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "")
+        (plus:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "")
+                 (match_operand:SI 2 "general_operand_msp430" "")))]
+  ""
+  "")
+
+(define_insn "*addsi3_cg"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "=m,r")
+	(plus:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "%0,0")
+		 (match_operand:SI 2 "const_int_operand"      "i,i")))]
+"(INTVAL(operands[2]) == -2
+  || INTVAL(operands[2]) == -4
+  || INTVAL(operands[2]) == -8 )"
+"* {
+     operands[2] = gen_rtx_CONST_INT(SImode, -INTVAL(operands[2]));
+     return \"sub\\t%A2, %A0\\n\\tsubc\\t%B2, %B0\" ;
+}"
+[(set_attr "length" "4,2")
+ (set_attr "cc" "further,further")])
+
+
+(define_insn "*addsi3_3"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"      "=rm")
+        (plus:SI (match_operand:SI 1 "general_operand_msp430"  "%0")
+                 (match_operand:SI 2 "general_operand_msp430"  " rmi")))]
+""
+"* return msp430_addsi_code(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "further")])
+
+
+;;============================================================================
+;; add 4 words (64 bits)
+;; same as above
+
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")   
+                 (match_operand:DI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*adddi3_cg"
+   [(set (match_operand:DI 0 "nonimmediate_operand_msp430" "=m,r")
+		  (plus:DI (match_operand:DI 1 "nonimmediate_operand_msp430" "%0,0")
+	          (match_operand:DI 2 "const_int_operand"      "i,i")))]
+"(INTVAL(operands[2]) == -2
+  || INTVAL(operands[2]) == -4
+  || INTVAL(operands[2]) == -8 )"
+"* {
+     operands[2] = gen_rtx_CONST_INT(DImode, -INTVAL(operands[2]));
+     return \"sub\\t%A2, %A0\\n\\tsubc\\t%B2, %B0\\n\\tsubc\\t%C2, %C0\\n\\tsubc\\t%D2, %D0\";
+}"
+[(set_attr "length" "4,2")
+(set_attr "cc" "further,further")])
+
+(define_insn "*adddi3_3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"      	"=rm")
+        (plus:DI (match_operand:DI 1 "nonimmediate_operand"  	"%0")
+                 (match_operand:DI 2 "general_operand"  	" rmi")))]
+""
+"* return msp430_adddi_code(insn, operands, NULL);"
+  [(set_attr "length" "12")
+   (set_attr "cc" "further")])
+
+
+;;-----------------------------------------------------------------------
+;;-----------------------------------------------------------------------
+;;-----------------------------------------------------------------------
+;;-----------------------------------------------------------------------
+;;-----------------------------------------------------------------------
+;; sub 1 byte 
+
+
+(define_expand "subqi3" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (minus:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")   
+                  (match_operand:QI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+(define_insn "*subqi3_3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"          "=m,m,m,m,r,r,r,r")  
+        (minus:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "0,0,0,0,0,0,0,0")  
+                 (match_operand:QI 2 "general_operand_msp430"      " m,r,P,i,m,r,P,i")))]  
+""
+  "sub.b	%2, %0"
+  [(set_attr "length" "3,2,2,3,2,1,1,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+;;============================================================================
+;; sub 1 word (16 bits)
+;; same as above
+
+
+(define_expand "subhi3" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (minus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "")
+                  (match_operand:HI 2 "general_operand_msp430" "")))]
+  ""
+  "")
+
+(define_insn "*subhi3_3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"          "=m,m,m,m,r,r,r,r")
+        (minus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0,0,0,0,0,0,0")
+                  (match_operand:HI 2 "general_operand_msp430"      "m,r,P,i,m,r,P,i")))]
+""
+  "sub	%2, %0"
+  [(set_attr "length" "3,2,2,3,2,1,1,2")
+   (set_attr "cc"
+"set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+;;============================================================================
+;; sub 2 words (32 bits)
+;; same as above
+
+(define_expand "subsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))]
+  "" 
+  "")
+
+
+(define_insn "*subsi3_3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"      "=rm")
+        (minus:SI (match_operand:SI 1 "general_operand"  "0")
+                 (match_operand:SI 2 "general_operand"  " rmi")))]
+""
+"* return msp430_subsi_code(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "further")])
+
+
+;;============================================================================
+;; sub 4 words (64 bits)
+;; same as above
+
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")   
+                 (match_operand:DI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*subdi3_3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"      	"=rm")
+        (minus:DI (match_operand:DI 1 "nonimmediate_operand"  	"0")
+                 (match_operand:DI 2 "general_operand"  	" rmi")))]
+""
+"* return msp430_subdi_code(insn, operands,NULL);"
+  [(set_attr "length" "12")
+   (set_attr "cc" "set_n")])
+
+
+
+
+
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+;; and 1 byte 
+
+
+(define_expand "andqi3" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (and:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:QI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+
+(define_insn "*andqi3_inv"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"         "=r,m")   
+        (and:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "%0,0")
+                (match_operand:QI 2 "immediate_operand"    " i,i")))]
+"(INTVAL(operands[2])==~1
+  || INTVAL(operands[2])==~2
+  || INTVAL(operands[2])==~4
+  || INTVAL(operands[2])==~8)"
+"* {
+	operands[2] = gen_rtx_CONST_INT(QImode, ~(INTVAL(operands[2])));
+	return \"bic.b	%2,%0\";
+}"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "none,none")])
+
+
+(define_insn "*andqi3_3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"      	"=r,m,r,m,r,m,m,r")
+        (and:QI (match_operand:QI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:QI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+"and.b	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+
+
+;;============================================================================
+;; and 1 word (16 bits)
+;; same as above
+
+(define_expand "andhi3" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (and:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0")   
+                 (match_operand:HI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+
+(define_insn "*andhi3_inv"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"         "=r,m")   
+        (and:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0")   
+                (match_operand:HI 2 "immediate_operand"    " i,i")))]
+"(INTVAL(operands[2])==~1
+  || INTVAL(operands[2])==~2
+  || INTVAL(operands[2])==~4
+  || INTVAL(operands[2])==~8)"
+"* {
+	operands[2] = gen_rtx_CONST_INT(HImode, ~(INTVAL(operands[2])));
+	return \"bic	%2,%0\";
+}"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "none,none")])
+
+(define_insn "*andhi3_clrup"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"         "=r,m")
+        (and:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0")
+                (match_operand:HI 2 "immediate_operand"    " i,i")))]
+"INTVAL(operands[2])==255"
+"* {
+	if(which_alternative == 0)
+	{
+		return \"and.b	#-1, %0\";
+	}
+	else if(which_alternative == 1)
+	{
+		return \"clr.b	%J0\";
+	}
+
+	return	\"bug\";
+}"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "clobber,clobber")])
+
+(define_insn "*andhi3_clrlw"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"         "=m,r")
+        (and:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0")
+                (match_operand:HI 2 "immediate_operand"     " i,i")))]
+"((0xffff&INTVAL(operands[2]))==0xff00)"
+"@
+clr.b	%I0
+and\\t#0xff00, %0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*andhi3_3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"      		"=r,m,r,m,r,m,m,r")
+        (and:HI (match_operand:HI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:HI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+"and	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+
+
+
+;;============================================================================
+;; and 2 words (32 bits)
+;; same as above
+
+(define_expand "andsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                (match_operand:SI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*andsi3_3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
+        (and:SI (match_operand:SI 1 "nonimmediate_operand"  "%0")
+                (match_operand:SI 2 "general_operand"       " rmi")))]
+""
+"* return msp430_andsi_code(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "set_n")])
+
+
+;;============================================================================
+;; and 4 words (64 bits)
+;; same as above
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (and:DI (match_operand:DI 1 "nonimmediate_operand" "")   
+                (match_operand:DI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*anddi3_3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"         "=rm")
+        (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+                (match_operand:DI 2 "general_operand"      " rmi")))]
+""
+"* return msp430_anddi_code(insn, operands, NULL);"
+  [(set_attr "length" "14")
+   (set_attr "cc" "clobber")])
+
+
+
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+;; ior 1 byte 
+;; looks like a 'mov' insn
+
+(define_expand "iorqi3" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (ior:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:QI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+(define_insn "*iorqi3_3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"      	"=r,m,r,m,r,m,m,r")
+        (ior:QI (match_operand:QI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:QI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+  "bis.b	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "none,none,none,none,none,none,none,none")])
+
+
+
+;;============================================================================
+;; ior 1 word (16 bits)
+;; same as above
+
+(define_expand "iorhi3" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (ior:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:HI 2 "general_operand_msp430" "")))]
+  "" 
+  "
+    if(const_int_operand(operands[2], VOIDmode))
+    {
+      int x = INTVAL(operands[2]) & 0xffff;
+      if(!x) DONE;
+    }
+  ")
+
+(define_insn "*iorhi3_3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"      	"=r,m,r,m,r,m,m,r")
+        (ior:HI (match_operand:HI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:HI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+  "bis	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "none,none,none,none,none,none,none,none")])
+
+
+
+;;============================================================================
+;; ior 2 words (32 bits)
+;; same as above
+
+
+(define_expand "iorsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*iorsi3_3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"      "=rm")
+        (ior:SI (match_operand:SI 1 "nonimmediate_operand"   "%0")
+                (match_operand:SI 2 "general_operand"   " rmi")))]
+""
+"* return msp430_iorsi_code(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "none")])
+
+(define_split
+ [(set (match_operand:SI 0 "nonimmediate_operand"          "")
+       (ior:SI (match_operand:SI 1 "nonimmediate_operand"  "")
+	       (match_operand:SI 2 "const_int_operand"     "")))]
+ "reload_completed
+  && (halfnibble_integer(operands[2], VOIDmode)
+       || halfnibble_constant(operands[2], VOIDmode))"
+ [(set (match_dup 3) (ior:HI (match_dup 4) (match_dup 5)))]
+ "{
+      int lo = trunc_int_for_mode(INTVAL(operands[2]),HImode);
+      int hi = trunc_int_for_mode(INTVAL(operands[2])>>16,HImode);
+ 
+      if(lo == -1)
+      {
+	rtx op = gen_lowpart(HImode, operands[0]);
+	emit_insn(gen_rtx_SET(HImode, op, GEN_INT(-1)));
+	DONE;
+      }
+      
+      if(hi == -1)
+      {
+	rtx op = gen_highpart(HImode, operands[0]);
+	emit_insn(gen_rtx_SET(HImode, op, GEN_INT(-1)));
+	DONE;
+      }
+      
+      if(lo)
+      {
+	operands[3] = gen_lowpart(HImode, operands[0]);
+	operands[4] = gen_lowpart(HImode, operands[1]);
+	operands[5] = GEN_INT(lo);
+      }
+      else if(hi)
+      {
+	operands[3] = gen_highpart(HImode, operands[0]);
+	operands[4] = gen_highpart(HImode, operands[1]);
+	operands[5] = GEN_INT(hi);
+      }
+ }")
+
+(define_peephole2
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "") 
+       (const_int 0))
+  (set (match_dup 0) (ior:HI (match_dup 0) 
+			     (match_operand:HI 1 "const_int_operand" "")))]
+ ""
+ [(set (match_dup 0) (match_dup 1))]
+ "")
+ 
+
+;;============================================================================
+;; ior 4 words (64 bits)
+;; same as above
+
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")   
+                (match_operand:DI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*iordi3_3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"          "=rm")
+        (ior:DI (match_operand:DI 1 "nonimmediate_operand"  "%0")
+                (match_operand:DI 2 "general_operand"  " rmi")))]
+""
+"* return msp430_iordi_code(insn, operands, NULL);"
+  [(set_attr "length" "12")
+   (set_attr "cc" "none")])
+
+
+
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;; xor 1 byte 
+;; looks like a 'mov' insn
+
+(define_expand "xorqi3" 
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (xor:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:QI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+(define_insn "*xorqi3_3"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"      	"=r,m,r,m,r,m,m,r")
+        (xor:QI (match_operand:QI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:QI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+  "xor.b	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+
+;;============================================================================
+;; xor 1 word (16 bits)
+;; same as above
+
+(define_expand "xorhi3" 
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (xor:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "")   
+                 (match_operand:HI 2 "general_operand_msp430" "")))]
+  "" 
+  "")
+
+(define_insn "*xorhi3_3"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"      	"=r,m,r,m,r,m,m,r")
+        (xor:HI (match_operand:HI 1 "nonimmediate_operand_msp430"  	"%0,0,0,0,0,0,0,0")
+                (match_operand:HI 2 "general_operand_msp430"  		" r,m,P,P,m,r,i,i")))]
+""
+  "xor	%2, %0"
+  [(set_attr "length" "1,3,1,2,2,2,3,2")
+   (set_attr "cc" "set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn,set_czn")])
+
+
+
+;;============================================================================
+;; xor 2 words (32 bits)
+;; same as above
+
+(define_expand "xorsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))]
+  "" 
+  "")
+
+
+(define_insn "*xorsi3_3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"      "=rm")
+        (xor:SI (match_operand:SI 1 "nonimmediate_operand"   "%0")
+                 (match_operand:SI 2 "general_operand"  " rmi")))]
+""
+"* return msp430_xorsi_code(insn, operands, NULL);"
+  [(set_attr "length" "6")
+   (set_attr "cc" "set_n")])
+
+
+(define_split
+ [(set (match_operand:SI 0 "nonimmediate_operand"          "")
+       (xor:SI (match_operand:SI 1 "nonimmediate_operand"  "")
+	       (match_operand:SI 2 "const_int_operand"     "")))]
+ "reload_completed 
+  && (halfnibble_integer(operands[2], VOIDmode)
+       || halfnibble_constant(operands[2], VOIDmode))
+  && INTVAL(operands[2])"
+ [(set (match_dup 3) (xor:HI (match_dup 4) (match_dup 5)))]
+ "{
+      int lo = trunc_int_for_mode(INTVAL(operands[2]),HImode);
+      int hi = trunc_int_for_mode(INTVAL(operands[2])>>16,HImode);
+      
+      if(lo)
+      {
+	operands[3] = gen_lowpart(HImode, operands[0]);
+	operands[4] = gen_lowpart(HImode, operands[1]);
+	operands[5] = GEN_INT(lo);
+      }
+      else if(hi)
+      {
+	operands[3] = gen_highpart(HImode, operands[0]);
+	operands[4] = gen_highpart(HImode, operands[1]);
+	operands[5] = GEN_INT(hi);
+      }
+ }")
+
+
+(define_peephole2
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "") 
+       (const_int 0))
+  (set (match_dup 0) (xor:HI (match_dup 0) 
+			     (const_int -1)))]
+ ""
+ [(set (match_dup 0) (const_int -1))]
+ "")
+ 
+
+;;============================================================================
+;; xor 4 words (64 bits)
+;; same as above
+
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")   
+                (match_operand:DI 2 "general_operand" "")))]
+  "" 
+  "")
+
+(define_insn "*xordi3_3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"          "=rm")
+        (xor:DI (match_operand:DI 1 "nonimmediate_operand"  "%0")
+                (match_operand:DI 2 "general_operand"  	    " rmi")))]
+""
+"* return msp430_xordi_code(insn, operands, NULL);"
+  [(set_attr "length" "4")
+   (set_attr "cc" "set_n")])
+
+
+
+
+
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;; neg
+;; same as above
+
+(define_expand "negqi2"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
+   (neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ ""
+ "{ emit_insn(gen_one_cmplqi2(operands[0],operands[1]));
+ emit_insn(gen_addqi3(operands[0],operands[0],const1_rtx));
+ DONE; }")
+
+(define_expand "neghi2"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))]
+ ""
+ "{ emit_insn(gen_one_cmplhi2(operands[0],operands[1]));
+ emit_insn(gen_addhi3(operands[0],operands[0],const1_rtx));
+ DONE; }")
+
+(define_expand "negsi2"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
+ ""
+
+ "{ emit_insn(gen_one_cmplsi2(operands[0],operands[1]));
+ emit_insn(gen_addsi3(operands[0],operands[0],const1_rtx));
+ DONE; }")
+
+(define_expand "negdi2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+   (neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
+ ""
+
+ "{ emit_insn(gen_one_cmpldi2(operands[0],operands[1]));
+ emit_insn(gen_adddi3(operands[0],operands[0],const1_rtx));
+ DONE; }")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,m")
+   (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))]
+ ""
+ "xor  #0x8000, %B0"
+ [(set_attr "length" "2,3")
+ (set_attr "cc" "clobber,clobber")])
+
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;; not	x = !x
+;; ones component
+
+(define_expand "one_cmplqi2"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+        (not:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "")))]
+  ""
+  "")
+
+(define_insn "*one_cmplqi2_2"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" 	   "=r,m")
+        (not:QI (match_operand:QI 1 "nonimmediate_operand_msp430" " 0, 0")))]
+  ""
+  "inv.b	%0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "set_czn,set_czn")])
+
+
+;;============================================================================
+;; not HI	x = !x
+;; - ones component
+
+(define_expand "one_cmplhi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "")
+        (not:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0")))]
+  ""
+  "")
+
+(define_insn "*one_cmplhi2_2"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" 	   "=r, m")
+        (not:HI (match_operand:HI 1 "nonimmediate_operand_msp430" " 0, 0")))]
+  ""
+  "inv	%0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "set_czn,set_czn")])
+
+
+
+;;============================================================================
+;; not SI	x = !x 
+;; - ones component
+
+(define_expand "one_cmplsi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
+  ""
+  "")
+
+(define_insn "*one_cmplsi2_2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" 	   "=r, m")
+        (not:SI (match_operand:SI 1 "nonimmediate_operand" " 0, 0")))]
+""
+  "inv	%A0
+	inv	%B0"
+  [(set_attr "length" "2,4")
+   (set_attr "cc" "set_n,set_n")])
+
+
+;;============================================================================
+;; not DI	x = !x
+;; - ones component
+
+(define_expand "one_cmpldi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
+  ""
+  "")
+
+(define_insn "*one_cmpldi2_2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" 	   "=r, m")
+        (not:DI (match_operand:DI 1 "nonimmediate_operand" " 0, 0")))]
+  ""
+  "inv	%A0
+	inv	%B0
+	inv	%C0
+	inv	%D0"
+  [(set_attr "length" "4,8")
+   (set_attr "cc" "set_n,set_n")])
+
+
+
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;;============================================================================
+;; abs
+;; x = |x|
+
+(define_expand "absqi2"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
+        (abs:QI (match_operand:QI 1 "nonimmediate_operand" "")))]
+  ""
+  "")
+
+(define_insn "*absqi2_2"
+  [(set (match_operand:QI 0 "nonimmediate_operand" 	   "=r,m")
+        (abs:QI (match_operand:QI 1 "nonimmediate_operand" " 0, 0")))]
+  ""
+	"tst.b	%0
+	jge	.Leaq%=
+	inv.b	%0
+	inc.b	%0
+.Leaq%=:"
+  [(set_attr "length" "4,7")
+   (set_attr "cc" "set_czn,set_czn")])
+
+
+;;============================================================================
+;; abs HI	x = |x|
+;; 
+
+(define_expand "abshi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
+        (abs:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
+  ""
+  "")
+
+
+(define_insn "*abshi2_2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" 	   "=r, m")
+        (abs:HI (match_operand:HI 1 "nonimmediate_operand" " 0, 0")))]
+  ""
+	"tst	%0
+	jge	.Lae%=
+	inv	%0
+	inc	%0
+.Lae%=:"
+  [(set_attr "length" "4,7")
+   (set_attr "cc" "set_czn,set_czn")])
+
+
+;;============================================================================
+;; abs SI	x = |x|
+
+(define_expand "abssi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (abs:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
+  ""
+  "")
+
+(define_insn "*abssi2_2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" 	   "=r, m")
+        (abs:SI (match_operand:SI 1 "nonimmediate_operand" " 0, 0")))]
+  ""
+  "* return msp430_emit_abssi(insn, operands,NULL);"
+  [(set_attr "length" "7,13")
+   (set_attr "cc" "clobber,clobber")])
+
+
+;;============================================================================
+;; abs DI	x = |x|
+
+(define_expand "absdi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (abs:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
+  ""
+  "")
+
+(define_insn "*absdi2_2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" 	   "=r, m")
+        (abs:DI (match_operand:DI 1 "nonimmediate_operand" " 0, 0")))]
+  ""
+  "* return msp430_emit_absdi(insn, operands,NULL);"
+  [(set_attr "length" "11,23")
+   (set_attr "cc" "clobber,clobber")])
+
+;;============================================================================
+;; abs SF
+
+(define_insn "abssf2"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,m")
+        (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))]
+""
+"and	#0x7fff, %B0"
+  [(set_attr "length" "2,3")
+   (set_attr "cc" "clobber,clobber")])
+
+
+;; ==========================================================================
+;; there are shift helpers
+
+(define_insn "trunchiqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,m") 
+	(truncate:QI (match_operand:HI 1 "register_operand" "r,r")))]
+""
+"mov.b	%1, %0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "none,none")])
+
+(define_insn "truncsihi"
+  [(set (match_operand:HI 0 "register_operand" "=r") 
+	(truncate:HI (match_operand:SI 1 "register_operand" "r")))]
+""
+"mov	%1, %0"
+  [(set_attr "length" "1")
+   (set_attr "cc" "none")])
+
+
+(define_insn "truncsiqi"
+  [(set (match_operand:QI 0 "register_operand" "=r") 
+	(truncate:QI (match_operand:SI 1 "register_operand" "r")))]
+""
+"mov.b	%1, %0"
+  [(set_attr "length" "1")
+   (set_attr "cc" "none")])
+
+
+(define_insn "truncdiqi"
+  [(set (match_operand:QI 0 "register_operand" "=r") 
+	(truncate:QI (match_operand:DI 1 "register_operand" "r")))]
+""
+"mov.b	%1, %0"
+  [(set_attr "length" "1")
+   (set_attr "cc" "none")])
+
+(define_insn "truncdisi"
+  [(set (match_operand:SI 0 "register_operand" "=r") 
+	(truncate:SI (match_operand:DI 1 "register_operand" "r")))]
+""
+"mov	%A1,%A0
+	mov    %B1,%B0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")])
+
+
+(define_expand "rotlhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand"       "")
+        (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "const_int_operand"  "")))]
+""
+"
+  if(INTVAL(operands[2])!=8) FAIL;
+")
+
+(define_insn "*rotlhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand"       "=rR,m")
+        (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
+                   (const_int 8)))]
+""
+"swpb\\t%0"
+  [(set_attr "length" "1,2")
+     (set_attr "cc" "none")])
+
+
+;;<< << << << << << << << << << << << << << << << << << << << << << << << <<
+;; << << << << << << << << << << << << << << << << << << << << << << << <<
+;;<< << << << << << << << << << << << << << << << << << << << << << << << <<
+;; << << << << << << << << << << << << << << << << << << << << << << << <<
+;;<< << << << << << << << << << << << << << << << << << << << << << << << <<
+;; arithmetic shift left
+
+(define_expand "ashlqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand"       "")
+        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
+                   (match_operand:QI 2 "general_operand"  "")))]
+""
+"{
+   if(!const_int_operand(operands[2],VOIDmode))
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(QImode,operands[0]);
+     op1 = force_reg(QImode,operands[1]);
+     operands[2] = copy_to_mode_reg(QImode,operands[2]);
+     emit_insn(gen_ashlqi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], QImode) 
+		&& is_shift_better_in_reg(operands))
+   {
+      operands[1] = copy_to_mode_reg(QImode,operands[1]);
+      emit_insn (gen_ashlqi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+}")
+
+(define_insn "ashlqi3_cnt"
+  [(parallel [(set (match_operand:QI 0 "register_operand"       "=r")
+	      (ashift:QI (match_operand:QI 1 "register_operand" "0")
+			 (match_operand:QI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_ashlqi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "ashlqi3fnl"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"       "=rm")
+        (ashift:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "0")
+                   (match_operand:QI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_ashlqi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+;; HImode  ======================================
+(define_expand "ashlhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand"       "")
+        (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                   (match_operand 2 "general_operand"  "")))]
+""
+"{ msp430_ashlhi3(operands); DONE; }")
+
+(define_insn "ashlhi3_cnt"
+  [(parallel [(set (match_operand:HI 0 "register_operand"       "=r")
+	      (ashift:HI (match_operand:HI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "r")))
+	      (clobber (match_dup 2))])]
+  ""
+  "* return msp430_emit_ashlhi3(insn, operands,NULL);"
+  [(set_attr "length" "5")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashlhi3_1"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashift:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0,0")
+                   (const_int 1)))]
+  ""
+  "rla\\t%0"
+  [(set_attr "length" "1,2,3")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashlhi3_15"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashift:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0,0")
+                   (const_int 15)))]
+  ""
+  "rra\\t%0
+\\tclr\\t%0
+\\trrc\\t%0"
+  [(set_attr "length" "3,5,7")
+   (set_attr "cc" "clobber")])
+
+
+;; SImode ======================================
+
+(define_expand "ashlsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"       "")
+        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{ msp430_ashlsi3(operands); DONE; }")
+
+(define_insn "ashlsi3_cnt"
+  [(parallel [(set (match_operand:SI 0 "register_operand"       "=r")
+	      (ashift:SI (match_operand:SI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_ashlsi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashlsi3_31"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashift:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+                   (const_int 31)))]
+  ""
+"rra\\t%A0
+\\tclr\\t%A0
+\\tclr\\t%B0
+\\trrc\\t%B0"
+[(set_attr "length" "4,7,8")
+  (set_attr "cc" "clobber")])
+
+
+(define_insn "*ashlsi3_8"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashift:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+                   (const_int 8)))]
+  ""
+"*{
+    if(which_alternative==0)
+    {
+      return \"xor.b\\t%A0, %B0\\n\\txor\\t%A0, %B0\\n\\tswpb\\t%B0\\n\\tand.b\\t#-1, %A0\\n\\tswpb\\t%A0 \";
+    }
+    else
+    {
+      return \"xor.b\\t%A0, %B0\\n\\tclr.b\\t%L0\\n\\txor\\t%A0, %B0\\n\\tswpb\\t%B0\\n\\tclr.b\\t%J0\\n\\tswpb\\t%A0\";
+    }
+}"
+  [(set_attr "length" "5,11,12")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashlsi3_16"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,m,r,m")
+        (ashift:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "rR,rR,m,m")
+                   (const_int 16)))]
+""
+"mov	%A1, %B0
+\tmov	#0, %A0"
+[(set_attr "length" "1,2,2,3")
+  (set_attr "cc" "clobber")])
+
+(define_insn "*ashlsi3_1"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=m,R,r")
+        (ashift:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+                   (const_int 1)))]
+  ""
+"rla\\t%A0
+\\trlc\\t%B0"
+[(set_attr "length" "6,5,2")
+  (set_attr "cc" "clobber")])
+
+;; DImode ======================================
+
+(define_expand "ashldi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "")
+        (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{
+   if( !const_int_operand(operands[2],VOIDmode) ||
+       INTVAL(operands[2]) > 1)
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(DImode,operands[0]);
+     op1 = force_reg(DImode,operands[1]);
+     operands[2] = copy_to_mode_reg(HImode,operands[2]);
+     emit_insn(gen_ashldi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], DImode) 
+		&& is_shift_better_in_reg(operands))
+   {
+      operands[1] = copy_to_mode_reg(DImode,operands[1]);
+      emit_insn (gen_ashldi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+}")
+
+(define_insn "ashldi3_cnt"
+  [(parallel [(set (match_operand:DI 0 "register_operand"       "=r")
+	      (ashift:DI (match_operand:DI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+  ""
+  "* return msp430_emit_ashldi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "ashldi3fnl"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "=rm")
+        (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                   (match_operand:HI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_ashldi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>      
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>      
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>      
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>      
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>     
+;; arithmetic shift right
+
+(define_expand "ashrqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand"       "")
+        (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
+                   (match_operand:QI 2 "general_operand"  "")))]
+""
+"{
+   if(!const_int_operand(operands[2],VOIDmode))
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(QImode,operands[0]);
+     op1 = force_reg(QImode,operands[1]);
+     operands[2] = copy_to_mode_reg(QImode,operands[2]);
+     emit_insn(gen_ashrqi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], QImode) 
+		&& INTVAL(operands[2])>2 
+		&& INTVAL(operands[2])!=7)
+   {
+      operands[1] = copy_to_mode_reg(QImode,operands[1]);
+      emit_insn (gen_ashrqi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+   else if(INTVAL(operands[2]) == 7)
+   {
+      /* to do it simple we need a register */
+      rtx r1 = gen_reg_rtx(HImode);
+      emit_insn(gen_extendqihi2(r1,operands[1]));
+      emit_insn(gen_swpb(r1,r1));
+      emit_insn(gen_trunchiqi(operands[0],r1));
+      DONE;
+   }
+}")
+
+(define_insn "ashrqi3_cnt"
+  [(parallel [(set (match_operand:QI 0 "register_operand"       "=r")
+	      (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+			 (match_operand:QI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_ashrqi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "ashrqi3fnl"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"       "=rm")
+        (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "0")
+                   (match_operand:QI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_ashrqi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+;; HImode  ======================================
+(define_expand "ashrhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand"       "")
+        (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                   (match_operand 2 "general_operand"  "")))]
+""
+"{msp430_ashrhi3(operands); DONE; }")
+
+(define_insn "ashrhi3_cnt"
+  [(parallel [(set (match_operand:HI 0 "register_operand"       "=r")
+	      (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_ashrhi3(insn, operands,NULL);"
+  [(set_attr "length" "5")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*ashrhi3_1"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=rR,m")
+        (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0")
+		     (const_int 1)))]
+  ""
+  "rra\\t%0"
+  [(set_attr "length" "1,2")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*ashrhi3_15"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=rR,m")
+        (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0")
+		     (const_int 15)))]
+  ""
+  "swpb\\t%0
+\\tsxt\\t%0
+\\tswpb\\t%0
+\\tsxt\\t%0"
+  [(set_attr "length" "4,8")
+   (set_attr "cc" "clobber")])
+
+
+
+;; SImode ======================================
+
+(define_expand "ashrsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"       "")
+        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{msp430_ashrsi3(operands);DONE; }")
+
+(define_insn "ashrsi3_cnt"
+  [(parallel [(set (match_operand:SI 0 "register_operand"       "=r")
+	      (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_ashrsi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashrsi3_1"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=rR,m")
+        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0")
+		     (const_int 1)))]
+  ""
+  "rra\\t%B0
+\\trrc\\t%A0"
+  [(set_attr "length" "2,4")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashrsi3_31"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 31)))]
+  ""
+"swpb	%B0
+\\tsxt	%B0
+\\tswpb	%B0
+\\tsxt	%B0
+\\tmov	%B0, %A0"
+  [(set_attr "length" "5,10,10")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*ashrsi3_8"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 8)))]
+  ""
+"*{
+    if(which_alternative==0)
+    {
+      return \" swpb\\t%A0\\n\\tswpb\\t%B0\\n\\txor.b\\t%B0, %A0\\n\\txor\\t%B0, %A0\\n\\tsxt\\t%B0\";
+    }
+    else
+    {
+      return \" swpb\\t%A0\\n\\tswpb\\t%B0\\n\\txor.b\\t%B0, %A0\\n\\tclr.b\\t%J0\\n\\txor\\t%B0, %A0\\n\\tsxt\\t%B0\";
+    }
+}"
+  [(set_attr "length" "5,11,12")
+   (set_attr "cc" "clobber")])
+
+;; DImode ======================================
+
+(define_expand "ashrdi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "")
+        (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{
+   if( !const_int_operand(operands[2],VOIDmode))
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(DImode,operands[0]);
+     op1 = force_reg(DImode,operands[1]);
+     operands[2] = copy_to_mode_reg(HImode,operands[2]);
+     emit_insn(gen_ashrdi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], DImode) 
+		&& is_shift_better_in_reg(operands))
+   {
+      operands[1] = copy_to_mode_reg(DImode,operands[1]);
+      emit_insn (gen_ashrdi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+}")
+
+(define_insn "ashrdi3_cnt"
+  [(parallel [(set (match_operand:DI 0 "register_operand"       "=r")
+	      (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+  ""
+  "* return msp430_emit_ashrdi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "ashrdi3fnl"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "=rm")
+        (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                   (match_operand:HI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_ashrdi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+
+
+
+
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>   
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>   
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>   
+;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>   
+;;  >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>   
+;; logical shift right
+
+(define_expand "lshrqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand"       "")
+        (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
+                   (match_operand:QI 2 "general_operand"  "")))]
+""
+"{
+   if(!const_int_operand(operands[2],VOIDmode))
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(QImode,operands[0]);
+     op1 = force_reg(QImode,operands[1]);
+     operands[2] = copy_to_mode_reg(QImode,operands[2]);
+     emit_insn(gen_lshrqi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], QImode) 
+		&& is_shift_better_in_reg(operands))
+   {
+      operands[1] = copy_to_mode_reg(QImode,operands[1]);
+      emit_insn (gen_lshrqi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+}")
+
+(define_expand "lshrqi3_cnt"
+  [(parallel [(set (match_operand:QI 0 "register_operand"       "=r")
+	      (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+			 (match_operand:QI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"")
+
+(define_insn "*lshrqi3_cnt"
+  [(parallel [(set (match_operand:QI 0 "register_operand"       "=r")
+	      (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+			 (match_operand:QI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_lshrqi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+(define_insn "lshrqi3fnl"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430"       "=rm")
+        (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "0")
+                   (match_operand:QI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_lshrqi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+;; HImode  ======================================
+
+(define_insn "clrc"
+ [(unspec:HI [(const_int 123454321)] 30)]
+""
+ "clrc"
+[(set_attr "length" "1")
+  (set_attr "cc" "clobber")])
+
+ 
+(define_expand "lshrhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand"       "")
+        (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                   (match_operand 2 "general_operand"  "")))]
+""
+"{msp430_lshrhi3(operands); DONE; }")
+
+(define_insn "lshrhi3_cnt"
+  [(parallel [(set (match_operand:HI 0 "register_operand"       "=r")
+	      (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_lshrhi3(insn, operands,NULL);"
+  [(set_attr "length" "5")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*lshrhi3_15"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 15)))]
+  ""
+  "rla\\t%0
+\\tclr\\t%0
+\\trlc\\t%0"
+  [(set_attr "length" "3,6,8")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*lshrhi3_1"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430"       "=rR,m")
+        (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "0,0")
+		     (const_int 1)))]
+  ""
+"clrc
+\\trrc\\t%0"
+  [(set_attr "length" "2,3")
+   (set_attr "cc" "clobber")])
+
+;; SImode ======================================
+
+(define_expand "lshrsi3"
+  [(set (match_operand:SI 0 "nonimmediate_operand"       "")
+        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{ msp430_lshrsi3(operands); DONE; }")
+
+(define_insn "lshrsi3_cnt"
+  [(parallel [(set (match_operand:SI 0 "register_operand"       "=r")
+	      (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+""
+"* return msp430_emit_lshrsi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*lshrsi3_31"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 31)))]
+  ""
+"rla	%B0
+\\tclr	%B0
+\\tclr	%A0
+\\trlc	%A0"
+  [(set_attr "length" "4,9,10")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "*lshrsi3_8"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 8)))]
+  ""
+"*{
+    if(which_alternative==0)
+    {
+      return \"swpb\\t%A0\\n\\tswpb\\t%B0\\n\\txor.b\\t%B0, %A0\\n\\txor\\t%B0, %A0\\n\\tand.b\\t#-1, %B0\";
+    }
+    else
+    {
+      return \"swpb\\t%A0\\n\\tswpb\\t%B0\\n\\txor.b\\t%B0, %A0\\n\\tclr.b\\t%J0\\n\\txor\\t%B0, %A0\\n\\tclr.b\\t%L0\";
+    }
+}"
+  [(set_attr "length" "5,11,12")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*lshrsi3_1"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430"       "=r,R,m")
+        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand_msp430" "0,0,0")
+		     (const_int 1)))]
+  ""
+"clrc
+\\trrc\\t%B0
+\\trrc\\t%A0"
+  [(set_attr "length" "3,4,5")
+   (set_attr "cc" "clobber")])
+
+;; DImode ======================================
+
+(define_expand "lshrdi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "")
+        (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                   (match_operand:HI 2 "general_operand"  "")))]
+""
+"{
+   if( !const_int_operand(operands[2],VOIDmode))
+   {
+     rtx op0,op1;
+     
+     op0 = force_reg(DImode,operands[0]);
+     op1 = force_reg(DImode,operands[1]);
+     operands[2] = copy_to_mode_reg(HImode,operands[2]);
+     emit_insn(gen_lshrdi3_cnt (op0, op1, operands[2]));
+     emit_move_insn(operands[0],op0);
+     /*emit_move_insn(operands[1],op1);*/ 
+     DONE;
+   }
+   else if(!register_operand(operands[1], DImode) 
+		&& is_shift_better_in_reg(operands))
+   {
+      operands[1] = copy_to_mode_reg(DImode,operands[1]);
+      emit_insn (gen_lshrdi3fnl(operands[0], operands[1], operands[2]));
+      DONE;
+   }
+}")
+
+(define_insn "lshrdi3_cnt"
+  [(parallel [(set (match_operand:DI 0 "register_operand"       "=r")
+	      (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+			 (match_operand:HI 2 "register_operand" "")))
+	      (clobber (match_dup 2))])]
+  ""
+  "* return msp430_emit_lshrdi3(insn, operands,NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "clobber")])
+
+
+(define_insn "lshrdi3fnl"
+  [(set (match_operand:DI 0 "nonimmediate_operand"       "=rm")
+        (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                   (match_operand:HI 2 "const_int_operand"  "i")))]
+  ""
+  "* return msp430_emit_lshrdi3(insn, operands,NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")])
+
+
+
+
+
+
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
+;; sign extend
+
+(define_insn "extendqihi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:HI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return signextendqihi(insn, operands,NULL);"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "set_n,set_n")])
+
+(define_insn "extendqisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:SI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return signextendqisi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")
+   (set_attr "cc" "set_n,set_n")])
+
+(define_insn "extendqidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:DI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return signextendqidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")
+   (set_attr "cc" "set_n,set_n")])
+
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:SI (match_operand:HI 1 "general_operand" "0,*rmi")))] 
+  ""
+  "* return signextendhisi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")  
+   (set_attr "cc" "set_n,set_n")])      
+
+(define_insn "extendhidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:DI (match_operand:HI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return signextendhidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")  
+   (set_attr "cc" "set_n,set_n")])
+
+(define_insn "extendsidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (sign_extend:DI (match_operand:SI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return signextendsidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")
+   (set_attr "cc" "set_n,set_n")])
+
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0 xx<---0
+;; zero extend
+
+(define_insn "zero_extendqihi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:HI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return zeroextendqihi(insn, operands,NULL);"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "clobber,clobber")])
+
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:SI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return zeroextendqisi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")
+   (set_attr "cc" "clobber,clobber")])
+
+(define_insn "zero_extendqidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:DI (match_operand:QI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return zeroextendqidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")
+   (set_attr "cc" "clobber,clobber")])
+
+
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:SI (match_operand:HI 1 "general_operand" "0,*rmi")))] 
+  ""
+  "* return zeroextendhisi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")  
+   (set_attr "cc" "clobber,clobber")])      
+
+(define_insn "zero_extendhidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:DI (match_operand:HI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return zeroextendhidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")  
+   (set_attr "cc" "clobber,clobber")])
+
+(define_insn "zero_extendsidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+        (zero_extend:DI (match_operand:SI 1 "general_operand" "0,*rmi")))]
+  ""
+  "* return zeroextendsidi(insn, operands,NULL);"
+  [(set_attr "length" "6,6")  
+   (set_attr "cc" "clobber,clobber")])
+
+;; =====================================================================
+;; single bit extract
+;; as soon as all operatoins performed on io registers
+;; let use only QImode. 
+
+(define_expand "extv"
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+       (sign_extract:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "") 
+			(match_operand 2 "const_int_operand" "")
+			(match_operand 3 "const_int_operand" "")))]
+""
+"{
+    if(INTVAL(operands[2]) != 1 || INTVAL(operands[3]) <= 0)
+      FAIL;
+}")
+
+(define_insn "*extv" 
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,r,r,r,m,m,m,m")
+       (sign_extract:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "r,m,r,m,r,m,r,m") 
+			(const_int 1)
+			(match_operand 2 "const_int_operand" "P,P,i,i,P,P,i,i")))]
+ ""
+"* {
+  operands[2] = GEN_INT(1<<INTVAL(operands[2]));
+  return 	\"bit.b\\t%2, %1\\n\"
+		\"\\tclr.b\\t%0\\n\"
+		\"\\tadc.b\\t%0\";
+}"
+  [(set_attr "length" "3,4,4,5,5,6,6,7")
+     (set_attr "cc" "clobber")])
+
+(define_expand "extzv"
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "")
+       (zero_extract:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "") 
+			(match_operand 2 "const_int_operand" "")
+			(match_operand 3 "const_int_operand" "")))]
+""
+"{
+    if(INTVAL(operands[2]) != 1 || INTVAL(operands[3]) <= 0) 
+      FAIL;
+}")
+
+(define_insn "*extzv" 
+ [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,r,r,r,m,m,m,m")
+       (zero_extract:QI (match_operand:QI 1 "nonimmediate_operand_msp430" "r,m,r,m,r,m,r,m")
+			(match_operand 2 "const_int_operand" "")
+			(match_operand 3 "const_int_operand" "P,P,i,i,P,P,i,i")))]
+ "INTVAL(operands[2]) == 1"
+"* {
+  operands[3] = GEN_INT(1<<INTVAL(operands[3]));
+  return 	\"bit.b\\t%3, %1\\n\"
+		\"\\tclr.b\\t%0\\n\"
+		\"\\tadc.b\\t%0\";
+}"
+  [(set_attr "length" "3,4,4,5,5,6,6,7")
+     (set_attr "cc" "clobber")])
+
+
+
+;;=======================================================================
+;;  various BRANCH insns...
+;;
+;;
+
+;; Unconditional jump instruction.
+(define_insn "jump"
+  [(set (pc) (label_ref (match_operand 0 "" "")))]
+  ""
+  "*
+{
+  int dist = msp430_jump_dist(operands[0],insn);
+  if (dist<500 && dist>-500)
+    return \"jmp	%0\";
+  return \"br	#%0\"; 
+}"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")])
+
+
+(define_insn "explicit_br"
+  [(unspec_volatile:HI [(const_int 0)] UNSPEC_EXPLICIT_BR)
+   (match_operand:HI 0 "immediate_operand" "")]
+   ""
+   "br	%0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")]
+)
+
+   
+; indirect jump
+(define_expand "indirect_jump"
+  [(set (pc) (match_operand:HI 0 "nonimmediate_operand" ""))]
+  ""
+  "")
+
+(define_insn "*indirect_jump_idx"
+  [(set (pc) (match_operand:HI 0 "memory_operand" "m"))]
+  "indexed_location(operands[0])"
+  "br	@%E0"
+  [(set_attr "length" "1")
+   (set_attr "cc" "none")])
+
+(define_insn "*indirect_jump_mem"
+  [(set (pc) (match_operand:HI 0 "memory_operand" "m"))]
+  "!indexed_location(operands[0])"
+  "br	%0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")])
+
+
+(define_insn "*indirect_jump_reg"
+  [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
+  ""
+  "br	%0"
+  [(set_attr "length" "1")
+   (set_attr "cc" "none")])
+
+
+;;=======================================================================
+;;=======================================================================
+;;=======================================================================
+;;=======================================================================
+
+
+;;=======================================================================
+;;
+;;    CASE
+;;
+
+/*
+(define_expand "casesi"
+  [(set (match_dup 6)  
+        (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0)
+                  (match_operand:HI 1 "register_operand" "")))
+   (parallel [(set (cc0)
+                   (compare (match_dup 6)
+                            (match_operand:HI 2 "register_operand" "")))])
+   (set (pc)
+        (if_then_else (gtu (cc0)
+                           (const_int 0))
+                      (label_ref (match_operand 4 "" ""))
+                      (pc)))
+   (set (match_dup 6)
+        (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
+
+   (parallel [(set (pc) (unspec:HI [(match_dup 6)] 1))
+              (use (label_ref (match_dup 3)))
+              (clobber (match_dup 6))])]
+  ""
+  " 
+{   
+  operands[6] = gen_reg_rtx (HImode);
+}")
+
+*/ 
+
+;; Table helper
+(define_insn "tablejump"
+  [(set (pc) (match_operand:HI 0 "general_operand" "rRP,i,m"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "br	%0	;	%1"
+ [(set_attr "length" "1,2,2")   
+   (set_attr "cc" "clobber")])
+
+
+;; =============================================================
+;; match De Morgan's law
+(define_insn "nandqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand_msp430" "=r,m,m,r")
+             (and:QI (not:QI (match_operand:QI 1 "general_operand_msp430" "rRP,mi,rRP,mi"))
+	                     (match_operand:QI 2 "nonimmediate_operand_msp430" "0,0,0,0")))]
+""
+"bic.b       %1, %0"
+[(set_attr "length" "1,3,2,2")
+  (set_attr "cc" "none")])
+
+(define_insn "nandhi"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m,m,r")
+             (and:HI (not:HI (match_operand:HI 1 "general_operand_msp430" "rRP,mi,rRP,mi"))
+	                     (match_operand:HI 2 "nonimmediate_operand_msp430" "0,0,0,0")))]
+""
+"bic %1, %0"
+[(set_attr "length" "1,3,2,2")
+  (set_attr "cc" "none")])
+
+(define_insn "nandsi"
+  [(set (match_operand:SI 0 "nonimmediate_operand_msp430" "=r,m,m,r,r,m")
+            (and:SI (not:SI (match_operand:SI 1 "general_operand_msp430" "rP,mi,rP,mi,R,R"))
+	                    (match_operand:SI 2 "nonimmediate_operand_msp430" "0,0,0,0,0,0")))]
+""
+"bic    %A1, %A0
+\\tbic  %B1, %B0"
+[(set_attr "length" "2,6,4,4,3,5")
+  (set_attr "cc" "none")])
+
+
+
+;; =============================================================
+;; PEEPHOLES
+
+;; a &= ~b;
+
+(define_insn "*bit_clear"
+ [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m,m,r") 
+       (unspec_volatile:HI [(match_operand:HI 1 "general_operand_msp430" "rRP,mi,rRP,mi")] 40))]
+""
+"bic	%1, %0"
+  [(set_attr "length" "1,3,2,2")
+     (set_attr "cc" "none")])
+
+(define_insn "bic_sr_irq"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m,m,r")
+           (unspec_volatile:HI [(match_operand:HI 1 "general_operand_msp430" "rRP,mi,rRP,mi")
+				(const_int 4100001)] 41))]
+  ""
+  "bic    %1, %0"
+    [(set_attr "length" "1,3,2,2")
+         (set_attr "cc" "none")])
+
+(define_insn "bis_sr_irq"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m,m,r")
+           (unspec_volatile:HI [(match_operand:HI 1 "general_operand_msp430" "rRP,mi,rRP,mi")
+				 (const_int 4200002)] 42))]
+  ""
+  "bis    %1, %0"
+    [(set_attr "length" "1,3,2,2")
+         (set_attr "cc" "none")])
+
+(define_insn "get_frame_address"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=r,m,m,r")
+           (unspec_volatile:HI [(match_operand:HI 1 "general_operand_msp430" "rRP,mi,rRP,mi")
+				 (const_int 4300003)] 43))]
+  ""
+  "mov	%1, %0"
+    [(set_attr "length" "1,3,2,2")
+         (set_attr "cc" "none")])
+
+;; these two for:
+;; (ulong) x = (ulong) func() << 16;
+;; x |= func();
+;; func() is uint
+;;
+
+;; do not check for zeros here, cause this insn already issued.
+(define_peephole2
+   [(set (match_operand:SI 1 "register_operand" "")
+         (sign_extend:SI (match_operand:HI 0 "register_operand" "")))
+    (set (match_dup 1) (ashift:SI (match_dup 1) (const_int 16)))]
+""
+  [(set (subreg:HI (match_dup 1) 2) (match_dup 0))]
+"")
+
+(define_peephole2
+   [(set (match_operand:SI 1 "register_operand" "")
+         (zero_extend:SI (match_operand:HI 0 "register_operand" "")))
+    (set (match_dup 1) (ashift:SI (match_dup 1) (const_int 16)))]
+""
+  [(set (subreg:HI (match_dup 1) 2) (match_dup 0))]
+"")
+
+(define_peephole2
+   [(set (match_operand:SI 0 "register_operand" "")
+         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))
+    (set (match_operand:SI 2 "register_operand" "")
+         (ior:SI (match_dup 2) (match_dup 0)))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (subreg:HI (match_dup 2) 0) 
+        (ior:HI (subreg:HI (match_dup 2) 0) (match_dup 1)))]
+"")
+
+(define_peephole2
+   [(set (match_operand:HI 0 "register_operand" "")  
+         (match_operand:HI 1 "general_operand_msp430" ""))
+    (set (match_operand:SI 2 "register_operand" "")
+         (zero_extend:SI (match_dup 0)))
+    (set (match_operand:SI 3 "register_operand" "") 
+         (ior:SI (match_dup 3) (match_dup 2)))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (subreg:HI (match_dup 3) 0) 
+        (ior:HI (subreg:HI (match_dup 3) 0) (match_dup 1)))]
+"")
+
+
+;; (ulong) x = (ulong) f >> 16;
+;;
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "register_operand" "")) 
+   (set (match_dup 0) 
+	(lshiftrt:SI (match_dup 0) 
+		     (const_int 16)))]
+""
+[(set (subreg:HI (match_dup 0) 0) (subreg:HI (match_dup 1) 2))
+ (set (subreg:HI (match_dup 0) 2) (const_int 0))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+	(ior:SI (match_dup 2) (match_dup 0)))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 2) (ior:SI (match_dup 2) 
+		              (match_dup 1)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(zero_extend:SI (match_operand:HI 1 "general_operand" "")))
+   (set (match_dup 0) 
+	(ashift:SI (match_dup 0) (const_int 16)))]
+""
+  [(set (subreg:HI (match_dup 0) 2) (match_dup 1))]
+"")
+
+
+;; shift right & set
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "register_operand" ""))
+   (set (match_operand:HI 2 "register_operand" "")
+	(match_dup 0))
+   (set (match_dup 2) 
+	(and:HI (match_dup 2) 
+		(match_operand 3 "const_int_operand" "")))
+   (set (match_dup 2) 
+	(lshiftrt:HI (match_dup 2) 
+		     (match_operand 4 "const_int_operand" ""))) 
+   (set (match_dup 1) (match_dup 2))]
+"dead_or_set_in_peep(4,insn, operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (set (match_dup 1)  
+	(and:HI (match_dup 1)  
+		(match_dup 3))) 
+   (set (match_dup 1) 
+	(lshiftrt:HI (match_dup 1) 
+		     (match_dup 4)))] 
+"")
+
+;; shift left and set
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "register_operand" ""))
+   (set (match_operand:HI 2 "register_operand" "")
+	(match_dup 0))
+   (set (match_dup 2) 
+	(and:HI (match_dup 2) 
+		(match_operand 3 "const_int_operand" "")))
+   (set (match_dup 2) 
+	(ashift:HI (match_dup 2) 
+		   (match_operand 4 "const_int_operand" ""))) 
+   (set (match_dup 1) (match_dup 2))]
+"dead_or_set_in_peep(4,insn, operands[2])"
+  [(set (match_dup 0) (match_dup 1))
+   (set (match_dup 1)  
+	(and:HI (match_dup 1)  
+		(match_dup 3))) 
+   (set (match_dup 1) 
+	(ashift:HI (match_dup 1) 
+		   (match_dup 4)))] 
+"")
+
+
+;;
+;; these for some shifts and stuff.
+;; every peephole saves up to 4 bytes.
+;;
+
+(define_insn "*addc_reg"
+  [(set (match_operand:HI 0 "register_operand" "=r,r") 
+	(unspec:HI [(match_operand:HI 1 "register_operand" "%0,0") 
+		    (match_operand:HI 2 "general_operand_msp430" "rP,mi")] 0))]
+""
+"addc	%2, %0"
+[(set_attr "length" "1,2")
+   (set_attr "cc" "clobber,clobber")])
+
+
+(define_insn "*addc_any"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=m,m") 
+	(unspec:HI [(match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0") 
+		    (match_operand:HI 2 "general_operand_msp430" "rP,mi")] 5))]
+""
+"addc	%2, %0"
+[(set_attr "length" "2,3")
+   (set_attr "cc" "clobber,clobber")])
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_operand:SI 2 "register_operand" "") 
+	(zero_extend:SI (match_dup 0)))
+   (set (match_operand:SI 3 "register_operand" "") 
+	(plus:SI (match_dup 3) (match_dup 2)))]
+"dead_or_set_in_peep(2,insn, operands[2])"
+  [(set (subreg:HI (match_dup 3) 0) 
+	(plus:HI (subreg:HI (match_dup 3) 0) 
+		 (match_dup 1)))
+   (set (subreg:HI (match_dup 3) 2) 
+	(unspec:HI [(subreg:HI (match_dup 3) 2) (const_int 0)] 0))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_operand:SI 2 "register_operand" "") 
+	(zero_extend:SI (match_dup 0)))
+   (set (match_operand:SI 3 "nonimmediate_operand_msp430" "") 
+	(plus:SI (match_dup 3) (match_dup 2)))]
+"dead_or_set_in_peep(2,insn, operands[2])"
+  [(set (subreg:HI (match_dup 3) 0) 
+	(plus:HI (subreg:HI (match_dup 3) 0) 
+		 (match_dup 1)))
+   (set (subreg:HI (match_dup 3) 2) 
+	(unspec:HI [(subreg:HI (match_dup 3) 2) (const_int 0)] 5))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_operand:SI 2 "nonimmediate_operand_msp430" "")
+        (zero_extend:SI (match_dup 0)))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (subreg:HI (match_dup 2) 0) (match_dup 1))
+   (set (subreg:HI (match_dup 2) 2) (const_int 0))]
+"")
+
+;;
+;; these are for redudant moves.
+;;
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+   (set (match_operand:SI 2 "register_operand" "") 
+	(ior:SI (match_dup 2) (match_dup 0)))
+   (set (match_dup 1) (match_dup 2))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 1) (ior:SI (match_dup 1) (match_dup 2)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(ior:SI (match_dup 0) 
+		(match_operand:SI 1 "register_operand" "")))
+   (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 1) (ior:SI (match_dup 1) (match_dup 0)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "register_operand" ""))
+   (set (match_dup 0) 
+	(not:HI (match_dup 0)))
+   (set (match_operand:HI 2 "register_operand" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && dead_or_set_in_peep(0,insn, operands[1])"
+  [(set (match_dup 1) (not:HI (match_dup 1)))
+   (set (match_dup 2) (match_dup 1))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "register_operand" ""))
+   (set (match_dup 0) 
+	(not:SI (match_dup 0)))
+   (set (match_operand:SI 2 "register_operand" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && dead_or_set_in_peep(0,insn, operands[1])"
+  [(set (match_dup 1) (not:SI (match_dup 1)))
+   (set (match_dup 2) (match_dup 1))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SF 0 "register_operand" "")
+	(match_operand:SF 1 "general_operand_msp430" ""))
+   (set (match_operand:SF 2 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 2) (match_dup 1))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "general_operand_msp430" ""))
+   (set (match_operand:SI 2 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 2) (match_dup 1))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_operand:HI 2 "nonimmediate_operand_msp430" "")
+        (match_dup 0))]
+"dead_or_set_in_peep(1,insn, operands[0])"
+  [(set (match_dup 2) (match_dup 1))]
+"")
+
+
+
+;; =========================================================================
+;;  This one for bit tests like:
+;;	volatile long a;
+;;	while(a&CONST_HALFNIBBLE) ;
+
+(define_insn "*bittest_lo"
+  [(set (cc0) 
+	(unspec:SI [(match_operand:SI 0 "nonimmediate_operand_msp430" "r,r,m,m") 
+		    (match_operand:SI 1 "general_operand_msp430" "rPR,mi,rPR,mi")] 1))]
+""
+"bit	%A1,%A0"
+[(set_attr "length" "1,2,2,3")
+   (set_attr "cc" "compare,compare,compare,compare")])
+
+(define_insn "*bittest_hi"
+  [(set (cc0) 
+	(unspec:SI [(match_operand:SI 0 "nonimmediate_operand_msp430" "r,r,m,m") 
+		    (match_operand:SI 1 "general_operand_msp430" "rPR,mi,rPR,mi")] 2))]
+""
+"bit	%B1,%B0"
+[(set_attr "length" "1,2,2,3")
+   (set_attr "cc" "compare,compare,compare,compare")])
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:SI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) 
+       (if_then_else (match_operator:SI 3 "equality_operator"
+		      [(match_dup 0) (const_int 0)]) 
+       (label_ref (match_operand 4 "" ""))
+       (pc)))]
+"(halfnibble_integer(operands[2], VOIDmode) 
+   || halfnibble_constant(operands[2], VOIDmode))
+        && dead_or_set_in_peep(2,insn, operands[0])
+	&& which_nibble(INTVAL(operands[2])) == 0"
+  [(set (cc0) 
+	(unspec:SI [(match_dup 1) (match_dup 2)] 1))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 4))
+	     (pc)))]
+"")
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:SI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) (if_then_else (match_operator:SI 3 "equality_operator"
+			   [(match_dup 0) (const_int 0)])
+	    (label_ref (match_operand 4 "" ""))
+	    (pc)))]
+"(halfnibble_integer(operands[2], VOIDmode) 
+   || halfnibble_constant(operands[2], VOIDmode))
+        && dead_or_set_in_peep(2,insn, operands[0])
+	&& which_nibble(INTVAL(operands[2])) == 1"
+  [(set (cc0) 
+	(unspec:SI [(match_dup 1) (match_dup 2)] 2))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 4))
+	     (pc)))]
+"")
+
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:SI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) 
+       (if_then_else (match_operator:HI 3 "equality_operator"
+		      [(match_operand:HI 4 "register_operand" "") (const_int 0)]) 
+       (label_ref (match_operand 5 "" ""))
+       (pc)))]
+"(halfnibble_integer(operands[2], VOIDmode) 
+   || halfnibble_constant(operands[2], VOIDmode))
+        && dead_or_set_in_peep(2,insn, operands[0])
+	&& which_nibble(INTVAL(operands[2])) == 1
+	&& REGNO(operands[4]) == REGNO(operands[0])+1"
+  [(set (cc0) 
+	(unspec:SI [(match_dup 1) (match_dup 2)] 1))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 5))
+	     (pc)))]
+"")
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:SI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) 
+       (if_then_else (match_operator:HI 3 "equality_operator"
+		      [(match_operand:HI 4 "register_operand" "") (const_int 0)]) 
+       (label_ref (match_operand 5 "" ""))
+       (pc)))]
+"(halfnibble_integer(operands[2], VOIDmode) 
+   || halfnibble_constant(operands[2], VOIDmode))
+        && dead_or_set_in_peep(2,insn, operands[0])
+	&& which_nibble(INTVAL(operands[2])) == 0
+	&& REGNO(operands[4]) == REGNO(operands[0])"
+  [(set (cc0) 
+	(unspec:SI [(match_dup 1) (match_dup 2)] 1))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 5))
+	     (pc)))]
+"")
+
+;;
+;;  The same for HI mode: while(smts&0xXXXX) ;
+;;
+(define_insn "*bittest"
+  [(set (cc0)
+        (unspec:HI [(match_operand:HI 0 "general_operand_msp430" "r,r,m,m")
+                    (match_operand:HI 1 "general_operand_msp430" "rPR,mi,rPR,mi")] 6))]
+""
+"bit	%1,%0"
+[(set_attr "length" "1,2,2,3")
+   (set_attr "cc" "compare,compare,compare,compare")])
+
+
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+       (match_operand:HI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:HI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) (if_then_else (match_operator:HI 3 "equality_operator"
+			   [(match_dup 0) (const_int 0)])
+	    (label_ref (match_operand 4 "" "")) 
+	    (pc)))]
+"dead_or_set_in_peep(2,insn, operands[0]) "
+  [(set (cc0) 
+	(unspec:HI [(match_dup 1) (match_dup 2)] 6))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 4))
+	     (pc)))]
+"")
+
+
+;; The same for QI mode
+
+(define_insn "*bittest_b"
+  [(set (cc0)
+        (unspec:QI [(match_operand:QI 0 "general_operand_msp430" "r,r,m,m")
+                    (match_operand:QI 1 "general_operand_msp430" "rPR,mi,rPR,mi")] 7))]
+""
+"bit.b	%1,%0"
+[(set_attr "length" "1,2,2,3")
+   (set_attr "cc" "compare,compare,compare,compare")])
+
+
+(define_peephole2
+ [(set (match_operand:QI 0 "register_operand" "")
+       (match_operand:QI 1 "nonimmediate_operand_msp430" ""))
+  (set (match_dup 0) (and:QI (match_dup 0) 
+                             (match_operand 2 "const_int_operand" "")))
+  (set (pc) (if_then_else (match_operator:QI 3 "equality_operator"
+			   [(match_dup 0) (const_int 0)])
+	    (label_ref (match_operand 4 "" "")) 
+	    (pc)))]
+"dead_or_set_in_peep(2,insn, operands[0]) "
+  [(set (cc0) 
+	(unspec:QI [(match_dup 1) (match_dup 2)] 7))
+   (set (pc) (if_then_else (match_op_dup 3
+			    [(cc0) (const_int 0)])
+	     (label_ref (match_dup 4))
+	     (pc)))]
+"")
+
+
+
+;;===========================================================================
+
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand" "")
+        (match_operand:QI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(minus:QI (match_dup 0) 
+		  (match_operand:QI 2 "general_operand_msp430" "")))
+   (set (match_operand:QI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (minus:QI (match_dup 3) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand" "")
+        (match_operand:QI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(plus:QI (match_dup 0) 
+		 (match_operand:QI 2 "general_operand_msp430" "")))
+   (set (match_operand:QI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (plus:QI (match_dup 3) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(minus:HI (match_dup 0) 
+		  (match_operand:HI 2 "general_operand_msp430" "")))
+   (set (match_operand:HI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+        (match_operand:HI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(plus:HI (match_dup 0) 
+		 (match_operand:HI 2 "general_operand_msp430" "")))
+   (set (match_operand:HI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (plus:HI (match_dup 3) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (match_operand:SI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(minus:SI (match_dup 0) 
+		  (match_operand:SI 2 "general_operand_msp430" "")))
+   (set (match_operand:SI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (minus:SI (match_dup 3) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+        (match_operand:SI 1 "general_operand_msp430" ""))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0) 
+		 (match_operand:SI 2 "general_operand_msp430" "")))
+   (set (match_operand:SI 3 "register_operand" "")
+   	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0]) && 0"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 3) (plus:SI (match_dup 3) (match_dup 2)))]
+"")
+
+
+;; =============================================================
+;; 
+;;  adjust frame pointer index
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(sign_extend:HI (match_operand:QI 1 "general_operand_msp430" "")))
+   (set (match_dup 0) 
+	(plus:HI (match_dup 0) (match_operand:HI 2 "general_operand_msp430" "")))
+   (set (match_operand:HI 3 "register_operand" "")
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 3) (sign_extend:HI (match_dup 1)))
+   (set (match_dup 3) (plus:HI (match_dup 3) (match_dup 2)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(sign_extend:SI (match_operand:HI 1 "general_operand_msp430" "")))
+   (set (match_dup 0) 
+	(plus:SI (match_dup 0) (match_operand:SI 2 "general_operand_msp430" "")))
+   (set (match_operand:SI 3 "register_operand" "")
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 3) (sign_extend:SI (match_dup 1)))
+   (set (match_dup 3) (plus:SI (match_dup 3) (match_dup 2)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(sign_extend:HI (match_operand:QI 1 "general_operand_msp430" "")))
+   (set (match_dup 0) 
+	(minus:HI (match_dup 0) (match_operand:HI 2 "general_operand_msp430" "")))
+   (set (match_operand:HI 3 "register_operand" "")
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 3) (sign_extend:HI (match_dup 1)))
+   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 2)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(sign_extend:SI (match_operand:HI 1 "general_operand_msp430" "")))
+   (set (match_dup 0) 
+	(minus:SI (match_dup 0) (match_operand:SI 2 "general_operand_msp430" "")))
+   (set (match_operand:SI 3 "register_operand" "")
+	(match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 3) (sign_extend:SI (match_dup 1)))
+   (set (match_dup 3) (minus:SI (match_dup 3) (match_dup 2)))]
+"")
+
+;; =============================================================
+;; mov & 'and'
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(match_operand:HI 1 "nonimmediate_operand_msp430" ""))
+   (set (match_dup 0) 
+	(and:HI (match_dup 0) 
+		(match_operand:HI 2 "general_operand_msp430" ""))) 
+   (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 1) 
+	(and:HI (match_dup 1) (match_dup 2)))]
+"")
+
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(match_operand:SI 1 "nonimmediate_operand_msp430" ""))
+   (set (match_dup 0) 
+	(and:SI (match_dup 0) 
+		(match_operand:SI 2 "general_operand_msp430" ""))) 
+   (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(2,insn, operands[0])"
+  [(set (match_dup 1) 
+	(and:SI (match_dup 1) (match_dup 2)))]
+"")
+
+
+
+;; =============================================================
+;; SWAP BYTES (should be a pattern for:
+;;   r = (a<<8)|(a>>8);
+
+(define_insn "swpb"
+  [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=rR,m") 
+	(unspec:HI [(match_operand:HI 1 "nonimmediate_operand_msp430" "0,0")] 4))]
+""
+"swpb	%0"
+[(set_attr "length" "1,2")
+   (set_attr "cc" "clobber,clobber")])
+
+;;
+;; after mult and stuff
+;;
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(reg:SI 14))
+   (set (match_operand:SI 1 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 1) (reg:SI 14))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(reg:HI 14))
+   (set (match_operand:HI 1 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 1) (reg:HI 14))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(reg:SI 12))
+   (set (match_operand:SI 1 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 1) (reg:SI 12))]
+"")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(reg:HI 12))
+   (set (match_operand:HI 1 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 1) (reg:HI 12))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(sign_extend:SI (match_operand:QI 1 "general_operand_msp430" "")))
+   (set (match_operand:SI 2 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 2) (sign_extend:SI (match_dup 1)))]
+"")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "") 
+	(sign_extend:SI (match_operand:HI 1 "general_operand_msp430" "")))
+   (set (match_operand:SI 2 "nonimmediate_operand_msp430" "") 
+	(match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+  [(set (match_dup 2) (sign_extend:SI (match_dup 1)))]
+"")
+
+
+;; =============================================================
+
+(define_peephole 
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(sign_extend:HI (match_operand:QI 1 "register_operand" ""))) 
+   (set (match_operand:HI 2 "register_operand" "") 
+	(plus:HI (match_dup 2) (match_dup 0)))]
+"dead_or_set_in_peep(1,insn,operands[0])" 
+"sxt	%1
+	add	%1, %2"
+[(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+
+(define_peephole 
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand_msp430" ""))) 
+   (set (match_operand:HI 2 "register_operand" "") (match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])" 
+"mov.b	%1, %2
+	sxt	%2"
+[(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
+;; ============================================================= 
+;; a = (uint16_t)( (uint8_t)SFR ) << 8;
+;; (inderect_jump + 50)
+(define_peephole 
+  [(set (match_operand:QI 0 "register_operand" "") 
+	(match_operand:QI 1 "memory_operand_msp430" "m"))
+   (set (match_operand:HI 2 "register_operand" "")
+	(ashift:HI (match_dup 2) (const_int 8)))]
+  "REGNO(operands[0]) == REGNO(operands[2])"
+"mov.b	%1, %0
+	swpb	%2"
+[(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "") 
+	(ior:HI (match_dup 0) 
+		(match_operand:HI 1 "register_operand" "")))
+   (set (match_operand:SI 2 "register_operand" "") 
+	(match_operand:SI 3 "register_operand" ""))]
+"(REGNO(operands[0]) == REGNO(operands[2])
+  && REGNO(operands[3])+1 == REGNO(operands[0]))"
+  [(set (match_dup 1) 
+	(ior:HI (match_dup 1) 
+		(match_dup 0)))
+   (set (subreg:HI (match_dup 2) 0)
+	(subreg:HI (match_dup 3) 0))]
+"")
+
+
+
+;; =============================================================
+;; combine ior and mov.
+;;
+(define_peephole2
+[(set (match_operand:QI 0 "register_operand" "") 
+      (ior:QI (match_dup 0) 
+      	      (match_operand:QI 1 "nonimmediate_operand_msp430" "")))
+ (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+[(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 0)))]
+"")
+
+(define_peephole2
+[(set (match_operand:HI 0 "register_operand" "") 
+      (ior:HI (match_dup 0) 
+      	      (match_operand:HI 1 "nonimmediate_operand_msp430" "")))
+ (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+[(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 0)))]
+"")
+
+(define_peephole2
+[(set (match_operand:SI 0 "register_operand" "") 
+      (ior:SI (match_dup 0) 
+      	      (match_operand:SI 1 "nonimmediate_operand_msp430" "")))
+ (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+[(set (match_dup 1) (ior:SI (match_dup 1) (match_dup 0)))]
+"")
+
+(define_peephole2
+[(set (match_operand:DI 0 "register_operand" "") 
+      (ior:DI (match_dup 0) 
+      	      (match_operand:DI 1 "nonimmediate_operand_msp430" "")))
+ (set (match_dup 1) (match_dup 0))]
+"dead_or_set_in_peep(1,insn,operands[0])"
+[(set (match_dup 1) (ior:DI (match_dup 1) (match_dup 0)))]
+"")
+
+
+;; ======================================================================
+
+;; Enable Interrupts
+(define_insn "enable_interrupt"
+  [(unspec [(const_int 0)] UNSPEC_EINT)]
+  ""
+  "eint"
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")
+  ])
+
+;; Disable Interrupts
+(define_insn "disable_interrupt"
+  [(unspec [(const_int 0)] UNSPEC_DINT)]
+  ""
+  "dint"
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")
+  ])
+
+
+;; return insn
+(define_insn "return"
+  [(return)]
+  "reload_completed && msp430_empty_epilogue()"
+  "* return msp430_emit_return(insn, operands, NULL);"
+  [(set_attr "length" "1")
+   (set_attr "cc" "clobber")]
+)
+
+(define_insn "return_from_epilogue"
+  [(return)]
+  "(reload_completed 
+    && cfun->machine 
+    && !(cfun->machine->is_interrupt || cfun->machine->is_critical)
+    && !cfun->machine->is_naked)"
+  "ret"
+  [(set_attr "cc" "none")
+   (set_attr "length" "1")])
+
+(define_insn "return_from_interrupt_epilogue"
+  [(return)]
+  "(reload_completed 
+    && cfun->machine 
+    && (cfun->machine->is_interrupt || cfun->machine->is_critical)
+    && !cfun->machine->is_naked)"
+  "reti"
+  [(set_attr "cc" "none")
+   (set_attr "length" "1")])
+
+(define_insn "return_from_naked_epilogue"
+  [(return)]
+  "(reload_completed 
+    && cfun->machine 
+    && cfun->machine->is_naked)"
+  ""
+  [(set_attr "cc" "none")
+   (set_attr "length" "0")])
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "
+  {
+    expand_prologue (); 
+    DONE;
+  }")
+
+(define_expand "epilogue"
+  [(const_int 0)]
+  ""
+  "
+  {
+    expand_epilogue (); 
+    DONE;
+  }")
diff -ruNp gcc-4.x/gcc/config/msp430/msp430.opt gcc-4.4.5/gcc/config/msp430/msp430.opt
--- gcc-4.x/gcc/config/msp430/msp430.opt	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/msp430.opt	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,81 @@
+; Options for the MSP430 port of the compiler.
+; Converted from msp430.c (gcc 3.2.3 port)
+
+; For every option from this file (such as PROF_STD), a corresponding command-line option is checked and an internal GCC flag is set.
+; To check such flag one should use the TARGET_xxx macro (such as TARGET_PROF_STD).
+; This replaces the deprecated #define TARGET_SWITCHES syntax
+; String options are defined similarily and replace the #define TARGET_OPTIONS syntax
+
+;; This work is partially financed by the European Commission under the
+;; Framework 6 Information Society Technologies Project
+;; "Wirelessly Accessible Sensor Populations (WASP)".
+
+mpgs
+Target Report Mask(PROF_STD)
+Add ordinary profile information
+
+mpgl
+Target Report Mask(PROF_LIB)
+Add ordinary profile information
+
+mpgr
+Target Report Mask(PROF_STACK)
+Add stack information to profiler
+
+mrtl
+Target Report Mask(RTL_DUMP)
+Dump RTL
+
+mdeb
+Target Report Mask(ALL_DEBUG)
+Dump all debug info
+
+mforce-hwmul
+Target Report Mask(FORCE_HWMUL)
+Force hardware multiplier
+
+mdisable-hwmul
+Target Report Mask(NO_HWMUL)
+Disable hardware multiplier
+
+minline-hwmul
+Target Report Mask(INLINESIHWMUL)
+Issue inline multiplication code for 32-bit integers
+
+mnoint-hwmul
+Target Report Mask(NOINT_HWMUL)
+Assume interrupt routine does not do hardware multiply
+
+mIAR
+Target Report Mask(IAR)
+Produce IAR assembler syntax
+
+mno-stack-init
+Target Report Mask(NO_STACK_INIT)
+No stack init in main()
+
+mno-volatile-workaround
+Target Report Mask(NVWA)
+Do not perform volatile workaround for bitwise operations
+
+msave-prologue
+Target Report Mask(SAVE_PROLOGUE)
+Use subroutine call for function prologue/epilogue when possible
+
+; ---------------------------------------- Here start the string options imported from TARGET_OPTIONS macro ----------------------------------------
+
+mmcu=
+Target RejectNegative Joined Var(msp430_mcu_name) Init("msp430x169")
+-mmcu=MCU	Select the target MCU
+
+mendup-at=
+Target RejectNegative Joined Var(msp430_endup) Init("__stop_progExec__")
+-mendup-at=ENDUP	Jump to specified routine at the end of main()
+
+minit-stack=
+Target RejectNegative Joined Var(msp430_init_stack) Init("__stack")
+-minit-stack=STACK	Use STACK as the initial value of the stack pointer
+
+maccumulate-outgoing-args
+Target Report Mask(ACCUMULATE_OUTGOING_ARGS) Save
+Reserve space for outgoing arguments in the function prologue
diff -ruNp gcc-4.x/gcc/config/msp430/objs-extra gcc-4.4.5/gcc/config/msp430/objs-extra
--- gcc-4.x/gcc/config/msp430/objs-extra	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/objs-extra	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1 @@
+msp430-emit-cbranch.o msp430-cbranch.o msp430-builtins.o msp430-function.o
\ No newline at end of file
diff -ruNp gcc-4.x/gcc/config/msp430/predicates.md gcc-4.4.5/gcc/config/msp430/predicates.md
--- gcc-4.x/gcc/config/msp430/predicates.md	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/predicates.md	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,106 @@
+;; Predicate definitions for MSP430
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; This work is partially financed by the European Commission under the
+;; Framework 6 Information Society Technologies Project
+;; "Wirelessly Accessible Sensor Populations (WASP)".
+
+;; <==== Comment by Ivan Shcherbakov ====>
+;; All predicates here were checked againist latest port of GCC 3.2.3
+(define_special_predicate "equality_operator"
+  (match_code "eq,ne")
+{
+  return ((mode == VOIDmode || GET_MODE (op) == mode) && (GET_CODE (op) == EQ || GET_CODE (op) == NE));
+})
+
+(define_special_predicate "inequality_operator"
+  (match_code "ge,gt,le,lt,geu,gtu,leu,ltu")
+{
+  return comparison_operator (op, mode) && !equality_operator (op, mode);
+})
+
+(define_predicate "nonimmediate_operand_msp430"
+  (match_code "reg,subreg,mem")
+{
+  int save_volatile_ok = volatile_ok;
+  int niop = 0;
+
+  if (!TARGET_NVWA)
+    volatile_ok = 1;
+  niop = nonimmediate_operand (op, mode);
+  volatile_ok = save_volatile_ok;
+
+  return niop;
+})
+
+(define_predicate "memory_operand_msp430"
+  (match_code "subreg,mem")
+{
+  int save_volatile_ok = volatile_ok;
+  int mop = 0;
+
+  if (!TARGET_NVWA)
+    volatile_ok = 1;
+  mop = memory_operand (op, mode);
+  volatile_ok = save_volatile_ok;
+  return mop;
+})
+
+(define_predicate "general_operand_msp430"
+  (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem")
+{
+  int save_volatile_ok = volatile_ok;
+  int gop = 0;
+
+  if (!TARGET_NVWA)
+    volatile_ok = 1;
+  gop = general_operand (op, mode);
+  volatile_ok = save_volatile_ok;
+  return gop;
+})
+
+(define_predicate "three_operands_msp430"
+  (match_code "plus,minus,and,ior,xor")
+{
+  enum rtx_code code = GET_CODE (op);
+  if (GET_MODE (op) != mode)
+    return 0;
+
+  return (code == PLUS || code == MINUS || code == AND || code == IOR || code == XOR);
+})
+
+;; True for any non-virtual or eliminable register.  Used in places where
+;; instantiation of such a register may cause the pattern to not be recognized.
+(define_predicate "register_no_elim_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return !(op == arg_pointer_rtx
+	   || op == frame_pointer_rtx
+	   || IN_RANGE (REGNO (op),
+			FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER));
+})
+
+;; Return false if this is any eliminable register.  Otherwise general_operand.
+(define_predicate "general_no_elim_operand"
+  (if_then_else (match_code "reg,subreg")
+    (match_operand 0 "register_no_elim_operand")
+    (match_operand 0 "general_operand")))
diff -ruNp gcc-4.x/gcc/config/msp430/t-msp430 gcc-4.4.5/gcc/config/msp430/t-msp430
--- gcc-4.x/gcc/config/msp430/t-msp430	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/t-msp430	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1,255 @@
+# Specific names for MSP430 tools
+AR_FOR_TARGET = msp430-ar
+RANLIB_FOR_TARGET = msp430-ranlib
+NM_FOR_TARGET = msp430-nm
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = msp430/libgcc.S
+LIB1ASMFUNCS = _cmpdi2 \
+	_cmpsf2 \
+	__stop_progExec__ \
+	_mulqi3 \
+	_mulhi3 \
+	_mulsi3 \
+	_mulsi3hw \
+	_umulqihi3 \
+	_umulhisi3 \
+	_mulqihi3 \
+	_mulhisi3 \
+	_udivmodqi4 \
+	_divmodqi4 \
+	_udivmodhi4 \
+	_divmodhi4 \
+	_udivmodsi4 \
+	_divmodsi4 \
+	_reset_vector__ \
+	__prologue_saver \
+	__epilogue_restorer \
+	__epilogue_restorer_intr \
+	_udivmoddi3_parts \
+	_udivdi3 \
+	_umoddi3 \
+	_divdi3 \
+	_moddi3 \
+	_muldi3	\
+	__low_level_init \
+	__init_stack \
+	_copy_data \
+	_clear_bss \
+	_ctors \
+	__jump_to_main \
+	_dtors
+	
+	
+
+# libgcc...
+LIBGCC1_TEST =
+
+# We do not have the DF type.
+# Most of the C functions in libgcc2 use almost all registers,
+TARGET_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc -g
+
+fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/msp430/t-msp430
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define FLOAT_ONLY' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	echo '#define DF SF' >> fp-bit.c
+	echo '#define DI SI' >> fp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+FPBIT = fp-bit.c
+
+MULTILIB_OPTIONS = mmcu=msp1/mmcu=msp2/mmcu=msp3/mmcu=msp4/mmcu=msp5/mmcu=msp6
+MULTILIB_DIRNAMES = msp1 msp2 msp3 msp4 msp5 msp6
+
+MULTILIB_MATCHES = \
+	mmcu?msp1=mmcu?msp430x110 \
+	mmcu?msp1=mmcu?msp430x112 \
+	mmcu?msp1=mmcu?msp430x1101 \
+	mmcu?msp1=mmcu?msp430x1111 \
+	mmcu?msp1=mmcu?msp430x1121 \
+	mmcu?msp1=mmcu?msp430x1122 \
+	mmcu?msp1=mmcu?msp430x1132 \
+	mmcu?msp1=mmcu?msp430x122 \
+	mmcu?msp1=mmcu?msp430x123 \
+	mmcu?msp1=mmcu?msp430x1222 \
+	mmcu?msp1=mmcu?msp430x1232 \
+	mmcu?msp1=mmcu?msp430x133 \
+	mmcu?msp1=mmcu?msp430x135 \
+	mmcu?msp1=mmcu?msp430x1331 \
+	mmcu?msp1=mmcu?msp430x1351 \
+	mmcu?msp2=mmcu?msp430x147 \
+	mmcu?msp2=mmcu?msp430x148 \
+	mmcu?msp2=mmcu?msp430x149 \
+	mmcu?msp2=mmcu?msp430x1471 \
+	mmcu?msp2=mmcu?msp430x1481 \
+	mmcu?msp2=mmcu?msp430x1491 \
+	mmcu?msp1=mmcu?msp430x155 \
+	mmcu?msp1=mmcu?msp430x156 \
+	mmcu?msp1=mmcu?msp430x157 \
+	mmcu?msp2=mmcu?msp430x167 \
+	mmcu?msp2=mmcu?msp430x168 \
+	mmcu?msp2=mmcu?msp430x169 \
+	mmcu?msp2=mmcu?msp430x1610 \
+	mmcu?msp2=mmcu?msp430x1611 \
+	mmcu?msp2=mmcu?msp430x1612 \
+	mmcu?msp1=mmcu?msp430x2001 \
+	mmcu?msp1=mmcu?msp430x2011 \
+	mmcu?msp1=mmcu?msp430x2002 \
+	mmcu?msp1=mmcu?msp430x2012 \
+	mmcu?msp1=mmcu?msp430x2003 \
+	mmcu?msp1=mmcu?msp430x2013 \
+	mmcu?msp1=mmcu?msp430x2101 \
+	mmcu?msp1=mmcu?msp430x2111 \
+	mmcu?msp1=mmcu?msp430x2121 \
+	mmcu?msp1=mmcu?msp430x2131 \
+	mmcu?msp1=mmcu?msp430x2112 \
+	mmcu?msp1=mmcu?msp430x2122 \
+	mmcu?msp1=mmcu?msp430x2132 \
+	mmcu?msp1=mmcu?msp430x2201 \
+	mmcu?msp1=mmcu?msp430x2211 \
+	mmcu?msp1=mmcu?msp430x2221 \
+	mmcu?msp1=mmcu?msp430x2231 \
+	mmcu?msp1=mmcu?msp430x2232 \
+	mmcu?msp1=mmcu?msp430x2252 \
+	mmcu?msp1=mmcu?msp430x2272 \
+	mmcu?msp1=mmcu?msp430x2234 \
+	mmcu?msp1=mmcu?msp430x2254 \
+	mmcu?msp1=mmcu?msp430x2274 \
+	mmcu?msp2=mmcu?msp430x233 \
+	mmcu?msp2=mmcu?msp430x235 \
+	mmcu?msp2=mmcu?msp430x2330 \
+	mmcu?msp2=mmcu?msp430x2350 \
+	mmcu?msp2=mmcu?msp430x2370 \
+	mmcu?msp2=mmcu?msp430x247 \
+	mmcu?msp2=mmcu?msp430x248 \
+	mmcu?msp2=mmcu?msp430x249 \
+	mmcu?msp2=mmcu?msp430x2410 \
+	mmcu?msp2=mmcu?msp430x2471 \
+	mmcu?msp2=mmcu?msp430x2481 \
+	mmcu?msp2=mmcu?msp430x2491 \
+	mmcu?msp3=mmcu?msp430x2416 \
+	mmcu?msp3=mmcu?msp430x2417 \
+	mmcu?msp3=mmcu?msp430x2418 \
+	mmcu?msp3=mmcu?msp430x2419 \
+	mmcu?msp3=mmcu?msp430x2616 \
+	mmcu?msp3=mmcu?msp430x2617 \
+	mmcu?msp3=mmcu?msp430x2618 \
+	mmcu?msp3=mmcu?msp430x2619 \
+	mmcu?msp1=mmcu?msp430x311 \
+	mmcu?msp1=mmcu?msp430x312 \
+	mmcu?msp1=mmcu?msp430x313 \
+	mmcu?msp1=mmcu?msp430x314 \
+	mmcu?msp1=mmcu?msp430x315 \
+	mmcu?msp1=mmcu?msp430x323 \
+	mmcu?msp1=mmcu?msp430x325 \
+	mmcu?msp2=mmcu?msp430x336 \
+	mmcu?msp2=mmcu?msp430x337 \
+	mmcu?msp1=mmcu?msp430x412 \
+	mmcu?msp1=mmcu?msp430x413 \
+	mmcu?msp1=mmcu?msp430x415 \
+	mmcu?msp1=mmcu?msp430x417 \
+	mmcu?msp2=mmcu?msp430x423 \
+	mmcu?msp2=mmcu?msp430x425 \
+	mmcu?msp2=mmcu?msp430x427 \
+	mmcu?msp1=mmcu?msp430x4250 \
+	mmcu?msp1=mmcu?msp430x4260 \
+	mmcu?msp1=mmcu?msp430x4270 \
+	mmcu?msp1=mmcu?msp430xG4250 \
+	mmcu?msp1=mmcu?msp430xG4260 \
+	mmcu?msp1=mmcu?msp430xG4270 \
+	mmcu?msp2=mmcu?msp430xE423 \
+	mmcu?msp2=mmcu?msp430xE425 \
+	mmcu?msp2=mmcu?msp430xE427 \
+	mmcu?msp2=mmcu?msp430xE4232 \
+	mmcu?msp2=mmcu?msp430xE4242 \
+	mmcu?msp2=mmcu?msp430xE4252 \
+	mmcu?msp2=mmcu?msp430xE4272 \
+	mmcu?msp1=mmcu?msp430xW423 \
+	mmcu?msp1=mmcu?msp430xW425 \
+	mmcu?msp1=mmcu?msp430xW427 \
+	mmcu?msp1=mmcu?msp430xG437 \
+	mmcu?msp1=mmcu?msp430xG438 \
+	mmcu?msp1=mmcu?msp430xG439 \
+	mmcu?msp1=mmcu?msp430x435 \
+	mmcu?msp1=mmcu?msp430x436 \
+	mmcu?msp1=mmcu?msp430x437 \
+	mmcu?msp1=mmcu?msp430x4351 \
+	mmcu?msp1=mmcu?msp430x4361 \
+	mmcu?msp1=mmcu?msp430x4371 \
+	mmcu?msp2=mmcu?msp430x447 \
+	mmcu?msp2=mmcu?msp430x448 \
+	mmcu?msp2=mmcu?msp430x449 \
+	mmcu?msp3=mmcu?msp430xG4616 \
+	mmcu?msp3=mmcu?msp430xG4617 \
+	mmcu?msp3=mmcu?msp430xG4618 \
+	mmcu?msp3=mmcu?msp430xG4619 \
+	mmcu?msp4=mmcu?msp430x4783 \
+	mmcu?msp4=mmcu?msp430x4784 \
+	mmcu?msp4=mmcu?msp430x4793 \
+	mmcu?msp4=mmcu?msp430x4794 \
+	mmcu?msp5=mmcu?msp430x47166 \
+	mmcu?msp5=mmcu?msp430x47176 \
+	mmcu?msp5=mmcu?msp430x47186 \
+	mmcu?msp5=mmcu?msp430x47196 \
+	mmcu?msp5=mmcu?msp430x47167 \
+	mmcu?msp5=mmcu?msp430x47177 \
+	mmcu?msp5=mmcu?msp430x47187 \
+	mmcu?msp5=mmcu?msp430x47197 \
+	mmcu?msp6=mmcu?msp430x5418 \
+	mmcu?msp6=mmcu?msp430x5419 \
+	mmcu?msp6=mmcu?msp430x5435 \
+	mmcu?msp6=mmcu?msp430x5436 \
+	mmcu?msp6=mmcu?msp430x5437 \
+	mmcu?msp6=mmcu?msp430x5438 \
+	mmcu?msp6=mmcu?msp430x5510 \
+	mmcu?msp6=mmcu?msp430x5513 \
+	mmcu?msp6=mmcu?msp430x5514 \
+	mmcu?msp6=mmcu?msp430x5515 \
+	mmcu?msp6=mmcu?msp430x5517 \
+	mmcu?msp6=mmcu?msp430x5519 \
+	mmcu?msp6=mmcu?msp430x5521 \
+	mmcu?msp6=mmcu?msp430x5522 \
+	mmcu?msp6=mmcu?msp430x5524 \
+	mmcu?msp6=mmcu?msp430x5525 \
+	mmcu?msp6=mmcu?msp430x5526 \
+	mmcu?msp6=mmcu?msp430x5527 \
+	mmcu?msp6=mmcu?msp430x5528 \
+	mmcu?msp6=mmcu?msp430x5529 \
+	mmcu?msp6=mmcu?msp430x6638 \
+	mmcu?msp6=mmcu?cc430x5133 \
+	mmcu?msp6=mmcu?cc430x5125 \
+	mmcu?msp6=mmcu?cc430x6125 \
+	mmcu?msp6=mmcu?cc430x6135 \
+	mmcu?msp6=mmcu?cc430x6126 \
+	mmcu?msp6=mmcu?cc430x5137 \
+	mmcu?msp6=mmcu?cc430x6127 \
+	mmcu?msp6=mmcu?cc430x6137
+
+MULTILIB_EXCEPTIONS =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+##STMP_FIXINC =
+
+msp430-cbranch.o: $(srcdir)/config/msp430/msp430-cbranch.c $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-cbranch.c
+
+msp430-emit-cbranch.o: $(srcdir)/config/msp430/msp430-cbranch.c $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-emit-cbranch.c
+
+msp430-builtins.o: $(srcdir)/config/msp430/msp430-builtins.c $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-builtins.c
+
+msp430-function.o: $(srcdir)/config/msp430/msp430-function.c $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/msp430/msp430-function.c
+
+
+	
diff -ruNp gcc-4.x/gcc/config/msp430/xm-msp430.h gcc-4.4.5/gcc/config/msp430/xm-msp430.h
--- gcc-4.x/gcc/config/msp430/xm-msp430.h	1969-12-31 16:00:00.000000000 -0800
+++ gcc-4.4.5/gcc/config/msp430/xm-msp430.h	2011-01-24 18:14:54.000000000 -0800
@@ -0,0 +1 @@
+#include "tm.h"
