+++ /dev/null
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 001-mspgcc-3.2.3-20080819.dpatch by <pkgs@titaniummirror.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Patch derived from mspgcc project gcc/3.3 directory, CVS 20080819
-
-@DPATCH@
-
-diff -urN -x CVS gcc-3.2.3.orig/configure.in gcc-3.2.3/configure.in
---- gcc-3.2.3.orig/configure.in 2002-07-08 04:00:57.000000000 -0600
-+++ gcc-3.2.3/configure.in 2008-08-22 09:17:00.000000000 -0600
-@@ -907,6 +907,9 @@
- target_configdirs="${target_configdirs} target-bsp target-libstub target-cygmon"
- fi
- ;;
-+ msp430-*-*)
-+ noconfigdirs="$noconfigdirs target-libiberty ${libstdcxx_version} ${libgcj}"
-+ ;;
- powerpc-*-aix*)
- # copied from rs6000-*-* entry
- # The configure and build of ld are currently disabled because
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.c gcc-3.2.3/gcc/config/msp430/libgcc.c
---- gcc-3.2.3.orig/gcc/config/msp430/libgcc.c 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/libgcc.c 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,74 @@
-+
-+/*
-+ 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 -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.S gcc-3.2.3/gcc/config/msp430/libgcc.S
---- gcc-3.2.3.orig/gcc/config/msp430/libgcc.S 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/libgcc.S 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,1326 @@
-+/* -*- Mode: Asm -*- */
-+
-+
-+ .section .text.libgcc, "ax", @progbits
-+
-+#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)
-+
-+__MPY=0x130
-+__MPYS=0x132
-+__MAC=0x134
-+__MACS=0x136
-+__OP2=0x138
-+__RESLO=0x13a
-+__RESHI=0x13c
-+__SUMEXT=0x13e
-+
-+ .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 */
-+
-+; actualy stack initialized in main() prologue, so don't link __init_stack
-+; .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
-+
-+set_stack_pointer:
-+ 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
-+ .global __init_stack ; stack has to be set before constructors calling
-+
-+
-+__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)
-+
-+__MPY=0x130
-+__MPYS=0x132
-+__MAC=0x134
-+__MACS=0x136
-+__OP2=0x138
-+__RESLO=0x13a
-+__RESHI=0x13c
-+__SUMEXT=0x13e
-+
-+#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 -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.c gcc-3.2.3/gcc/config/msp430/msp430.c
---- gcc-3.2.3.orig/gcc/config/msp430/msp430.c 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/msp430.c 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,9851 @@
-+/* 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 "rtl.h"
-+#include "regs.h"
-+#include "hard-reg-set.h"
-+#include "real.h"
-+#include "insn-config.h"
-+#include "conditions.h"
-+#include "output.h"
-+#include "insn-attr.h"
-+#include "flags.h"
-+#include "reload.h"
-+#include "tree.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"
-+
-+
-+/* This holds the last insn address. */
-+static int last_insn_address = 0;
-+
-+/* Commands count in the compiled file */
-+static int commands_in_file;
-+
-+/* Commands in the functions prologues in the compiled file */
-+static int commands_in_prologues;
-+
-+/* Commands in the functions epilogues in the compiled file */
-+static int commands_in_epilogues;
-+
-+/* 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;
-+
-+/* the size of the stack space freed during mdr pass */
-+
-+/* actual frame offset */
-+static int msp430_current_frame_offset = 0;
-+
-+/* ret/reti issue indicator for _current_ function */
-+static int return_issued = 0;
-+
-+/* registers used for incoming funct arguments */
-+static char arg_register_used[16];
-+
-+/* push helper */
-+int self_push PARAMS ((rtx));
-+
-+
-+/* aux functions */
-+static int msp430_cc_source PARAMS ((rtx, enum rtx_code, rtx, rtx));
-+static int msp430_func_num_saved_regs PARAMS ((void));
-+static int noint_hwmul_function_p PARAMS ((tree func));
-+static int interrupt_function_p PARAMS ((tree func));
-+static int msp430_naked_function_p PARAMS ((tree func));
-+static int msp430_task_function_p PARAMS ((tree func));
-+static int signal_function_p PARAMS ((tree func));
-+static int wakeup_function_p PARAMS ((tree func));
-+static int msp430_num_arg_regs PARAMS ((enum machine_mode mode, tree type));
-+static int msp430_critical_function_p PARAMS ((tree func));
-+static int msp430_reentrant_function_p PARAMS ((tree func));
-+static int msp430_save_prologue_function_p PARAMS ((tree func));
-+
-+const char * msp430_emit_bltnoovfl PARAMS ((rtx *, int));
-+
-+
-+
-+const char *msp430_init_stack = "__stack";
-+const char *msp430_endup = "__stop_progExec__";
-+
-+int msp430_case_values_threshold = 30000;
-+int msp430_has_hwmul = 0;
-+
-+struct rtx_def *msp430_compare_op0;
-+struct rtx_def *msp430_compare_op1;
-+
-+
-+const char *msp430_mcu_name = "msp430x110";
-+
-+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
-+};
-+
-+struct mcu_type_s
-+{
-+ const char *name;
-+ enum msp430_arch arch;
-+ int has_hwmul;
-+};
-+
-+static struct mcu_type_s msp430_mcu_types[] = {
-+ /* generic types */
-+ {"msp1", MSP430_ISA_1, 0},
-+ {"msp2", MSP430_ISA_2, 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},
-+
-+ {"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},
-+
-+ {"msp430xE423", MSP430_ISA_42, 1},
-+ {"msp430xE425", MSP430_ISA_42, 1},
-+ {"msp430xE427", 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},
-+
-+ {"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},
-+
-+ {NULL, 0, 0}
-+};
-+
-+
-+
-+const struct attribute_spec msp430_attribute_table[];
-+static tree msp430_handle_fndecl_attribute
-+PARAMS ((tree *, tree, tree, int, bool *));
-+
-+#undef TARGET_ASM_FUNCTION_PROLOGUE
-+#define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
-+#undef TARGET_ASM_FUNCTION_EPILOGUE
-+#define TARGET_ASM_FUNCTION_EPILOGUE function_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
-+
-+
-+
-+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}
-+};
-+
-+unsigned int
-+msp430_section_type_flags (decl, name, reloc)
-+ 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 (node, name, args, flags, no_add_attrs)
-+ tree *node;
-+ tree name;
-+ tree args ATTRIBUTE_UNUSED;
-+ int flags ATTRIBUTE_UNUSED;
-+ bool *no_add_attrs;
-+{
-+ if (TREE_CODE (*node) != FUNCTION_DECL)
-+ {
-+ warning ("%s' attribute only applies to functions.",
-+ IDENTIFIER_POINTER (name));
-+ *no_add_attrs = true;
-+ }
-+ return NULL_TREE;
-+}
-+
-+
-+static int
-+msp430_naked_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+static int
-+msp430_task_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("task", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+static int
-+msp430_save_prologue_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("saveprologue", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+static int
-+interrupt_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+static int
-+msp430_critical_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("critical", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+
-+}
-+
-+static int
-+msp430_reentrant_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("reentrant", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+
-+}
-+
-+static int
-+noint_hwmul_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("noint_hwmul", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+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);
-+}
-+
-+static int
-+signal_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+
-+static int
-+wakeup_function_p (func)
-+ tree func;
-+{
-+ tree a;
-+ if (TREE_CODE (func) != FUNCTION_DECL)
-+ abort ();
-+ a = lookup_attribute ("wakeup", DECL_ATTRIBUTES (func));
-+ return a != NULL_TREE;
-+}
-+
-+enum msp430_arch
-+msp430_get_arch ()
-+{
-+ 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;
-+}
-+
-+int
-+msp430_is_xarch ()
-+{
-+ switch (msp430_get_arch())
-+ {
-+ case MSP430_ISA_241:
-+ case MSP430_ISA_26:
-+ case MSP430_ISA_46:
-+ return TRUE;
-+ }
-+ return FALSE;
-+}
-+
-+void
-+msp430_override_options ()
-+{
-+ 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;
-+ }
-+
-+ msp430_has_hwmul = t->has_hwmul || TARGET_HWMUL;
-+
-+ if (TARGET_NO_HWMUL)
-+ msp430_has_hwmul = 0;
-+
-+ msp430_case_values_threshold = 8; /* ? or there is a better value ? */
-+}
-+
-+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(mode, arg)
-+enum machine_mode mode;
-+const 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;
-+}
-+
-+
-+void
-+msp430_init_once ()
-+{
-+/******************************
-+
-+ __MPY=0x130
-+ __MPYS=0x132
-+ __MAC=0x134
-+ __MACS=0x136
-+ __OP2=0x138
-+ __RESLO=0x13a
-+ __RESHI=0x13c
-+ __SUMEXT=0x13e
-+ __RESSI <- not natural
-+ *****************************/
-+
-+ mpy_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__MPY"));
-+ mpys_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__MPYS"));
-+ mac_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__MAC"));
-+ macs_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__MACS"));
-+ op2_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__OP2"));
-+ reslo_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__RESLO"));
-+ reshi_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__RESHI"));
-+ sumext_rtx = gen_rtx_MEM (HImode, sym_ref (HImode, "__SUMEXT"));
-+ ressi_rtx = gen_rtx_MEM (SImode, sym_ref (SImode, "__RESLO"));
-+ return;
-+}
-+
-+static int reg_class_tab[16] = {
-+ 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 */
-+};
-+
-+
-+int
-+msp430_regno_ok_for_base_p (r)
-+ 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 (r)
-+ int r;
-+{
-+ if (r < FIRST_PSEUDO_REGISTER)
-+ return reg_class_tab[r];
-+
-+ return NO_REGS;
-+}
-+
-+
-+enum reg_class
-+msp430_reg_class_from_letter (c)
-+ int c;
-+{
-+ switch (c)
-+ {
-+ case 'd':
-+ return SP_REG;
-+ default:
-+ break;
-+ }
-+
-+ return NO_REGS;
-+}
-+
-+
-+
-+#define NOVECTOR 0xff
-+
-+void
-+asm_declare_function_name (file, name, decl)
-+ FILE *file;
-+ 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
-+ *
-+ */
-+ if (msp430_is_xarch())
-+ {
-+ vectors_start = 0xffc0;
-+ }
-+ else
-+ {
-+ 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 ("No valid interrupt vector assigned to ISR `%s'.", name);
-+ }
-+
-+ if ((vector < vectors_start || vector > 0xfffe || (vector & 1))
-+ && (vector != NOVECTOR && vector != -1))
-+ {
-+ warning
-+ ("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);
-+ }
-+}
-+
-+
-+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 leaf_func_p = leaf_function_p ();
-+ int offset = interrupt_func_p ? 0 : (cfp ? 2 : 0);
-+ int reg;
-+
-+ for (reg = 4; reg < 16; ++reg)
-+ {
-+ if ((!leaf_func_p && call_used_regs[reg] && (interrupt_func_p))
-+ || (regs_ever_live[reg]
-+ && (!call_used_regs[reg] || interrupt_func_p)))
-+ {
-+ offset += 2;
-+ }
-+ }
-+
-+ return offset;
-+}
-+
-+int
-+msp430_empty_epilogue ()
-+{
-+ 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;
-+}
-+
-+/* Returns a number of pushed registers */
-+static int
-+msp430_func_num_saved_regs ()
-+{
-+ int i;
-+ int saves = 0;
-+ int interrupt_func_p = interrupt_function_p (current_function_decl);
-+ int leaf_func_p = leaf_function_p ();
-+
-+ for (i = 4; i < 16; i++)
-+ {
-+ if ((regs_ever_live[i]
-+ && (!call_used_regs[i]
-+ || interrupt_func_p))
-+ || (!leaf_func_p && (call_used_regs[i] && interrupt_func_p)))
-+ {
-+ saves += 1;
-+ }
-+ }
-+
-+ return saves;
-+}
-+
-+
-+/* Output function prologue */
-+void
-+function_prologue (file, size)
-+ FILE *file;
-+ int size;
-+{
-+ int i;
-+ int interrupt_func_p = interrupt_function_p (current_function_decl);
-+ int signal_func_p = signal_function_p (current_function_decl);
-+ int leaf_func_p = leaf_function_p ();
-+ int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
-+ int stack_reserve = 0;
-+ tree ss = 0;
-+ rtx x = DECL_RTL (current_function_decl);
-+ const char *fnname = XSTR (XEXP (x, 0), 0);
-+ int offset;
-+ int cfp = msp430_critical_function_p (current_function_decl);
-+ int tfp = msp430_task_function_p (current_function_decl);
-+ int ree = msp430_reentrant_function_p (current_function_decl);
-+ int save_prologue_p =
-+ msp430_save_prologue_function_p (current_function_decl);
-+ int num_saved_regs;
-+
-+ return_issued = 0;
-+ last_insn_address = 0;
-+ jump_tables_size = 0;
-+ prologue_size = 0;
-+
-+ /* check attributes compatibility */
-+
-+ if ((cfp && ree) || (ree && interrupt_func_p))
-+ {
-+ warning ("attribute 'reentrant' ignored");
-+ ree = 0;
-+ }
-+
-+ if (cfp && interrupt_func_p)
-+ {
-+ warning ("attribute 'critical' ignored");
-+ cfp = 0;
-+ }
-+
-+ if (signal_func_p && !interrupt_func_p)
-+ {
-+ warning ("attribute 'signal' does not make sense.");
-+ signal_func_p = 0;
-+ }
-+
-+ /* naked function discards everything */
-+ if (msp430_naked_function_p (current_function_decl))
-+ {
-+ fprintf (file, "\t/* prologue: naked */\n");
-+ fprintf (file, ".L__FrameSize_%s=0x%x\n", fnname, size);
-+ return;
-+ }
-+ 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;
-+ }
-+ }
-+
-+ fprintf (file, "\t/* prologue: frame size = %d */\n", size);
-+ fprintf (file, ".L__FrameSize_%s=0x%x\n", fnname, size);
-+
-+
-+ offset = initial_elimination_offset (0, 0) - 2;
-+
-+ msp430_current_frame_offset = offset;
-+
-+ fprintf (file, ".L__FrameOffset_%s=0x%x\n", fnname, offset);
-+
-+ if (signal_func_p && interrupt_func_p)
-+ {
-+ prologue_size += 1;
-+ fprintf (file, "\teint\t; enable nested interrupt\n");
-+ }
-+
-+ if (main_p)
-+ {
-+ if (TARGET_NSI)
-+ {
-+ if (size || stack_reserve)
-+ fprintf (file, "\tsub\t#%d, r1\t", size + stack_reserve);
-+ if (frame_pointer_needed)
-+ {
-+ fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM);
-+ 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);
-+
-+ if (frame_pointer_needed)
-+ {
-+ fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM);
-+ prologue_size += 1;
-+ }
-+ prologue_size += 2;
-+ }
-+ }
-+ else
-+ {
-+ /* Here, we've got a chance to jump to prologue saver */
-+ num_saved_regs = msp430_func_num_saved_regs ();
-+
-+ if ((TARGET_SAVE_PROLOGUE || save_prologue_p)
-+ && !interrupt_func_p && !arg_register_used[12] && num_saved_regs > 4)
-+ {
-+ 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);
-+
-+ if (cfp && 8 - num_saved_regs)
-+ {
-+ int n = 16 - num_saved_regs * 2;
-+ fprintf (file, "\tadd\t#%d, r1\n", 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(!tfp)
-+ {
-+ for (i = 15; i >= 4; i--)
-+ {
-+ if ((regs_ever_live[i]
-+ && (!call_used_regs[i]
-+ || interrupt_func_p))
-+ || (!leaf_func_p && (call_used_regs[i]
-+ && (interrupt_func_p))))
-+ {
-+ fprintf (file, "\tpush\tr%d\n", i);
-+ prologue_size += 1;
-+ }
-+ }
-+ }
-+
-+ if (!interrupt_func_p && cfp)
-+ {
-+ prologue_size += 3;
-+ fprintf (file, "\tpush\tr2\n");
-+ fprintf (file, "\tdint\n");
-+ if (!size)
-+ fprintf (file, "\tnop\n");
-+ }
-+
-+ if (size)
-+ {
-+ /* The next is a hack... I do not undestand why, but if there
-+ ARG_POINTER_REGNUM and FRAME/STACK are different,
-+ the compiler fails to compute corresponding
-+ displacement */
-+ if (!optimize && !optimize_size
-+ && regs_ever_live[ARG_POINTER_REGNUM])
-+ {
-+ int o = initial_elimination_offset (0, 0) - size;
-+ fprintf (file, "\tmov\tr1, r%d\n", ARG_POINTER_REGNUM);
-+ fprintf (file, "\tadd\t#%d, r%d\n", o, ARG_POINTER_REGNUM);
-+ prologue_size += 2;
-+ if (o != 0 && o != 1 && o != 2 && o != 4 && o != 8)
-+ prologue_size += 1;
-+ }
-+
-+ /* adjust frame ptr... */
-+ if (size > 0)
-+ fprintf (file, "\tsub\t#%d, r1\t; %d, fpn %d\n", (size + 1) & ~1,
-+ size, frame_pointer_needed);
-+ else
-+ {
-+ size = -size;
-+ fprintf (file, "\tadd\t#%d, r1\t; %d, fpn %d\n",
-+ (size + 1) & ~1, size, frame_pointer_needed);
-+ }
-+
-+ if (frame_pointer_needed)
-+ {
-+ fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM);
-+ prologue_size += 1;
-+ }
-+
-+ if (size == 1 || size == 2 || size == 4 || size == 8)
-+ prologue_size += 1;
-+ else
-+ prologue_size += 2;
-+ }
-+
-+ /* disable interrupt for reentrant function */
-+ if (!interrupt_func_p && ree)
-+ {
-+ prologue_size += 1;
-+ fprintf (file, "\tdint\n");
-+ }
-+ }
-+
-+ fprintf (file, "\t/* prologue end (size=%d) */\n\n", prologue_size);
-+}
-+
-+
-+/* Output function epilogue */
-+
-+void
-+function_epilogue (file, size)
-+ FILE *file;
-+ int size;
-+{
-+ int i;
-+ int interrupt_func_p = interrupt_function_p (current_function_decl);
-+ int leaf_func_p = leaf_function_p ();
-+ int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
-+ int wakeup_func_p = wakeup_function_p (current_function_decl);
-+ int cfp = msp430_critical_function_p (current_function_decl);
-+ int ree = msp430_reentrant_function_p (current_function_decl);
-+ int save_prologue_p =
-+ msp430_save_prologue_function_p (current_function_decl);
-+ int still_return = 1;
-+ int function_size;
-+
-+
-+ 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 (msp430_task_function_p (current_function_decl))
-+ {
-+ fprintf (file, "\n\t/* epilogue: empty, task functions never return */\n");
-+ return;
-+ }
-+
-+ if (msp430_naked_function_p (current_function_decl))
-+ {
-+ fprintf (file, "\n\t/* epilogue: naked */\n");
-+ return;
-+ }
-+
-+ if (msp430_empty_epilogue ())
-+ {
-+ if (!return_issued)
-+ {
-+ fprintf (file, "\t%s\n", msp430_emit_return (NULL, NULL, NULL));
-+ 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)
-+ {
-+ if (size)
-+ fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);
-+ fprintf (file, "\tbr\t#%s\n", msp430_endup);
-+ epilogue_size += 4;
-+ if (size == 1 || size == 2 || size == 4 || size == 8)
-+ epilogue_size--;
-+ }
-+ else
-+ {
-+ if (ree)
-+ {
-+ fprintf (file, "\teint\n");
-+ epilogue_size += 1;
-+ }
-+
-+ if (size)
-+ {
-+ fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);
-+ if (size == 1 || size == 2 || size == 4 || size == 8)
-+ epilogue_size += 1;
-+ else
-+ epilogue_size += 2;
-+ }
-+
-+ if (!interrupt_func_p && cfp)
-+ {
-+ epilogue_size += 1;
-+ if (msp430_saved_regs_frame () == 2)
-+ {
-+ fprintf (file, "\treti\n");
-+ still_return = 0;
-+ }
-+ else
-+ fprintf (file, "\tpop\tr2\n");
-+ }
-+
-+ 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);
-+ 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);
-+ }
-+ else
-+ {
-+ for (i = 4; i < 16; i++)
-+ {
-+ if ((regs_ever_live[i]
-+ && (!call_used_regs[i]
-+ || interrupt_func_p))
-+ || (!leaf_func_p && (call_used_regs[i] && interrupt_func_p)))
-+ {
-+ fprintf (file, "\tpop\tr%d\n", i);
-+ epilogue_size += 1;
-+ }
-+ }
-+
-+ if (interrupt_func_p)
-+ {
-+ if (wakeup_func_p)
-+ {
-+ fprintf (file, "\tbic\t#0xf0,0(r1)\n");
-+ epilogue_size += 3;
-+ }
-+
-+ fprintf (file, "\treti\n");
-+ epilogue_size += 1;
-+ }
-+ else
-+ {
-+ if (still_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);
-+
-+ commands_in_file += prologue_size + function_size + epilogue_size;
-+ commands_in_prologues += prologue_size;
-+ commands_in_epilogues += epilogue_size;
-+}
-+
-+
-+/* 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, x, code)
-+ 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')
-+ fprintf (file, "#%s(%d)", trim_array[shift], INTVAL (x));
-+ 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 (x, insn)
-+ rtx x;
-+ rtx insn;
-+{
-+ 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;
-+}
-+
-+
-+
-+#define FIRST_CUM_REG 16
-+static CUMULATIVE_ARGS *cum_incoming = 0;
-+
-+/* Initializing the variable cum for the state at the beginning
-+ of the argument list. */
-+void
-+init_cumulative_args (cum, fntype, libname, indirect)
-+ 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;
-+ }
-+}
-+
-+/* the same in scope of the cum.args., buf usefull for a
-+ function call */
-+void
-+init_cumulative_incoming_args (cum, fntype, libname)
-+ 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;
-+}
-+
-+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));
-+}
-+
-+/* Returns the number of registers to allocate for a function argument. */
-+static int
-+msp430_num_arg_regs (mode, type)
-+ 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;
-+}
-+
-+/* Controls whether a function argument is passed
-+ in a register, and which register. */
-+rtx
-+function_arg (cum, mode, type, named)
-+ 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;
-+}
-+
-+
-+/* Update the summarizer variable CUM to advance past an argument
-+ in the argument list. */
-+void
-+function_arg_advance (cum, mode, type, named)
-+ 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;
-+ }
-+}
-+
-+/* Workaround for volatile variables */
-+int
-+nonimmediate_operand_msp430 (op, mode)
-+ rtx op;
-+ enum machine_mode mode;
-+{
-+ 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;
-+}
-+
-+int
-+memory_operand_msp430 (op, mode)
-+ rtx op;
-+ enum machine_mode mode;
-+{
-+ 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;
-+}
-+
-+int
-+general_operand_msp430 (op, mode)
-+ rtx op;
-+ enum machine_mode mode;
-+{
-+ 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;
-+}
-+
-+
-+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;
-+}
-+
-+
-+int
-+default_rtx_costs (X, code, outer_code)
-+ rtx X ATTRIBUTE_UNUSED;
-+ enum rtx_code code;
-+ enum rtx_code outer_code ATTRIBUTE_UNUSED;
-+{
-+ int cost = 0;
-+
-+ switch (code)
-+ {
-+ case SYMBOL_REF:
-+ cost = 1;
-+ break;
-+ case LABEL_REF:
-+ cost = 1;
-+ break;
-+ case MEM:
-+ cost += 1;
-+ break;
-+ case CONST_INT:
-+ cost = 1;
-+ break;
-+ case SIGN_EXTEND:
-+ case ZERO_EXTEND:
-+ cost += 2;
-+ break;
-+ default:
-+ break;
-+ }
-+ return cost;
-+}
-+
-+
-+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");
-+}
-+
-+/* 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);
-+}
-+
-+/* Sets section name for declaration DECL */
-+void
-+unique_section (decl, reloc)
-+ tree decl;
-+ int reloc ATTRIBUTE_UNUSED;
-+{
-+ int len;
-+ const char *name, *prefix;
-+ char *string;
-+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-+ STRIP_NAME_ENCODING (name, name);
-+
-+ if ((TREE_CODE (decl) == FUNCTION_DECL) || DECL_READONLY_SECTION (decl, 0))
-+ prefix = ".text.";
-+ else if ((DECL_INITIAL (decl) == 0) || (DECL_INITIAL (decl) == error_mark_node))
-+ prefix = ".bss.";
-+ else
-+ prefix = ".data.";
-+
-+ len = strlen (name) + strlen (prefix);
-+ string = alloca (len + 1);
-+ sprintf (string, "%s%s", prefix, name);
-+ DECL_SECTION_NAME (decl) = build_string (len, string);
-+}
-+
-+
-+/* 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. */
-+
-+void
-+asm_file_start (file)
-+ FILE *file;
-+{
-+ output_file_directive (file, main_input_filename);
-+ fprintf (file, "\t.arch %s\n\n", msp430_mcu_name);
-+
-+ if (msp430_has_hwmul)
-+ {
-+ 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");
-+
-+ }
-+
-+ commands_in_file = 0;
-+ commands_in_prologues = 0;
-+ commands_in_epilogues = 0;
-+}
-+
-+/* Outputs to the stdio stream FILE some
-+ appropriate text to go at the end of an assembler file. */
-+
-+void
-+asm_file_end (file)
-+ FILE *file;
-+{
-+ fprintf (file,
-+ "\n"
-+ "/*********************************************************************\n"
-+ " * File %s: code size: %d words (0x%x)\n * incl. words in prologues: %d, epilogues: %d\n"
-+ " *********************************************************************/\n",
-+ main_input_filename,
-+ commands_in_file,
-+ commands_in_file, commands_in_prologues, commands_in_epilogues);
-+}
-+
-+int
-+msp430_hard_regno_mode_ok (regno, mode)
-+ int regno ATTRIBUTE_UNUSED;
-+ enum machine_mode mode ATTRIBUTE_UNUSED;
-+{
-+ return 1;
-+}
-+
-+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;
-+}
-+
-+/* cfp minds the fact that the function may save r2 */
-+int
-+initial_elimination_offset (from, to)
-+ int from;
-+ int to;
-+{
-+ int reg;
-+ if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-+ return 0;
-+ else
-+ {
-+ int interrupt_func_p = interrupt_function_p (current_function_decl);
-+ int cfp = msp430_critical_function_p (current_function_decl);
-+ int leaf_func_p = leaf_function_p ();
-+ int offset = interrupt_func_p ? 0 : (cfp ? 2 : 0);
-+
-+ for (reg = 4; reg < 16; ++reg)
-+ {
-+ if ((!leaf_func_p && call_used_regs[reg] && (interrupt_func_p))
-+ || (regs_ever_live[reg]
-+ && (!call_used_regs[reg] || interrupt_func_p)))
-+ {
-+ offset += 2;
-+ }
-+ }
-+ return get_frame_size () + offset + 2;
-+ }
-+ return 0;
-+}
-+
-+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);
-+ }
-+ }
-+ 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);
-+ }
-+
-+ 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;
-+}
-+
-+
-+/* 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 (insn, operand, num_operands)
-+ rtx insn, *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));
-+ }
-+ last_insn_address = INSN_ADDRESSES (uid);
-+}
-+
-+void
-+msp430_output_addr_vec_elt (stream, value)
-+ FILE *stream;
-+ int value;
-+{
-+ fprintf (stream, "\t.word .L%d\n", value);
-+ jump_tables_size++;
-+}
-+
-+
-+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)) && leaf_function_p ())
-+ {
-+ 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 (!regs_ever_live[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 *********************/
-+
-+RTX_CODE
-+msp430_canonicalize_comparison (code, op0, op1)
-+ 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;
-+}
-+
-+
-+void
-+msp430_emit_cbranch (code, loc)
-+ 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 (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 (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 (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 (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 (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 (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 (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;
-+}
-+
-+
-+/* x - dst
-+ y - src */
-+static int
-+msp430_cc_source (insn, code, x, y)
-+ rtx insn;
-+ enum rtx_code code ATTRIBUTE_UNUSED;
-+ 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;
-+}
-+
-+
-+
-+const char *
-+msp430_cbranch (insn, operands, len)
-+ rtx insn;
-+ rtx operands[];
-+ int *len;
-+{
-+ 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 = get_attr_length (insn);
-+ 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 (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 "";
-+}
-+
-+/***************** 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 (GET_CODE (pat) == RETURN)
-+ 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;
-+}
-+
-+/******** jumps ************/
-+
-+const char *
-+msp430_emit_blt0si (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_beq (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bne (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bgt (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bgtu (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_blt (operands, len)
-+ 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 "";
-+}
-+
-+
-+const char *
-+msp430_emit_bltnoovfl (operands, len)
-+ 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 "";
-+}
-+
-+
-+
-+const char *
-+msp430_emit_bltu (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bge (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bgeu (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_ble (operands, len)
-+ 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 "";
-+}
-+
-+const char *
-+msp430_emit_bleu (operands, len)
-+ 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 "";
-+}
-+
-+
-+/* 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]));
-+
-+ 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 (x)
-+ 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;
-+}
-+
-+/* 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 (which, insn, x)
-+ int which;
-+ rtx insn ATTRIBUTE_UNUSED;
-+ rtx x;
-+{
-+ rtx r;
-+ rtx next;
-+
-+ 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);
-+}
-+
-+const char *
-+msp430_emit_return (insn, operands, len)
-+ rtx insn ATTRIBUTE_UNUSED;
-+ rtx operands[] ATTRIBUTE_UNUSED;
-+ int *len ATTRIBUTE_UNUSED;
-+{
-+ return_issued = 1;
-+ if (msp430_empty_epilogue () == 1)
-+ return "ret";
-+
-+ return "reti";
-+}
-+
-+int
-+three_operands_msp430 (x, mode)
-+ rtx x;
-+ enum machine_mode mode;
-+{
-+ enum rtx_code code = GET_CODE (x);
-+ if (GET_MODE (x) != mode)
-+ return 0;
-+
-+ return (code == PLUS
-+ || code == MINUS || code == AND || code == IOR || code == XOR);
-+}
-+
-+int
-+equality_operator (op, mode)
-+ register rtx op;
-+ enum machine_mode mode;
-+{
-+ return ((mode == VOIDmode || GET_MODE (op) == mode)
-+ && (GET_CODE (op) == EQ || GET_CODE (op) == NE));
-+}
-+
-+/* Return 1 if this is a comparison operator but not an EQ or NE operator. */
-+int
-+inequality_operator (op, mode)
-+ register rtx op;
-+ enum machine_mode mode;
-+{
-+ return comparison_operator (op, mode) && !equality_operator (op, mode);
-+}
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/msp430/msp430.h
---- gcc-3.2.3.orig/gcc/config/msp430/msp430.h 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/msp430.h 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,3378 @@
-+
-+/* Definitions of target machine for GNU compiler,
-+ for Texas Instruments MSP430 microcontrollers.
-+ Copyright (C) 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. */
-+
-+/* Names to predefine in the preprocessor for this target machine. */
-+
-+#define CPP_PREDEFINES "-DMSP430"
-+/* Define this to be a string constant containing `-D' options to
-+ define the predefined macros that identify this machine and system.
-+ These macros will be predefined unless the `-ansi' option is
-+ specified.
-+
-+ In addition, a parallel set of macros are predefined, whose names
-+ are made by appending `__' at the beginning and at the end. These
-+ `__' macros are permitted by the ANSI standard, so they are
-+ predefined regardless of whether `-ansi' is specified.
-+
-+ For example, on the Sun, one can use the following value:
-+
-+ "-Dmc68000 -Dsun -Dunix"
-+
-+ The result is to define the macros `__mc68000__', `__sun__' and
-+ `__unix__' unconditionally, and the macros `mc68000', `sun' and
-+ `unix' provided `-ansi' is not specified. */
-+
-+
-+/* This declaration should be present. */
-+/*
-+#include <stdio.h>
-+*/
-+
-+extern int target_flags;
-+
-+#define MASK_PROF_STD 0x00000001
-+#define MASK_PROF_LIB 0x00000002
-+#define MASK_PROF_STACK 0x00000004
-+
-+#define MASK_RTL_DUMP 0x00000010
-+#define MASK_ALL_DEBUG 0x00000FE0
-+#define MASK_FORCE_HWMUL 0x00001000
-+#define MASK_STRICT_ALIGN 0x00002000
-+#define MASK_IAR 0x00004000
-+#define MASK_NO_STACK_INIT 0x00008000
-+#define MASK_NO_VOLAT_WRKAR 0x00010000
-+#define MASK_REORDER 0x00020000
-+#define MASK_INLINESIHWMUL 0x00040000
-+#define MASK_NO_HWMUL 0x00100000
-+#define MASK_NOINT_HWMUL 0x00200000
-+#define MASK_SAVE_PROLOGUE 0x00400000
-+
-+
-+
-+#define TARGET_PROF_STD (target_flags & MASK_PROF_STD)
-+#define TARGET_PROF_LIB (target_flags & MASK_PROF_LIB)
-+#define TARGET_PROF_STACK (target_flags & MASK_PROF_STACK)
-+#define TARGET_NO_HWMUL (target_flags & MASK_NO_HWMUL)
-+#define TARGET_HWMUL (target_flags & MASK_FORCE_HWMUL)
-+#define TARGET_NOINT_HWMUL (target_flags & MASK_NOINT_HWMUL)
-+#define TARGET_RTL_DUMP (target_flags & MASK_RTL_DUMP)
-+#define TARGET_ALL_DEBUG (target_flags & MASK_ALL_DEBUG)
-+#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
-+#define TARGET_IAR (target_flags & MASK_IAR)
-+#define TARGET_NSI (target_flags & MASK_NO_STACK_INIT)
-+#define TARGET_NVWA (target_flags & MASK_NO_VOLAT_WRKAR)
-+#define TARGET_REORDER (target_flags & MASK_REORDER)
-+#define TARGET_INLINESIHWMUL (target_flags & MASK_INLINESIHWMUL)
-+#define TARGET_SAVE_PROLOGUE (target_flags & MASK_SAVE_PROLOGUE)
-+
-+
-+#define TARGET_SWITCHES { \
-+ { "pgs", MASK_PROF_STD, N_("Add ordinary profile information")}, \
-+ { "pgl", MASK_PROF_LIB, N_("Add library profile information")}, \
-+ { "pgr", MASK_PROF_STACK,N_("Add stack information to profiler") }, \
-+ { "rtl", MASK_RTL_DUMP, NULL }, \
-+ { "deb", MASK_ALL_DEBUG, NULL }, \
-+ { "strict-align", MASK_STRICT_ALIGN,N_("Strict alignment for all structures") }, \
-+ { "force-hwmul", MASK_FORCE_HWMUL,N_("Force hardware multiplier") },\
-+ { "disable-hwmul", MASK_NO_HWMUL, N_("Disable hardware multiplier") }, \
-+ { "inline-hwmul", MASK_INLINESIHWMUL, N_("Issue inline multiplication code for 32-bit integers") }, \
-+ { "noint-hwmul", MASK_NOINT_HWMUL, ("Assume interrupt routine does not do hardware multiply")}, \
-+ { "IAR",MASK_IAR,N_("Produce IAR assembler syntax") }, \
-+ { "no-stack-init",MASK_NO_STACK_INIT,N_("No stack init in main()") }, \
-+ { "no-volatile-workaround",MASK_NO_STACK_INIT,N_("Do not perform volatile workaround for bitwise operations") }, \
-+ { "save-prologue",MASK_SAVE_PROLOGUE, ("Use subroutine call for function prologue/epilogue when possible")}, \
-+ { "", 0, NULL } \
-+}
-+
-+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_OPTIONS { \
-+ { "init-stack=", &msp430_init_stack, N_("Specify the initial stack address") }, \
-+ { "mcu=", &msp430_mcu_name, N_("Specify the MCU name") }, \
-+ { "endup-at=",&msp430_endup,N_("Jump to specified routine at the end of main()")} \
-+}
-+
-+
-+#define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)");
-+
-+#define OVERRIDE_OPTIONS msp430_override_options()
-+
-+#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
-+
-+/* Define this if move instructions will actually fail to work
-+ when given unaligned data. */
-+#define STRICT_ALIGNMENT TARGET_STRICT_ALIGN
-+
-+/* 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 MAX_LONG_TYPE_SIZE 32
-+/* Maximum number for the size in bits of the type `long' on the
-+ target machine. If this is undefined, the default is
-+ `LONG_TYPE_SIZE'. Otherwise, it is the constant value that is the
-+ largest value that `LONG_TYPE_SIZE' can have at run-time. This is
-+ used in `cpp'. */
-+
-+
-+#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 16
-+/* 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 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 */\
-+}
-+/* 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 */ \
-+}
-+/* 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 NON_SAVING_SETJMP 0
-+/* If this macro is defined and has a nonzero value, it means that
-+ `setjmp' and related functions fail to save the registers, or that
-+ `longjmp' fails to restore them. To compensate, the compiler
-+ avoids putting variables in registers in functions that use
-+ `setjmp'. */
-+
-+#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 */ \
-+ {0x0000fff2ul}, /* r4 - r15,r1 */ \
-+ {0x0000fff2ul}, /* r4 - r15,r1 */ \
-+ {0x0000fff0ul}, /* r4 - r15 */ \
-+ {0x0000fffful} /* 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 POST_DEC
-+
-+#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. */
-+
-+#define ARG_POINTER_REGNUM 5
-+/* 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 { \
-+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
-+ {ARG_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
-+/* 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'. */
-+
-+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
-+init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT)
-+
-+#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
-+init_cumulative_incoming_args(&(CUM), FNTYPE, LIBNAME)
-+
-+/* 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 STRUCT_VALUE_INCOMING 0
-+/* If the incoming location is not a register, then you should define
-+ `STRUCT_VALUE_INCOMING' as an expression for an RTX for where the
-+ called function should find the value. If it should find the
-+ value on the stack, define this to create a `mem' which refers to
-+ the frame pointer. A definition of 0 means that the address is
-+ passed as an "invisible" first argument. */
-+
-+#define STRICT_ARGUMENT_NAMING 1
-+/* Define this macro if the location where a function argument is
-+ passed depends on whether or not it is a named argument.
-+
-+ This macro controls how the NAMED argument to `FUNCTION_ARG' is
-+ set for varargs and stdarg functions. With this macro defined,
-+ the NAMED argument is always true for named arguments, and false
-+ for unnamed arguments. If this is not defined, but
-+ `SETUP_INCOMING_VARARGS' is defined, then all arguments are
-+ treated as named. Otherwise, all named arguments except the last
-+ are treated as named. */
-+
-+
-+/*
-+#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 &®NO(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;
-+
-+/* A part of a C `switch' statement that describes the relative costs
-+ of constant RTL expressions. It must contain `case' labels for
-+ expression codes `const_int', `const', `symbol_ref', `label_ref'
-+ and `const_double'. Each case must ultimately reach a `return'
-+ statement to return the relative cost of the use of that kind of
-+ constant value in an expression. The cost may depend on the
-+ precise value of the constant, which is available for examination
-+ in X, and the rtx code of the expression in which it is contained,
-+ found in OUTER_CODE.
-+
-+ CODE is the expression code--redundant, since it can be obtained
-+ with `GET_CODE (X)'. */
-+
-+#define DEFAULT_RTX_COSTS(x, code, outer_code) \
-+{ \
-+ int cst = default_rtx_costs (x, code, outer_code); \
-+ if (cst>0) \
-+ return cst; \
-+ else if (cst<0) \
-+ total += -cst; \
-+ break; \
-+}
-+
-+/* 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 ADDRESS_COST(ADDRESS) 2
-+
-+/* An expression giving the cost of an addressing mode that contains
-+ ADDRESS. If not defined, the cost is computed from the ADDRESS
-+ expression and the `CONST_COSTS' values.
-+
-+ For most CISC machines, the default cost is a good approximation
-+ of the true cost of the addressing mode. However, on RISC
-+ machines, all instructions normally have the same length and
-+ execution time. Hence all addresses will have equal costs.
-+
-+ In cases where more than one form of an address is known, the form
-+ with the lowest cost will be used. If multiple forms have the
-+ same, lowest, cost, the one that is the most complex will be used.
-+
-+ For example, suppose an address that is equal to the sum of a
-+ register and a constant is used twice in the same basic block.
-+ When this macro is not defined, the address will be computed in a
-+ register and memory references will be indirect through that
-+ register. On machines where the cost of the addressing mode
-+ containing the sum is no higher than that of a simple indirect
-+ reference, this will produce an additional instruction and
-+ possibly require an additional register. Proper specification of
-+ this macro eliminates this overhead for such machines.
-+
-+ Similar use of this macro is made in strength reduction of loops.
-+
-+ ADDRESS need not be valid as an address. In such a case, the cost
-+ is not relevant and can be any value; invalid addresses need not be
-+ assigned a different cost.
-+
-+ On machines where an address involving more than one register is as
-+ cheap as an address computation involving only one register,
-+ defining `ADDRESS_COST' to reflect this can cause two registers to
-+ be live over a region of code where only one would have been if
-+ `ADDRESS_COST' were not defined in that manner. This effect should
-+ be considered in the definition of this macro. Equivalent costs
-+ should probably only be given to addresses with different numbers
-+ of registers on machines with lots of registers.
-+
-+ This macro will normally either not be defined or be defined as a
-+ constant. */
-+
-+#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. */
-+
-+#define BRANCH_COST 0
-+/* 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 NO_RECURSIVE_FUNCTION_CSE
-+/* Define this macro if it is as good or better for a function to call
-+ itself with an explicit address than to call an address kept in a
-+ register.
-+
-+ `ADJUST_COST (INSN, LINK, DEP_INSN, COST)'
-+ A C statement (sans semicolon) to update the integer variable COST
-+ based on the relationship between INSN that is dependent on
-+ DEP_INSN through the dependence LINK. The default is to make no
-+ adjustment to COST. This can be used for example to specify to
-+ the scheduler that an output- or anti-dependence does not incur
-+ the same cost as a data-dependence.
-+
-+ `ADJUST_PRIORITY (INSN)'
-+ A C statement (sans semicolon) to update the integer scheduling
-+ priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute
-+ the INSN earlier, increase the priority to execute INSN later.
-+ Do not define this macro if you do not need to adjust the
-+ scheduling priorities of insns. */
-+
-+
-+#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). */
-+
-+#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; \
-+ } \
-+}
-+
-+
-+/* 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). */
-+
-+
-+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-+ (VAR) = (SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*' || (SYMBOL_NAME)[0] == '@');
-+/* `STRIP_NAME_ENCODING (VAR, SYM_NAME)'
-+ Decode SYM_NAME and store the real name part in VAR, sans the
-+ characters that encode section info. Define this macro if
-+ `ENCODE_SECTION_INFO' alters the symbol's name string. */
-+/* `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 UNIQUE_SECTION(DECL, RELOC) unique_section (DECL, RELOC)
-+/* `UNIQUE_SECTION (DECL, RELOC)'
-+ A C statement to build up a unique section name, expressed as a
-+ STRING_CST node, and assign it to `DECL_SECTION_NAME (DECL)'.
-+ RELOC indicates whether the initial value of EXP requires
-+ link-time relocations. If you do not define this macro, GNU CC
-+ will use the symbol name prefixed by `.' as the section name. */
-+
-+
-+#define ASM_FILE_START(STREAM) asm_file_start (STREAM)
-+/* A C expression which outputs to the stdio stream STREAM some
-+ appropriate text to go at the start of an assembler file.
-+
-+ Normally this macro is defined to output a line containing
-+ `#NO_APP', which is a comment that has no effect on most
-+ assemblers but tells the GNU assembler that it can save time by not
-+ checking for certain assembler constructs.
-+
-+ On systems that use SDB, it is necessary to output certain
-+ commands; see `attasm.h'. */
-+
-+#define ASM_FILE_END(STREAM) asm_file_end (STREAM)
-+/* A C expression which outputs to the stdio stream STREAM some
-+ appropriate text to go at the end of an assembler file.
-+
-+ If this macro is not defined, the default is to output nothing
-+ special at the end of the file. Most systems don't require any
-+ definition.
-+
-+ On systems that use SDB, it is necessary to output certain
-+ commands; see `attasm.h'. */
-+
-+#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_SOURCE_LINE(STREAM, LINE) fprintf (STREAM,"/* line: %d */\n",LINE)
-+/* A C statement to output DBX or SDB debugging information before
-+ code for line number LINE of the current source file to the stdio
-+ stream STREAM.
-+
-+ This macro need not be defined if the standard form of debugging
-+ information for the debugger in use is appropriate. */
-+
-+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
-+ asm_output_section_name(FILE, DECL, NAME, RELOC)
-+
-+/* `ASM_OUTPUT_SECTION_NAME (STREAM, DECL, NAME, RELOC)'
-+ A C statement to output something to the assembler file to switch
-+ to section NAME for object DECL which is either a `FUNCTION_DECL',
-+ a `VAR_DECL' or `NULL_TREE'. RELOC indicates whether the initial
-+ value of EXP requires link-time relocations. Some target formats
-+ do not support arbitrary sections. Do not define this macro in
-+ such cases.
-+
-+ At present this macro is only used to support section attributes.
-+ When this macro is undefined, section attributes are disabled. */
-+
-+#define OBJC_PROLOGUE {}
-+/* A C statement to output any assembler statements which are
-+ required to precede any Objective C object definitions or message
-+ sending. The statement is executed only when compiling an
-+ Objective C program. */
-+
-+
-+
-+#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'. */
-+
-+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
-+/* 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)
-+
-+/* 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)
-+
-+/* macro to output uninitialized varible in normal case where -fno-common is not specified */
-+
-+#undef ASM_OUTPUT_ALIGNED_DECL_COMMON
-+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
-+ do \
-+ { \
-+ char *p = NAME; \
-+ if(*p == '*' || *p == '@' ) p++; \
-+ if(*p >= '0' && *p <= '9' ) break; \
-+ if (IN_NAMED_SECTION (DECL)) \
-+ { \
-+ /* case where -fdata-sections is specified */ \
-+ named_section (DECL, NULL, 0); \
-+ ASM_GLOBALIZE_LABEL (FILE, NAME); \
-+ ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
-+ last_assemble_variable_decl = DECL; \
-+ ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL); \
-+ ASM_OUTPUT_SKIP (FILE, SIZE ? SIZE : 1); \
-+ } \
-+ else \
-+ { \
-+ /* default case */ \
-+ fputs ("\t.comm ", (FILE)); \
-+ assemble_name ((FILE), (NAME)); \
-+ fprintf ((FILE), ",%d%s", (SIZE), (SIZE)>1?",2\n":"\n"); \
-+ } \
-+ } \
-+ while (0)
-+
-+
-+/* macro to output uninitialized variable when -fno-common _is_ specified */
-+#undef ASM_OUTPUT_ALIGNED_BSS
-+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
-+ do \
-+ { \
-+ char *p = NAME; \
-+ if(*p == '*' || *p == '@' ) p++; \
-+ if(*p >= '0' && *p <= '9' ) break; \
-+ if (IN_NAMED_SECTION (DECL)) \
-+ named_section (DECL, NULL, 0); \
-+ else \
-+ bss_section (); \
-+ \
-+ ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
-+ \
-+ last_assemble_variable_decl = DECL; \
-+ ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL); \
-+ ASM_OUTPUT_SKIP (FILE, SIZE ? SIZE : 1); \
-+ } \
-+ while (0)
-+
-+
-+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
-+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
-+ do \
-+ { \
-+ char *p = NAME; \
-+ if(*p == '*' || *p == '@' ) p++; \
-+ if(*p >= '0' && *p <= '9' ) break; \
-+ if ((DECL) != NULL && IN_NAMED_SECTION (DECL)) \
-+ named_section (DECL, NULL, 0); \
-+ else \
-+ bss_section (); \
-+ \
-+ ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
-+ ASM_OUTPUT_LABEL (FILE, NAME); \
-+ fprintf (FILE, "\t.space\t%d\n", SIZE); \
-+ } \
-+ while (0)
-+
-+#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) \
-+{ \
-+ 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); \
-+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "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)
-+/* A C statement (sans semicolon) to output to the stdio stream
-+ STREAM any text necessary for declaring the size of a function
-+ which is being defined. The argument NAME is the name of the
-+ function. The argument DECL is the `FUNCTION_DECL' tree node
-+ representing the function.
-+
-+ If this macro is not defined, then the function size is not
-+ defined. */
-+
-+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
-+do { \
-+ 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; \
-+ fprintf (FILE, "%s", SIZE_ASM_OP); \
-+ assemble_name (FILE, NAME); \
-+ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
-+ } \
-+ ASM_OUTPUT_LABEL(FILE, NAME); \
-+} while (0)
-+/* A C statement (sans semicolon) to output to the stdio stream
-+ STREAM any text necessary for declaring the name NAME of an
-+ initialized variable which is being defined. This macro must
-+ output the label definition (perhaps using `ASM_OUTPUT_LABEL').
-+ The argument DECL is the `VAR_DECL' tree node representing the
-+ variable.
-+
-+ If this macro is not defined, then the variable name is defined in
-+ the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). */
-+
-+#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)
-+/* A C statement (sans semicolon) to finish up declaring a variable
-+ name once the compiler has processed its initializer fully and
-+ thus has had a chance to determine the size of an array when
-+ controlled by an initializer. This is used on systems where it's
-+ necessary to declare something about the size of the object.
-+
-+ If you don't define this macro, that is equivalent to defining it
-+ to do nothing. */
-+
-+
-+#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 ASM_GLOBALIZE_LABEL(STREAM, NAME) \
-+do { \
-+ char *p = NAME; \
-+ if(*p == '*' || *p == '@' ) p++; \
-+ if(*p >= '0' && *p <= '9' ) break; \
-+ fprintf (STREAM, ".global\t"); \
-+ assemble_name (STREAM, NAME); \
-+ fprintf (STREAM, "\n"); \
-+} \
-+while (0)
-+
-+/* A C statement (sans semicolon) to output to the stdio stream
-+ STREAM some commands that will make the label NAME global; that
-+ is, available for reference from other files. 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 global, and a newline. */
-+
-+#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. */
-+
-+#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
-+fprintf(STREAM, ".%s%d:\n", PREFIX, NUM)
-+/* 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" \
-+}
-+/* 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. */
-+
-+
-+#define PREDICATE_CODES \
-+{"memory_operand_msp430", {SUBREG, MEM}}, \
-+{"nonimmediate_operand_msp430", {SUBREG, REG, MEM}},\
-+{"general_operand_msp430", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, LABEL_REF, SUBREG, REG, MEM}},\
-+{"three_operands_msp430", {PLUS, MINUS, AND, IOR, XOR}}, \
-+{"equality_operator", {EQ, NE }}, \
-+{"inequality_operator", {GE, GT, LE, LT, GEU, GTU, LEU, LTU }},
-+
-+
-+
-+
-+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 INTEGRATE_THRESHOLD(DECL) (1 + (3 * list_length (DECL_ARGUMENTS (DECL)) / 2))
-+
-+/* A C expression for the maximum number of instructions above which
-+ the function DECL should not be inlined. DECL is a
-+ `FUNCTION_DECL' node.
-+
-+ The default definition of this macro is 64 plus 8 times the number
-+ of arguments that the function accepts. Some people think a larger
-+ threshold should be used on RISC machines. */
-+
-+/*
-+#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 MACHINE_DEPENDENT_REORG(INSN) machine_dependent_reorg (INSN)
-+/* In rare cases, correct code generation requires extra machine
-+ dependent processing between the second jump optimization pass and
-+ delayed branch scheduling. On those machines, define this macro
-+ as a C statement to act on the code starting at INSN. */
-+
-+#define GIV_SORT_CRITERION(X, Y) \
-+ if (GET_CODE ((X)->add_val) == CONST_INT \
-+ && GET_CODE ((Y)->add_val) == CONST_INT) \
-+ return INTVAL ((X)->add_val) - INTVAL ((Y)->add_val);
-+
-+/* `GIV_SORT_CRITERION(GIV1, GIV2)'
-+ In some cases, the strength reduction optimization pass can
-+ produce better code if this is defined. This macro controls the
-+ order that induction variables are combined. This macro is
-+ particularly useful if the target has limited addressing modes.
-+ For instance, the SH target has only positive offsets in
-+ addresses. Thus sorting to put the smallest address first allows
-+ the most combinations to be found. */
-+
-+/* Define results of standard character escape sequences. */
-+#define TARGET_BELL 007
-+#define TARGET_BS 010
-+#define TARGET_TAB 011
-+#define TARGET_NEWLINE 012
-+#define TARGET_VT 013
-+#define TARGET_FF 014
-+#define TARGET_CR 015
-+#define TARGET_ESC 033
-+
-+#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 TARGET_MEM_FUNCTIONS
-+/* Define this macro if GNU CC should generate calls to the System V
-+ (and ANSI C) library functions `memcpy' and `memset' rather than
-+ the BSD functions `bcopy' and `bzero'. */
-+
-+#define CPP_SPEC "\
-+%{!mmcu*|mmcu=msp1:%(cpp_msp1)} \
-+%{mmcu=msp2:%(cpp_msp2) -DMSP430_HAS_HWMUL} \
-+%{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__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x148:%(cpp_msp2) -D__MSP430_148__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x149:%(cpp_msp2) -D__MSP430_149__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1471:%(cpp_msp2) -D__MSP430_1471__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1481:%(cpp_msp2) -D__MSP430_1481__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1491:%(cpp_msp2) -D__MSP430_1491__ -DMSP430_HAS_HWMUL} \
-+%{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__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x168:%(cpp_msp2) -D__MSP430_168__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x169:%(cpp_msp2) -D__MSP430_169__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1610:%(cpp_msp2) -D__MSP430_1610__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1611:%(cpp_msp2) -D__MSP430_1611__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x1612:%(cpp_msp2) -D__MSP430_1612__ -DMSP430_HAS_HWMUL} \
-+%{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=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__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x235:%(cpp_msp2) -D__MSP430_235__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2330:%(cpp_msp2) -D__MSP430_2330__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2350:%(cpp_msp2) -D__MSP430_2350__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2370:%(cpp_msp2) -D__MSP430_2370__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x247:%(cpp_msp2) -D__MSP430_247__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x248:%(cpp_msp2) -D__MSP430_248__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x249:%(cpp_msp2) -D__MSP430_249__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2410:%(cpp_msp2) -D__MSP430_2410__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2471:%(cpp_msp2) -D__MSP430_2471__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2481:%(cpp_msp2) -D__MSP430_2481__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2491:%(cpp_msp2) -D__MSP430_2491__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2416:%(cpp_msp2) -D__MSP430_2416__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2417:%(cpp_msp2) -D__MSP430_2417__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2418:%(cpp_msp2) -D__MSP430_2418__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2419:%(cpp_msp2) -D__MSP430_2419__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2616:%(cpp_msp2) -D__MSP430_2616__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2617:%(cpp_msp2) -D__MSP430_2617__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2618:%(cpp_msp2) -D__MSP430_2618__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x2619:%(cpp_msp2) -D__MSP430_2619__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{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__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x337:%(cpp_msp2) -D__MSP430_337__ -DMSP430_HAS_HWMUL} \
-+%{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__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x425:%(cpp_msp2) -D__MSP430_425__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x427:%(cpp_msp2) -D__MSP430_427__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x4250:%(cpp_msp1) -D__MSP430_4250__} \
-+%{mmcu=msp430x4260:%(cpp_msp1) -D__MSP430_4260__} \
-+%{mmcu=msp430x4270:%(cpp_msp1) -D__MSP430_4270__} \
-+%{mmcu=msp430xE423:%(cpp_msp2) -D__MSP430_E423__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xE425:%(cpp_msp2) -D__MSP430_E425__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xE427:%(cpp_msp2) -D__MSP430_E427__ -DMSP430_HAS_HWMUL} \
-+%{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=msp430x447:%(cpp_msp2) -D__MSP430_447__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x448:%(cpp_msp2) -D__MSP430_448__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430x449:%(cpp_msp2) -D__MSP430_449__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xG4616:%(cpp_msp2) -D__MSP430_G4616__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xG4617:%(cpp_msp2) -D__MSP430_G4617__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xG4618:%(cpp_msp2) -D__MSP430_G4618__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mmcu=msp430xG4619:%(cpp_msp2) -D__MSP430_G4619__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
-+%{mint8:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long -D__INT_MAX__=127} \
-+%{!mint*:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int -D__INT_MAX__=32767} \
-+%{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 NO_BUILTIN_SIZE_TYPE
-+/* If this macro is defined, the preprocessor will not define the
-+ builtin macro `__SIZE_TYPE__'. The macro `__SIZE_TYPE__' must
-+ then be defined by `CPP_SPEC' instead.
-+
-+ This should be defined if `SIZE_TYPE' depends on target dependent
-+ flags which are not accessible to the preprocessor. Otherwise, it
-+ should not be defined. */
-+
-+#define NO_BUILTIN_PTRDIFF_TYPE
-+/* If this macro is defined, the preprocessor will not define the
-+ builtin macro `__PTRDIFF_TYPE__'. The macro `__PTRDIFF_TYPE__'
-+ must then be defined by `CPP_SPEC' instead.
-+
-+ This should be defined if `PTRDIFF_TYPE' depends on target
-+ dependent flags which are not accessible to the preprocessor.
-+ Otherwise, it should not be defined.
-+
-+ `SIGNED_CHAR_SPEC'
-+ A C string constant that tells the GNU CC driver program options to
-+ pass to CPP. By default, this macro is defined to pass the option
-+ `-D__CHAR_UNSIGNED__' to CPP if `char' will be treated as
-+ `unsigned char' by `cc1'.
-+
-+ Do not define this macro unless you need to override the default
-+ definition. */
-+
-+#define CC1_SPEC "%{profile:-p}"
-+/* 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 ""
-+/* 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 msp430x336} \
-+%{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=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=msp430xE423:-m msp430xE423 } \
-+%{mmcu=msp430xE425:-m msp430xE425 } \
-+%{mmcu=msp430xE427:-m msp430xE427 } \
-+%{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=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 }"
-+
-+/* A C string constant that tells the GNU CC driver program options to
-+ pass to the linker. It can also specify how to translate options
-+ you give to GNU CC into options for GNU CC to pass to the linker.
-+
-+ Do not define this macro if it does not need to do anything. */
-+
-+#define LIB_SPEC \
-+ "%{*:-lc }"
-+/* Another C string constant used much like `LINK_SPEC'. The
-+ difference between the two is that `LIB_SPEC' is used at the end
-+ of the command given to the linker.
-+
-+ If this macro is not defined, a default is provided that loads the
-+ standard C library from the usual place. See `gcc.c'. */
-+
-+#define LIBGCC_SPEC \
-+ "%{*: -lgcc }"
-+/* Another C string constant that tells the GNU CC driver program how
-+ and when to place a reference to `libgcc.a' into the linker
-+ command line. This constant is placed both before and after the
-+ value of `LIB_SPEC'.
-+
-+ If this macro is not defined, the GNU CC driver provides a default
-+ that passes the string `-lgcc' to the linker unless the `-shared'
-+ option is specified. */
-+
-+#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. */
-+
-+/* recently added:
-+1222 1232 */
-+
-+#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=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=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=msp430xE423:crt430xE423.o%s} \
-+%{mmcu=msp430xE425:crt430xE425.o%s} \
-+%{mmcu=msp430xE427:crt430xE427.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=msp430x447:crt430x447.o%s} \
-+%{mmcu=msp430x448:crt430x448.o%s} \
-+%{mmcu=msp430x449:crt430x449.o%s} \
-+%{mmcu=msp430xG4616:crt430xG4616.o%s} \
-+%{mmcu=msp430xG4617:crt430xG4617.o%s} \
-+%{mmcu=msp430xG4618:crt430xG4618.o%s} \
-+%{mmcu=msp430xG4619:crt430xG4619.o%s}"
-+
-+
-+
-+#define CPP_MSP1_SPEC " -DMSP430_NO_HW_MUL "
-+#define CPP_MSP2_SPEC " -DMSP430_HAS_HW_MUL "
-+
-+#define EXTRA_SPECS \
-+{"cpp_msp1",CPP_MSP1_SPEC}, \
-+{"cpp_msp2",CPP_MSP2_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" }
-+
-+/* This is undefined macro for collect2 disabling */
-+#define LINKER_NAME "msp430-ld"
-+
-+#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 this macro as a C statement that declares additional library
-+ routines renames existing ones. `init_optabs' calls this macro
-+ after initializing all the normal library routines. */
-+
-+#define INIT_TARGET_OPTABS \
-+{ \
-+ msp430_init_once (); \
-+}
-+
-+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-+
-+/* Define to use software floating point emulator for REAL_ARITHMETIC and
-+ decimal <-> binary conversion. */
-+
-+#ifndef REAL_ARITHMETIC
-+#define REAL_ARITHMETIC
-+#endif
-+
-+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-+#define DWARF2_DEBUGGING_INFO 1
-+#define OBJECT_FORMAT_ELF
-+
-+#define DBX_REGISTER_NUMBER(r) (r)
-+
-+/* Get the standard ELF stabs definitions. */
-+#include "dbxelf.h"
-+
-+
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config/msp430/msp430.md
---- gcc-3.2.3.orig/gcc/config/msp430/msp430.md 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/msp430.md 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,4079 @@
-+;; -*- 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>
-+
-+;; 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.
-+
-+;; 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
-+
-+
-+;; 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 (mem:QI (post_dec (reg:HI 1)))
-+ (match_operand:QI 0 "general_operand" "rim"))]
-+ ""
-+ "* return msp430_pushqi(insn, operands, NULL);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*pushhi"
-+ [(set (mem:HI (post_dec (reg:HI 1)))
-+ (match_operand:HI 0 "general_operand" "rim"))]
-+ ""
-+ "* return msp430_pushhi(insn, operands, NULL);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*pushsi"
-+ [(set (mem:SI (post_dec (reg:HI 1)))
-+ (match_operand:SI 0 "general_operand" "rmi"))]
-+ ""
-+ "* return msp430_pushsisf(insn, operands, NULL);"
-+ [(set_attr "length" "4")])
-+
-+
-+(define_insn "*pushdi"
-+ [(set (mem:DI (post_dec (reg:HI 1)))
-+ (match_operand:DI 0 "general_operand" "rmi"))]
-+ ""
-+ "* return msp430_pushdi(insn, operands, NULL);"
-+ [(set_attr "length" "8")])
-+
-+
-+(define_insn "*pushsf"
-+ [(set (mem:SF (post_dec (reg:HI 1)))
-+ (match_operand:SF 0 "general_operand" "rmi"))]
-+ ""
-+ "* return msp430_pushsisf(insn, operands, NULL);"
-+ [(set_attr "length" "4")])
-+
-+
-+(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);"
-+ [(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);"
-+ [(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);"
-+[(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);"
-+[(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);"
-+[(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"))]
-+""
-+"call\\t%0"
-+[ (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" ""))]
-+ ""
-+ "")
-+
-+(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 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 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 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 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 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 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 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 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 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...
-+;;
-+;;
-+
-+;; 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")]
-+
-+)
-+
-+
-+;; 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")])
-+
-+
-+; 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")])
-+
-+
-+;; 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)))]
-+"")
-+
-+
-+
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430-protos.h gcc-3.2.3/gcc/config/msp430/msp430-protos.h
---- gcc-3.2.3.orig/gcc/config/msp430/msp430-protos.h 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/msp430-protos.h 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,301 @@
-+/* 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 *, 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_emit_blt0si PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_beq PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bne PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bgt PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bgtu PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_blt PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bltu PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bge PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bgeu PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_ble PARAMS ((rtx operands[], int len));
-+extern const char * msp430_emit_bleu PARAMS ((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_return PARAMS ((rtx insn, rtx operands[], int *len));
-+extern const char *msp430_cbranch PARAMS ((rtx insn, rtx operands[], int *len));
-+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 [] ));
-+
-+
-+#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 -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/t-msp430 gcc-3.2.3/gcc/config/msp430/t-msp430
---- gcc-3.2.3.orig/gcc/config/msp430/t-msp430 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/t-msp430 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,116 @@
-+# 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
-+MULTILIB_DIRNAMES = msp1 msp2
-+
-+
-+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?msp430x2232 mmcu?msp1=mmcu?msp430x2252 mmcu?msp1=mmcu?msp430x2272 \
-+ mmcu?msp1=mmcu?msp430x2234 mmcu?msp1=mmcu?msp430x2254 mmcu?msp1=mmcu?msp430x2274 \
-+ 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?msp2=mmcu?msp430x2416 mmcu?msp2=mmcu?msp430x2417 mmcu?msp2=mmcu?msp430x2418 \
-+ mmcu?msp2=mmcu?msp430x2419 \
-+ mmcu?msp2=mmcu?msp430x2616 mmcu?msp2=mmcu?msp430x2617 mmcu?msp2=mmcu?msp430x2618 \
-+ mmcu?msp2=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?msp2=mmcu?msp430xE423 mmcu?msp2=mmcu?msp430xE425 mmcu?msp2=mmcu?msp430xE427 \
-+ 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?msp2=mmcu?msp430x447 mmcu?msp2=mmcu?msp430x448 mmcu?msp2=mmcu?msp430x449 \
-+ mmcu?msp2=mmcu?msp430xG4616 mmcu?msp2=mmcu?msp430xG4617 mmcu?msp2=mmcu?msp430xG4618 \
-+ mmcu?msp2=mmcu?msp430xG4619
-+
-+MULTILIB_EXCEPTIONS =
-+
-+LIBGCC = stmp-multilib
-+INSTALL_LIBGCC = install-multilib
-+
-+##STMP_FIXINC =
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/xm-msp430.h gcc-3.2.3/gcc/config/msp430/xm-msp430.h
---- gcc-3.2.3.orig/gcc/config/msp430/xm-msp430.h 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc/config/msp430/xm-msp430.h 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1 @@
-+#include "tm.h"
-diff -urN -x CVS gcc-3.2.3.orig/gcc/config.gcc gcc-3.2.3/gcc/config.gcc
---- gcc-3.2.3.orig/gcc/config.gcc 2003-02-28 11:38:19.000000000 -0700
-+++ gcc-3.2.3/gcc/config.gcc 2008-08-22 09:17:00.000000000 -0600
-@@ -2667,6 +2667,8 @@
- ;;
- mmix-knuth-mmixware)
- ;;
-+msp430-*-*)
-+ ;;
- mn10200-*-*)
- float_format=i32
- tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
-diff -urN -x CVS gcc-3.2.3.orig/gcc/cp/decl.c gcc-3.2.3/gcc/cp/decl.c
---- gcc-3.2.3.orig/gcc/cp/decl.c 2003-03-17 16:16:55.000000000 -0700
-+++ gcc-3.2.3/gcc/cp/decl.c 2008-08-22 09:17:00.000000000 -0600
-@@ -454,9 +454,9 @@
- /* The binding level currently in effect. */
-
- #define current_binding_level \
-- (cfun && cp_function_chain->bindings \
-- ? cp_function_chain->bindings \
-- : scope_chain->bindings)
-+ (*(cfun && cp_function_chain->bindings \
-+ ? &cp_function_chain->bindings \
-+ : &scope_chain->bindings))
-
- /* The binding level of the current class, if any. */
-
-diff -urN -x CVS gcc-3.2.3.orig/gcc-3.2.3-cygwin.patch gcc-3.2.3/gcc-3.2.3-cygwin.patch
---- gcc-3.2.3.orig/gcc-3.2.3-cygwin.patch 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/gcc-3.2.3-cygwin.patch 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,57 @@
-+--- gcc-3.2.3.orig/ggc/gcc-page.c 2003-05-06 15:37:04 +0800
-++++ gcc-3.2.3/gcc/ggc-page.c 2003-05-06 15:37:54 +0800
-+@@ -495,28 +495,35 @@
-+ }
-+ printf ("NULL\n");
-+ fflush (stdout);
-+ }
-+
-++static char *last_allocated_page = NULL;
-++
-+ #ifdef USING_MMAP
-+ /* Allocate SIZE bytes of anonymous memory, preferably near PREF,
-+ (if non-null). The ifdef structure here is intended to cause a
-+ compile error unless exactly one of the HAVE_* is defined. */
-+
-+ static inline char *
-+ alloc_anon (pref, size)
-+ char *pref ATTRIBUTE_UNUSED;
-+ size_t size;
-+ {
-++ char *page;
-++
-++ do {
-+ #ifdef HAVE_MMAP_ANON
-+- char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
-+- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-++ page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
-++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ #endif
-+ #ifdef HAVE_MMAP_DEV_ZERO
-+- char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
-+- MAP_PRIVATE, G.dev_zero_fd, 0);
-++ page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
-++ MAP_PRIVATE, G.dev_zero_fd, 0);
-+ #endif
-++ } while (page == last_allocated_page);
-++ last_allocated_page = page;
-+
-+ if (page == (char *) MAP_FAILED)
-+ {
-+ perror ("virtual memory exhausted");
-+ exit (FATAL_EXIT_CODE);
-+--- gcc-3.2.3.orig/gcc/fixinc/gnu-regex.c 2003-05-06 15:37:04 +0800
-++++ gcc-3.2.3/gcc/fixinc/gnu-regex.c 2003-05-06 15:37:42 +0800
-+@@ -5718,11 +5718,11 @@
-+ if (errbuf_size != 0)
-+ {
-+ if (msg_size > errbuf_size)
-+ {
-+ #if defined HAVE_MEMPCPY || defined _LIBC
-+- *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-++ *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-+ #else
-+ memcpy (errbuf, msg, errbuf_size - 1);
-+ errbuf[errbuf_size - 1] = 0;
-+ #endif
-+ }
-diff -urN -x CVS gcc-3.2.3.orig/include/obstack.h gcc-3.2.3/include/obstack.h
---- gcc-3.2.3.orig/include/obstack.h 2001-03-14 12:44:38.000000000 -0700
-+++ gcc-3.2.3/include/obstack.h 2008-08-22 09:17:00.000000000 -0600
-@@ -423,7 +423,8 @@
- ({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
- _obstack_newchunk (__o, sizeof (void *)); \
-- *((void **)__o->next_free)++ = ((void *)datum); \
-+ *((void **)__o->next_free) = ((void *)datum); \
-+ __o->next_free += sizeof (void *); \
- (void) 0; })
-
- # define obstack_int_grow(OBSTACK,datum) \
-diff -urN -x CVS gcc-3.2.3.orig/THIS_ACTUALLY_WORKS_WITH_VERSION_3_2_AND_BELOW_2002_09_02 gcc-3.2.3/THIS_ACTUALLY_WORKS_WITH_VERSION_3_2_AND_BELOW_2002_09_02
---- gcc-3.2.3.orig/THIS_ACTUALLY_WORKS_WITH_VERSION_3_2_AND_BELOW_2002_09_02 1969-12-31 17:00:00.000000000 -0700
-+++ gcc-3.2.3/THIS_ACTUALLY_WORKS_WITH_VERSION_3_2_AND_BELOW_2002_09_02 2008-08-22 09:17:00.000000000 -0600
-@@ -0,0 +1,6 @@
-+-------------------------------------------------------------------
-+this directory works with gcc-3.2.x (tested with 3.2.3)
-+
-+The mismatch between the numbering of gcc and this directory is an
-+historical accident.
-+-------------------------------------------------------------------
--- /dev/null
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## ports-gcc-4.x.dpatch by <smckown@stevex2>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+@DPATCH@
+diff -urNad msp430-gcc~/gcc/config/msp430/framehelpers.inl msp430-gcc/gcc/config/msp430/framehelpers.inl
+--- msp430-gcc~/gcc/config/msp430/framehelpers.inl 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/framehelpers.inl 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/libgcc.S msp430-gcc/gcc/config/msp430/libgcc.S
+--- msp430-gcc~/gcc/config/msp430/libgcc.S 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/libgcc.S 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1,1342 @@
++/* -*- Mode: Asm -*- */
++
++
++ .section .text.libgcc, "ax", @progbits
++
++#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)
++
++__MPY=0x130
++__MPYS=0x132
++__MAC=0x134
++__MACS=0x136
++__OP2=0x138
++__RESLO=0x13a
++__RESHI=0x13c
++__SUMEXT=0x13e
++
++ .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)
++
++__MPY=0x130
++__MPYS=0x132
++__MAC=0x134
++__MACS=0x136
++__OP2=0x138
++__RESLO=0x13a
++__RESHI=0x13c
++__SUMEXT=0x13e
++
++#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 -urNad msp430-gcc~/gcc/config/msp430/libgcc.c msp430-gcc/gcc/config/msp430/libgcc.c
+--- msp430-gcc~/gcc/config/msp430/libgcc.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/libgcc.c 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-builtins.c msp430-gcc/gcc/config/msp430/msp430-builtins.c
+--- msp430-gcc~/gcc/config/msp430/msp430-builtins.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-builtins.c 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-cbranch.c msp430-gcc/gcc/config/msp430/msp430-cbranch.c
+--- msp430-gcc~/gcc/config/msp430/msp430-cbranch.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-cbranch.c 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-emit-cbranch.c msp430-gcc/gcc/config/msp430/msp430-emit-cbranch.c
+--- msp430-gcc~/gcc/config/msp430/msp430-emit-cbranch.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-emit-cbranch.c 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-function.c msp430-gcc/gcc/config/msp430/msp430-function.c
+--- msp430-gcc~/gcc/config/msp430/msp430-function.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-function.c 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-predicates.inl msp430-gcc/gcc/config/msp430/msp430-predicates.inl
+--- msp430-gcc~/gcc/config/msp430/msp430-predicates.inl 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-predicates.inl 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430-protos.h msp430-gcc/gcc/config/msp430/msp430-protos.h
+--- msp430-gcc~/gcc/config/msp430/msp430-protos.h 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430-protos.h 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/msp430.c msp430-gcc/gcc/config/msp430/msp430.c
+--- msp430-gcc~/gcc/config/msp430/msp430.c 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430.c 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1,8514 @@
++/* 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[] = {
++ /* generic types */
++ {"msp1", MSP430_ISA_1, 0},
++ {"msp2", MSP430_ISA_2, 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},
++
++ {"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},
++
++ /* CC430 family */
++ {"cc430x5123", 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},
++
++ {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;
++
++ 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)
++{
++ /******************************
++
++ __MPY=0x130
++ __MPYS=0x132
++ __MAC=0x134
++ __MACS=0x136
++ __OP2=0x138
++ __RESLO=0x13a
++ __RESHI=0x13c
++ __SUMEXT=0x13e
++ __RESSI <- not natural
++ *****************************/
++
++ 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 (GET_CODE (pat) == RETURN)
++ 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 -urNad msp430-gcc~/gcc/config/msp430/msp430.h msp430-gcc/gcc/config/msp430/msp430.h
+--- msp430-gcc~/gcc/config/msp430/msp430.h 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430.h 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1,3118 @@
++/* 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 &®NO(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) -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x148:%(cpp_msp2) -D__MSP430_148__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x149:%(cpp_msp2) -D__MSP430_149__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1471:%(cpp_msp2) -D__MSP430_1471__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1481:%(cpp_msp2) -D__MSP430_1481__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1491:%(cpp_msp2) -D__MSP430_1491__ -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x168:%(cpp_msp2) -D__MSP430_168__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x169:%(cpp_msp2) -D__MSP430_169__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1610:%(cpp_msp2) -D__MSP430_1610__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1611:%(cpp_msp2) -D__MSP430_1611__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x1612:%(cpp_msp2) -D__MSP430_1612__ -DMSP430_HAS_HWMUL} \
++%{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=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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x235:%(cpp_msp2) -D__MSP430_235__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2330:%(cpp_msp2) -D__MSP430_2330__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2350:%(cpp_msp2) -D__MSP430_2350__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2370:%(cpp_msp2) -D__MSP430_2370__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x247:%(cpp_msp2) -D__MSP430_247__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x248:%(cpp_msp2) -D__MSP430_248__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x249:%(cpp_msp2) -D__MSP430_249__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2410:%(cpp_msp2) -D__MSP430_2410__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2471:%(cpp_msp2) -D__MSP430_2471__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2481:%(cpp_msp2) -D__MSP430_2481__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2491:%(cpp_msp2) -D__MSP430_2491__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2416:%(cpp_msp2) -D__MSP430_2416__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2417:%(cpp_msp2) -D__MSP430_2417__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2418:%(cpp_msp2) -D__MSP430_2418__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2419:%(cpp_msp2) -D__MSP430_2419__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2616:%(cpp_msp2) -D__MSP430_2616__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2617:%(cpp_msp2) -D__MSP430_2617__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2618:%(cpp_msp2) -D__MSP430_2618__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x2619:%(cpp_msp2) -D__MSP430_2619__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x337:%(cpp_msp2) -D__MSP430_337__ -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x425:%(cpp_msp2) -D__MSP430_425__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x427:%(cpp_msp2) -D__MSP430_427__ -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE425:%(cpp_msp2) -D__MSP430_E425__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE427:%(cpp_msp2) -D__MSP430_E427__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE4232:%(cpp_msp2) -D__MSP430_E4232__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE4242:%(cpp_msp2) -D__MSP430_E4242__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE4252:%(cpp_msp2) -D__MSP430_E4252__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xE4272:%(cpp_msp2) -D__MSP430_E4272__ -DMSP430_HAS_HWMUL} \
++%{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__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x448:%(cpp_msp2) -D__MSP430_448__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x449:%(cpp_msp2) -D__MSP430_449__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xG4616:%(cpp_msp2) -D__MSP430_G4616__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xG4617:%(cpp_msp2) -D__MSP430_G4617__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xG4618:%(cpp_msp2) -D__MSP430_G4618__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430xG4619:%(cpp_msp2) -D__MSP430_G4619__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x4783:%(cpp_msp2) -D__MSP430_4783__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x4784:%(cpp_msp2) -D__MSP430_4784__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x4793:%(cpp_msp2) -D__MSP430_4793__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x4794:%(cpp_msp2) -D__MSP430_4794__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47166:%(cpp_msp2) -D__MSP430_47166__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47176:%(cpp_msp2) -D__MSP430_47176__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47186:%(cpp_msp2) -D__MSP430_47186__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47196:%(cpp_msp2) -D__MSP430_47196__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47167:%(cpp_msp2) -D__MSP430_47167__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47177:%(cpp_msp2) -D__MSP430_47177__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47187:%(cpp_msp2) -D__MSP430_47187__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x47197:%(cpp_msp2) -D__MSP430_47197__ -D__MSP430X__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5418:%(cpp_msp2) -D__MSP430_5418__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5419:%(cpp_msp2) -D__MSP430_5419__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5435:%(cpp_msp2) -D__MSP430_5435__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5436:%(cpp_msp2) -D__MSP430_5436__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5437:%(cpp_msp2) -D__MSP430_5437__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=msp430x5438:%(cpp_msp2) -D__MSP430_5438__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x5123:%(cpp_msp2) -D__CC430_5123__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x5125:%(cpp_msp2) -D__CC430_5125__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x6125:%(cpp_msp2) -D__CC430_6125__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x6135:%(cpp_msp2) -D__CC430_6135__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x6126:%(cpp_msp2) -D__CC430_6126__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x5137:%(cpp_msp2) -D__CC430_5137__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x6127:%(cpp_msp2) -D__CC430_6127__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{mmcu=cc430x6137:%(cpp_msp2) -D__CC430_6137__ -D__MSP430X2__ -DMSP430_HAS_HWMUL} \
++%{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 msp430x336} \
++%{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=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=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=cc430x5123: -m cc430x5123 } \
++%{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=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:crt430xG4616.o%s} \
++%{mmcu=msp430xG4617:crt430xG4617.o%s} \
++%{mmcu=msp430xG4618:crt430xG4618.o%s} \
++%{mmcu=msp430xG4619:crt430xG4619.o%s}\
++%{mmcu=msp430x4783:crt430x4783.o%s} \
++%{mmcu=msp430x4784:crt430x4784.o%s} \
++%{mmcu=msp430x4793:crt430x4793.o%s} \
++%{mmcu=msp430x4794:crt430x4794.o%s} \
++%{mmcu=msp430x5418: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=cc430x5123:crtcc430x5123.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 "
++
++#define EXTRA_SPECS \
++{"cpp_msp1",CPP_MSP1_SPEC}, \
++{"cpp_msp2",CPP_MSP2_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 -urNad msp430-gcc~/gcc/config/msp430/msp430.md msp430-gcc/gcc/config/msp430/msp430.md
+--- msp430-gcc~/gcc/config/msp430/msp430.md 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430.md 2010-05-20 16:31:52.000000000 -0600
+@@ -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 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 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 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 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 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 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 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 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 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 -urNad msp430-gcc~/gcc/config/msp430/msp430.opt msp430-gcc/gcc/config/msp430/msp430.opt
+--- msp430-gcc~/gcc/config/msp430/msp430.opt 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/msp430.opt 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/objs-extra msp430-gcc/gcc/config/msp430/objs-extra
+--- msp430-gcc~/gcc/config/msp430/objs-extra 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/objs-extra 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1 @@
++msp430-emit-cbranch.o msp430-cbranch.o msp430-builtins.o msp430-function.o
+\ No newline at end of file
+diff -urNad msp430-gcc~/gcc/config/msp430/predicates.md msp430-gcc/gcc/config/msp430/predicates.md
+--- msp430-gcc~/gcc/config/msp430/predicates.md 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/predicates.md 2010-05-20 16:31:52.000000000 -0600
+@@ -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 -urNad msp430-gcc~/gcc/config/msp430/t-msp430 msp430-gcc/gcc/config/msp430/t-msp430
+--- msp430-gcc~/gcc/config/msp430/t-msp430 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/t-msp430 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1,153 @@
++# 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
++MULTILIB_DIRNAMES = msp1 msp2
++
++
++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?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?msp2=mmcu?msp430x2416 mmcu?msp2=mmcu?msp430x2417 mmcu?msp2=mmcu?msp430x2418 \
++ mmcu?msp2=mmcu?msp430x2419 \
++ mmcu?msp2=mmcu?msp430x2616 mmcu?msp2=mmcu?msp430x2617 mmcu?msp2=mmcu?msp430x2618 \
++ mmcu?msp2=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?msp2=mmcu?msp430xG4616 mmcu?msp2=mmcu?msp430xG4617 mmcu?msp2=mmcu?msp430xG4618 \
++ mmcu?msp2=mmcu?msp430xG4619 \
++ mmcu?msp2=mmcu?msp430x4783 mmcu?msp2=mmcu?msp430x4784 mmcu?msp2=mmcu?msp430x4793 \
++ mmcu?msp2=mmcu?msp430x4794 \
++ mmcu?msp2=mmcu?msp430x5418 mmcu?msp2=mmcu?msp430x5419 \
++ mmcu?msp2=mmcu?msp430x5435 mmcu?msp2=mmcu?msp430x5436 mmcu?msp2=mmcu?msp430x5437 \
++ mmcu?msp2=mmcu?msp430x5438 \
++ mmcu?msp2=mmcu?cc430x5123 \
++ mmcu?msp2=mmcu?cc430x5125 mmcu?msp2=mmcu?cc430x6125 mmcu?msp2=mmcu?cc430x6135 \
++ mmcu?msp2=mmcu?cc430x6126 \
++ mmcu?msp2=mmcu?cc430x5137 mmcu?msp2=mmcu?cc430x6127 mmcu?msp2=mmcu?cc430x6137
++#todo: 47xx has 32*32 HW MUL
++#todo: 54xx has 32*32 HW MUL
++
++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
++
++
++
+\ No newline at end of file
+diff -urNad msp430-gcc~/gcc/config/msp430/xm-msp430.h msp430-gcc/gcc/config/msp430/xm-msp430.h
+--- msp430-gcc~/gcc/config/msp430/xm-msp430.h 1969-12-31 17:00:00.000000000 -0700
++++ msp430-gcc/gcc/config/msp430/xm-msp430.h 2010-05-20 16:31:52.000000000 -0600
+@@ -0,0 +1 @@
++#include "tm.h"