From ed54066d0752082b14a3f96c251fbc04edd411ec Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Thu, 20 May 2010 16:26:12 -0600 Subject: [PATCH] Update patches and debian/changelog --- debian/changelog | 6 + .../003-mspgcc-3.2.3-20080819-FUNCTION.dpatch | 31 - debian/patches/00list | 4 +- debian/patches/gcc-4.4.3.dpatch | 153 + ...3-20080819.dpatch => ports-gcc-4.x.dpatch} | 19813 ++++++++-------- 5 files changed, 10468 insertions(+), 9539 deletions(-) delete mode 100755 debian/patches/003-mspgcc-3.2.3-20080819-FUNCTION.dpatch create mode 100755 debian/patches/gcc-4.4.3.dpatch rename debian/patches/{002-mspgcc-3.2.3-20080819.dpatch => ports-gcc-4.x.dpatch} (57%) diff --git a/debian/changelog b/debian/changelog index 3efb3189..210d6fcd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +msp430-gcc (4.4.3-1tm) hardy; urgency=low + + * Update to gcc-4.4.3 from mspgcc4.sf.net + + -- TMI Packages Thu, 20 May 2010 16:24:30 -0600 + msp430-gcc (3.2.3-1tmi) hardy; urgency=low * Sign the package, update the maintainer, minor doc changes. diff --git a/debian/patches/003-mspgcc-3.2.3-20080819-FUNCTION.dpatch b/debian/patches/003-mspgcc-3.2.3-20080819-FUNCTION.dpatch deleted file mode 100755 index cacd3a04..00000000 --- a/debian/patches/003-mspgcc-3.2.3-20080819-FUNCTION.dpatch +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/sh /usr/share/dpatch/dpatch-run -## 002-mspgcc-3.2.3-20080819-FUNCTION.dpatch by pkgs@titaniummirror.com> -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: __FUNCTION__ patch from mspgcc 3.2.3 CVS 20080819 - -@DPATCH@ - ---- gcc-3.2.3.orig/gcc/c-common.c 2002-12-01 12:19:08.000000000 -0600 -+++ gcc-3.2.3/gcc/c-common.c 2006-03-18 22:08:27.000000000 -0600 -@@ -581,18 +581,20 @@ - if (TREE_TYPE (t) == wchar_array_type_node) - { - wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes); - wide_flag = 1; - } - else - { - length += (TREE_STRING_LENGTH (t) - 1); -+#if 0 - if (C_ARTIFICIAL_STRING_P (t) && !in_system_header) - warning ("concatenation of string literals with __FUNCTION__ is deprecated"); -+#endif - } - } - - /* If anything is wide, the non-wides will be converted, - which makes them take more space. */ - if (wide_flag) - length = length * wchar_bytes + wide_length; - diff --git a/debian/patches/00list b/debian/patches/00list index bc2568ba..b4c04edf 100644 --- a/debian/patches/00list +++ b/debian/patches/00list @@ -1,2 +1,2 @@ -002-mspgcc-3.2.3-20080819.dpatch -003-mspgcc-3.2.3-20080819-FUNCTION.dpatch +ports-gcc-4.x +gcc-4.4.3.dpatch diff --git a/debian/patches/gcc-4.4.3.dpatch b/debian/patches/gcc-4.4.3.dpatch new file mode 100755 index 00000000..daf62f29 --- /dev/null +++ b/debian/patches/gcc-4.4.3.dpatch @@ -0,0 +1,153 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## gcc-4.4.3.dpatch by R. Steve McKown +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: dpatch-ized version of gcc-4.4.3.patch from mspgcc4. + +@DPATCH@ +diff -urNad msp430-gcc~/configure msp430-gcc/configure +--- msp430-gcc~/configure 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/configure 2010-05-20 16:20:02.000000000 -0600 +@@ -2360,6 +2360,9 @@ + avr-*-*) + noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj} target-libssp" + ;; ++ msp430-*-*) ++ noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj} target-libssp" ++ ;; + bfin-*-*) + noconfigdirs="$noconfigdirs gdb" + if test x${is_cross_compiler} != xno ; then +diff -urNad msp430-gcc~/gcc/config.gcc msp430-gcc/gcc/config.gcc +--- msp430-gcc~/gcc/config.gcc 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/gcc/config.gcc 2010-05-20 16:20:02.000000000 -0600 +@@ -804,6 +804,12 @@ + avr-*-*) + tm_file="avr/avr.h dbxelf.h" + ;; ++msp430-*-*) ++ tm_file="msp430/msp430.h dbxelf.h" ++ c_target_objs=`cat ${srcdir}/config/msp430/objs-extra` ++ cxx_target_objs=`cat ${srcdir}/config/msp430/objs-extra` ++ use_fixproto=yes ++ ;; + bfin*-elf*) + tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h" + tmake_file=bfin/t-bfin-elf +diff -urNad msp430-gcc~/gcc/configure msp430-gcc/gcc/configure +--- msp430-gcc~/gcc/configure 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/gcc/configure 2010-05-20 16:20:02.000000000 -0600 +@@ -1595,6 +1595,7 @@ + + + gcc_version=`cat $srcdir/BASE-VER` ++echo $gcc_version | sed s/\\\([0-9]\\\)\.\\\([0-9]\\\)\.\\\([0-9]\\\)/\#define\ GCC_VERSION_INT\ 0x\\1\\2\\3/g > $srcdir/_gccver.h + + # Determine the host, build, and target systems + ac_aux_dir= +diff -urNad msp430-gcc~/gcc/expr.c msp430-gcc/gcc/expr.c +--- msp430-gcc~/gcc/expr.c 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/gcc/expr.c 2010-05-20 16:20:02.000000000 -0600 +@@ -955,7 +955,7 @@ + data.autinc_from = 1; + data.explicit_inc_from = -1; + } +- if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from) ++ if (USE_LOAD_POST_INCREMENT (mode) && !data.reverse && !data.autinc_from) + { + data.from_addr = copy_addr_to_reg (from_addr); + data.autinc_from = 1; +diff -urNad msp430-gcc~/gcc/loop-invariant.c msp430-gcc/gcc/loop-invariant.c +--- msp430-gcc~/gcc/loop-invariant.c 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/gcc/loop-invariant.c 2010-05-20 16:20:02.000000000 -0600 +@@ -1171,11 +1171,13 @@ + rtx reg, set, dest, note; + struct use *use; + bitmap_iterator bi; ++ int n_validated; + + if (inv->reg) + return true; + if (!repr->move) + return false; ++ n_validated = num_validated_changes (); + /* If this is a representative of the class of equivalent invariants, + really move the invariant. Otherwise just replace its use with + the register used for the representative. */ +@@ -1200,7 +1202,17 @@ + reg = gen_reg_rtx_and_attrs (dest); + + /* Try replacing the destination by a new pseudoregister. */ +- if (!validate_change (inv->insn, &SET_DEST (set), reg, false)) ++ validate_change (inv->insn, &SET_DEST (set), reg, true); ++ ++ /* Replace the uses we know to be dominated. It saves work for copy ++ propagation, and also it is necessary so that dependent invariants ++ are computed right. */ ++ /* Note that we must test the changes for validity, lest we might ++ rip apart a match_dup between a use and a clobber. */ ++ if (inv->def) ++ for (use = inv->def->uses; use; use = use->next) ++ validate_change (use->insn, use->pos, reg, true); ++ if (!apply_change_group ()) + goto fail; + df_insn_rescan (inv->insn); + +@@ -1219,9 +1231,23 @@ + } + else + { +- if (!move_invariant_reg (loop, repr->invno)) +- goto fail; ++ /* Replace the uses we know to be dominated. It saves work for copy ++ propagation, and also it is necessary so that dependent invariants ++ are computed right. */ + reg = repr->reg; ++ if (inv->def) ++ for (use = inv->def->uses; use; use = use->next) ++ validate_change (use->insn, use->pos, reg, true); ++ ++ if (verify_changes (n_validated) ++ && move_invariant_reg (loop, repr->invno)) ++ confirm_change_group (); ++ else ++ { ++ cancel_changes (n_validated); ++ goto fail; ++ } ++ + set = single_set (inv->insn); + emit_insn_after (gen_move_insn (SET_DEST (set), reg), inv->insn); + delete_insn (inv->insn); +@@ -1230,17 +1256,9 @@ + + inv->reg = reg; + +- /* Replace the uses we know to be dominated. It saves work for copy +- propagation, and also it is necessary so that dependent invariants +- are computed right. */ + if (inv->def) +- { +- for (use = inv->def->uses; use; use = use->next) +- { +- *use->pos = reg; +- df_insn_rescan (use->insn); +- } +- } ++ for (use = inv->def->uses; use; use = use->next) ++ df_insn_rescan (use->insn); + + return true; + +diff -urNad msp430-gcc~/libgcc/config.host msp430-gcc/libgcc/config.host +--- msp430-gcc~/libgcc/config.host 2010-05-20 16:18:52.000000000 -0600 ++++ msp430-gcc/libgcc/config.host 2010-05-20 16:20:02.000000000 -0600 +@@ -224,6 +224,8 @@ + # Make HImode functions for AVR + tmake_file=${cpu_type}/t-avr + ;; ++msp430-*-*) ++ ;; + bfin*-elf*) + ;; + bfin*-uclinux*) diff --git a/debian/patches/002-mspgcc-3.2.3-20080819.dpatch b/debian/patches/ports-gcc-4.x.dpatch similarity index 57% rename from debian/patches/002-mspgcc-3.2.3-20080819.dpatch rename to debian/patches/ports-gcc-4.x.dpatch index 3b50dc81..b0d2a6aa 100755 --- a/debian/patches/002-mspgcc-3.2.3-20080819.dpatch +++ b/debian/patches/ports-gcc-4.x.dpatch @@ -1,106 +1,130 @@ #! /bin/sh /usr/share/dpatch/dpatch-run -## 001-mspgcc-3.2.3-20080819.dpatch by +## ports-gcc-4.x.dpatch by ## ## All lines beginning with `## DP:' are a description of the patch. -## DP: Patch derived from mspgcc project gcc/3.3 directory, CVS 20080819 +## DP: No description. @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 -+ */ +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); + -+typedef unsigned long __XX; ++/* ++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 ++*/ + -+__XX -+__udivmodXI3 ( __XX a, __XX b) ++/* ++Functions beginning with msp430_fh_ are prologue/epilogue (frame) helpers. ++*/ ++static inline void msp430_fh_emit_push_reg(int reg_num) +{ -+ __XX al = a; // quotant -+ __XX ah = 0; // reminder -+ __XX tmpf; -+ int i; ++ 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; ++} + -+ 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; -+ } ++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;*/ + -+ return al; // for __udivXi3 -+ return ah; // for __umodXi3 ++ rtx insn = emit_insn(gen_pophi_reg(gen_rtx_REG (HImode, reg_num))); +} + -+/* Signed: */ -+ -+__XX -+__divmodXI3 ( __XX a, __XX b) ++static inline void msp430_fh_sub_sp_const(int num_bytes) +{ -+ unsigned at = abs(a); -+ unsigned bt = abs(b); -+ unsigned al, ah; -+ -+ __udivmodXI3 (at, bt); ++ 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; ++} + -+ // now we get al, ah ++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; ++} + -+ if (a < 0) -+ ah = -ah, al = -al; ++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; ++} + -+ if (b < 0) -+ al = -al; ++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; ++} + -+ return al; -+ return ah; ++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))); +} + -+#if 1 -+int main() ++static inline const char *msp430_format_sym_plus_off(const char *sym_name, int offset) +{ -+ __XX a,b, r; ++ 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; ++} + -+ a = 100; -+ b = 0; -+ r = __udivmodXI3(a,b); -+ printf("R=%d\n",r); ++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))); +} -+#endif + ++/* ++ 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); ++} + -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 @@ ++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 -*- */ + + @@ -667,8 +691,26 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.S gcc-3.2.3/gcc/config/ + + /* link following functions if library _reset_vector__ used */ + -+; actualy stack initialized in main() prologue, so don't link __init_stack -+; .global __init_stack ++; 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=
ld option ++; or via -Wl,defsym,__stack=
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 @@ -690,7 +732,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.S gcc-3.2.3/gcc/config/ + + .func __init_stack + -+set_stack_pointer: ++__init_stack: + mov #__stack, r1 + + .endfunc @@ -775,8 +817,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.S gcc-3.2.3/gcc/config/ + .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 @@ -1427,43 +1467,111 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/libgcc.S gcc-3.2.3/gcc/config/ + 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 -+ -+ 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. */ +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 ++*/ + +#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 "output.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" @@ -1472,7072 +1580,7751 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.c gcc-3.2.3/gcc/config/ +#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 + -+/* 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; ++/* 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); + -+/* 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 */ ++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} ++}; + -+/* actual frame offset */ -+static int msp430_current_frame_offset = 0; ++static int msp430_codegen_test_entry_idx = 3; /* Still redefined later */ + -+/* ret/reti issue indicator for _current_ function */ -+static int return_issued = 0; ++void msp430_init_builtins(void) ++{ ++ tree args; ++ int builtin_idx = 0; + -+/* registers used for incoming funct arguments */ -+static char arg_register_used[16]; ++ args = tree_cons (NULL_TREE, integer_type_node, void_list_node); + -+/* push helper */ -+int self_push PARAMS ((rtx)); ++ add_builtin_function (msp430builtins[builtin_idx].name, ++ build_function_type (void_type_node, args), ++ builtin_idx, BUILT_IN_MD, NULL, NULL_TREE); + ++ builtin_idx++; + -+/* 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)); ++ add_builtin_function (msp430builtins[builtin_idx].name, ++ build_function_type (void_type_node, args), ++ builtin_idx, BUILT_IN_MD, NULL, NULL_TREE); + -+const char * msp430_emit_bltnoovfl PARAMS ((rtx *, int)); -+ ++ 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); + -+const char *msp430_init_stack = "__stack"; -+const char *msp430_endup = "__stop_progExec__"; ++ builtin_idx++; + -+int msp430_case_values_threshold = 30000; -+int msp430_has_hwmul = 0; ++ 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); + -+struct rtx_def *msp430_compare_op0; -+struct rtx_def *msp430_compare_op1; ++ msp430_codegen_test_entry_idx = builtin_idx; + ++ builtin_idx++; ++} + -+const char *msp430_mcu_name = "msp430x110"; ++#include "framehelpers.inl" + -+enum msp430_arch ++static void msp430_codegen_test(void) +{ -+ 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 -+}; ++ 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()); ++} + -+struct mcu_type_s ++rtx msp430_expand_builtin(tree exp, rtx target ATTRIBUTE_UNUSED, ++ rtx subtarget ATTRIBUTE_UNUSED, ++ enum machine_mode mode ATTRIBUTE_UNUSED, ++ int ignore ATTRIBUTE_UNUSED) +{ -+ const char *name; -+ enum msp430_arch arch; -+ int has_hwmul; -+}; ++ 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 + -+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} -+}; ++ 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; + -+const struct attribute_spec msp430_attribute_table[]; -+static tree msp430_handle_fndecl_attribute -+PARAMS ((tree *, tree, tree, int, bool *)); ++ pos = (char*)ggc_alloc(16+strlen(fnname)+1); ++ snprintf(pos,16+strlen(fnname)+1,".L__FrameOffset_%s",fnname); + -+#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 ++ 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"); + -+struct gcc_target targetm = TARGET_INITIALIZER; ++ if(insn) ++ emit_insn(insn); ++ else ++ error("Unknown built-in function"); + -+/****** 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} -+}; ++ 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)". ++*/ + -+unsigned int -+msp430_section_type_flags (decl, name, reloc) -+ tree decl; -+ const char *name; -+ int reloc; -+{ -+ unsigned int flags = 0; ++/* ++GCC 4.x port by Ivan Shcherbakov ++*/ ++ ++#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); + -+ if (!strcmp (name, ".infomemnobits") || !strcmp (name, ".noinit")) -+ flags = SECTION_BSS; ++#define OUT_INSN(x,p,o) \ ++ do { \ ++ if(!x) output_asm_insn (p,o); \ ++ } while(0) + -+ 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; ++const char *msp430_cbranch (rtx insn, rtx operands[], int *len, int is_cc0_branch) +{ -+ if (TREE_CODE (*node) != FUNCTION_DECL) -+ { -+ warning ("%s' attribute only applies to functions.", -+ IDENTIFIER_POINTER (name)); -+ *no_add_attrs = true; -+ } -+ return NULL_TREE; -+} -+ ++ 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; + -+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; -+} ++#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]; + -+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; -+} ++ 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]); ++ } + -+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; -+} ++ /* 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))); + -+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; ++ 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; ++ } ++ } + -+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; ++ /* 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; + -+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; -+} ++ 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--; ++ } ++ } ++ } ++ } + -+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); ++ distance -= dummy; + -+ return (TARGET_NOINT_HWMUL || rval); -+} ++ if (distance > 500 || distance < -500) ++ predist = 3; ++ else ++ predist = 1; + -+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; -+} ++ /* 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; ++ } + -+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; ++ if (len) ++ *len = dummy; ++ return ""; +} + -+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 () ++static const char *msp430_emit_blt0si (rtx operands[], int len) +{ -+ switch (msp430_get_arch()) ++ output_asm_insn ("tst\t%B2", operands); ++ switch (len) + { -+ case MSP430_ISA_241: -+ case MSP430_ISA_26: -+ case MSP430_ISA_46: -+ return TRUE; ++ 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 FALSE; ++ ++ return ""; +} + -+void -+msp430_override_options () ++static const char *msp430_emit_beq (rtx operands[], int len) +{ -+ 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; ++ 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!!!"; ++ } + -+ msp430_case_values_threshold = 8; /* ? or there is a better value ? */ ++ return ""; +} + -+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; ++static const char *msp430_emit_bne (rtx operands[], int len) +{ -+ 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; -+} + ++ 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!!!"; ++ } + -+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; ++ 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; ++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); + -+ 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; ++ 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 ""; +} + -+enum reg_class -+msp430_regno_reg_class (r) -+ int r; ++static const char *msp430_emit_bgtu (rtx operands[], int len) +{ -+ if (r < FIRST_PSEUDO_REGISTER) -+ return reg_class_tab[r]; ++ switch (len) ++ { ++ case 2: ++ output_asm_insn ("jeq\t+2", operands); ++ output_asm_insn ("jhs\t%0", operands); + -+ return NO_REGS; -+} ++ 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 ""; ++} + -+enum reg_class -+msp430_reg_class_from_letter (c) -+ int c; ++static const char *msp430_emit_blt (rtx operands[], int len) +{ -+ switch (c) -+ { -+ case 'd': -+ return SP_REG; -+ default: -+ break; -+ } ++ 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 NO_REGS; ++ return ""; +} + + -+ -+#define NOVECTOR 0xff -+ -+void -+asm_declare_function_name (file, name, decl) -+ FILE *file; -+ char *name; -+ tree decl ATTRIBUTE_UNUSED; ++static const char *msp430_emit_bltnoovfl (rtx operands[], int len) +{ -+ 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) ++ switch (len) + { -+ ss = TREE_VALUE (ss); -+ if (ss) -+ vector = TREE_INT_CST_LOW (ss); -+ -+ if (vector != NOVECTOR) -+ vector += vectors_start; ++ 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!!!"; + } + -+ if (vector == -1) -+ { -+ warning ("No valid interrupt vector assigned to ISR `%s'.", name); -+ } ++ return ""; ++} + -+ if ((vector < vectors_start || vector > 0xfffe || (vector & 1)) -+ && (vector != NOVECTOR && vector != -1)) ++static const char *msp430_emit_bltu (rtx operands[], int len) ++{ ++ switch (len) + { -+ warning -+ ("Interrupt vector 0x%x assigned to ISR `%s' is invalid.", -+ vector, name); ++ 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!!!"; + } + -+ 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"); ++ return ""; ++} + -+ if (vector != NOVECTOR) ++static const char *msp430_emit_bge (rtx operands[], int len) ++{ ++ switch (len) + { -+ fprintf (file, "vector_%04x:\n", vector); ++ 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!!!"; + } + -+ 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); -+ } ++ return ""; +} + -+ -+static int -+msp430_saved_regs_frame (void) ++static const char *msp430_emit_bgeu (rtx operands[], int len) +{ -+ 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))) ++ switch (len) + { -+ offset += 2; ++ 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 offset; ++ return ""; +} + -+int -+msp430_empty_epilogue () ++static const char *msp430_emit_ble (rtx operands[], int len) +{ -+ 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; ++ 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 0; ++ return ""; +} + -+/* Returns a number of pushed registers */ -+static int -+msp430_func_num_saved_regs () ++static const char *msp430_emit_bleu (rtx operands[], int len) +{ -+ 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))) ++ switch (len) + { -+ saves += 1; ++ 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 saves; ++ return ""; +} + -+ -+/* Output function prologue */ -+void -+function_prologue (file, size) -+ FILE *file; -+ int size; ++/* x - dst ++y - src */ ++static int msp430_cc_source (rtx insn, enum rtx_code code, rtx x, rtx y) +{ -+ 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; -+ } ++ rtx prev = insn; ++ enum attr_cc cc; ++ rtx set; ++ rtx src, dst; ++ rtx x1 = 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) ++ if(GET_CODE(x) == MEM) + { -+ ss = TREE_VALUE (ss); -+ if (ss) -+ stack_reserve = TREE_INT_CST_LOW (ss); -+ stack_reserve++; -+ stack_reserve &= ~1; ++ x1 = XEXP(x,0); ++ if(GET_CODE(x1) == PLUS) ++ { ++ x1 = XEXP(x1,0); ++ } ++ ++ if(!REG_P(x1)) x1 = 0; + } -+ } + -+ fprintf (file, "\t/* prologue: frame size = %d */\n", size); -+ fprintf (file, ".L__FrameSize_%s=0x%x\n", fnname, size); ++ 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); + -+ offset = initial_elimination_offset (0, 0) - 2; ++ if(!set) ++ return 0; + -+ msp430_current_frame_offset = offset; ++ cc = get_attr_cc (prev); + -+ fprintf (file, ".L__FrameOffset_%s=0x%x\n", fnname, offset); ++ 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 (signal_func_p && interrupt_func_p) -+ { -+ prologue_size += 1; -+ fprintf (file, "\teint\t; enable nested interrupt\n"); -+ } ++ if (cc == CC_CLOBBER) /* clobber */ ++ return 0; + -+ 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 (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; ++ } ++ } + -+ 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"); ++ /* 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)". ++*/ + -+ 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; -+ } ++/* ++GCC 4.x port by Ivan Shcherbakov ++*/ + -+ /* 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); -+ } ++#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 (frame_pointer_needed) -+ { -+ fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM); -+ prologue_size += 1; -+ } ++struct rtx_def *msp430_compare_op0; ++struct rtx_def *msp430_compare_op1; + -+ if (size == 1 || size == 2 || size == 4 || size == 8) -+ prologue_size += 1; -+ else -+ prologue_size += 2; -+ } ++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; + -+ /* disable interrupt for reentrant function */ -+ if (!interrupt_func_p && ree) ++ if (!msp430_compare_op0 && !msp430_compare_op1) + { -+ prologue_size += 1; -+ fprintf (file, "\tdint\n"); ++ /* 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; + } -+ } -+ -+ fprintf (file, "\t/* prologue end (size=%d) */\n\n", prologue_size); -+} + ++ mode = GET_MODE (op0); ++ if (mode != SImode && mode != HImode && mode != QImode) ++ abort (); + -+/* 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; -+ } ++ /* now convert codes */ ++ code = msp430_canonicalize_comparison (code, &op0, &op1); + -+ if (msp430_naked_function_p (current_function_decl)) -+ { -+ fprintf (file, "\n\t/* epilogue: naked */\n"); -+ return; -+ } ++ /* for HI and QI modes everything is simple. ++ Also, if code is eq or ne in SI mode, no clobbers required. */ + -+ if (msp430_empty_epilogue ()) -+ { -+ if (!return_issued) ++ if (mode == SImode && !(code == EQ || code == NE)) + { -+ fprintf (file, "\t%s\n", msp430_emit_return (NULL, NULL, NULL)); -+ epilogue_size++; ++ /* 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; ++ } + } -+ fprintf (file, "\n\t/* epilogue: not required */\n"); -+ goto done_epilogue; -+ } ++ else if(mode == SImode && code == NE ++ && GET_CODE(op1)!= CONST_INT && op1 != const0_rtx) ++ { ++ rtx op0lo, op0hi, op1lo, op1hi; + -+ if ((cfp || interrupt_func_p) && ree) -+ ree = 0; -+ if (cfp && interrupt_func_p) -+ cfp = 0; ++ mem_volatil = MEM_VOLATILE_P(op0); ++ op0lo = gen_lowpart(HImode, op0); ++ op0hi = gen_highpart(HImode, op0); ++ MEM_VOLATILE_P(op0) = mem_volatil; + -+ fprintf (file, "\n\t/* epilogue: frame size=%d */\n", size); ++ mem_volatil = MEM_VOLATILE_P(op1); ++ op1lo = gen_lowpart(HImode, op1); ++ op1hi = gen_highpart(HImode, op1); ++ MEM_VOLATILE_P(op1) = mem_volatil; + -+ 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; ++ 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; + } -+ -+ if (size) ++ else if(mode == SImode && code == EQ && GET_CODE(op1)!= CONST_INT ) + { -+ 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; -+ } ++ 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); + -+ 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"); ++ 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 ; + } + -+ 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) ++ 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) ) + { -+ fprintf (file, "\tbr\t#__epilogue_restorer_intr+%d\n", -+ (12 - msp430_func_num_saved_regs ()) * 2); ++ ; /* nothing to be done */ + } -+ else ++ 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) ++ switch (code) + { -+ fprintf (file, "\tbic\t#0xf0,0(r1)\n"); -+ epilogue_size += 3; ++ case GT: ++ case LE: ++ case GTU: ++ case LEU: ++ { ++ rtx x; ++ rc = swap_condition (code); ++ x = *op0; ++ *op0 = *op1; ++ *op1 = x; ++ } ++ break; ++ default: ++ break; + } -+ -+ 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; ++ 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 ++*/ + -+/* 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; ++#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) +{ -+ /* 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; ++ return regs_ever_live[reg]; +} ++#endif + -+int -+legitimate_address_p (mode, operand, strict) -+ enum machine_mode mode ATTRIBUTE_UNUSED; -+ rtx operand; -+ int strict; -+{ -+ rtx xfoob, x = operand; ++extern int msp430_commands_in_file; ++extern int msp430_commands_in_prologues; ++extern int msp430_commands_in_epilogues; + -+ xfoob = XEXP (operand, 0); ++/* ret/reti issue indicator for _current_ function */ ++static int return_issued = 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; ++/* Prologue/Epilogue size in words */ ++static int prologue_size; ++static int epilogue_size; + -+ /* accept address */ -+ if (CONSTANT_P (operand)) -+ goto granted; ++/* Size of all jump tables in the current function, in words. */ ++static int jump_tables_size; + -+ /* 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; ++/* This holds the last insn address. */ ++static int last_insn_address = 0; + -+ if (TARGET_ALL_DEBUG) -+ fprintf (stderr, "Address Failed\n"); -+ return 0; ++static int msp430_func_num_saved_regs (void); + -+granted: -+ if (TARGET_ALL_DEBUG) -+ fprintf (stderr, "Address granted\n"); -+ return 1; -+} ++/* actual frame offset */ ++static int msp430_current_frame_offset = 0; + ++/* registers used for incoming funct arguments */ ++static char arg_register_used[16]; + -+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); -+} ++#define FIRST_CUM_REG 16 ++static CUMULATIVE_ARGS *cum_incoming = 0; + -+void print_sub_operand PARAMS ((FILE *, rtx, int)); ++static int msp430_num_arg_regs (enum machine_mode mode, tree type); ++static int msp430_saved_regs_frame (void); + -+const char *trim_array[] = { "llo", "lhi", "hlo", "hhi" }; ++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 -+print_sub_operand (file, x, code) -+ FILE *file; -+ rtx x; -+ int code; ++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 (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 (); ++ 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 -+print_operand (file, x, code) -+ FILE *file; -+ rtx x; -+ int code; ++void msp430_function_begin_epilogue (FILE * file) +{ -+ int shift = 0; -+ int ml = GET_MODE_SIZE (x->mode); -+ int source_reg = 0; ++ 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); + -+ if (ml > 1) -+ ml = 2; ++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; ++} + -+ if (code >= 'A' && code <= 'D') -+ shift = code - 'A'; ++#include "framehelpers.inl" + -+ if (code >= 'E' && code <= 'H') -+ { -+ shift = code - 'E'; -+ source_reg = 1; -+ } ++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); + -+ 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); ++ /* check attributes compatibility */ + -+ if (GET_CODE (addr) == POST_INC) ++ if ((cfun->machine->is_critical && cfun->machine->is_reenterant) || (cfun->machine->is_reenterant && cfun->machine->is_interrupt)) + { -+ fprintf (file, "@r%d+", REGNO (XEXP(addr,0))); ++ warning (OPT_Wattributes, "attribute 'reentrant' ignored"); ++ cfun->machine->is_reenterant = 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) ++ ++ if (cfun->machine->is_critical && cfun->machine->is_interrupt) + { -+ fprintf (file, "&"); -+ output_addr_const (file, addr); -+ if (shift) -+ fprintf (file, "+%d", shift * ml); ++ warning (OPT_Wattributes, "attribute 'critical' ignored"); ++ cfun->machine->is_critical = 0; + } -+ else if (GET_CODE (addr) == CONST || GET_CODE (addr) == CONST_INT) ++ ++ if (cfun->machine->is_signal && !cfun->machine->is_interrupt) + { -+ fputc ('&', file); -+ output_addr_const (file, addr); -+ if (shift) -+ fprintf (file, "+%d", shift * ml); ++ warning (OPT_Wattributes, "attribute 'signal' has no meaning on MSP430 without 'interrupt' attribute."); ++ cfun->machine->is_signal = 0; + } -+ else if (GET_CODE (addr) == PLUS) -+ { + -+ print_sub_operand (file, XEXP (addr, 1), code); ++ /* naked function discards everything */ ++ if (cfun->machine->is_naked) ++ return; + -+ /* shift if the indirect pointer register is the stack pointer */ -+ if ((code >= 'M' && code <= 'N') && (REGNO (XEXP (addr, 0)) == 1)) -+ shift = code - 'M'; ++ stack_reserve = msp430_get_stack_reserve(); ++ offset = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - 2; + -+ if (shift) -+ fprintf (file, "+%d", shift * ml); ++ msp430_current_frame_offset = offset; + -+ 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) ++ if (cfun->machine->is_signal && cfun->machine->is_interrupt) + { -+ 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); ++ prologue_size += 1; ++ ++ insn = emit_insn (gen_enable_interrupt()); ++ /* fprintf (file, "\teint\t; enable nested interrupt\n"); */ + } -+ else ++ ++ if (main_p) + { -+ fatal_insn ("Internal compiler bug. Unknown mode:", x); -+ } -+ } -+ else -+ print_operand_address (file, x); -+} ++ if (TARGET_NO_STACK_INIT) ++ { ++ if (size || stack_reserve) ++ { ++ /* fprintf (file, "\tsub\t#%d, r1\t", size + stack_reserve); */ + -+/* 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; ++ 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; + -+ return jump_distance; -+} ++ 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; + -+#define FIRST_CUM_REG 16 -+static CUMULATIVE_ARGS *cum_incoming = 0; ++ 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 (); + -+/* 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; -+ } -+} ++ 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()); ++ } + -+/* 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; ++ 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; -+ 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; -+ } ++ 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; ++ } + -+ for (i = 0; i < 16; i++) -+ arg_register_used[i] = 0; ++ 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);*/ + -+ cum_incoming = cum; ++ msp430_commands_in_file += prologue_size + /*function_size +*/ epilogue_size; ++ msp430_commands_in_prologues += prologue_size; ++ msp430_commands_in_epilogues += epilogue_size; +} + -+rtx -+msp430_libcall_value (mode) -+ enum machine_mode mode; ++/* Returns a number of pushed registers */ ++static int msp430_func_num_saved_regs (void) +{ -+ int offs = GET_MODE_SIZE (mode); -+ offs >>= 1; -+ if (offs < 1) -+ offs = 1; -+ return gen_rtx (REG, mode, (RET_REGISTER + 1 - offs)); ++ 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; +} + -+rtx -+msp430_function_value (type, func) -+ tree type; -+ tree func ATTRIBUTE_UNUSED; ++const char *msp430_emit_return (rtx insn ATTRIBUTE_UNUSED, rtx operands[] ATTRIBUTE_UNUSED, int *len 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)); ++ return_issued = 1; ++ if (msp430_critical_function_p (current_function_decl) || interrupt_function_p(current_function_decl)) ++ return "reti"; ++ ++ return "ret"; +} + -+/* 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; ++void msp430_output_addr_vec_elt (FILE *stream, int value) +{ -+ int size; ++ fprintf (stream, "\t.word .L%d\n", value); ++ jump_tables_size++; ++} + -+ if (mode == BLKmode) -+ size = int_size_in_bytes (type); -+ else -+ size = GET_MODE_SIZE (mode); ++/* 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. */ + -+ if (size < 2) -+ size = 2; ++void final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, int num_operands ATTRIBUTE_UNUSED) ++{ ++ int uid = INSN_UID (insn); + -+ /* 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; ++ 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 (cum, mode, type, named) -+ CUMULATIVE_ARGS *cum; -+ enum machine_mode mode; -+ tree type; -+ int named ATTRIBUTE_UNUSED; ++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); ++ int regs = msp430_num_arg_regs (mode, type); + -+ if (cum->nregs && regs <= cum->nregs) -+ { -+ int regnum = cum->regno - regs; ++ 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; ++} + -+ if (cum == cum_incoming) ++/* 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) + { -+ 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; ++ int stdarg = (TYPE_ARG_TYPES (fntype) != 0 ++ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) ++ != void_type_node)); ++ if (stdarg) ++ cum->nregs = 0; + } + -+ return gen_rtx (REG, mode, regnum); -+ } -+ return NULL_RTX; ++ 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 (cum, mode, type, named) -+ CUMULATIVE_ARGS *cum; -+ enum machine_mode mode; -+ tree type; -+ int named ATTRIBUTE_UNUSED; ++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); ++ int regs = msp430_num_arg_regs (mode, type); + -+ cum->nregs -= regs; -+ cum->regno -= regs; ++ cum->nregs -= regs; ++ cum->regno -= regs; + -+ if (cum->nregs <= 0) -+ { -+ cum->nregs = 0; -+ cum->regno = FIRST_CUM_REG; -+ } ++ 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; ++/* Returns the number of registers to allocate for a function argument. */ ++static int msp430_num_arg_regs (enum machine_mode mode, tree type) +{ -+ int save_volatile_ok = volatile_ok; -+ int niop = 0; ++ int size; + -+ if (!TARGET_NVWA) -+ volatile_ok = 1; -+ niop = nonimmediate_operand (op, mode); -+ volatile_ok = save_volatile_ok; ++ if (mode == BLKmode) ++ size = int_size_in_bytes (type); ++ else ++ size = GET_MODE_SIZE (mode); + -+ return niop; ++ 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; +} + -+int -+memory_operand_msp430 (op, mode) -+ rtx op; -+ enum machine_mode mode; ++static int msp430_saved_regs_frame (void) +{ -+ int save_volatile_ok = volatile_ok; -+ int mop = 0; ++ 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; + -+ if (!TARGET_NVWA) -+ volatile_ok = 1; -+ mop = memory_operand (op, mode); -+ volatile_ok = save_volatile_ok; -+ return mop; ++ 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 -+general_operand_msp430 (op, mode) -+ rtx op; -+ enum machine_mode mode; ++int msp430_empty_epilogue (void) +{ -+ int save_volatile_ok = volatile_ok; -+ int gop = 0; ++ 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; + -+ if (!TARGET_NVWA) -+ volatile_ok = 1; -+ gop = general_operand (op, mode); -+ volatile_ok = save_volatile_ok; -+ return gop; ++ 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)); + -+int -+halfnibble_integer (op, mode) -+ rtx op; -+ enum machine_mode mode; ++ 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) +{ -+ int hi, lo; -+ int val; ++ gcc_assert(TREE_CODE (func) == FUNCTION_DECL); ++ return lookup_attribute (attr_name, DECL_ATTRIBUTES (func)) != NULL_TREE; ++} + -+ if (!const_int_operand (op, mode)) -+ return 0; ++static inline int msp430_naked_function_p(tree func) ++{ ++ return msp430_attribute_exists(func, "naked"); ++} + -+ /* 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); ++static inline int msp430_task_function_p (tree func) ++{ ++ return msp430_attribute_exists(func, "task"); ++} + -+ if (hi && lo) -+ return 0; ++static inline int msp430_save_prologue_function_p (tree func) ++{ ++ return msp430_attribute_exists(func, "saveprologue"); ++} + -+ 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; ++static inline int interrupt_function_p (tree func) ++{ ++ return msp430_attribute_exists(func, "interrupt"); ++} + -+ return 0; ++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"); ++} + -+int -+halfnibble_constant (op, mode) -+ rtx op; -+ enum machine_mode mode; ++static inline int noint_hwmul_function_p (tree func) +{ -+ int hi, lo; -+ int val; ++ return msp430_attribute_exists(func, "noint_hwmul"); ++} + -+ if (!const_int_operand (op, mode)) -+ return 0; ++static inline int signal_function_p (tree func) ++{ ++ return msp430_attribute_exists(func, "signal"); ++} + -+ /* 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); ++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 + -+ if ((hi && lo) || (!hi && !lo)) -+ return 0; ++ This file is part of GNU CC. + -+ 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; ++ 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. + -+ if (!(hi && lo)) -+ return 1; ++ 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. + -+ return 0; -+} ++ 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. */ + + -+int -+halfnibble_integer_shift (op, mode) -+ rtx op; -+ enum machine_mode mode; -+{ -+ int hi, lo; -+ int val; ++extern void bootloader_section PARAMS ((void)); ++extern void infomem_section PARAMS ((void)); + -+ if (!immediate_operand (op, mode)) -+ return 0; ++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)); + -+ /* 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; ++extern int frame_pointer_required_p PARAMS ((void)); ++extern int msp430_empty_epilogue PARAMS ((void)); + -+ 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; ++int msp430_regno_ok_for_base_p PARAMS ((int)); + -+ return 0; -+} ++ ++#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)); + + -+int -+halfnibble_constant_shift (op, mode) -+ rtx op; -+ enum machine_mode mode; -+{ -+ int hi, lo; -+ int val; + -+ if (!immediate_operand (op, mode)) -+ return 0; ++#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 ++*/ ++ ++/* Subroutines for insn-output.c for Texas Instruments MSP430 MCU ++Copyright (C) 2001, 2002 Free Software Foundation, Inc. ++Contributed by Dmitry Diky ++ ++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 *)); + -+ /* 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); ++/* 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 + -+ if (hi && lo) -+ return 0; ++struct gcc_target targetm = TARGET_INITIALIZER; + -+ 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; ++/****** 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 0; ++ return (TARGET_NOINT_HWMUL || rval); +} + ++unsigned int ++msp430_section_type_flags (tree decl, const char *name, int reloc) + -+int -+which_nibble (val) -+ int val; +{ -+ if (val & 0xffff0000ul) -+ return 1; -+ return 0; -+} ++ unsigned int flags = 0; + ++ if (!strcmp (name, ".infomemnobits") || !strcmp (name, ".noinit")) ++ flags = SECTION_BSS; + -+int -+which_nibble_shift (val) -+ int val; ++ 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 (val & 0xffff0000ul) -+ return 1; -+ return 0; ++ 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); + -+int -+extra_constraint (x, c) -+ rtx x; -+ int c; ++enum msp430_arch ++msp430_get_arch (void) +{ ++ const struct mcu_type_s *t; + -+ 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) ++ for (t = msp430_mcu_types; t->name; t++) + { -+ rtx xx = XEXP (x, 0); -+ int regno = REGNO (xx); -+ if (regno >= 4 || regno == 1) -+ return 1; ++ if (strcmp (t->name, msp430_mcu_name) == 0) ++ break; + } + -+ if (GET_CODE (x) == MEM -+ && GET_CODE (XEXP (x, 0)) == PLUS -+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) ++ if (!t->name) + { -+ rtx xx = XEXP (XEXP (x, 0), 0); -+ int regno = REGNO (xx); -+ if (regno >= 4 || regno == 1) -+ return 1; ++ error ("MCU %s not supported", msp430_mcu_name); ++ fprintf (stderr, "Known MCU names:\n"); ++ for (t = msp430_mcu_types; t->name; t++) ++ fprintf (stderr, " %s\n", t->name); ++ abort (); ++ return -1; + } ++ return t->arch; ++} ++ ++void ++msp430_override_options (void) ++{ ++ const struct mcu_type_s *t; + -+ if (GET_CODE (x) == MEM -+ && GET_CODE (XEXP (x, 0)) == PLUS && REG_P (XEXP (XEXP (x, 0), 0))) ++ for (t = msp430_mcu_types; t->name; t++) + { -+ return 1; ++ if (strcmp (t->name, msp430_mcu_name) == 0) ++ break; + } + -+ } -+ else if (c == 'S') -+ { -+ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) ++ if (!t->name) + { -+ return 1; ++ 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; + } -+ } + -+ return 0; -+} -+ -+int -+indexed_location (x) -+ rtx x; -+{ -+ int r = 0; -+ -+ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG) -+ { -+ r = 1; -+ } ++ msp430_has_hwmul = t->has_hwmul || TARGET_FORCE_HWMUL; + -+ if (TARGET_ALL_DEBUG) -+ { -+ fprintf (stderr, "indexed_location %s: %s \n", -+ r ? "granted" : "failed", -+ reload_completed ? "reload completed" : "reload in progress"); -+ debug_rtx (x); -+ } ++ if (TARGET_NO_HWMUL) ++ msp430_has_hwmul = 0; + -+ return r; ++ 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; + -+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; -+} + ++static char __dummy[1024]; ++rtx sym_ref(enum machine_mode mode, char *arg); + -+int -+default_rtx_costs (X, code, outer_code) -+ rtx X ATTRIBUTE_UNUSED; -+ enum rtx_code code; -+ enum rtx_code outer_code ATTRIBUTE_UNUSED; ++rtx sym_ref(enum machine_mode mode, char *arg) +{ -+ 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; ++ 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 -+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"); -+} ++rtx gen_rtx_HWREG(const char *name); + -+/* Output VALUE as .byte to file FILE */ -+void -+asm_output_byte (file, value) -+ FILE *file; -+ int value; ++rtx gen_rtx_HWREG(const char *name) +{ -+ fprintf (file, "\t.byte 0x%x\n", value & 0xff); ++ rtx ret = gen_rtx_MEM (HImode, sym_ref (HImode, name)); ++ //MEM_VOLATILE_P(ret) = 1; ++ return ret; +} + -+/* Output rtx VALUE as .word to file FILE */ -+void -+asm_output_short (file, value) -+ FILE *file; -+ rtx value; ++void msp430_init_once (void) +{ -+ fprintf (file, "\t.word "); -+ output_addr_const (file, (value)); -+ fprintf (file, "\n"); ++ /****************************** ++ ++ __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; +} + -+/* Output real N to file FILE */ -+void -+asm_output_float (file, n) -+ FILE *file; -+ REAL_VALUE_TYPE n; -+{ -+ long val; -+ char dstr[100]; ++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 */ ++}; + -+ 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 msp430_regno_ok_for_base_p (int r) +{ -+ 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); -+} ++ 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; + -+/* 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; ++enum reg_class ++msp430_regno_reg_class (int r) +{ -+ fprintf (file, ".section %s, \"%s\", @progbits\n", name, -+ decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" : -+ decl && TREE_READONLY (decl) ? "a" : "aw"); -+} ++ if (r < (sizeof(reg_class_tab) / sizeof(reg_class_tab[0]))) ++ return reg_class_tab[r]; + ++ return NO_REGS; ++} + -+/* 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; ++enum reg_class ++msp430_reg_class_from_letter ( ++ int c) +{ -+ 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]) ++ switch (c) + { -+ case 0: -+ putc (ch, file); -+ break; -+ case 1: -+ fprintf (file, "\\%03o", ch); -+ break; ++ case 'd': ++ return SP_REG; + default: -+ putc ('\\', file); -+ putc (escape, file); -+ break; ++ break; + } -+ } -+ fprintf (file, "\"\n"); ++ ++ return NO_REGS; +} + -+/* The routine used to output sequences of byte values. We use a special -+ version of this for most svr4 targets because doing so makes the -+ generated assembly code more compact (and thus faster to assemble) -+ as well as more readable. Note that if we find subparts of the -+ character sequence which end with NUL (and which are shorter than -+ STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ ++ ++ ++#define NOVECTOR 0xff + +void -+gas_output_ascii (file, str, length) -+ FILE *file; -+ const char *str; -+ size_t length; ++asm_declare_function_name ( ++ FILE *file, ++ const char *name, ++ tree decl ATTRIBUTE_UNUSED) +{ -+ 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"); -+} ++ 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); + -+/* Outputs to the stdio stream FILE some -+ appropriate text to go at the start of an assembler file. */ ++ if (vector != NOVECTOR) ++ vector += vectors_start; ++ } + -+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 (vector == -1) ++ { ++ warning (OPT_Wattributes, "No valid interrupt vector assigned to ISR `%s'.", 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"); ++ 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); ++ } + -+ commands_in_file = 0; -+ commands_in_prologues = 0; -+ commands_in_epilogues = 0; ++ 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); ++ } +} + -+/* 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; ++/* 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; +{ -+ 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); -+} ++ /* 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; ++ } + -+int -+msp430_hard_regno_mode_ok (regno, mode) -+ int regno ATTRIBUTE_UNUSED; -+ enum machine_mode mode ATTRIBUTE_UNUSED; -+{ -+ return 1; ++ return oldx; ++ */ ++ return x; +} + +int -+frame_pointer_required_p () ++legitimate_address_p (mode, operand, strict) ++enum machine_mode mode ATTRIBUTE_UNUSED; ++rtx operand; ++int strict; +{ -+ return (current_function_calls_alloca -+ /* || current_function_args_info.nregs == 0 */ -+ || current_function_varargs); ++ 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; + -+ /* || get_frame_size () > 0); */ ++granted: ++ if (TARGET_ALL_DEBUG) ++ fprintf (stderr, "Address granted\n"); ++ return 1; +} + -+enum reg_class -+preferred_reload_class (x, class) -+ rtx x ATTRIBUTE_UNUSED; -+ enum reg_class class; ++ ++void ++print_operand_address (file, addr) ++FILE *file; ++rtx addr; +{ -+ return class; ++ /* 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); +} + -+/* cfp minds the fact that the function may save r2 */ -+int -+initial_elimination_offset (from, to) -+ int from; -+ int to; ++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; +{ -+ 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 (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) + { -+ if ((!leaf_func_p && call_used_regs[reg] && (interrupt_func_p)) -+ || (regs_ever_live[reg] -+ && (!call_used_regs[reg] || interrupt_func_p))) -+ { -+ offset += 2; -+ } ++ output_addr_const (file, x); ++ return; + } -+ return get_frame_size () + offset + 2; -+ } -+ return 0; ++ 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 (); +} + -+int -+adjust_insn_length (insn, len) -+ rtx insn; -+ int len; ++void print_operand (FILE *file, rtx x, int code) +{ ++ int shift = 0; ++ int ml = GET_MODE_SIZE (x->mode); ++ int source_reg = 0; + -+ rtx patt = PATTERN (insn); -+ rtx set; + -+ set = single_set (insn); ++ if (ml > 1) ++ ml = 2; + -+ 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; ++ if (code >= 'A' && code <= 'D') ++ shift = code - 'A'; + -+ default: -+ break; -+ } ++ if (code >= 'E' && code <= 'H') ++ { ++ shift = code - 'E'; ++ source_reg = 1; ++ } ++ ++ if (code >= 'I' && code <= 'L') ++ { ++ ml = 1; ++ shift = code - 'I'; ++ } + -+ if (GET_CODE (op[2]) == CONST_INT) -+ { -+ if (GET_MODE (op[0]) == DImode) ++ 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 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--; ++ 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 if (GET_MODE (op[0]) == SImode) ++ else ++ fprintf (file, "%d", INTVAL (x)); ++ } ++ else if (GET_CODE (x) == MEM) ++ { ++ rtx addr = XEXP (x, 0); ++ ++ if (GET_CODE (addr) == POST_INC) + { -+ 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--; ++ fprintf (file, "@r%d+", REGNO (XEXP(addr,0))); + } -+ 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--; ++ 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)); ++ } + } -+ } -+ -+ if (GET_CODE (op[2]) == CONST_DOUBLE) -+ { -+ if (GET_MODE (op[0]) == SFmode) ++ else if (GET_CODE (addr) == SYMBOL_REF) + { -+ 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--; ++ fprintf (file, "&"); ++ output_addr_const (file, addr); ++ if (shift) ++ fprintf (file, "+%d", shift * ml); + } -+ else ++ else if (GET_CODE (addr) == CONST || GET_CODE (addr) == CONST_INT) + { -+ 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--; ++ fputc ('&', file); ++ output_addr_const (file, addr); ++ if (shift) ++ fprintf (file, "+%d", shift * ml); + } -+ } -+ -+ 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])) ++ else if (GET_CODE (addr) == PLUS) + { -+ 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; ++ print_sub_operand (file, XEXP (addr, 1), code); + -+ 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; ++ /* 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 (!zero_shifted (ops[2]) && indexed_location (ops[2])) ++ else if (GET_CODE (addr) == MEM) + { -+ len -= 1; ++ fprintf (file, "@(Invalid addressing mode)"); ++ print_operand (file, addr, code); + } -+ 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)) ++ else + { -+ rtx reg = XEXP (ops[2], 0); -+ if (dead_or_set_p (insn, reg)) -+ len -= 1; ++ fprintf (file, "Unknown operand. Please check."); + } -+ else if (!zero_shifted (ops[2]) && indexed_location (ops[2])) ++ } ++ 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?? */ + { -+ len -= 1; ++ 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)); + } -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (GET_MODE (ops[0]) == SImode) -+ { -+ if (GET_CODE (ops[2]) == CONST_INT) ++ else if (GET_MODE (x) == SFmode || GET_MODE (x) == SImode) + { -+ 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--; -+ } -+ } ++ 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); + } -+ } -+ -+ if (GET_MODE (ops[0]) == SFmode || GET_MODE (ops[0]) == DImode) -+ { -+ if (GET_CODE (ops[2]) == CONST_DOUBLE) ++ else + { -+ -+ 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--; -+ } ++ fatal_insn ("Internal compiler bug. Unknown mode:", x); + } -+ } -+ -+ 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; ++ else ++ print_operand_address (file, x); ++} + -+ 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; ++/* 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; + -+ default: -+ break; -+ } -+ } ++ return jump_distance; + } -+ } -+ -+ return len; ++ else ++ return 1024; +} + + -+/* 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; ++rtx ++msp430_libcall_value (mode) ++enum machine_mode mode; +{ -+ 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); ++ int offs = GET_MODE_SIZE (mode); ++ offs >>= 1; ++ if (offs < 1) ++ offs = 1; ++ return gen_rtx_REG (mode, (RET_REGISTER + 1 - offs)); +} + -+void -+msp430_output_addr_vec_elt (stream, value) -+ FILE *stream; -+ int value; ++rtx ++msp430_function_value (type, func) ++tree type; ++tree func ATTRIBUTE_UNUSED; +{ -+ fprintf (stream, "\t.word .L%d\n", value); -+ jump_tables_size++; ++ 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)); +} + -+ -+void -+machine_dependent_reorg (first_insn) -+ rtx first_insn ATTRIBUTE_UNUSED; ++int ++halfnibble_integer (op, mode) ++rtx op; ++enum machine_mode mode; +{ -+ /* nothing to be done here this time */ -+ return; -+} ++ int hi, lo; ++ int val; + ++ if (!const_int_operand (op, mode)) ++ return 0; + -+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); ++ /* 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; +} + + -+/* 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; ++halfnibble_constant (op, mode) ++rtx op; ++enum machine_mode mode; +{ -+ 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; ++ int hi, lo; ++ int val; + -+ size >>= 1; -+ if (!size) -+ size = 1; ++ if (!const_int_operand (op, mode)) ++ return 0; + -+ last_reg = first_reg + size - 1; ++ /* 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); + -+ for (reg = first_reg; reg <= last_reg; reg++) -+ { -+ if (!regs_ever_live[reg]) -+ return 0; -+ } -+ } ++ if ((hi && lo) || (!hi && !lo)) ++ return 0; + -+ return 1; -+} ++ 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; + -+/* Update the condition code in the INSN. -+ now mostly unused */ ++ return 0; ++} + -+void -+notice_update_cc (body, insn) -+ rtx body ATTRIBUTE_UNUSED; -+ rtx insn ATTRIBUTE_UNUSED; ++ ++int ++halfnibble_integer_shift (op, mode) ++rtx op; ++enum machine_mode mode; +{ -+ CC_STATUS_INIT; -+} ++ 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; ++} + -+/* -+ Next two return non zero for rtx as -+ (set (reg:xx) -+ (mem:xx (reg:xx)) -+ -+*/ + +int -+regsi_ok_safe (operands) -+ rtx operands[]; ++halfnibble_constant_shift (op, mode) ++rtx op; ++enum machine_mode mode; +{ -+ rtx dest = operands[0]; -+ rtx areg; -+ int src_reg; -+ int dst_reg; ++ int hi, lo; ++ int val; + -+ if (operands[2]) -+ areg = XEXP (operands[2], 0); -+ else -+ areg = XEXP (operands[1], 0); ++ if (!immediate_operand (op, mode)) ++ return 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; -+ } ++ /* 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 (REGNO (dest) >= FIRST_PSEUDO_REGISTER -+ || REGNO (areg) >= FIRST_PSEUDO_REGISTER) -+ return 1; ++ if (hi && lo) ++ return 0; + -+ dst_reg = true_regnum (dest); -+ src_reg = true_regnum (areg); -+ if (dst_reg > src_reg || dst_reg + 1 < src_reg) -+ { -+ return 1; -+ } -+ 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 -+regsi_ok_clobber (operands) -+ rtx operands[]; ++which_nibble (val) ++int val; +{ -+ 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 (val & 0xffff0000ul) ++ return 1; ++ return 0; ++} + -+ 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 ++which_nibble_shift (val) ++int val; ++{ ++ if (val & 0xffff0000ul) ++ return 1; ++ return 0; +} + ++ +int -+regdi_ok_safe (operands) -+ rtx operands[]; ++extra_constraint (x, c) ++rtx x; ++int c; +{ -+ 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) ++ if (c == 'R') + { -+ dest = XEXP (dest, 0); ++ 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 (GET_CODE (dest) == REG) ++ else if (c == 'Q') + { -+ ; /* register */ -+ } -+ else -+ return 1; -+ } ++ 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 (REGNO (dest) >= FIRST_PSEUDO_REGISTER -+ || REGNO (areg) >= FIRST_PSEUDO_REGISTER) -+ return 1; ++ if (GET_CODE (x) == MEM ++ && GET_CODE (XEXP (x, 0)) == PLUS && REG_P (XEXP (XEXP (x, 0), 0))) ++ { ++ return 1; ++ } + -+ dst_reg = true_regnum (dest); -+ src_reg = true_regnum (areg); -+ if (dst_reg > src_reg || dst_reg + 3 < src_reg) -+ { -+ return 1; -+ } ++ } ++ else if (c == 'S') ++ { ++ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) ++ { ++ return 1; ++ } ++ } + -+ return 0; ++ return 0; +} + +int -+regdi_ok_clobber (operands) -+ rtx operands[]; ++indexed_location (x) ++rtx x; +{ -+ rtx dest = operands[0]; -+ rtx areg = XEXP (operands[2], 0); -+ int src_reg; -+ int dst_reg; -+ int regno = REGNO (dest); ++ int r = 0; + -+ if (GET_CODE (dest) == MEM) -+ { -+ dest = XEXP (operands[0], 0); -+ if (GET_CODE (dest) == PLUS && GET_CODE (XEXP (dest, 0)) == REG) ++ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG) + { -+ dest = XEXP (dest, 0); ++ r = 1; + } -+ else if (GET_CODE (dest) == REG) ++ ++ if (TARGET_ALL_DEBUG) + { -+ ; /* register */ ++ fprintf (stderr, "indexed_location %s: %s \n", ++ r ? "granted" : "failed", ++ reload_completed ? "reload completed" : "reload in progress"); ++ debug_rtx (x); + } -+ 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; ++ return r; +} + + -+/***************** ARITHMETIC *******************/ -+ +int -+emit_indexed_arith (insn, operands, m, cmd, iscarry) -+ rtx insn; -+ rtx operands[]; -+ int m; -+ const char *cmd; -+ int iscarry; ++zero_shifted (x) ++rtx x; +{ -+ 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) ++ 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 */ ) + { -+ reg = XEXP (operands[1], 0); ++ r = 1; + } ++ return r; ++} + -+ 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); ++void ++order_regs_for_local_alloc () ++{ ++ unsigned int i; + -+ if (i && iscarry) ++ if (TARGET_REORDER) + { -+ strcat (template, "c\t"); -+ p += 2; ++ 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 ++ else + { -+ strcat (template, "\t"); -+ p += 1; ++ for (i = 0; i < 16; i++) ++ reg_alloc_order[i] = 15 - i; + } -+ 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); -+ } ++ return; ++} + -+ 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); -+ } ++/* 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"); ++} + -+ return len; ++/* 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); +} + -+static int sameoperand_p PARAMS ((rtx, rtx)); ++/* 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"); ++} + -+int -+sameoperand (operands, i) -+ rtx operands[]; -+ int i; ++#if 0 ++/* Output real N to file FILE */ ++void ++asm_output_float (file, n) ++FILE *file; ++REAL_VALUE_TYPE n; +{ -+ rtx dst = operands[0]; -+ rtx src = operands[i]; ++ long val; ++ char dstr[100]; + -+ return sameoperand_p (src, dst); ++ 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 + -+static int -+sameoperand_p (src, dst) -+ rtx src; -+ rtx dst; ++/* 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; +{ -+ enum rtx_code scode = GET_CODE (src); -+ enum rtx_code dcode = GET_CODE (dst); -+ /* cannot use standard functions here -+ cause operands have different modes: -+ */ ++ fprintf (file, ".section %s, \"%s\", @progbits\n", name, ++ decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" : ++ decl && TREE_READONLY (decl) ? "a" : "aw"); ++} + -+ 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; ++/* 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"); +} + -+#define OUT_INSN(x,p,o) \ -+do { \ -+if(!x) output_asm_insn (p,o); \ -+} while(0) + + ++/* Outputs to the stdio stream FILE some ++appropriate text to go at the start of an assembler file. */ + -+/************** MOV CODE *********************************/ -+ -+const char * -+movstrsi_insn (insn, operands, l) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++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"); ++ } + -+ /* 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 ""; ++ 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. */ + -+const char * -+clrstrsi_insn (insn, operands, l) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++static void msp430_file_end (void) +{ -+ -+ /* 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 ""; ++ 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); +} + -+const char * -+movstrhi_insn (insn, operands, l) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++int ++msp430_hard_regno_mode_ok (regno, mode) ++int regno ATTRIBUTE_UNUSED; ++enum machine_mode mode 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 ""; ++ return 1; +} + -+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 ""; -+} ++#if GCC_VERSION_INT >= 0x440 ++#define current_function_calls_alloca cfun->calls_alloca ++#endif + +int -+msp430_emit_indexed_mov (insn, operands, m, cmd) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int m; -+ const char *cmd; ++frame_pointer_required_p () +{ -+ 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 (current_function_calls_alloca ++ /* || current_function_args_info.nregs == 0 */ ++ /*|| current_function_varargs*/); + -+ return len; ++ /* || get_frame_size () > 0); */ +} + -+const char * -+msp430_emit_indexed_mov2 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++enum reg_class ++preferred_reload_class (x, class) ++rtx x ATTRIBUTE_UNUSED; ++enum reg_class class; +{ -+ msp430_emit_indexed_mov (insn, operands, 2, "mov"); -+ return ""; ++ return class; +} + -+const char * -+msp430_emit_indexed_mov4 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++int ++adjust_insn_length (insn, len) ++rtx insn; ++int len; +{ -+ 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); ++ rtx patt = PATTERN (insn); ++ rtx set; + ++ set = single_set (insn); + -+ 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)) ++ if (GET_CODE (patt) == SET) + { -+ 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 */ -+} ++ 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; ++ } + -+/* From Max Behensky -+ 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; ++ 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--; ++ } ++ } + -+ code = GET_CODE (x); ++ 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--; ++ } ++ } + -+ if (code != MEM) -+ return (-1); ++ 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); + -+ x = XEXP (x, 0); -+ code = GET_CODE (x); -+ if (code == REG) -+ return (REGNO (x)); ++ 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); + -+ if (code != PLUS) -+ return (-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); + -+ x = XEXP (x, 0); -+ code = GET_CODE (x); -+ if (code != REG) -+ return (-1); ++ if (GET_CODE (op[1]) == AND && !general_operand (ops[1], VOIDmode)) ++ return len; + -+ return (REGNO (x)); -+} ++ 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--; ++ } ++ } ++ } ++ } + -+const char * -+msp430_movesi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; -+{ -+ rtx op0 = operands[0]; -+ rtx op1 = operands[1]; ++ 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 (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 (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 (!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); ++ 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); ++ } + } -+ } -+ 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 (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 (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); ++ 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 (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 ""; ++ return len; +} + -+const char * -+msp430_movedi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++void ++machine_dependent_reorg (first_insn) ++rtx first_insn ATTRIBUTE_UNUSED; +{ -+ 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 ""; -+ } ++ /* nothing to be done here this time */ ++ 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 ""; ++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; + -+/************** ADD CODE *********************************/ ++ last_reg = first_reg + size - 1; + ++ for (reg = first_reg; reg <= last_reg; reg++) ++ { ++ if (!df_regs_ever_live_p(reg)) ++ return 0; ++ } ++ } + -+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 ""; ++ return 1; +} + -+const char * -+msp430_emit_indexed_add4 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++ ++/* Update the condition code in the INSN. ++now mostly unused */ ++ ++void ++notice_update_cc (body, insn) ++rtx body ATTRIBUTE_UNUSED; ++rtx insn ATTRIBUTE_UNUSED; +{ -+ emit_indexed_arith (insn, operands, 4, "add", 1); -+ return ""; ++ CC_STATUS_INIT; +} + -+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); -+ } ++/* ++Next two return non zero for rtx as ++(set (reg:xx) ++(mem:xx (reg:xx)) + -+ 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; ++int ++regsi_ok_safe (operands) ++rtx operands[]; +{ -+ rtx op0 = operands[0]; -+ rtx op2 = operands[2]; ++ rtx dest = operands[0]; ++ rtx areg; ++ int src_reg; ++ int dst_reg; + -+ 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; -+ } ++ if (operands[2]) ++ areg = XEXP (operands[2], 0); ++ else ++ areg = XEXP (operands[1], 0); + -+ return ""; -+ } -+ else if (memory_operand (op2, DImode) -+ && zero_shifted (operands[2]) && regdi_ok_clobber (operands)) -+ { -+ if (!len) ++ if (GET_CODE (dest) == MEM) + { -+ 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 (); ++ 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; + } -+ 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 (REGNO (dest) >= FIRST_PSEUDO_REGISTER ++ || REGNO (areg) >= FIRST_PSEUDO_REGISTER) ++ return 1; + -+ if (register_operand (op2, DImode)) -+ *len += 0; -+ else if (memory_operand (op2, DImode)) -+ *len += 4; -+ else if (immediate_operand (op2, DImode)) ++ dst_reg = true_regnum (dest); ++ src_reg = true_regnum (areg); ++ if (dst_reg > src_reg || dst_reg + 1 < src_reg) + { -+ int x = INTVAL (op2); -+ -+ if (x == -2 || x == -4 || x == -8) -+ *len += 0; -+ else -+ *len += 4; ++ return 1; + } -+ else -+ abort (); -+ } ++ 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); + -+ return ""; -+} + ++ 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; ++ } + -+/************** SUB CODE *********************************/ ++ if (regno >= FIRST_PSEUDO_REGISTER || REGNO (areg) >= FIRST_PSEUDO_REGISTER) ++ return 1; + -+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 ""; ++ dst_reg = true_regnum (dest); ++ src_reg = true_regnum (areg); ++ if (dst_reg + 1 == src_reg) ++ return 1; ++ return 0; +} + -+const char * -+msp430_emit_indexed_sub4 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++int ++regdi_ok_safe (operands) ++rtx operands[]; +{ -+ emit_indexed_arith (insn, operands, 4, "sub", 1); -+ return ""; -+} ++ rtx dest = operands[0]; ++ rtx areg = XEXP (operands[2], 0); ++ int src_reg; ++ int dst_reg; + -+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 (GET_CODE (dest) == MEM) + { -+ if (memory_operand (op0, SImode)) -+ *len = 5; -+ else if (register_operand (op0, SImode)) -+ *len = 3; ++ 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; + } + -+ return ""; -+ } -+ else if (memory_operand (op2, SImode) -+ && zero_shifted (operands[2]) && regsi_ok_clobber (operands)) -+ { -+ if (!len) ++ 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) + { -+ output_asm_insn ("sub\t@%E2+, %A0", operands); -+ output_asm_insn ("subc\t@%E2+, %B0", operands); ++ return 1; + } -+ else ++ ++ 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) + { -+ if (register_operand (op0, SImode)) -+ *len = 2; -+ else if (memory_operand (op0, SImode)) -+ *len = 4; -+ else -+ abort (); ++ 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; + } -+ 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; -+ } ++ if (regno >= FIRST_PSEUDO_REGISTER || REGNO (areg) >= FIRST_PSEUDO_REGISTER) ++ return 1; + -+ return ""; ++ dst_reg = true_regnum (dest); ++ src_reg = true_regnum (areg); ++ if (dst_reg + 3 == src_reg) ++ return 1; ++ return 0; +} + + -+const char * -+msp430_subdi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++/***************** ARITHMETIC *******************/ ++ ++int ++emit_indexed_arith (insn, operands, m, cmd, iscarry) ++rtx insn; ++rtx operands[]; ++int m; ++const char *cmd; ++int iscarry; +{ -+ rtx op0 = operands[0]; -+ rtx op2 = operands[2]; ++ 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); + -+ 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 ++ pattern = PATTERN (next); ++ ++ if (pattern && GET_CODE (pattern) == PARALLEL) + { -+ if (register_operand (op0, DImode)) -+ *len = 4; -+ else if (memory_operand (op0, DImode)) -+ *len = 8; -+ else -+ abort (); ++ pattern = XVECEXP (pattern, 0, 0); + } -+ 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 ""; -+} ++ 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); + -+/************** AND CODE *********************************/ ++ if (m == 2) ++ return len; + -+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 ""; -+} ++ 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); + -+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 ""; -+} ++ return len; ++ } + -+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); ++ if (operands[2]) ++ reg = XEXP (operands[2], 0); ++ else ++ reg = XEXP (operands[1], 0); + -+ rtx op[4]; ++ if (GET_CODE (x) == REG) ++ { ++ int src; ++ int dst = REGNO (x); + -+ op[0] = operands[0]; -+ op[1] = operands[1]; -+ op[2] = operands[2]; ++ if (!reg) ++ { ++ reg = XEXP (operands[1], 0); ++ } + -+ /* check nibbles */ ++ src = REGNO (reg); + -+ 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++; ++ /* 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; ++ } + } -+ else ++ ++ while (i < (m - havestop)) + { -+ 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--; ++ 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++; + } -+ } + -+ v = (l >> 16) & 0xffff; -+ if (v != 0xffff) -+ { -+ if (v == list1 || v == list2 || v == list4 || v == list8) ++ if (havestop) + { -+ op[2] = gen_rtx_CONST_INT (SImode, ~v); -+ OUT_INSN (len, "bic\t%A2, %B0", op); -+ dummy++; -+ if (!r) -+ dummy++; ++ 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); + } -+ else ++ ++ if (!dead_or_set_p (insn, reg) && !havestop) + { -+ 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--; ++ 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); + } -+ } + -+ if (len) -+ *len = dummy; -+ return ""; ++ return len; +} + -+const char * -+msp430_emit_immediate_and4 (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++static int sameoperand_p PARAMS ((rtx, rtx)); ++ ++int ++sameoperand (operands, i) ++rtx operands[]; ++int i; +{ -+ 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; -+ } ++ rtx dst = operands[0]; ++ rtx src = operands[i]; + -+ /* 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--; -+ } -+ } ++ return sameoperand_p (src, dst); ++} + -+ 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--; -+ } -+ } ++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: ++ */ + -+ 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--; -+ } -+ } ++ if (scode != dcode) ++ return 0; + -+ v = (h >> 16) & 0xffff; -+ if (v != 0xffff) -+ { -+ if (v == list1 || v == list2 || v == list4 || v == list8) ++ switch (scode) + { -+ 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--; ++ 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; + -+ if (len) -+ *len = dummy; -+ return ""; +} + ++#define OUT_INSN(x,p,o) \ ++ do { \ ++ if(!x) output_asm_insn (p,o); \ ++ } while(0) ++ ++ ++ ++/************** MOV CODE *********************************/ ++ +const char * -+msp430_andsi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++movstrsi_insn (insn, operands, l) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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 ""; -+ } ++ /* 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); + -+ 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 ""; ++} + -+ 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; -+ } ++const char * ++clrstrsi_insn (insn, operands, l) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; ++{ + -+ return ""; ++ /* 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 * -+msp430_anddi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++clrstrhi_insn (insn, operands, l) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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 ""; -+ } ++ /* 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 ""; ++} + -+ if (memory_operand (op2, DImode) -+ && zero_shifted (operands[2]) && regdi_ok_safe (operands)) -+ { -+ if (!len) -+ msp430_emit_indexed_and4 (insn, operands, NULL); -+ else ++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 (memory_operand (op0, DImode)) -+ *len = 9; -+ else if (register_operand (op0, DImode)) -+ *len = 5; ++ 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)); + } + -+ return ""; -+ } -+ else if (memory_operand (op2, DImode) -+ && zero_shifted (operands[2]) && regdi_ok_clobber (operands)) -+ { -+ if (!len) ++ ++ sreg = REGNO(XEXP(operands[1],0)); ++ ++ while (i < m) + { -+ 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); ++ 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++; + } -+ else ++ ++ if (!dead_or_set_p (insn, reg)) + { -+ if (register_operand (op0, DImode)) -+ *len = 4; -+ else if (memory_operand (op0, DImode)) -+ *len = 8; -+ else -+ abort (); ++ 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 ""; -+ } -+ -+ 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 ""; ++ return len; +} + -+/************** IOR CODE *********************************/ -+ +const char * -+msp430_emit_indexed_ior2 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++msp430_emit_indexed_mov2 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ emit_indexed_arith (insn, operands, 2, "bis", 0); -+ return ""; ++ msp430_emit_indexed_mov (insn, operands, 2, "mov"); ++ return ""; +} + +const char * -+msp430_emit_indexed_ior4 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++msp430_emit_indexed_mov4 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ emit_indexed_arith (insn, operands, 4, "bis", 0); -+ return ""; ++ msp430_emit_indexed_mov (insn, operands, 4, "mov"); ++ return ""; +} + +const char * -+msp430_emit_immediate_ior2 (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++movsisf_regmode (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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++; -+ } ++ 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); + -+ 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 (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); ++ } + -+ if (len) -+ *len = dummy; -+ return ""; ++ return ""; /* make compiler happy */ +} + -+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++; -+ } ++/* From Max Behensky ++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; + -+ l = h; -+ v = l & 0xffff; ++ code = GET_CODE (x); + -+ 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++; -+ } ++ if (code != MEM) ++ return (-1); + -+ v = (l >> 16) & 0xffff; ++ x = XEXP (x, 0); ++ code = GET_CODE (x); ++ if (code == REG) ++ return (REGNO (x)); + -+ 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 (code != PLUS) ++ return (-1); + -+ if (len) -+ *len = dummy; -+ return ""; ++ x = XEXP (x, 0); ++ code = GET_CODE (x); ++ if (code != REG) ++ return (-1); ++ ++ return (REGNO (x)); +} + ++ +const char * -+msp430_iorsi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++msp430_movesi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ rtx op0 = operands[0]; -+ rtx op2 = operands[2]; ++ rtx op0 = operands[0]; ++ rtx op1 = operands[1]; + -+ 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, 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 (memory_operand (op0, SImode)) -+ *len = 5; -+ else if (register_operand (op0, SImode)) -+ *len = 3; ++ if (!len) ++ movsisf_regmode (insn, operands, NULL); ++ else ++ *len = 3; ++ return ""; + } + -+ return ""; -+ } -+ else if (memory_operand (op2, SImode) -+ && zero_shifted (operands[2]) && regsi_ok_clobber (operands)) -+ { -+ if (!len) ++ if (!len) + { -+ output_asm_insn ("bis\t@%E2+, %A0", operands); -+ output_asm_insn ("bis\t@%E2+, %B0", operands); ++ 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 ++ else + { -+ if (register_operand (op0, SImode)) -+ *len = 2; -+ else if (memory_operand (op0, SImode)) -+ *len = 4; -+ else -+ abort (); ++ *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 ""; -+ } -+ -+ 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 ""; ++ return ""; +} + +const char * -+msp430_iordi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++movdidf_regmode (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ rtx op0 = operands[0]; -+ rtx op2 = operands[2]; ++ rtx dest = operands[0]; ++ rtx src = operands[1]; ++ rtx areg = XEXP (src, 0); + -+ if (nonimmediate_operand (op0, DImode) && immediate_operand (op2, DImode)) -+ { -+ if (!len) -+ msp430_emit_immediate_ior4 (insn, operands, NULL); -+ return ""; -+ } ++ int src_reg = true_regnum (areg); ++ int dst_reg = true_regnum (dest); + -+ if (memory_operand (op2, DImode) -+ && zero_shifted (operands[2]) && regdi_ok_safe (operands)) -+ { -+ if (!len) -+ msp430_emit_indexed_ior4 (insn, operands, NULL); -+ else ++ ++ 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 + { -+ if (memory_operand (op0, DImode)) -+ *len = 9; -+ else if (register_operand (op0, DImode)) -+ *len = 5; ++ /* 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 ""; -+ } -+ else if (memory_operand (op2, DImode) -+ && zero_shifted (operands[2]) && regdi_ok_clobber (operands)) -+ { -+ if (!len) ++ 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)) + { -+ 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); ++ if (!len) ++ msp430_emit_indexed_mov4 (insn, operands, NULL); ++ else ++ *len = 9; ++ return ""; + } -+ else ++ else if (register_operand (op0, DImode) ++ && memory_operand (op1, DImode) && zero_shifted (op1)) + { -+ if (register_operand (op0, DImode)) -+ *len = 4; -+ else if (memory_operand (op0, DImode)) -+ *len = 8; -+ else -+ abort (); ++ if (!len) ++ movdidf_regmode (insn, operands, NULL); ++ else ++ *len = 5; ++ return ""; + } -+ 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 (); -+ } ++ 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 ""; ++ 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 ""; -+} ++/************** ADD CODE *********************************/ + + +const char * -+msp430_emit_indexed_xor2_3 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l; ++msp430_emit_indexed_add2 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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 ""; ++ emit_indexed_arith (insn, operands, 2, "add", 1); ++ return ""; +} + +const char * -+msp430_emit_indexed_xor4_3 (insn, operands, l) -+ rtx insn; -+ rtx operands[]; -+ int *l; ++msp430_emit_indexed_add4 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ -+ 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 ""; ++ emit_indexed_arith (insn, operands, 4, "add", 1); ++ return ""; +} + +const char * -+msp430_xorsi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++msp430_addsi_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; -+ } ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; ++ rtx ops[4]; + -+ return ""; -+ } -+ else if (memory_operand (op2, SImode) -+ && zero_shifted (operands[2]) && regsi_ok_clobber (operands)) -+ { -+ if (!len) ++ if (memory_operand (op2, SImode) ++ && zero_shifted (operands[2]) && regsi_ok_safe (operands)) + { -+ output_asm_insn ("xor\t@%E2+, %A0", operands); -+ output_asm_insn ("xor\t@%E2+, %B0", 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 ++ else if (memory_operand (op2, SImode) ++ && zero_shifted (operands[2]) && regsi_ok_clobber (operands)) + { -+ if (register_operand (op0, SImode)) -+ *len = 2; -+ else if (memory_operand (op0, SImode)) -+ *len = 4; -+ else -+ abort (); ++ 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 ""; + } -+ return ""; -+ } -+ -+ if (!len) -+ { + -+ if (immediate_operand (op2, SImode)) -+ { -+ if (INTVAL (op2) & 0xfffful) -+ output_asm_insn ("xor\t%A2, %A0", operands); ++ ops[0] = operands[0]; ++ ops[2] = operands[2]; + -+ if (INTVAL (op2) & 0xffff0000ul) -+ output_asm_insn ("xor\t%B2, %B0", operands); -+ } -+ else ++ if (!len) + { -+ output_asm_insn ("xor\t%A2, %A0", operands); -+ output_asm_insn ("xor\t%B2, %B0", operands); ++ output_asm_insn ("add\t%A2, %A0", ops); ++ output_asm_insn ("addc\t%B2, %B0", ops); + } + -+ } -+ 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 (len) + { -+ if (INTVAL (op2) & 0xfffful) -+ *len += 1; -+ if (INTVAL (op2) & 0xffff0000ul) -+ *len += 1; ++ *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 ""; ++ return ""; +} + +const char * -+msp430_xordi_code (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++msp430_adddi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ rtx op0 = operands[0]; -+ rtx op2 = operands[2]; ++ 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 (op2, DImode) ++ && zero_shifted (operands[2]) && regdi_ok_safe (operands)) + { -+ if (memory_operand (op0, DImode)) -+ *len = 9; -+ else if (register_operand (op0, DImode)) -+ *len = 5; -+ } ++ 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) ++ return ""; ++ } ++ else if (memory_operand (op2, DImode) ++ && zero_shifted (operands[2]) && regdi_ok_clobber (operands)) + { -+ 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); ++ 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 ""; + } -+ else ++ ++ if (!len) + { -+ if (register_operand (op0, DImode)) -+ *len = 4; -+ else if (memory_operand (op0, DImode)) -+ *len = 8; -+ else -+ abort (); ++ 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); + } -+ return ""; -+ } ++ 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 (!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 (); -+ } ++ if (x == -2 || x == -4 || x == -8) ++ *len += 0; ++ else ++ *len += 4; ++ } ++ else ++ abort (); ++ } + -+ return ""; ++ return ""; +} + + -+/********* ABS CODE ***************************************/ ++/************** SUB CODE *********************************/ ++ +const char * -+msp430_emit_abssi (insn, operands, l) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++msp430_emit_indexed_sub2 (insn, operands, l) ++rtx insn; ++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 ""; ++ emit_indexed_arith (insn, operands, 2, "sub", 1); ++ return ""; +} + +const char * -+msp430_emit_absdi (insn, operands, l) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *l ATTRIBUTE_UNUSED; ++msp430_emit_indexed_sub4 (insn, operands, l) ++rtx insn; ++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 ""; ++ emit_indexed_arith (insn, operands, 4, "sub", 1); ++ return ""; +} + -+ -+/***** SIGN EXTEND *********/ +const char * -+signextendqihi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_subsi_code (insn, operands, len) ++rtx insn; ++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--; -+ } ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ OUT_INSN (len, "sxt\t%A0", operands); -+ dummy += 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; ++ } + -+ if (zs || GET_CODE (operands[0]) == REG) -+ dummy -= 1; ++ 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) -+ *len = dummy; ++ 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 ""; ++ return ""; +} + ++ +const char * -+signextendqisi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_subdi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; -+ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ 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--; -+ } ++ 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 (); ++ } + -+ 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); ++ return ""; ++} + -+ if (GET_CODE (operands[0]) == REG) -+ dummy += 5; -+ else if (zs) -+ dummy += 10; -+ else -+ dummy += 12; + -+ if (len) -+ *len = dummy; ++/************** AND CODE *********************************/ + -+ return ""; ++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 * -+signextendqidi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_indexed_and4 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ int dummy = 0; -+ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ emit_indexed_arith (insn, operands, 4, "and", 0); ++ return ""; ++} + -+ 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--; -+ } ++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); + -+ 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); ++ rtx op[4]; + ++ op[0] = operands[0]; ++ op[1] = operands[1]; ++ op[2] = operands[2]; + -+ if (GET_CODE (operands[0]) == REG) -+ dummy += 7; -+ else if (zs) -+ dummy += 16; -+ else -+ dummy += 18; ++ /* check nibbles */ + -+ if (len) -+ *len = dummy; ++ 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--; ++ } ++ } + -+ return ""; ++ if (len) ++ *len = dummy; ++ return ""; +} + +const char * -+signextendhisi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_immediate_and4 (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; -+ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ 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; ++ } + -+ 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--; -+ } ++ /* 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--; ++ } ++ } + -+ 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); ++ 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 (GET_CODE (operands[0]) == REG) -+ dummy += 4; -+ else if (zs) -+ dummy += 9; -+ else -+ dummy += 11; ++ 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--; ++ } ++ } + -+ if (len) -+ *len = 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--; ++ } ++ } + -+ return ""; ++ if (len) ++ *len = dummy; ++ return ""; +} + +const char * -+signextendhidi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_andsi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; -+ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ 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--; -+ } ++ if (nonimmediate_operand (op0, SImode) && immediate_operand (op2, SImode)) ++ { ++ if (!len) ++ msp430_emit_immediate_and2 (insn, operands, NULL); ++ return ""; ++ } + -+ 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 (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) -+ *len = dummy; ++ 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 ""; ++ return ""; +} + ++ +const char * -+signextendsidi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_anddi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ 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; -+ } ++ if (nonimmediate_operand (op0, DImode) && immediate_operand (op2, DImode)) ++ { ++ if (!len) ++ msp430_emit_immediate_and4 (insn, operands, NULL); ++ return ""; ++ } + -+ 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 (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; ++ } + -+ if (GET_CODE (operands[0]) == REG) -+ dummy += 5; -+ else -+ dummy += 13; ++ 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) -+ *len = dummy; ++ 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 ""; ++ return ""; +} + -+ -+/**** ZERO EXTEND *****/ ++/************** IOR CODE *********************************/ + +const char * -+zeroextendqihi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_indexed_ior2 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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 ""; ++ emit_indexed_arith (insn, operands, 2, "bis", 0); ++ return ""; +} + +const char * -+zeroextendqisi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_indexed_ior4 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l ATTRIBUTE_UNUSED; +{ -+ 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 ""; ++ emit_indexed_arith (insn, operands, 4, "bis", 0); ++ return ""; +} + -+ +const char * -+zeroextendqidi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_immediate_ior2 (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; -+ int zs = zero_shifted (operands[1]) || indexed_location (operands[1]); ++ int dummy = 0; ++ int l = INTVAL (operands[2]); ++ int r = REG_P (operands[0]); ++ int v; + -+ 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); ++ 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++; ++ } + -+ if (GET_CODE (operands[0]) == REG && len) -+ *len -= 3; ++ v = (l >> 16) & 0xffff; + -+ if (len) -+ *len = dummy; ++ 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++; ++ } + -+ return ""; ++ if (len) ++ *len = dummy; ++ return ""; +} + +const char * -+zeroextendhisi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_emit_immediate_ior4 (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--; -+ } ++ 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; + -+ OUT_INSN (len, "clr\t%B0", operands); -+ dummy += 2; -+ if (GET_CODE (operands[0]) == REG) -+ dummy--; ++ if (GET_CODE (operands[2]) == CONST_INT) ++ { ++ l = INTVAL (operands[2]); ++ h = 0; ++ } + -+ if (len) -+ *len = dummy; ++ v = l & 0xffff; + -+ return ""; ++ 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; + -+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 (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 (!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--; -+ } ++ l = h; ++ v = l & 0xffff; + -+ dummy += 6; -+ OUT_INSN (len, "clr\t%B0", operands); -+ OUT_INSN (len, "clr\t%C0", operands); -+ OUT_INSN (len, "clr\t%D0", operands); ++ 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++; ++ } + -+ if (GET_CODE (operands[0]) == REG) -+ dummy -= 3; ++ v = (l >> 16) & 0xffff; + -+ if (len) -+ *len = dummy; ++ 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++; ++ } + -+ return ""; ++ if (len) ++ *len = dummy; ++ return ""; +} + +const char * -+zeroextendsidi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++msp430_iorsi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ 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--; ++ if (nonimmediate_operand (op0, SImode) && immediate_operand (op2, SImode)) ++ { ++ if (!len) ++ msp430_emit_immediate_ior2 (insn, operands, NULL); ++ return ""; + } -+ } + -+ dummy += 4; -+ OUT_INSN (len, "clr\t%C0", operands); -+ OUT_INSN (len, "clr\t%D0", operands); ++ 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; ++ } + -+ if (GET_CODE (operands[0]) == REG) -+ dummy -= 2; ++ 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) -+ *len = dummy; ++ 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 ""; ++ return ""; +} + -+/******************* TESTS AND JUMPS *********************/ -+ -+RTX_CODE -+msp430_canonicalize_comparison (code, op0, op1) -+ RTX_CODE code; -+ rtx *op0; -+ rtx *op1; ++const char * ++msp430_iordi_code (insn, operands, len) ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ RTX_CODE rc = code; ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ if ( CONSTANT_P(*op1) ) -+ { -+ ; /* nothing to be done */ -+ } -+ else -+ { -+ switch (code) ++ if (nonimmediate_operand (op0, DImode) && immediate_operand (op2, DImode)) + { -+ case GT: -+ case LE: -+ case GTU: -+ case LEU: -+ { -+ rtx x; -+ rc = swap_condition (code); -+ x = *op0; -+ *op0 = *op1; -+ *op1 = x; -+ } -+ break; -+ default: -+ break; ++ if (!len) ++ msp430_emit_immediate_ior4 (insn, operands, NULL); ++ return ""; + } -+ } -+ return rc; -+} + ++ 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; ++ } + -+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; ++ 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 ""; + } -+ } -+ 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); ++ 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 (); ++ } + -+ msp430_compare_op0 = 0; -+ msp430_compare_op1 = 0; -+ return; ++ 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; ++/************************* XOR CODE *****************/ ++ ++const char * ++msp430_emit_indexed_xor2 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l; +{ -+ rtx prev = insn; -+ enum attr_cc cc; -+ rtx set; -+ rtx src, dst; -+ rtx x1 = 0; ++ int dummy = emit_indexed_arith (insn, operands, 2, "xor", 0); ++ if (!l) ++ l = &dummy; ++ *l = dummy; ++ return ""; ++} + -+ if(GET_CODE(x) == MEM) -+ { -+ x1 = XEXP(x,0); -+ if(GET_CODE(x1) == PLUS) -+ { -+ x1 = XEXP(x1,0); -+ } -+ -+ if(!REG_P(x1)) x1 = 0; -+ } ++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 ""; ++} + -+ 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) ++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)) + { -+ set = single_set (prev); -+ -+ if(!set) -+ return 0; -+ -+ cc = get_attr_cc (prev); ++ 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 (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 (!l) ++ l = &dummy; ++ *l = dummy; ++ return ""; ++} + -+ if (cc == CC_CLOBBER) /* clobber */ -+ return 0; ++const char * ++msp430_emit_indexed_xor4_3 (insn, operands, l) ++rtx insn; ++rtx operands[]; ++int *l; ++{ + -+ 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; ++ 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); + } -+ } -+ return 0; -+} -+ + ++ if (!l) ++ l = &dummy; ++ *l = dummy; ++ return ""; ++} + +const char * -+msp430_cbranch (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++msp430_xorsi_code (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]); -+ } ++ rtx op0 = operands[0]; ++ rtx op2 = operands[2]; + -+ /* 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) ++ if (memory_operand (op2, SImode) ++ && zero_shifted (operands[2]) && regsi_ok_safe (operands)) + { -+ 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; ++ 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 (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) ++ else if (memory_operand (op2, SImode) ++ && zero_shifted (operands[2]) && regsi_ok_clobber (operands)) + { -+ case GT: -+ code = GE; -+ break; -+ case LE: -+ code = LT; -+ break; -+ case GTU: -+ code = GEU; -+ break; -+ case LEU: -+ code = LTU; -+ break; -+ default: -+ break; ++ 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 (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) ++ if (!len) ++ { ++ ++ if (immediate_operand (op2, SImode)) + { -+ int x = INTVAL (ops[1]) & 0xffff; -+ if (x == 0 || x == 1 || x == -1 || x == 2 || x == 4 -+ || x == 8) -+ dummy--; ++ 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); + } -+ distance -= dummy; -+ if (distance > 500 || distance < -500) -+ predist = 3; -+ else -+ predist = 1; + -+ if (code == EQ) ++ } ++ 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)) + { -+ OUT_INSN (len, "jne\t.LcmpSIe%=", ops); -+ OUT_INSN (len, "cmp\t%B1, %B0", ops); -+ dummy++; ++ if (INTVAL (op2) & 0xfffful) ++ *len += 1; ++ if (INTVAL (op2) & 0xffff0000ul) ++ *len += 1; + } -+ else ++ } ++ ++ 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 + { -+ ECOND (ne, 0); -+ OUT_INSN (len, "cmp\t%B1, %B0", ops); ++ if (memory_operand (op0, DImode)) ++ *len = 9; ++ else if (register_operand (op0, DImode)) ++ *len = 5; + } + -+ dummy += 3; -+ if (REG_P (ops[0])) -+ dummy--; -+ if (REG_P (ops[1])) -+ dummy--; -+ if (GET_CODE (ops[1]) == CONST_INT) ++ return ""; ++ } ++ else if (memory_operand (op2, DImode) ++ && zero_shifted (operands[2]) && regdi_ok_clobber (operands)) ++ { ++ if (!len) + { -+ int x = (INTVAL (ops[1]) >> 16) & 0xffff; -+ if (x == 0 || x == 0xffff || x == 1 || x == 2 || x == 4 -+ || x == 8) -+ dummy--; ++ 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 (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) ++ else + { -+ 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--; ++ 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 (); + } -+ } + -+ distance -= dummy; ++ return ""; ++} + -+ 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; -+ } ++/********* 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 ""; ++} + -+ if (len) -+ *len = dummy; -+ 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 ""; +} + -+/***************** AUXES FOR TESTS *********************/ + -+RTX_CODE -+followed_compare_condition (insn) -+ rtx insn; ++/***** SIGN EXTEND *********/ ++const char * ++signextendqihi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *len; +{ -+ rtx next = next_real_insn (insn); -+ RTX_CODE cond = UNKNOWN; -+ -+ if (next && GET_CODE (next) == JUMP_INSN) -+ { -+ rtx pat = PATTERN (next); -+ rtx src, t; ++ int dummy = 0; ++ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); + -+ if (GET_CODE (pat) == RETURN) -+ return UNKNOWN; ++ 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--; ++ } + -+ 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 */ ++ OUT_INSN (len, "sxt\t%A0", operands); ++ dummy += 2; + -+ rtx pat = PATTERN (next); -+ rtx src; ++ if (zs || GET_CODE (operands[0]) == REG) ++ dummy -= 1; + -+ if (!pat || GET_CODE (pat) != SET) -+ return UNKNOWN; ++ if (len) ++ *len = dummy; + -+ src = SET_SRC (pat); -+ cond = GET_CODE (src); /* this must be IF_THEN_ELSE */ -+ if (cond != IF_THEN_ELSE) -+ return UNKNOWN; -+ } -+ return cond; ++ return ""; +} + -+/******** jumps ************/ -+ +const char * -+msp430_emit_blt0si (operands, len) -+ rtx operands[]; -+ int len; ++signextendqisi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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 ""; ++ return ""; +} + +const char * -+msp430_emit_beq (operands, len) -+ rtx operands[]; -+ int len; ++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]); + -+ 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!!!"; -+ } ++ 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--; ++ } + -+ return ""; ++ 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 * -+msp430_emit_bne (operands, len) -+ rtx operands[]; -+ int len; ++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]); + -+ 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!!!"; -+ } ++ 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 ""; ++ return ""; +} + +const char * -+msp430_emit_bgt (operands, len) -+ rtx operands[]; -+ int len; ++signextendhidi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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; + -+ return ""; ++ if (len) ++ *len = dummy; ++ ++ return ""; +} + +const char * -+msp430_emit_bgtu (operands, len) -+ rtx operands[]; -+ int len; ++signextendsidi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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; ++ } + -+ return ""; ++ 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 * -+msp430_emit_blt (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendqihi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ int dummy = 0; ++ int zs = zero_shifted (operands[1]) || indexed_location (operands[1]); + -+ return ""; -+} ++ 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 * -+msp430_emit_bltnoovfl (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendqisi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ int dummy = 0; ++ int zs = zero_shifted (operands[1]) || indexed_location (operands[1]); + -+ return ""; -+} ++ 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 * -+msp430_emit_bltu (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendqidi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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; + -+ return ""; ++ if (len) ++ *len = dummy; ++ ++ return ""; +} + +const char * -+msp430_emit_bge (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendhisi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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 ""; + -+ return ""; +} + +const char * -+msp430_emit_bgeu (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendhidi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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 ""; ++ return ""; +} + +const char * -+msp430_emit_ble (operands, len) -+ rtx operands[]; -+ int len; ++zeroextendsidi (insn, operands, len) ++rtx insn ATTRIBUTE_UNUSED; ++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!!!"; -+ } ++ 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; + -+ return ""; ++ if (len) ++ *len = dummy; ++ ++ return ""; +} + -+const char * -+msp430_emit_bleu (operands, len) -+ rtx operands[]; -+ int len; ++/******************* TESTS AND JUMPS *********************/ ++ ++ ++/***************** AUXES FOR TESTS *********************/ ++ ++RTX_CODE ++followed_compare_condition (insn) ++rtx insn; +{ -+ 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!!!"; -+ } ++ 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; + -+ return ""; ++ 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[]; ++rtx operands[]; +{ -+ int x; -+ rtx set, shift; -+ rtx dst; ++ 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; -+ } ++ 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]); ++ x = INTVAL (operands[2]); + -+ if (x > 15 || x < 0) -+ { -+ emit_move_insn (operands[0], const0_rtx); -+ return 1; -+ } ++ 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 == 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 < 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 (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; -+ } ++ 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); ++ 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; ++ while (x--) ++ emit_insn (set); ++ if (dst != operands[0]) ++ emit_move_insn (operands[0], dst); ++ return 1; +} + +int +msp430_ashlsi3 (operands) -+ rtx operands[]; ++rtx operands[]; +{ -+ int x; -+ rtx shift, set, dst; ++ 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; -+ } ++ 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]); ++ x = INTVAL (operands[2]); + -+ if (x >= 32 || x < 0) -+ { -+ emit_move_insn (operands[0], const0_rtx); -+ return 1; -+ } ++ 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 == 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 (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 (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 == 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 >= 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; -+ } ++ 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); ++ 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; ++ 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[]; ++rtx operands[]; +{ -+ int x; -+ rtx shift, set, dst; ++ 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; -+ } ++ 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; -+ } ++ 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 == 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 (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 (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; -+ } ++ 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); ++ shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx); ++ set = gen_rtx_SET (HImode, dst, shift); + -+ while (x--) -+ emit_insn (set); ++ while (x--) ++ emit_insn (set); + -+ if (dst != operands[0]) -+ emit_move_insn (operands[0], dst); ++ if (dst != operands[0]) ++ emit_move_insn (operands[0], dst); + -+ return 1; ++ return 1; +} + +int +msp430_ashrsi3 (operands) -+ rtx 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; -+ } ++ int x; ++ rtx shift, set, dst; + -+ x = INTVAL (operands[2]); ++ 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; ++ } + -+ if (x == 0) -+ { -+ emit_move_insn (operands[0], operands[1]); -+ return 1; -+ } ++ x = INTVAL (operands[2]); + -+ if (operands[0] != operands[1]) -+ dst = copy_to_mode_reg (SImode, operands[1]); -+ else -+ dst = operands[1]; ++ if (x == 0) ++ { ++ emit_move_insn (operands[0], operands[1]); ++ return 1; ++ } + -+ if (x >= 31 || x < 0) -+ { ++ if (operands[0] != operands[1]) ++ dst = copy_to_mode_reg (SImode, operands[1]); ++ else ++ dst = operands[1]; + -+ shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (31)); -+ set = gen_rtx_SET (SImode, dst, shift); -+ emit_insn (set); ++ if (x >= 31 || x < 0) ++ { + -+ if (dst != operands[0]) -+ emit_move_insn (operands[0], dst); -+ return 1; -+ } ++ shift = gen_rtx_ASHIFTRT (SImode, dst, GEN_INT (31)); ++ set = gen_rtx_SET (SImode, dst, shift); ++ emit_insn (set); + -+ 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 (dst != operands[0]) ++ emit_move_insn (operands[0], dst); ++ return 1; ++ } + -+ if (x >= 16) -+ { -+ rtx dlo = gen_lowpart (HImode, operands[0]); -+ rtx shi = gen_highpart (HImode, dst); ++ 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; ++ } + -+ emit_move_insn (gen_highpart (HImode, operands[0]), const0_rtx); -+ emit_insn (gen_extendhisi2 (operands[0], shi)); -+ x -= 16; -+ if (x) ++ if (x >= 16) + { -+ rtx ops[3]; -+ ops[0] = dlo; -+ ops[1] = dlo; -+ ops[2] = GEN_INT (x); -+ msp430_ashrhi3 (ops); ++ 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; + } -+ 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; -+ } ++ 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); ++ 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; ++ 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[]; ++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; -+ } ++ int x; ++ rtx shift, set, dst; + -+ x = INTVAL (operands[2]); -+ if (x > 15 || x < 0) -+ { -+ emit_move_insn (operands[0], const0_rtx); -+ return 1; -+ } ++ 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; ++ } + -+ if (x == 0) -+ { -+ emit_move_insn (operands[0], operands[1]); -+ return 1; -+ } ++ x = INTVAL (operands[2]); ++ if (x > 15 || x < 0) ++ { ++ emit_move_insn (operands[0], const0_rtx); ++ 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 == 0) ++ { ++ emit_move_insn (operands[0], operands[1]); ++ return 1; ++ } + -+ if (x) ++ if (x < 3) + { -+ shift = gen_rtx_ASHIFTRT (HImode, dst, const1_rtx); -+ set = gen_rtx_SET (HImode, dst, shift); -+ emit_insn (set); ++ 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; + } -+ 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 (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 (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 >= 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); ++ 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); ++ while (x--) ++ emit_insn (set); + -+ if (dst != operands[0]) -+ emit_move_insn (operands[0], dst); ++ if (dst != operands[0]) ++ emit_move_insn (operands[0], dst); + -+ return 1; ++ return 1; +} + +int +msp430_lshrsi3 (operands) -+ rtx operands[]; ++rtx operands[]; +{ -+ int x; -+ rtx shift, set, dst; ++ 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 (!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; ++ } + -+ if (x == 0) -+ { -+ emit_move_insn (operands[0], operands[1]); -+ return 1; -+ } ++ x = INTVAL (operands[2]); + -+ 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 == 0) ++ { ++ emit_move_insn (operands[0], operands[1]); ++ return 1; ++ } + -+ if (x > 31 || x < 0) -+ { -+ emit_move_insn (operands[0], const0_rtx); -+ 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 (operands[0] != operands[1]) -+ dst = copy_to_mode_reg (SImode, operands[1]); -+ else -+ dst = operands[1]; ++ if (x > 31 || x < 0) ++ { ++ emit_move_insn (operands[0], const0_rtx); ++ return 1; ++ } + -+ if (x >= 16) -+ { -+ rtx dlo = gen_lowpart (HImode, operands[0]); -+ rtx shi = gen_highpart (HImode, dst); ++ if (operands[0] != operands[1]) ++ dst = copy_to_mode_reg (SImode, operands[1]); ++ else ++ dst = operands[1]; + -+ emit_move_insn (gen_highpart (HImode, operands[0]), const0_rtx); -+ emit_insn (gen_zero_extendhisi2 (operands[0], shi)); -+ x -= 16; -+ if (x) ++ if (x >= 16) + { -+ rtx ops[3]; -+ ops[0] = dlo; -+ ops[1] = dlo; -+ ops[2] = GEN_INT (x); -+ msp430_lshrhi3 (ops); ++ 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; + } -+ 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 >= 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--; -+ } ++ 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); ++ 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; ++ 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 operands[]; +{ -+ rtx x = operands[0]; -+ rtx cnt = operands[2]; -+ int size = GET_MODE_SIZE (x->mode); -+ int icnt = -1; -+ int r = 0; ++ 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 (!optimize) ++ return 0; + -+ if (GET_CODE (cnt) == CONST_INT) -+ icnt = INTVAL (cnt); -+ else -+ return 1; ++ 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; -+ } ++ 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; ++ return r; +} + + @@ -8545,74 +9332,74 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.c gcc-3.2.3/gcc/config/ +/* 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 */ ++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; ++ 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 */ ++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; ++ 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 */ ++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; ++ 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; +} + + @@ -8621,35 +9408,35 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.c gcc-3.2.3/gcc/config/ + +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; ++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; ++ 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; ++ if (len) ++ *len = dummy; ++ return 0; +} + + @@ -8657,2639 +9444,2893 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.c gcc-3.2.3/gcc/config/ + +const char * +msp430_emit_ashlqi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *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"; ++ int dummy = 0; ++ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ const char *pattern; ++ int shiftpos; + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ shiftpos = INTVAL (operands[2]); ++ if (zs) ++ pattern = "rla.b\t@%E0"; ++ else ++ pattern = "rla.b\t%A0"; + -+ switch (shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ 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; ++ shiftpos = INTVAL (operands[2]); + -+ 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; -+ } ++ 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; + -+ 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; ++ } + -+ if (len) -+ *len = dummy; -+ return ""; ++ break; ++ } + -+ } -+ else -+ { -+ msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 3); -+ } ++ if (len) ++ *len = dummy; ++ return ""; ++ ++ } ++ else ++ { ++ msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 3); ++ } + -+ return ""; ++ return ""; +} + + +const char * +msp430_emit_ashlhi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++rtx insn; ++rtx operands[]; ++int *len; +{ -+ int dummy = 0; -+ int zs; -+ const char *pattern; -+ int shiftpos; ++ int dummy = 0; ++ int zs; ++ const char *pattern; ++ int shiftpos; + -+ zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ zs = zero_shifted (operands[0]) || indexed_location (operands[0]); + -+ if (zs) -+ pattern = "rla\t@%E0"; -+ else -+ pattern = "rla\t%A0"; ++ if (zs) ++ pattern = "rla\t@%E0"; ++ else ++ pattern = "rla\t%A0"; + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ shiftpos = INTVAL (operands[2]); ++ 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]); + -+ switch (shiftpos) ++ 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) + { -+ case 0: /* paranoia setting */ -+ dummy = 0; -+ break; ++ 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); ++ } + -+ 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; ++ if (len) ++ *len = dummy; ++ return ""; + -+ 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; + -+ 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; ++ } + -+ default: ++ if (len) ++ *len = dummy; ++ return ""; ++ break; + -+ OUT_INSN (len, "clr\t%A0", operands); -+ dummy = 2; -+ if (REG_P (operands[0])) -+ dummy = 1; -+ 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); + -+ if (len) -+ *len = dummy; -+ return ""; -+ } -+ else -+ { -+ msp430_emit_shift_cnt (set_len, pattern, insn, operands, len, 3); -+ } ++ return ""; + -+ return ""; +} + -+ +const char * -+msp430_emit_ashlsi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++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\tsub\t#4, %E0"; -+ else -+ pattern = "rla\t%A0\n\trlc\t%B0"; ++ int dummy = 0; ++ int zs; ++ const char *pattern; + ++ zs = zero_shifted (operands[0]); + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ int shiftpos = INTVAL (operands[2]); ++ 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"; + -+ switch (shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { ++ int shiftpos = INTVAL (operands[2]); + -+ 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; ++ 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); + -+ 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); ++ } ++ 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); + -+ return ""; ++ } ++ 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); ++ } + -+const char * -+msp430_emit_ashldi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; -+{ ++ 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; + -+ int dummy = 0; -+ int zs; -+ const char *pattern; ++ shiftpos -= 32; ++ while (shiftpos--) ++ { ++ OUT_INSN (len, pattern, operands); ++ dummy += set_len (operands[0], 12, 1); ++ } + -+ zs = zero_shifted (operands[0]); ++ 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); ++ } + -+ 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"; ++ shiftpos -= 48; ++ while (shiftpos--) ++ { ++ OUT_INSN (len, pattern, operands); ++ dummy += set_len (operands[0], 12, 1); ++ } + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ int shiftpos = INTVAL (operands[2]); ++ if (GET_CODE (operands[0]) == REG) ++ dummy = 4; ++ if (len) ++ *len = dummy; + -+ switch (shiftpos) -+ { -+ case 0: -+ dummy = 0; -+ if (len) -+ *len = dummy; -+ break; ++ 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; -+ } ++ 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; ++ if (len) ++ *len = dummy; + -+ break; /* make compiler happy */ ++ 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); ++ 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 */ ++ return ""; /* make compiler happy */ +} + +/********* SHIFT RIGHT CODE ***************************************/ +const char * +msp430_emit_ashrqi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *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; ++ 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 (zs) ++ pattern = "rra.b\t@%E0"; ++ else ++ pattern = "rra.b\t%A0"; + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { ++ if (GET_CODE (operands[2]) == CONST_INT) ++ { + -+ shiftpos = INTVAL (operands[2]); ++ shiftpos = INTVAL (operands[2]); + -+ switch (shiftpos) -+ { -+ case 0: /* paranoia setting */ -+ dummy = 0; -+ break; ++ 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 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; ++ 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 ""; + -+ default: -+ OUT_INSN (len, "clr.b\t%A0", operands); -+ dummy = 2; -+ if (REG_P (operands[0])) -+ dummy = 1; -+ } ++ break; + -+ if (len) -+ *len = dummy; -+ return ""; -+ } -+ else -+ { -+ msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 2); -+ } ++ 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 ""; ++ return ""; +} + +const char * +msp430_emit_ashrhi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *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"; ++ int dummy = 0; ++ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ const char *pattern; ++ int shiftpos; + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ shiftpos = INTVAL (operands[2]); ++ if (zs) ++ pattern = "rra\t@%E0"; ++ else ++ pattern = "rra\t%A0"; + -+ switch (shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ case 0: /* paranoia setting */ -+ dummy = 0; -+ break; ++ shiftpos = INTVAL (operands[2]); + -+ 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; ++ 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 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; ++ 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; -+ } ++ 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); -+ } ++ if (len) ++ *len = dummy; ++ return ""; ++ } ++ else ++ { ++ msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 2); ++ } + -+ return ""; ++ return ""; +} + +const char * +msp430_emit_ashrsi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++rtx insn; ++rtx operands[]; ++int *len; +{ + -+ int dummy = 0; -+ const char *pattern; -+ int zs = zero_shifted (operands[0]); ++ int dummy = 0; ++ const char *pattern; ++ int zs = zero_shifted (operands[0]); + -+ pattern = "rra\t%B0\n\trrc\t%A0"; ++ pattern = "rra\t%B0\n\trrc\t%A0"; + -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ int shiftpos = INTVAL (operands[2]); -+ -+ switch (shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ 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; ++ int shiftpos = INTVAL (operands[2]); + -+ 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; ++ 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--; ++ } + -+ default: -+ dummy = 0; /* leave it alone!!! */ -+ break; ++ 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 */ ++ } /* switch */ + -+ if (len) -+ *len = dummy; -+ return ""; -+ } -+ else -+ msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 4); ++ if (len) ++ *len = dummy; ++ return ""; ++ } ++ else ++ msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 4); + -+ return ""; ++ return ""; + +} + +const char * +msp430_emit_ashrdi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *len; ++rtx insn; ++rtx operands[]; ++int *len; +{ + -+ int dummy = 0; -+ const char *pattern; ++ int dummy = 0; ++ const char *pattern; + -+ pattern = "rra\t%D0\n\trrc\t%C0\n\trrc\t%B0\n\trrc\t%A0"; ++ 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) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ 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; ++ int shiftpos = INTVAL (operands[2]); + -+ default: -+ dummy = 0; ++ 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); ++ } + -+ } /* case */ ++ 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; + -+ if (len) -+ *len = dummy; -+ return ""; -+ } -+ else -+ msp430_emit_shift_cnt (set_ren, pattern, insn, operands, len, 8); -+ return ""; ++ 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; ++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]); ++ int dummy = 0; ++ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ const char *pattern; ++ const char *second_pat; ++ int shiftpos; + -+ if (shiftpos != 7 && shiftpos) ++ if (zs) + { -+ OUT_INSN (len, pattern, operands); -+ dummy += set_rel (operands[0], 2, 1); -+ shiftpos--; ++ 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"; + } + -+ switch (shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ 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; ++ shiftpos = INTVAL (operands[2]); + -+ default: -+ OUT_INSN (len, "clr.b\t%A0", operands); -+ dummy = 2; -+ if (REG_P (operands[0])) -+ dummy = 1; -+ break; -+ } ++ if (shiftpos != 7 && shiftpos) ++ { ++ OUT_INSN (len, pattern, operands); ++ dummy += set_rel (operands[0], 2, 1); ++ shiftpos--; ++ } + -+ if (len) -+ *len = dummy; -+ } -+ else -+ { -+ msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 2); -+ } ++ 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; + -+ return ""; ++ 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; ++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]); ++ int dummy = 0; ++ int zs = zero_shifted (operands[0]) || indexed_location (operands[0]); ++ const char *pattern; ++ const char *second_pat; ++ int shiftpos; + -+ if (shiftpos < 8 && shiftpos) ++ if (zs) + { -+ OUT_INSN (len, pattern, operands); -+ dummy += set_rel (operands[0], 2, 1); -+ shiftpos--; ++ 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; + -+ switch (shiftpos) -+ { -+ case 0: -+ break; ++ case 8: ++ case 9: ++ case 10: ++ case 11: ++ case 12: ++ case 13: ++ case 14: + -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ case 5: -+ case 6: -+ case 7: ++ 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; + -+ while (shiftpos--) -+ { -+ OUT_INSN (len, second_pat, operands); -+ dummy += set_rel (operands[0], 2, 1) - 1; -+ } ++ case 15: + -+ break; ++ 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; + -+ 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; ++ } + -+ 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); + } + -+ if (len) -+ *len = dummy; -+ return ""; -+ } -+ else -+ { -+ msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 2); -+ } -+ -+ return ""; ++ return ""; + +} + +const char * +msp430_emit_lshrsi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *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"; ++ 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]); ++ pattern = "clrc\n\trrc\t%B0\n\trrc\t%A0"; + -+ if (shiftpos < 8 && shiftpos) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ 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--; -+ } ++ int shiftpos = INTVAL (operands[2]); + -+ switch (shiftpos) -+ { -+ case 0: -+ break; ++ 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--; ++ } + -+ 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; -+ } ++ 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; ++ 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--; ++ } + -+ 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; ++ 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); ++ 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 ""; ++ return ""; +} + +const char * +msp430_emit_lshrdi3 (insn, operands, len) -+ rtx insn; -+ rtx operands[]; -+ int *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"; ++ 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"; ++ 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) ++ if (GET_CODE (operands[2]) == CONST_INT) + { -+ OUT_INSN (len, pattern, operands); -+ dummy += set_rel (operands[0], 2, 1); -+ shiftpos--; -+ } ++ int shiftpos = INTVAL (operands[2]); + -+ switch (shiftpos) -+ { -+ case 0: -+ break; ++ if (shiftpos < 16 && shiftpos) ++ { ++ OUT_INSN (len, pattern, operands); ++ dummy += set_rel (operands[0], 2, 1); ++ shiftpos--; ++ } + -+ 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--; -+ } ++ 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; ++ } + -+ 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; ++ 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--; ++ } + -+ 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--; ++ } + -+ 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; ++ 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--; ++ } + -+ default: -+ break; -+ } /* case */ ++ 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; + -+ if (len) -+ *len = dummy; -+ } -+ else -+ msp430_emit_shift_cnt (set_rel, pattern, insn, operands, len, 8); ++ 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 ""; ++ return ""; +} + +/* -+ * Multiplication helpers -+ * 1. As shifts, 2. the rest -+ */ ++* Multiplication helpers ++* 1. As shifts, 2. the rest ++*/ + +#define SOME_SHIFT_THRESHOLD_VAL 10 + +int +msp430_easy_mul (operands, sext) -+ rtx operands[]; -+ int 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++; -+ } ++ 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; + -+ return 0; -+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; ++ } + -+ ops = shift0 * (op0mode == SImode ? 2 : 1); -+ ops += shift1 + add1 + sub1; -+ if (op0mode != op1mode) -+ { -+ ops += (op0mode == SImode ? 2 : 1) * ((add1 || sub1) ? 2 : 1); -+ } ++ if (t0 + t1 * 3 == m) ++ { ++ add1 = 3; ++ goto done; ++ } + -+ if (ops > SOME_SHIFT_THRESHOLD_VAL) -+ return 0; ++ if (t0 - t1 * 3 == m) ++ { ++ sub1 = 3; ++ goto done; ++ } + -+ 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); -+ } ++ add1 = 0; ++ sub1 = 0; ++ shift1++; + -+ /* 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 (); -+ } ++ } ++ shift1 = 0; ++ shift0++; ++ } + -+ 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; -+ } ++ return 0; ++done: + -+ if (shift1 && (add1 || sub1)) -+ { -+ switch (op1mode) ++ ops = shift0 * (op0mode == SImode ? 2 : 1); ++ ops += shift1 + add1 + sub1; ++ if (op0mode != 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 (); ++ ops += (op0mode == SImode ? 2 : 1) * ((add1 || sub1) ? 2 : 1); + } -+ } -+ else if (shift1) -+ abort (); /* paranoia */ + -+ while (add1--) -+ { -+ insn = -+ gen_rtx_SET (VOIDmode, op0, gen_rtx_PLUS (GET_MODE (op0), op0, op1)); -+ emit_insn (insn); -+ } ++ if (ops > SOME_SHIFT_THRESHOLD_VAL) ++ return 0; + -+ while (sub1--) -+ { -+ insn = -+ gen_rtx_SET (VOIDmode, op0, -+ gen_rtx_MINUS (GET_MODE (op0), op0, op1)); -+ emit_insn (insn); -+ } ++ 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); ++ } + -+ if (sign) -+ { -+ switch (op0mode) ++ /* shift0 */ ++ switch (op0mode) + { + case QImode: -+ emit_insn (gen_negqi2 (op0, op0)); -+ break; ++ emit_insn (gen_ashlqi3 (op0, op0, GEN_INT (shift0))); ++ break; + case HImode: -+ emit_insn (gen_neghi2 (op0, op0)); -+ break; ++ emit_insn (gen_ashlhi3 (op0, op0, GEN_INT (shift0))); ++ break; + case SImode: -+ emit_insn (gen_negsi2 (op0, op0)); -+ break; ++ emit_insn (gen_ashlsi3 (op0, op0, GEN_INT (shift0))); ++ break; + case DImode: -+ emit_insn (gen_negdi2 (op0, op0)); -+ break; ++ emit_insn (gen_ashldi3 (op0, op0, GEN_INT (shift0))); ++ break; + default: -+ abort (); ++ 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; + } -+ } + -+ return 1; ++ 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)); \ ++ do{ \ ++ if(GET_MODE(x) == QImode) \ ++ emit_insn(gen_load_mpyq(x)); \ + else \ -+ emit_insn(gen_load_mpy(x)); \ -+}while(0) ++ emit_insn(gen_load_mpy(x)); \ ++ }while(0) + +#define LOAD_MPYS(x) \ -+do{ \ -+ if(GET_MODE(x) == QImode) \ -+ emit_insn(gen_load_mpysq(x)); \ ++ do{ \ ++ if(GET_MODE(x) == QImode) \ ++ emit_insn(gen_load_mpysq(x)); \ + else \ -+ emit_insn(gen_load_mpys(x)); \ -+}while(0) ++ emit_insn(gen_load_mpys(x)); \ ++ }while(0) + +#define LOAD_OP2(x) \ -+do{ \ -+ if(GET_MODE(x) == QImode) \ -+ emit_insn(gen_load_op2q(x)); \ ++ do{ \ ++ if(GET_MODE(x) == QImode) \ ++ emit_insn(gen_load_op2q(x)); \ + else \ -+ emit_insn(gen_load_op2(x)); \ -+}while(0) ++ emit_insn(gen_load_op2(x)); \ ++ }while(0) + +int +msp430_mul3_guard (operands, sext) -+ rtx operands[]; -+ int 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); -+ } ++ 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 (op0mode == QImode) ++ m_reslo = gen_lowpart (QImode, reslo_rtx); + -+ if (!MSP430_NOINT_HWMUL) -+ emit_insn (gen_reent_in ()); ++ 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])); -+ } ++ 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)); + -+ return 1; ++ 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 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; -+ } ++ 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); ++ m_mpy = gen_lowpart (QImode, mpy_rtx); ++ m_op2 = gen_lowpart (QImode, op2_rtx); + -+ if (!MSP430_NOINT_HWMUL) -+ emit_insn (gen_reent_in ()); ++ 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])); ++ /* 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]));*/ + -+ return 1; ++ //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[]; ++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 ()); ++ 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]); ++ 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])); ++ if (MSP430_NOINT_HWMUL) ++ { ++ emit_insn (gen_fetch_result_si_nint (operands[0])); ++ } ++ else ++ emit_insn (gen_fetch_result_si (operands[0])); + -+ return 1; ++ return 1; +} + + +int +msp430_umulhisi_guard (operands) -+ rtx 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; -+ } ++ 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 ()); ++ if (!MSP430_NOINT_HWMUL) ++ emit_insn (gen_reent_in ()); + -+ LOAD_MPY (operands[1]); -+ LOAD_OP2 (operands[2]); ++ 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])); ++ 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; + -+ return 1; ++ 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; +} + -+ -+/* something like 'push x(r1)' or 'push @r1' */ -+int -+self_push (x) -+ rtx x; ++const char * msp430_emit_call (rtx operands[]) +{ -+ rtx c; -+ rtx r; ++ rtx x = operands[0]; ++ rtx c; ++ rtx r; + -+ if (GET_CODE (x) != MEM) -+ return 0; ++ if (GET_CODE (x) == MEM) ++ { ++ c = XEXP (x, 0); + -+ c = XEXP (x, 0); ++ if (REG_P (c) && REGNO (c) == 1) ++ { ++ OUT_INSN (NULL, "call\t2(%E0)", operands); ++ return ""; ++ } + -+ 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) ++ { ++ OUT_INSN (NULL, "call\t2+%A0", operands); ++ return ""; ++ } ++ } ++ } + -+ if (GET_CODE (c) == PLUS) -+ { -+ r = XEXP (c, 0); -+ if (REG_P (r) && REGNO (r) == 1) -+ return 1; -+ } -+ return 0; ++ 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 */ -+ ++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; ++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; ++ int sp = self_push (operands[0]); ++ int dummy = 0; + -+ if (GET_CODE (operands[0]) == CONST_INT) ++ 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 + { -+ int cval = INTVAL (operands[0]); -+ int x = (cval) & 0x0fffful; -+ if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff) -+ dummy--; ++ 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--; + } -+ else if (GET_CODE (operands[0]) == REG) -+ dummy--; -+ else if (GET_CODE (operands[0]) == MEM && REG_P (XEXP (operands[0], 0))) -+ dummy--; -+ } + -+ return ""; ++ return ""; +} + +const char * +msp430_pushhi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *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; ++ int sp = self_push (operands[0]); ++ int dummy = 0; + -+ if (GET_CODE (operands[0]) == CONST_INT) ++ 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 + { -+ int cval = INTVAL (operands[0]); -+ int x = (cval) & 0x0fffful; ++ 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 (cval == 99999999) ++ { ++ if (len) ++ *len = 3; ++ return ""; ++ } + -+ if (x == 0 || x == 1 || x == 2 || x == 4 || x == 8 || x == 0xffff) -+ dummy--; ++ 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--; + } -+ 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 ""; ++ if (len) ++ *len = dummy; ++ return ""; +} + +const char * +msp430_pushsisf (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *len; +{ -+ int sp = self_push (operands[0]); -+ int dummy = 0; ++ 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--; ++ 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; + } -+ } -+ else -+ { -+ OUT_INSN (len, "push\t2+%B0", operands); -+ OUT_INSN (len, "push\t2+%B0", operands); -+ dummy = 4; -+ } + -+ if (len) -+ *len = dummy; ++ if (len) ++ *len = dummy; + -+ return ""; ++ return ""; +} + + +const char * +msp430_pushdi (insn, operands, len) -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx operands[]; -+ int *len; ++rtx insn ATTRIBUTE_UNUSED; ++rtx operands[]; ++int *len; +{ -+ int sp = self_push (operands[0]); -+ int dummy = 0; ++ 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--; ++ 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; + } -+ } -+ 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; ++ if (len) ++ *len = dummy; + -+ return ""; ++ return ""; +} + -+int -+dead_or_set_in_peep (which, insn, x) -+ int which; -+ rtx insn ATTRIBUTE_UNUSED; -+ rtx x; ++int dead_or_set_in_peep (int which, rtx insn ATTRIBUTE_UNUSED, rtx x) +{ -+ rtx r; -+ rtx next; ++ extern int peep2_current_count; ++ 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 (which > peep2_current_count) ++ return 0; + -+ if (!r) -+ 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)); + -+ r = XEXP (r, 0); -+ return GET_MODE (r) == GET_MODE (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"); ++ 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; ++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); ++ 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; ++//---------------------------------------------------------------------------------------------------------------------------------------------- ++ ++static bool ++msp430_rtx_costs (rtx x, int code, int outer_code, int *total) +{ -+ return_issued = 1; -+ if (msp430_empty_epilogue () == 1) -+ return "ret"; ++ 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; + -+ return "reti"; ++ *total = cst; ++ if (cst) ++ return true; ++ return false; +} + +int -+three_operands_msp430 (x, mode) -+ rtx x; -+ enum machine_mode mode; ++default_rtx_costs (rtx X ATTRIBUTE_UNUSED, enum rtx_code code, enum rtx_code outer_code ATTRIBUTE_UNUSED) +{ -+ enum rtx_code code = GET_CODE (x); -+ if (GET_MODE (x) != mode) -+ return 0; ++ int cost = 4; + -+ return (code == PLUS -+ || code == MINUS || code == AND || code == IOR || code == XOR); ++ 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; +} + -+int -+equality_operator (op, mode) -+ register rtx op; -+ enum machine_mode mode; ++ ++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) +{ -+ return ((mode == VOIDmode || GET_MODE (op) == mode) -+ && (GET_CODE (op) == EQ || GET_CODE (op) == NE)); ++ 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; +} + -+/* 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; ++msp430_address_costs (rtx x) +{ -+ return comparison_operator (op, mode) && !equality_operator (op, mode); ++ 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); +} -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 @@ ++ ++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 Free Software Foundation, Inc. ++ Copyright (C) 2001-2009 Free Software Foundation, Inc. + Contributed by Dmitry Diky + +This file is part of GNU CC. @@ -11309,88 +12350,26 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +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 +*/ + -+extern int target_flags; ++#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) + -+#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 int target_flags; + +extern const char *msp430_endup; +extern const char *msp430_init_stack; @@ -11403,17 +12382,12 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +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 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 @@ -11454,9 +12428,12 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +/* 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 TARGET_STRICT_ALIGN ++#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. */ @@ -11473,14 +12450,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -11553,12 +12522,14 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + characters. This is used in `cpp', which cannot make use of + `WCHAR_TYPE'. */ + -+#define FIRST_PSEUDO_REGISTER 16 ++#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*/\ @@ -11568,6 +12539,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -11597,6 +12569,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -11608,13 +12581,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -11740,8 +12706,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + MODE2)' must be zero. */ + + -+ -+ +enum reg_class { + NO_REGS, + PC_REG, /* r0 - PC */ @@ -11797,10 +12761,10 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + {0x00000004ul}, /* r2 */ \ + {0x00000008ul}, /* r3 */ \ + {0x0000000cul}, /* r2,r3 */ \ -+ {0x0000fff2ul}, /* r4 - r15,r1 */ \ -+ {0x0000fff2ul}, /* r4 - r15,r1 */ \ -+ {0x0000fff0ul}, /* r4 - r15 */ \ -+ {0x0000fffful} /* ALL_REGS */ \ ++ {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 @@ -12112,7 +13076,10 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + +/* This is an undocumented variable which describes + how GCC will push a data */ -+#define STACK_PUSH_CODE POST_DEC ++#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 @@ -12173,7 +13140,10 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 ++/* 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 @@ -12222,8 +13192,9 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + information. */ + +#define ELIMINABLE_REGS { \ ++ {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ ++ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + {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 @@ -12252,6 +13223,11 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -12395,12 +13371,32 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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) ++ ++/* ++ 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 @@ -12538,27 +13534,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 +*/ @@ -12816,7 +13791,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + is a suitable definition for this macro on machines where anything + `CONSTANT_P' is valid. */ + -+#define CONST_COSTS(x,CODE,OUTER_CODE) \ ++/*#define CONST_COSTS(x,CODE,OUTER_CODE) \ + case CONST_INT: \ + if (OUTER_CODE == PLUS \ + || OUTER_CODE == IOR \ @@ -12837,30 +13812,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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; \ -+} ++ return 4;*/ + +/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. + This can be used, for example, to indicate how costly a multiply @@ -12872,49 +13824,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 : \ @@ -12949,7 +13858,12 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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. + @@ -13014,27 +13928,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +/* 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. @@ -13047,11 +13940,12 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + +#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section + -+#define EXTRA_SECTIONS in_bootloader, in_infomem ++/*#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 \ @@ -13079,7 +13973,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -13158,12 +14052,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -13171,38 +14059,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + `-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 @@ -13222,36 +14078,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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)' @@ -13311,7 +14137,11 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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. + @@ -13355,6 +14185,38 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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. */ @@ -13362,76 +14224,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + ((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 @@ -13443,10 +14235,18 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +*/ + + -+ +#define ASM_OUTPUT_LABEL(STREAM, NAME) \ +{ \ -+ assemble_name (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 @@ -13491,6 +14291,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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) \ @@ -13499,27 +14300,22 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + static int labelno; \ + labelno++; \ + ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ -+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "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"); \ ++ 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 { \ ++ 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); \ @@ -13529,21 +14325,14 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ ++ fprintf (FILE, ",%ld\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 { \ @@ -13559,14 +14348,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 \ @@ -13605,24 +14386,8 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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) ++#define GLOBAL_ASM_OP ".global\t" + -+/* 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 \ + { \ @@ -13674,8 +14439,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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. + @@ -13748,7 +14511,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + +#define REGISTER_NAMES { \ + "r0","r1","r2","r3","r4","r5","r6","r7", \ -+ "r8","r9","r10","r11","r12","r13","r14","r15" \ ++ "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 @@ -13933,18 +14696,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +/* 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; + + @@ -14009,16 +14760,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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) @@ -14048,36 +14789,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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 @@ -14129,11 +14840,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + 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} \ @@ -14177,6 +14883,9 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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__} \ @@ -14222,9 +14931,16 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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__} \ @@ -14234,6 +14950,9 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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} \ @@ -14241,8 +14960,32 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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} \ ++%{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 @@ -14251,41 +14994,17 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + + 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'. ++#define CC1_SPEC "%{profile:-p}" + -+ Do not define this macro unless you need to override the default -+ definition. */ ++#define CC1PLUS_SPEC "-fno-rtti -fno-exceptions" + -+#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 "" ++#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 @@ -14345,6 +15064,9 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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 } \ @@ -14390,9 +15112,16 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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 } \ @@ -14408,33 +15137,38 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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'. ++%{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 } \ ++" + -+ 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 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 @@ -14451,9 +15185,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + + 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} \ @@ -14495,12 +15226,20 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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} \ @@ -14535,9 +15274,16 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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} \ @@ -14547,13 +15293,35 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +%{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=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} \ ++" + + + @@ -14612,9 +15380,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ + +#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) + @@ -14636,45 +15401,64 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.h gcc-3.2.3/gcc/config/ +#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 PREFERRED_DEBUGGING_TYPE DWARF2_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" ++/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ ++ ++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; ++}; + -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 @@ ++#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 ++;; GCC 4.x port by Ivan Shcherbakov + -+;; This file is part of GCC. ++;; 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 @@ -14691,6 +15475,8 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config +;; 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. @@ -14718,6 +15504,19 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config +;; 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. + @@ -14765,21 +15564,48 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config +[(set_attr "length" "2")]) + +(define_insn "*pushqi" -+ [(set (mem:QI (post_dec (reg:HI 1))) ++ [(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 (mem:HI (post_dec (reg:HI 1))) -+ (match_operand:HI 0 "general_operand" "rim"))] ++ [(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 (mem:SI (post_dec (reg:HI 1))) ++ [(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);" @@ -14787,7 +15613,8 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + + +(define_insn "*pushdi" -+ [(set (mem:DI (post_dec (reg:HI 1))) ++ [(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);" @@ -14795,12 +15622,64 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + + +(define_insn "*pushsf" -+ [(set (mem:SF (post_dec (reg:HI 1))) ++ [(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" "") @@ -14943,7 +15822,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (label_ref (match_operand 0 "" "")) + (pc)))] +"" -+"* return msp430_cbranch(insn, operands, NULL);" ++"* return msp430_cbranch(insn, operands, NULL, 0);" + [(set_attr "length" "9") + (set_attr "cc" "cbranch")]) + @@ -14957,7 +15836,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (label_ref (match_operand 0 "" "")) + (pc)))] +"" -+"* return msp430_cbranch(insn, operands, NULL);" ++"* return msp430_cbranch(insn, operands, NULL, 0);" + [(set_attr "length" "9") + (set_attr "cc" "cbranch")]) + @@ -14970,7 +15849,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (label_ref (match_operand 0 "" "")) + (pc)))] +"" -+"* return msp430_cbranch(insn, operands, NULL);" ++"* return msp430_cbranch(insn, operands, NULL, 0);" +[(set_attr "length" "9") + (set_attr "cc" "cbranch")]) + @@ -14984,7 +15863,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (pc))) + (clobber (match_dup 2))])] +"" -+"* return msp430_cbranch(insn, operands, NULL);" ++"* return msp430_cbranch(insn, operands, NULL, 0);" +[(set_attr "length" "9") + (set_attr "cc" "cbranch")]) + @@ -14997,7 +15876,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (label_ref (match_operand 0 "" "")) + (pc)))] +"" -+"* return msp430_cbranch(insn, operands, NULL);" ++"* return msp430_cbranch(insn, operands, NULL, 1);" +[(set_attr "length" "9") +(set_attr "cc" "cbranch")]) + @@ -15026,7 +15905,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + [(call (mem:HI (match_operand:HI 0 "general_operand" "r,P,mi")) + (match_operand:HI 1 "general_operand" "X,X,X"))] +"" -+"call\\t%0" ++"* return msp430_emit_call(operands);" +[ (set_attr "length" "1,1,2") + (set_attr "cc" "clobber")]) + @@ -15610,8 +16489,8 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + operands[5] = addr0; + operands[6] = addr1; + -+ operands[0] = gen_rtx (MEM, BLKmode, addr0); -+ operands[1] = gen_rtx (MEM, BLKmode, addr1); ++ operands[0] = gen_rtx_MEM (BLKmode, addr0); ++ operands[1] = gen_rtx_MEM (BLKmode, addr1); + + if(INTVAL (operands[2]) <= 10 && !(INTVAL(operands[3])&1)) + { @@ -15621,14 +16500,14 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + + while(y--) + { -+ rtx dest = gen_rtx (MEM, HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(i))); ++ 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))); ++ rtx real_dst = gen_rtx_MEM (HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(x-1))); + emit_insn(gen_movstrqi5(real_dst,addr1)); + } + DONE; @@ -15640,7 +16519,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + + while(x--) + { -+ rtx dst = gen_rtx (MEM, HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(i))); ++ rtx dst = gen_rtx_MEM (HImode, gen_rtx_PLUS(HImode, addr0,GEN_INT(i))); + emit_insn(gen_movstrqi5(dst,addr1)); + i++; + } @@ -15721,7 +16600,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + operands[3] = operands[1]; + addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); + operands[4] = addr0; -+ operands[0] = gen_rtx (MEM, BLKmode, addr0); ++ operands[0] = gen_rtx_MEM (BLKmode, addr0); +}") + + @@ -15758,7 +16637,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + 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[1] = gen_rtx_MEM (BLKmode, addr); + operands[5] = addr; + operands[4] = gen_reg_rtx (HImode); + @@ -15825,7 +16704,7 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + [(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") @@ -17818,17 +18697,6 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config +;; +;; + -+;; 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 "" "")))] @@ -17844,6 +18712,16 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + (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" ""))] @@ -17966,6 +18844,32 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config + [(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; @@ -18679,383 +19583,354 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/msp430.md gcc-3.2.3/gcc/config +;; 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 -+ -+ 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 )); ++ [(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))] ++"") + -+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)); + ++;; ============================================================= ++;; 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)))] ++"") + -+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)); ++(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)))] ++"") + -+extern int emit_indexed_arith PARAMS ((rtx insn, rtx operands[], int, const char *, int)); ++(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)))] ++"") + -+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)); ++(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)))] ++"") + -+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)); ++;; Enable Interrupts ++(define_insn "enable_interrupt" ++ [(unspec [(const_int 0)] UNSPEC_EINT)] ++ "" ++ "eint" ++ [(set_attr "length" "1") ++ (set_attr "cc" "none") ++ ]) + -+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)); ++;; Disable Interrupts ++(define_insn "disable_interrupt" ++ [(unspec [(const_int 0)] UNSPEC_DINT)] ++ "" ++ "dint" ++ [(set_attr "length" "1") ++ (set_attr "cc" "none") ++ ]) + + -+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)); ++;; 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")]) + -+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)); ++(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")]) + -+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)); ++(define_insn "return_from_naked_epilogue" ++ [(return)] ++ "(reload_completed ++ && cfun->machine ++ && cfun->machine->is_naked)" ++ "" ++ [(set_attr "cc" "none") ++ (set_attr "length" "0")]) + -+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)); ++(define_expand "prologue" ++ [(const_int 0)] ++ "" ++ " ++ { ++ expand_prologue (); ++ DONE; ++ }") + -+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)); ++(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. + -+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)); ++;; This file is part of GCC. + -+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)); ++;; 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. + -+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)); ++;; 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. + -+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)); ++;; 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. + -+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)); ++;; 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)); ++}) + -+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)); ++(define_special_predicate "inequality_operator" ++ (match_code "ge,gt,le,lt,geu,gtu,leu,ltu") ++{ ++ return comparison_operator (op, mode) && !equality_operator (op, mode); ++}) + -+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)); ++(define_predicate "nonimmediate_operand_msp430" ++ (match_code "reg,subreg,mem") ++{ ++ int save_volatile_ok = volatile_ok; ++ int niop = 0; + -+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 [] )); ++ if (!TARGET_NVWA) ++ volatile_ok = 1; ++ niop = nonimmediate_operand (op, mode); ++ volatile_ok = save_volatile_ok; + ++ return niop; ++}) + -+#endif /* RTX_CODE */ ++(define_predicate "memory_operand_msp430" ++ (match_code "subreg,mem") ++{ ++ int save_volatile_ok = volatile_ok; ++ int mop = 0; + -+#ifdef HAVE_MACHINE_MODES -+extern int class_max_nregs PARAMS ((enum reg_class class, -+ enum machine_mode mode)); -+#endif /* HAVE_MACHINE_MODES */ ++ if (!TARGET_NVWA) ++ volatile_ok = 1; ++ mop = memory_operand (op, mode); ++ volatile_ok = save_volatile_ok; ++ return mop; ++}) + -+#ifdef REAL_VALUE_TYPE ++(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; + -+extern void asm_output_float PARAMS ((FILE *file, REAL_VALUE_TYPE n)); ++ if (!TARGET_NVWA) ++ volatile_ok = 1; ++ gop = general_operand (op, mode); ++ volatile_ok = save_volatile_ok; ++ return gop; ++}) + -+#endif ++(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); ++}) + -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 @@ ++;; 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 @@ -19141,8 +20016,11 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/t-msp430 gcc-3.2.3/gcc/config/ + 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 \ @@ -19158,13 +20036,28 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/t-msp430 gcc-3.2.3/gcc/config/ + 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?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 = + @@ -19172,120 +20065,28 @@ diff -urN -x CVS gcc-3.2.3.orig/gcc/config/msp430/t-msp430 gcc-3.2.3/gcc/config/ +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 ++ ++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" -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. -+------------------------------------------------------------------- -- 2.39.2