public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RE: CR16 Port addition
@ 2011-04-08 13:26 Sumanth Gundapaneni
  2011-04-08 14:56 ` Joseph S. Myers
  0 siblings, 1 reply; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-04-08 13:26 UTC (permalink / raw)
  To: gcc-patches, Joseph Myers, rth; +Cc: Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 6313 bytes --]

Hi Richard and Joseph,

Thanks for your detailed review and valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications 
as suggested by Richard in his previous mail.

For your kind information, I am providing the recent posts regarding 
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html  

Please review the patch and let me know if there should be any 
modifications in it.

Richard, please go through my explanation for your comments.

>> +targetm = TARGET_INITIALIZER;
>I find it much cleaner to move the target initializer to the end 
I moved this to the end of the file as advised.

>> +  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS \
>Trailing \.  Left over from macro-to-function conversion?
The trailing \ has been removed in the current patch.

>> + flag_split_wide_types = 0;
>I would really like to know more about this.
This particular flag causes the compiler to generate an ICE in 
gen_rtx_SUBREG. The subreg rtx with offset byte "2" is the reason 
for the issue. Though I disabled this flag I am hitting this ICE in 
dejagnu regression for a specific test case named 
"gcc.c-torture/compile/ptr-conv-1.c". Hacking at backend specifically 
in predicates doesn't seem to solve my problem. I believe this issue 
is due to the variable width registers in CR16 port 
(r0-r11 are 16-bit wide register, r12-r15 are 32-bit wide registers). 
Any hints on solving this problem would be much appreciated. 

>> +    flag_gcse = 0;
>Why?  It works for other targets.
This is probably related to SUBREG issue mentioned above.

>> +cr16_compute_frame (void)
>I would be very much happier if these functions did not store their 
>results into
I defined a structure "cr16_frame_info" to store these variables.

>> +if ((mode == Pmode) && (regno == 11))
>Is there a symbolic name for 11?
There is no symbolic name for register number 11. 
We will add a definition for readability.

>> +  last_parm_in_reg = 0;
>Using a global here is definitely wrong.  
I defined this variable in CUMULATIVE_ARGS structure as per your suggestion.

>> +      if ((next_param == (tree) 0) && (TREE_VALUE (param) !=
>s/(tree) 0/NULL_TREE/g
I am not sure what needs to be modified here.

>I don't see a constraints.md file?
I added the constraints.md file and deleted the traditional macros.

>> +  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")
>The constraint here is almost certainly wrong.  It should be only "=Z".
This has been modified.

 
>> +(define_predicate "reg_operand"
>This is wrong.  This issue should be handled with 
>CANNOT_CHANGE_MODE_CLASS
This predicate definition has been deleted and changes have been made in patterns 
to avoid common subreg issues.

>> +(define_expand "adddi3"
>You should trust the predicates to do the right thing. 
This pattern has been modified and defined in a normal manner. 
Please verify the same.


>> +	(plus:SI (mult:SI (sz_xtnd:SI (match_operand:HI 1 "reg_operand" 
>> +"%r"))
>% should be used only when the constraints of the two operands are different.
This is rectified.

>> +  [(set (match_operand:HI 0 "reg_operand" "=r,=r")
>Extra = in operand 0.
This is rectified.

>> +(define_expand "andhi3"
>What is this for?  Disallowing subregs of pseudos?!?
This pattern has been adjusted correctly. Please verify the same.


>> +  "andd\t%T2,%T0\;andd\t%U2,%U0"
>You'd be better off without this, and let the compiler generate it 
>itself from two SImode ands.
This is handled with rtx. Please verify the same.


>> +(define_insn "*mov<mode>_double"
>This whole pattern has got to get cleaned up.  
I am planning to solve this once I am finished with subreg issues.

>> +(define_insn "*cmp<mode>_insn"
>I'm not sure I understand the logic here.  If you have a cbranch insn, 
>which you never split
This compare pattern is for scond instruction which you can find 
in the updated patch.

>> +(define_insn "indirect_jump_return"
>Extra parallel.  It's implicit in define_insn.
>> +(define_expand "call"
>These can be trivially merged.
Yes, I plan to work on them after fixing the subreg issues. 

>> +;;  Nop
>Nop really needs to output something.  
This has been fixed as suggested.

>> +;; Shared FLAT
> Huh?
These patterns are to support the target option MID_SHARED_LIBRARY.
I will enable this target option soon.  
 

gcc/ChangeLog:
--------------
2011-04-08	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/constraints.md: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-dw2-cr16.c: New file.
	* config/cr16/unwind-dw2.h: New file. 

libgcc/ChangeLog:
-----------------
2011-04-08  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
		
libstdc++-v3/ChangeLog:
-----------------------
2011-04-08  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	*configure: Add National Semiconductor CR16 target (cr16-*-*).		
	*crossconfig.m4 : Add support for National Semiconductor CR16 target.

ChangeLog:
----------
2011-04-08  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* configure.ac: Add National Semiconductor CR16 target.
	* configure: Regenerate
   
Thanks in advance,
Sumanth G,
PUNE (India).


[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 227465 bytes --]

diff -uprN -x'*.orig' -x'*.rej' orig/configure mod/configure
--- orig/configure	2011-03-16 23:57:36.000000000 +0530
+++ mod/configure	2011-04-08 16:43:49.000000000 +0530
@@ -3279,7 +3279,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
     ;;
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
diff -uprN -x'*.orig' -x'*.rej' orig/configure.ac mod/configure.ac
--- orig/configure.ac	2011-03-16 23:57:36.000000000 +0530
+++ mod/configure.ac	2011-04-08 16:42:27.000000000 +0530
@@ -725,7 +725,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
     ;;
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/constraints.md mod/gcc/config/cr16/constraints.md
--- orig/gcc/config/cr16/constraints.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/constraints.md	2011-04-08 17:01:57.000000000 +0530
@@ -0,0 +1,86 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;; Constraints
+;; Register constraints
+(define_register_constraint "b" "NOSP_REGS"
+  "@no sp registers")
+
+(define_register_constraint "c" "SHORT_REGS"
+  "@short registers")
+
+(define_register_constraint "d" "LONG_REGS"
+  "@long registers")
+
+;; Integer constraints.
+(define_constraint "I"
+  "A signed 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "J"
+  "A signed 5-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)")))
+
+(define_constraint "K"
+  "A signed 6-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)")))
+
+(define_constraint "L"
+  "A unsigned 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "M"
+  "A unsigned and customized  4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) || (ival != 11)))  ")))
+
+(define_constraint "N"
+  "A signed 16-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -32768, 32767)")))
+
+(define_constraint "O"
+  "A unsigned 20-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 1048575)")))
+
+(define_constraint "P"
+  "A signed 32-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -2147483648, 2147483647)")))
+
+(define_constraint "Q"
+  "A shift QI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 7)")))
+
+(define_constraint "R"
+  "A shift HI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 15)")))
+
+(define_constraint "S"
+  "A shift SI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 31)")))
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.c mod/gcc/config/cr16/cr16.c
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-04-08 17:50:38.000000000 +0530
@@ -0,0 +1,2309 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Structure for stack computations.  */
+
+/* variable definitions in the struture
+   args_size             Number of bytes saved on the stack for local 
+			 variables
+
+   reg_size		 Number of bytes saved on the stack for 
+			 non-scratch registers
+
+   total_size 		 The sum of 2 sizes: locals vars and padding byte 
+			 for saving the registers. Used in expand_prologue() 
+			 and expand_epilogue()
+
+   last_reg_to_save      Will hold the number of the last register the 
+			 prologue saves, -1 if no register is saved
+
+   save_regs[16]	 Each object in the array is a register number. 
+			 Mark 1 for registers that need to be saved
+
+   num_regs		 Number of registers saved
+
+   initialized		 Non-zero if frame size already calculated, not 
+			 used yet
+
+   function_makes_calls  Does the function make calls ? not used yet
+  */
+
+struct cr16_frame_info
+{
+  unsigned long var_size;
+  unsigned long args_size;
+  unsigned int  reg_size;
+  unsigned long total_size;
+  long          last_reg_to_save;
+  long          save_regs[FIRST_PSEUDO_REGISTER];
+  int           num_regs;
+  int           initialized;
+  int           function_makes_calls;
+};
+
+/* Current frame information calculated by cr16_compute_frame_size.  */
+static struct cr16_frame_info current_frame_info;
+
+/* Static Variables.  */
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* Nonzero if -mshared-library-id was given.  */
+static int cr16_lib_id_given;
+
+/* Global Variables.  */
+
+/* Specify the identification number of the library being built.  */
+const char *cr16_library_id_string = "__current_shared_library_r12_offset_";
+
+/* Table of machine attributes.  */
+const struct attribute_spec cr16_attribute_table[];
+
+/* TARGETM Function Prototypes.  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
+static int cr16_address_cost (rtx);
+static bool cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+
+/* Stack layout and calling conventions.  */
+
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+
+const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  {"interrupt", 0, 0, false, true, true, NULL},
+  {NULL, 0, 0, false, false, false, NULL}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+		       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, CR16_STRUCT_VALUE_REGNUM);
+}
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS 
+       || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, int size)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* To avoid gen_rtx_SUBREG ICE. SI gets splitted to two HIs where 
+     validate_subreg is invalid with the second HI having offset 2
+     .Offset applicable to big endian machines.  */
+  flag_split_wide_types = 0;
+
+  /* If EH, disable optimization GCSE.  */
+  if (flag_exceptions)
+    flag_gcse = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture.");
+	}
+      else
+	error ("Invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+  /* Library identification.  */
+  if (cr16_lib_id_given && !TARGET_ID_SHARED_LIBRARY)
+    error ("-mshared-library-id= specified without -mid-shared-library");
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    flag_pic = FAR_PIC;
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array current_frame_info.save_regs and the variable 
+   current_frame_info.reg_size. The index of current_frame_info.save_regs 
+   is numbers of register, each will get 1 if we need to save it in the 
+   current function, 0 if not. current_frame_info.reg_size is the total sum 
+   of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  current_frame_info.last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  current_frame_info.reg_size = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (!TARGET_ID_SHARED_LIBRARY &&
+      FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (TARGET_ID_SHARED_LIBRARY && PIC_OFFSET_TABLE_REGNUM == regno)
+	{
+	  current_frame_info.save_regs[regno] = 1;
+	  continue;
+	}
+      else if (fixed_regs[regno])
+	{
+	  current_frame_info.save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    current_frame_info.save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    current_frame_info.save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  current_frame_info.save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (current_frame_info.save_regs[regno] == 1)
+      {
+	current_frame_info.last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
+	else
+	  current_frame_info.reg_size += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  current_frame_info.var_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = current_frame_info.var_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  current_frame_info.var_size += padding_locals;
+  current_frame_info.total_size = current_frame_info.var_size 
+			   + (ACCUMULATE_OUTGOING_ARGS
+			    ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use current_frame_info.reg_size.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use current_frame_info.var_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size 
+	    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
+        return 0;
+ 
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  if ((TARGET_INT32)
+      && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
+     return 0;
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  cum->last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!cum->last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/*Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+NOTE: @BRO is added using unspec:BRO
+NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+  rtx pic_ref;
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	  pic_ref = reg;
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	  pic_ref = reg;
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of got_operand.  */
+rtx
+got_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_got_addr (reg, orig));
+  return reg;
+}
+
+/* Implementation of bro_operand.  */
+rtx
+bro_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_bro_addr (reg, orig));
+  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+  return reg;
+}
+
+/* Implementation of GO_IF_LEGITIMATE_ADDRESS.  */
+int
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, int strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "Invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "Absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "Register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "Register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "Index + Register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\nCR16 Address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /*
+     CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9
+  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+
+int
+cr16_memory_move_cost (enum machine_mode mode,
+		       enum reg_class class ATTRIBUTE_UNUSED,
+		       int in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (class, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "UNSPEC!!");
+	  switch (XINT (x, 1))
+	    {
+	    case UNSPEC_LIBRARY_OFFSET:
+	      inform (input_location, "UNSPEC_LIBRARY_OFFSET!!!");
+	      fprintf (file, "%s", cr16_library_id_string);
+	      return;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "UNSPEC 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+void
+cr16_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
+			   rtx tmp_reg, unsigned HOST_WIDE_INT * offset_p)
+{
+  rtx addr, mem;
+  unsigned HOST_WIDE_INT offset = *offset_p;
+
+  /* Load.  */
+  addr = plus_constant (src, offset);
+  mem = adjust_automodify_address (srcbase, SImode, addr, offset);
+  emit_move_insn (tmp_reg, mem);
+
+  /* Store.  */
+  addr = plus_constant (dst, offset);
+  mem = adjust_automodify_address (dstbase, SImode, addr, offset);
+  emit_move_insn (mem, tmp_reg);
+
+  *offset_p = offset + 4;
+}
+
+int
+cr16_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
+{
+  unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
+  HOST_WIDE_INT align = 0;
+
+  rtx src, dst;
+  rtx tmp_reg;
+
+  if (GET_CODE (align_exp) == CONST_INT)
+    {				/* Only if aligned.  */
+      align = INTVAL (align_exp);
+      if (align & 3)
+	return 0;
+    }
+
+  if (GET_CODE (count_exp) == CONST_INT)
+    {				/* No more than 16 SImode moves.  */
+      count = INTVAL (count_exp);
+      if (count > 64)
+	return 0;
+    }
+
+  tmp_reg = gen_reg_rtx (SImode);
+
+  /* Create psrs for the src and dest pointers.  */
+  dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
+  if (dst != XEXP (dstbase, 0))
+    dstbase = replace_equiv_address_nv (dstbase, dst);
+  src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
+  if (src != XEXP (srcbase, 0))
+    srcbase = replace_equiv_address_nv (srcbase, src);
+
+  offset = 0;
+
+  /* Emit SImode moves.  */
+  si_moves = count >> 2;
+  for (i = 0; i < si_moves; i++)
+    cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
+
+  /* Special cases.  */
+  if (count & 3)
+    {
+      offset = count - 4;
+      cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg,
+				 &offset);
+    }
+
+  gcc_assert (offset == count);
+
+  return 1;
+}
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of current_frame_info.save_regs[], going from 0 until 
+     current_frame_info.last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= current_frame_info.last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) 
+	     && (i <= current_frame_info.last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!current_frame_info.save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* pop.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
+    {
+      if (current_frame_info.save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = current_frame_info.last_reg_to_save + 1;
+  to = current_frame_info.last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = current_frame_info.last_reg_to_save; i >= 0;)
+    {
+      if (!current_frame_info.save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && current_frame_info.save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+					REG_NOTES (insn));
+}
+
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
+    return;
+
+  if (current_frame_info.last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue
+			(GEN_INT (current_frame_info.reg_size)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    emit_insn (gen_unspec_library_offset ());
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+  rtx return_reg;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
+			&& (current_frame_info.reg_size 
+			 == CR16_UNITS_PER_DWORD));
+
+  /* Return register.  */
+  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);
+
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (current_frame_info.last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_indirect_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static bool
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return
+	  || cfun->has_nonlocal_label || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* Implement TARGET_HANDLE_OPTION.  */
+static bool
+cr16_handle_option (size_t code, const char *arg, int value)
+{
+  switch (code)
+    {
+    case OPT_mshared_library_id_:
+      if (value > MAX_LIBRARY_ID)
+	error ("-mshared-library-id=%s is not between 0"
+	       " and %d", arg, MAX_LIBRARY_ID);
+      cr16_lib_id_given = 1;
+      return true;
+
+    default:
+      return true;
+    }
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION cr16_handle_option
+
+void
+notice_update_cc (exp)
+     rtx exp;
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+rtx
+gen_compare_reg (code, x, y)
+     enum rtx_code code;
+     rtx x, y;
+{
+  enum machine_mode mode;
+
+  mode = GET_MODE (x);
+
+  /* For floating point compare insns, a call is generated so don't
+     do anything here.  */
+
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return cc0_rtx;
+
+  emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
+			  gen_rtx_COMPARE (VOIDmode,
+					   force_reg (mode, x),
+					   force_reg (mode, y))));
+  return cc0_rtx;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
+
+/* Helper function for md file. This function is used to emit arithmetic 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_add_sub_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi0_op[2] ;
+  rtx hi1_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
+  hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
+  hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
+
+  if (num == 0)
+    {
+        output_asm_insn ("addd\t%1, %0", lo_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("subd\t%1, %0", lo_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else
+    return "";
+
+}
+
+
+/* Helper function for md file. This function is used to emit logical 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_logical_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
+  if (num == 0)
+    {
+        output_asm_insn ("andd\t%1, %0", lo_op) ;
+        output_asm_insn ("andd\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("ord\t%1, %0", lo_op) ;
+        output_asm_insn ("ord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 2)
+    {
+        output_asm_insn ("xord\t%1, %0", lo_op) ;
+        output_asm_insn ("xord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else
+    return "";
+}
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.h mod/gcc/config/cr16/cr16.h
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-04-08 17:19:47.000000000 +0530
@@ -0,0 +1,662 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES         	\
+  {                                 	\
+    GENERAL_REGS, LIM_REG_CLASSES  	\
+  }
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+    if (TARGET_ID_SHARED_LIBRARY)          \
+      builtin_define ("__ID_SHARED_LIB__"); \
+  }                                        \
+while (0)
+#endif
+
+#define TARGET_VERSION fputs (" (CR16/ELF)", stderr);
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+/* Maximum number of library ids we permit.  */
+#define MAX_LIBRARY_ID 255
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+   values must be in memory.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Order of allocation of registers. Need to experiment on it
+   to for effective code density.  */
+#define REG_ALLOC_ORDER {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+  (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Macros to check the range of integers . These macros were used across
+   the port, majorly in constraints.md, predicates.md files. */
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+#define IN_RANGE_P(VALUE, LOW, HIGH)                            \
+  ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))           \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+#define IN_RAN(VALUE, LOW, HIGH)                             \
+  (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))       \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0)
+
+/* This check is for sbit/cbit instruction.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+  int last_parm_in_reg;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Returning function value.  */
+
+/* On the CR16, the return value is in R0.  */
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+    gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
+
+#define LIBCALL_VALUE(MODE)     gen_rtx_REG (MODE, 0)
+
+#define FUNCTION_VALUE_REGNO_P(N)   ((N) == 0)
+
+#define CR16_STRUCT_VALUE_REGNUM  0
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("Profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 1))       \
+    goto LABEL;                                   \
+}
+#else /* not REG_OK_STRICT.  */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 0))       \
+    goto LABEL;                                   \
+}
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P.
+   In cr16c treat legitimize float constant as an immediate operand.  */
+#define LEGITIMATE_CONSTANT_P(X)  1
+
+/* Relative costs of operations.  */
+#define MEMORY_MOVE_COST(MODE, CLASS, IN) \
+  cr16_memory_move_cost (MODE, CLASS, IN)
+
+/* Moving to processor register flushes pipeline - thus asymmetric.  */
+#define REGISTER_MOVE_COST(MODE, FROM, TO) ((TO != GENERAL_REGS) ? 8 : 2)
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+#define PRINT_OPERAND(STREAM, X, CODE) \
+  cr16_print_operand (STREAM, X, CODE)
+
+#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
+  cr16_print_operand_address (STREAM, ADDR)
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+
+#endif /* End of GCC_CR16_H.  */
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16-libgcc.s mod/gcc/config/cr16/cr16-libgcc.s
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,578 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.md mod/gcc/config/cr16/cr16.md
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-04-08 17:54:10.000000000 +0530
@@ -0,0 +1,1289 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+;;  Register numbers
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates & Constraints
+(include "predicates.md")
+(include "constraints.md")
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+   (UNSPEC_RETURN_ADDR          5)
+  ]
+)
+
+;; Attributes
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+;;  Code Macro Definitions
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;; Arithmetic Instuction  Patterns
+;;
+;; Addition insns.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0")
+		 (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 0);
+  "
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+		 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,P")))]
+  ""
+  "addd\t%2, %0"
+  [(set_attr "length" "2,2,4,4,6")]
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "addw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+		 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "addb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(minus:DI (match_operand:DI 1 "register_operand" "")
+		  (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(minus:DI (match_operand:DI 1 "register_operand" "0")
+		  (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 1);
+  "
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,0")
+		  (match_operand:SI 2 "reg_si_int_operand" "r,P")))]
+  ""
+  "subd\t%2, %0"
+  [(set_attr "length" "4,6")]
+)
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+		  (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "subw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(minus:QI (match_operand:QI 1 "register_operand" "0,0")
+		  (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "subb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Multiply and Accumulate Instructions
+(define_insn "smachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macsw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "umachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macuw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_set_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Logical Instructions - and
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(and:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 0);
+  "
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,P")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(and:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - or 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ior:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 1);
+  "
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,P")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - xor 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(xor:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 2);
+  "
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,P")))]
+  ""
+  "xord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(xor:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(not:DI (match_operand:DI 1 "register_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "register_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
+  ""
+  "ashub\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c")
+	(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
+  ""
+  "ashuw\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
+  ""
+  "ashud\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "ashrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
+  ""
+  "ashub\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
+  ""
+  "ashuw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
+  ""
+  "ashud\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashub\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashuw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrdi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "ashud\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "reg_or_int_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "lshrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_operand" "Q")))]
+  ""
+  "lshb\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_operand" "R")))]
+  ""
+  "lshw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_operand" "S")))]
+  ""
+  "lshd\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshb\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "lshd\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "general_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "nonmemory_operand" "")))
+    (clobber (match_scratch:HI 2 "=r"))] ) ]
+  ""
+  "")
+
+;;  Scond Instructions
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 2 "register_operand" "")
+		 (match_operand:CR16IM 3 "nonmemory_operand" "")))
+   (set (match_operand:HI 0 "register_operand")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  ""
+)
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
+  ""
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "sCOND_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  "s%d1\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "jump_return"
+  [(parallel
+    [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
+     (return)])]
+  "reload_completed"
+  "jump\t(ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
+      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      return "bal (ra), %b1";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop/t"
+)
+
+;; PIC
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
+
+;; Shared FLAT
+(define_insn "unspec_library_offset"
+  [(const_int UNSPEC_LIBRARY_OFFSET)]
+  ""
+  "push \t$2, r0;\n\tmovd \t$__current_shared_library_r12_offset_, (r1,r0);\n\tloadd \t[r12]0(r1,r0), (r12);\n\tpop \t$2, r0\n\t"
+  [(set_attr "length" "12")]
+)
+
+(define_insn "unspec_sh_lib_push_r12"
+  [(const_int UNSPEC_SH_LIB_PUSH_R12)]
+  ""
+  "push \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "unspec_sh_lib_pop_r12"
+  [(const_int UNSPEC_SH_LIB_POP_R12)]
+  ""
+  "pop \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.opt mod/gcc/config/cr16/cr16.opt
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,59 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2010 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
+mid-shared-library
+Target Report Mask(ID_SHARED_LIBRARY)
+Enabled ID based shared library
+
+mshared-library-id=
+Target RejectNegative Joined UInteger Var(cr16_library_id)
+ID of shared library to build
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16-protos.h mod/gcc/config/cr16/cr16-protos.h
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,112 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_legitimate_address_p (enum machine_mode, rtx, int);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+/* Instruction output.  */
+extern void cr16_print_operand (FILE *, rtx, int);
+extern void cr16_print_operand_address (FILE *, rtx);
+extern void cr16_expand_movmem_single (rtx, rtx, rtx, rtx, rtx,
+				       unsigned HOST_WIDE_INT *);
+extern int cr16_expand_movmem (rtx, rtx, rtx, rtx);
+extern rtx got_operand (rtx, enum machine_mode);
+extern rtx bro_operand (rtx, enum machine_mode);
+
+#endif /* RTX_CODE.  */
+
+/* Routines to compute costs.  */
+extern int cr16_memory_move_cost (enum machine_mode, enum reg_class, int);
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+extern const char *cr16_emit_add_sub_di (rtx *, int);
+extern const char *cr16_emit_logical_di (rtx *, int);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/divmodhi3.c mod/gcc/config/cr16/divmodhi3.c
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/predicates.md mod/gcc/config/cr16/predicates.md
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-04-08 17:01:46.000000000 +0530
@@ -0,0 +1,227 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;;  Predicates
+
+;; Predicates for sbit/cbit instructions
+;; bit operand used for the generation of bit insn generation
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Predicates for shift instructions
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0;
+})
+
+;; Predicates for jump/call instructions
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Helper predicate 
+(define_predicate "reg_or_int_operand"
+  (ior (match_code "const_int")
+       (match_operand 0 "register_operand")))
+
+;;
+;;
+;; Atithmetic/logical predicates
+
+;; QI Helper
+(define_predicate "arith_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) 
+                || (INTVAL (op) != 11))) ? 1 : 0 ; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "reg_qi_int_operand"
+  (ior (match_operand 0 "arith_qi_operand")
+       (match_operand 0 "register_operand")))
+
+;; HI Helper
+(define_predicate "arith_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "reg_hi_int_operand"
+  (ior (match_operand 0 "arith_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "arith_si_operand"
+   (match_code "const_int")
+{
+        return IN_RAN(INTVAL (op), -2147483648, 2147483647) ? 1 : 0 ; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "reg_si_int_operand"
+  (ior (match_operand 0 "arith_si_operand")
+       (match_operand 0 "register_operand")))
+
+;;
+;; Shift predicates
+
+;; QI Helper
+(define_predicate "shift_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_qi_int_operand"
+  (ior (match_operand 0 "shift_qi_operand")
+       (match_operand 0 "register_operand")))
+;; HI Helper
+(define_predicate "shift_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_hi_int_operand"
+  (ior (match_operand 0 "shift_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "shift_si_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_si_int_operand"
+  (ior (match_operand 0 "shift_si_operand")
+       (match_operand 0 "register_operand")))
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/t-cr16 mod/gcc/config/cr16/t-cr16
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,73 @@
+# CR16 Target Makefile
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+LIB2ADDEH = $(srcdir)/config/cr16/unwind-dw2-cr16.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-c.c
+
+#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+#$(T)crti.o: $(srcdir)/config/cr16/crti.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.s
+
+#$(T)crtn.o: $(srcdir)/config/cr16/crtn.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.s
+
+#$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crtlibid.o \
+#	  -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.s
+
+MULTILIB_OPTIONS     = fPIC mint32 mid-shared-library
+MULTILIB_DIRNAMES    = far-pic int32 mid-shared-library
+MULTILIB_EXCEPTIONS  = fno-PIC/mid-shared-library
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/unwind-dw2-cr16.c mod/gcc/config/cr16/unwind-dw2-cr16.c
--- orig/gcc/config/cr16/unwind-dw2-cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2-cr16.c	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,1597 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2008, 2009, 2010  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
+#endif
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  void *reg[DWARF_FRAME_REGISTERS+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[DWARF_FRAME_REGISTERS+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+  unsigned u2 __attribute__ ((mode (HI)));
+  unsigned u4 __attribute__ ((mode (SI)));
+  unsigned u8 __attribute__ ((mode (DI)));
+  signed s2 __attribute__ ((mode (HI)));
+  signed s4 __attribute__ ((mode (SI)));
+  signed s8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+
+static inline int
+read_1u (const void *p) { return *(const unsigned char *) p; }
+
+static inline int
+read_1s (const void *p) { return *(const signed char *) p; }
+
+static inline int
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
+
+static inline int
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
+
+static inline unsigned int
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
+
+static inline int
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
+
+static inline unsigned long
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
+
+static inline unsigned long
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return context->flags & EXTENDED_CONTEXT_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  void *ptr;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  ptr = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) ptr;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) ptr;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+      return;
+    }
+  ptr = context->reg[index];
+    if ( size == sizeof(_Unwind_Word) )
+      * (_Unwind_Word *) ptr = val;
+    else {
+      typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
+      gcc_assert (index + 1  <  (int) sizeof(dwarf_reg_size_table));
+      * (_CR16_Unwind_Word *) ptr = val & 0xffff ;  /* low 16-bit.  */
+      ptr = context->reg[index + 1];
+      * (_CR16_Unwind_Word *) ptr = val >> 16 ;  /* high 16-bit.  */
+         }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+		    _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
+
+  context->by_value[index] = 1;
+  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+#endif
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* Immediately following the augmentation are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
+   onto the stack to start.  */
+
+static _Unwind_Word
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
+		  struct _Unwind_Context *context, _Unwind_Word initial)
+{
+  _Unwind_Word stack[64];	/* ??? Assume this is enough.  */
+  int stack_elt;
+
+  stack[0] = initial;
+  stack_elt = 1;
+
+  while (op_ptr < op_end)
+    {
+      enum dwarf_location_atom op = *op_ptr++;
+      _Unwind_Word result;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      switch (op)
+	{
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	  result = op - DW_OP_lit0;
+	  break;
+
+	case DW_OP_addr:
+	  result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
+	  op_ptr += sizeof (void *);
+	  break;
+
+	case DW_OP_GNU_encoded_addr:
+	  {
+	    _Unwind_Ptr presult;
+	    op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+	    result = presult;
+	  }
+	  break;
+
+	case DW_OP_const1u:
+	  result = read_1u (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const1s:
+	  result = read_1s (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const2u:
+	  result = read_2u (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const2s:
+	  result = read_2s (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const4u:
+	  result = read_4u (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const4s:
+	  result = read_4s (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const8u:
+	  result = read_8u (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_const8s:
+	  result = read_8s (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_constu:
+	  op_ptr = read_uleb128 (op_ptr, &utmp);
+	  result = (_Unwind_Word)utmp;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &stmp);
+	  result = (_Unwind_Sword)stmp;
+	  break;
+
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+	  result = _Unwind_GetGR (context, op - DW_OP_reg0);
+	  break;
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  result = _Unwind_GetGR (context, reg);
+	  break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+	  break;
+	case DW_OP_bregx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+	  break;
+
+	case DW_OP_dup:
+	  gcc_assert (stack_elt);
+	  result = stack[stack_elt - 1];
+	  break;
+
+	case DW_OP_drop:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+	  goto no_push;
+
+	case DW_OP_pick:
+	  offset = *op_ptr++;
+	  gcc_assert (offset < stack_elt - 1);
+	  result = stack[stack_elt - 1 - offset];
+	  break;
+
+	case DW_OP_over:
+	  gcc_assert (stack_elt >= 2);
+	  result = stack[stack_elt - 2];
+	  break;
+
+	case DW_OP_swap:
+	  {
+	    _Unwind_Word t;
+	    gcc_assert (stack_elt >= 2);
+	    t = stack[stack_elt - 1];
+	    stack[stack_elt - 1] = stack[stack_elt - 2];
+	    stack[stack_elt - 2] = t;
+	    goto no_push;
+	  }
+
+	case DW_OP_rot:
+	  {
+	    _Unwind_Word t1, t2, t3;
+
+	    gcc_assert (stack_elt >= 3);
+	    t1 = stack[stack_elt - 1];
+	    t2 = stack[stack_elt - 2];
+	    t3 = stack[stack_elt - 3];
+	    stack[stack_elt - 1] = t2;
+	    stack[stack_elt - 2] = t3;
+	    stack[stack_elt - 3] = t1;
+	    goto no_push;
+	  }
+
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	case DW_OP_abs:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_plus_uconst:
+	  /* Unary operations.  */
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  result = stack[stack_elt];
+
+	  switch (op)
+	    {
+	    case DW_OP_deref:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		result = (_Unwind_Ptr) read_pointer (ptr);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		switch (*op_ptr++)
+		  {
+		  case 1:
+		    result = read_1u (ptr);
+		    break;
+		  case 2:
+		    result = read_2u (ptr);
+		    break;
+		  case 4:
+		    result = read_4u (ptr);
+		    break;
+		  case 8:
+		    result = read_8u (ptr);
+		    break;
+		  default:
+		    gcc_unreachable ();
+		  }
+	      }
+	      break;
+
+	    case DW_OP_abs:
+	      if ((_Unwind_Sword) result < 0)
+		result = -result;
+	      break;
+	    case DW_OP_neg:
+	      result = -result;
+	      break;
+	    case DW_OP_not:
+	      result = ~result;
+	      break;
+	    case DW_OP_plus_uconst:
+	      op_ptr = read_uleb128 (op_ptr, &utmp);
+	      result += (_Unwind_Word)utmp;
+	      break;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_le:
+	case DW_OP_ge:
+	case DW_OP_eq:
+	case DW_OP_lt:
+	case DW_OP_gt:
+	case DW_OP_ne:
+	  {
+	    /* Binary operations.  */
+	    _Unwind_Word first, second;
+	    gcc_assert (stack_elt >= 2);
+	    stack_elt -= 2;
+
+	    second = stack[stack_elt];
+	    first = stack[stack_elt + 1];
+
+	    switch (op)
+	      {
+	      case DW_OP_and:
+		result = second & first;
+		break;
+	      case DW_OP_div:
+		result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+		break;
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		result = second % first;
+		break;
+	      case DW_OP_mul:
+		result = second * first;
+		break;
+	      case DW_OP_or:
+		result = second | first;
+		break;
+	      case DW_OP_plus:
+		result = second + first;
+		break;
+	      case DW_OP_shl:
+		result = second << first;
+		break;
+	      case DW_OP_shr:
+		result = second >> first;
+		break;
+	      case DW_OP_shra:
+		result = (_Unwind_Sword) second >> first;
+		break;
+	      case DW_OP_xor:
+		result = second ^ first;
+		break;
+	      case DW_OP_le:
+		result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ge:
+		result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_eq:
+		result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+		break;
+	      case DW_OP_lt:
+		result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+		break;
+	      case DW_OP_gt:
+		result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ne:
+		result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  }
+	  break;
+
+	case DW_OP_skip:
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_bra:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  if (stack[stack_elt] != 0)
+	    op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_nop:
+	  goto no_push;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* Decode DWARF 2 call frame information. Takes pointers the
+   instruction sequence to decode, current register information and
+   CIE info, and the PC range to evaluate.  */
+
+static void
+execute_cfa_program (const unsigned char *insn_ptr,
+		     const unsigned char *insn_end,
+		     struct _Unwind_Context *context,
+		     _Unwind_FrameState *fs)
+{
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
+	      (_Unwind_Word)reg2;
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
+
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_GNU_window_save:
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  for (reg = 16; reg < 32; ++reg)
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	    }
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#else
+      return _URC_END_OF_STACK;
+#endif
+    }
+
+  fs->pc = context->bases.func;
+
+  cie = get_cie (fde);
+  insn = extract_cie_info (cie, context, fs);
+  if (insn == NULL)
+    /* CIE contained unknown augmentation.  */
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* First decode all the insns in the CIE.  */
+  end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  context.flags = EXTENDED_CONTEXT_BIT;
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
+
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+	{
+	case REG_SAVED_REG:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+	  break;
+	default:
+	  state_in->reg_or_offset[reg] = 0;
+	  break;
+	}
+    }
+
+  state_in->cfa_offset = fs.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+		     _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef EH_RETURN_STACKADJ_RTX
+  /* Special handling here: Many machines do not use a frame pointer,
+     and track the CFA only through offsets from the stack pointer from
+     one frame to the next.  In this case, the stack pointer is never
+     stored, so it has no saved address in the context.  What we do
+     have is the CFA from the previous stack frame.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+	const unsigned char *exp = fs->regs.cfa_exp;
+	_uleb128_t len;
+
+	exp = read_uleb128 (exp, &len);
+	cfa = (void *) (_Unwind_Ptr)
+	  execute_stack_op (exp, exp + len, &orig_context, 0);
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  context->cfa = cfa;
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
+    switch (fs->regs.reg[i].how)
+      {
+      case REG_UNSAVED:
+      case REG_UNDEFINED:
+	break;
+
+      case REG_SAVED_OFFSET:
+	_Unwind_SetGRPtr (context, i,
+			  (void *) (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_REG:
+	if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+	  _Unwind_SetGRValue (context, i,
+			      _Unwind_GetGR (&orig_context,
+					     fs->regs.reg[i].loc.reg));
+	else
+	  _Unwind_SetGRPtr (context, i,
+			    _Unwind_GetGRPtr (&orig_context,
+					      fs->regs.reg[i].loc.reg));
+	break;
+
+      case REG_SAVED_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRPtr (context, i, (void *) val);
+	}
+	break;
+
+      case REG_SAVED_VAL_OFFSET:
+	_Unwind_SetGRValue (context, i,
+			    (_Unwind_Internal_Ptr)
+			    (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_VAL_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRValue (context, i, val);
+	}
+	break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+    context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      /* Do any necessary initialization to access arbitrary stack frames. \
+	 On the SPARC, this means flushing the register windows.  */	   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context,
+		   void *outer_cfa, void *outer_ra)
+{
+  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  _Unwind_FrameState fs;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#if __GTHREADS
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
+	&& dwarf_reg_size_table[0] == 0)
+      init_dwarf_reg_size_table ();
+  }
+#else
+  if (dwarf_reg_size_table[0] == 0)
+    init_dwarf_reg_size_table ();
+#endif
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.cfa_offset -= context->args_size ;
+  uw_update_context_1 (context, &fs);
+
+  /* If the return address column was saved in a register in the
+     initialization context, then we can't see it in the given
+     call frame data.  So have the initialization context tell us.  */
+  context->ra = __builtin_extract_return_addr (outer_ra);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+  asm ("");
+}
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+
+#define uw_install_context(CURRENT, TARGET)                              \
+  do                                                                     \
+    {                                                                    \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
+      handler = (void*)( ( (unsigned)handler ) >> 1 ) ;                  \
+      __builtin_eh_return (offset, handler);                             \
+    }                                                                    \
+  while (0)
+
+
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+	{
+	  _Unwind_Word w;
+	  _Unwind_Ptr p;
+	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	    {
+	      w = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &w, sizeof (_Unwind_Word));
+	    }
+	  else
+	    {
+	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      p = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &p, sizeof (_Unwind_Ptr));
+	    }
+	}
+      else if (t && c && t != c)
+	memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
+      if (STACK_GROWS_DOWNWARD)
+	return target_cfa - current->cfa + target->args_size;
+      else
+	return current->cfa - target_cfa - target->args_size;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (STACK_GROWS_DOWNWARD)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/unwind-dw2.h mod/gcc/config/cr16/unwind-dw2.h
--- orig/gcc/config/cr16/unwind-dw2.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2.h	2011-04-08 16:43:35.000000000 +0530
@@ -0,0 +1,87 @@
+/* DWARF2 frame unwind data structure.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* A target can override (perhaps for backward compatibility) how
+   many dwarf2 columns are unwound.  */
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* The result of interpreting the frame unwind info for a frame.
+   This is all symbolic at this point, as none of the values can
+   be resolved until the target pc is located.  */
+typedef struct
+{
+  /* Each register save state can be described in terms of a CFA slot,
+     another register, or a location expression.  */
+  struct frame_state_reg_info
+  {
+    struct {
+      union {
+	_Unwind_Word reg;
+	_Unwind_Sword offset;
+	const unsigned char *exp;
+      } loc;
+      enum {
+	REG_UNSAVED,
+	REG_SAVED_OFFSET,
+	REG_SAVED_REG,
+	REG_SAVED_EXP,
+	REG_SAVED_VAL_OFFSET,
+	REG_SAVED_VAL_EXP,
+	REG_UNDEFINED
+      } how;
+    } reg[DWARF_FRAME_REGISTERS+1];
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct frame_state_reg_info *prev;
+
+    /* The CFA can be described in terms of a reg+offset or a
+       location expression.  */
+    _Unwind_Sword cfa_offset;
+    _Unwind_Word cfa_reg;
+    const unsigned char *cfa_exp;
+    enum {
+      CFA_UNSET,
+      CFA_REG_OFFSET,
+      CFA_EXP
+    } cfa_how;
+  } regs;
+
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Sword data_align;
+  _Unwind_Word code_align;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+} _Unwind_FrameState;
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config.gcc mod/gcc/config.gcc
--- orig/gcc/config.gcc	2011-03-14 11:35:29.000000000 +0530
+++ mod/gcc/config.gcc	2011-04-08 16:42:35.000000000 +0530
@@ -955,6 +955,12 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+        tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} cr16/t-cr16 "
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        use_collect2=no
+        ;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/extend.texi mod/gcc/doc/extend.texi
--- orig/gcc/doc/extend.texi	2011-03-28 01:38:35.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-04-08 16:42:42.000000000 +0530
@@ -2551,7 +2551,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, CRX, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, CRX, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/install.texi mod/gcc/doc/install.texi
--- orig/gcc/doc/install.texi	2011-03-21 17:43:26.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-04-08 16:42:42.000000000 +0530
@@ -3215,6 +3215,33 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/invoke.texi mod/gcc/doc/invoke.texi
--- orig/gcc/doc/invoke.texi	2011-03-29 19:54:42.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-04-08 16:42:42.000000000 +0530
@@ -502,6 +502,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32 -mbit-ops
+-mdata-model=@var{model}}
+
 @emph{CRX Options}
 @gccoptlist{-mmac -mpush-args}
 
@@ -9973,6 +9979,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * CRX Options::
 * Darwin Options::
 * DEC Alpha Options::
@@ -10801,6 +10808,46 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mbit-ops
+@opindex mbit-ops
+Generates sbit/cbit instructions for bit manipulations.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near},
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
 @node CRX Options
 @subsection CRX Options
 @cindex CRX Options
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/md.texi mod/gcc/doc/md.texi
--- orig/gcc/doc/md.texi	2011-01-04 02:22:22.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-04-08 18:37:22.000000000 +0530
@@ -1775,6 +1775,55 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item c
+Register from r0 to r11 (all 16-bit registers)
+
+@item d
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Unsigned constant that fits in specific 4 bits
+
+@item N
+Signed constant that fits in 16 bits
+
+@item O
+Unsigned constant that fits in 20 bits
+
+@item P
+Signed constant that fits in 32 bits
+
+@item Q
+A shift operation immediate value that fits in QI mode.
+
+@item R
+A shift operation immediate value that fits in HI mode.
+
+@item S
+A shift operation immediate value that fits in SI mode.
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item CRX Architecture---@file{config/crx/crx.h}
 @table @code
 
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config/cr16/crti.S mod/libgcc/config/cr16/crti.S
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-04-08 16:42:28.000000000 +0530
@@ -0,0 +1,55 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.file   "crti.o"
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config/cr16/crtlibid.S mod/libgcc/config/cr16/crtlibid.S
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-04-08 16:42:28.000000000 +0530
@@ -0,0 +1,29 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.file   "crtlibid.o"
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config/cr16/crtn.S mod/libgcc/config/cr16/crtn.S
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-04-08 16:42:28.000000000 +0530
@@ -0,0 +1,45 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.file   "crtn.o"
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config/cr16/t-cr16 mod/libgcc/config/cr16/t-cr16
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-04-08 16:42:28.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config.host mod/libgcc/config.host
--- orig/libgcc/config.host	2011-03-14 11:36:23.000000000 +0530
+++ mod/libgcc/config.host	2011-04-08 16:42:28.000000000 +0530
@@ -79,6 +79,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+        ;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -250,6 +252,10 @@ cris-*-linux* | crisv32-*-linux*)
 	;;
 crx-*-elf)
 	;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 fido-*-elf)
 	;;
 fr30-*-elf)
diff -uprN -x'*.orig' -x'*.rej' orig/libstdc++-v3/configure mod/libstdc++-v3/configure
--- orig/libstdc++-v3/configure	2011-03-08 05:34:05.000000000 +0530
+++ mod/libstdc++-v3/configure	2011-04-08 16:43:48.000000000 +0530
@@ -26492,6 +26492,9 @@ case "${host}" in
     # This is a freestanding configuration; there is nothing to do here.
     ;;
 
+  cr16-*-*)
+    ;;
+
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
     SECTION_FLAGS='-ffunction-sections -fdata-sections'
diff -uprN -x'*.orig' -x'*.rej' orig/libstdc++-v3/crossconfig.m4 mod/libstdc++-v3/crossconfig.m4
--- orig/libstdc++-v3/crossconfig.m4	2011-02-04 12:56:57.000000000 +0530
+++ mod/libstdc++-v3/crossconfig.m4	2011-04-08 16:43:47.000000000 +0530
@@ -8,6 +8,9 @@ case "${host}" in
   arm*-*-symbianelf*)
     # This is a freestanding configuration; there is nothing to do here.
     ;;
+  cr16-*-*)
+    # SiTel
+    ;; 
 
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-04-08 13:26 CR16 Port addition Sumanth Gundapaneni
@ 2011-04-08 14:56 ` Joseph S. Myers
  2011-05-20 13:59   ` Sumanth Gundapaneni
  0 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2011-04-08 14:56 UTC (permalink / raw)
  To: Sumanth Gundapaneni; +Cc: gcc-patches, rth, Jayant R. Sonar

This is not a patch against GCC trunk.  Please try again with a patch that 
is diffed against current GCC SVN trunk and that builds cleanly (including 
building with --enable-werror-always, starting from a native bootstrapped 
build of current trunk as the compiler you use to compile your cross 
compiler).  For example, it includes the obsolete poisoned target macros 
TARGET_VERSION and IRA_COVER_CLASSES, and the handle_option hook has not 
been updated for the interface changes to avoid global state in such 
hooks.  Furthermore, the code has at least one old-style function 
definition (notice_update_cc), which should have been caught by the 
warnings in the build.  Beyond anything caught by warnings, if the code 
defines any target macros that are in the process of being converted to 
hooks (default hook definitions in targhooks.c that use the macro, but no 
code elsewhere in the compiler using the macro, only defining it) then 
please convert the target to define the hooks directly and not the 
obsolescent macros.  FUNCTION_VALUE is one example of an obsolescent macro 
still defined by some ports, but that new ports should not define.  
GO_IF_LEGITIMATE_ADDRESS is another.

Please see the GNU Coding Standards regarding proper formatting of 
diagnostic messages (don't start with an uppercase letter or end with 
".").

The toplevel changes are incorrect.  See my recent cleanups.  There is no 
such target as target-mudflap, and there is generic code to handle 
target-libmudflap depending on target OS so the cases based on target 
architecture shouldn't care about that.  Furthermore, a case for 
cr16-uclinux can never match, because config.sub maps that to 
cr16-unknown-elf.  If you want to do any toplevel changes in future 
relating to a GDB port for uClinux (say) then you'll need to adjust 
config.sub in config.git first.

Remove .file directives from your .S files unless you're really sure they 
are needed and correct.  See my 2008-07-02 patch.

The libstdc++-v3 changes also seem suspicious.  Newlib-using ports 
shouldn't need changes to crossconfig.m4 because that code isn't used for 
them; see the

  if test "x${with_newlib}" = "xyes"; then

conditional in configure.ac.  And the comment "# SiTel" makes no sense to 
me; comments should be full English sentences.

I'm still not satisfied with the forked version of the unwind code.  
Please show a diff of what the minimum changes would be to the 
target-independent unwind-dw2-* files for CR16 to work with those files 
based on behavior in those files being conditioned as needed on target 
macros defined by CR16; we should only use forked files if such changes to 
condition the generic ones are unmaintainably messy.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-04-08 14:56 ` Joseph S. Myers
@ 2011-05-20 13:59   ` Sumanth Gundapaneni
  2011-05-20 17:07     ` Joseph S. Myers
  0 siblings, 1 reply; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-05-20 13:59 UTC (permalink / raw)
  To: Joseph Myers, gcc-patches, rth; +Cc: Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 4721 bytes --]

Hi Joseph and Richard,

Thanks for your patience in reviewing the CR16 port and I am grateful for
your valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications 
as suggested by Joseph in his previous mail.

For your kind information, I am providing the recent posts regarding 
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html  
Third post   : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg00624.html

Please review the patch and let me know if there should be any 
modifications in it.

Joseph, please go through my explanation for your comments.

>This is not a patch against GCC trunk.
The patch has been updated for the latest sources.

>that builds cleanly (including building with --enable-werror-always
The patched source is built with --enable-werror-always and it builds
cleanly. As suggested, the cross compiler is built with the native 
bootstrapped build of current trunk to avoid warning turned errors 
related to gcc diagnostic functions.

> obsolete poisoned target macros TARGET_VERSION and IRA_COVER_CLASSES 
These macros are removed.

> the code has at least one old-style function 
This has been rectified.
 
>please convert the target to define the hooks directly and not the 
>FUNCTION_VALUE is one example of an obsolescent macro 
>GO_IF_LEGITIMATE_ADDRESS is another.
The hooks have been defined as per gcc internals. Most of the
obsolete macros have been eliminated. 

> proper formatting of diagnostic messages 
This has been modified.

> There is no such target as target-mudflap,
The configure file is altered as per your suggestion.

> then you'll need to adjust config.sub in config.git first.
I will do the necessary modification and update the same in config.git.

>Remove .file directives from your .S files.
All the .file directives in .S files are removed

>The libstdc++-v3 changes also seem suspicious.  
The configure files of libstdc++-v3 are changed as advised.  

>I'm still not satisfied with the forked version of the unwind code.  
>Please show a diff of what the minimum changes would be to the 
I have attached diff file (unwind.diff) for your reference. Please
go through it. As explicated before the CR16's programming memory 
is 2-byte aligned and the least significant bit of PC is always zero. 
The Return Address (RA) register always saves the value of PC right 
shifted by 1(PC >> 1). This conversion seems broken at some places 
during unwinding which results in terminate() function  being called.
Being said that all the required changes (macros) were implemented to 
Handle exceptions in C++.
These files were added to help fix this problem. However, we have not yet
completely solved this problem. If we are able to fix this without major 
modifications, we will move these files back in which case customized
unwind files would not be needed.

gcc/ChangeLog:
--------------
2011-05-20	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/constraints.md: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-dw2-cr16.c: New file.
	* config/cr16/unwind-dw2.h: New file. 

libgcc/ChangeLog:
-----------------
2011-05-20  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
		
libstdc++-v3/ChangeLog:
-----------------------
2011-05-20  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	*configure: Add National Semiconductor CR16 target (cr16-*-*).		
	
ChangeLog:
----------
2011-05-20  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* configure.ac: Add National Semiconductor CR16 target.
	* configure: Regenerate
   
Thanks in advance,
Sumanth G,
PUNE (India).


[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 219765 bytes --]

diff -uprN orig/configure mod/configure
--- orig/configure	2011-05-09 13:09:45.000000000 +0530
+++ mod/configure	2011-05-20 15:16:40.000000000 +0530
@@ -3443,7 +3443,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libgloss gdb"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs ${libgcj} gdb";;
+    esac
     ;;
   d10v-*-*)
     noconfigdirs="$noconfigdirs target-libgloss"
diff -uprN orig/configure.ac mod/configure.ac
--- orig/configure.ac	2011-05-09 13:09:45.000000000 +0530
+++ mod/configure.ac	2011-05-20 15:16:38.000000000 +0530
@@ -889,7 +889,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libgloss gdb"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs ${libgcj} gdb";;
+    esac
     ;;
   d10v-*-*)
     noconfigdirs="$noconfigdirs target-libgloss"
diff -uprN orig/gcc/config/cr16/constraints.md mod/gcc/config/cr16/constraints.md
--- orig/gcc/config/cr16/constraints.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/constraints.md	2011-05-20 16:27:19.000000000 +0530
@@ -0,0 +1,81 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;; Constraints
+;; Register constraints
+(define_register_constraint "b" "NOSP_REGS"
+  "@no sp registers")
+
+(define_register_constraint "c" "SHORT_REGS"
+  "@short registers")
+
+(define_register_constraint "d" "LONG_REGS"
+  "@long registers")
+
+;; Integer constraints.
+(define_constraint "I"
+  "A signed 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "J"
+  "A signed 5-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)")))
+
+(define_constraint "K"
+  "A signed 6-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)")))
+
+(define_constraint "L"
+  "A unsigned 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "M"
+  "A unsigned and customized  4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) || (ival != 11)))  ")))
+
+(define_constraint "N"
+  "A signed 16-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -32768, 32767)")))
+
+(define_constraint "O"
+  "A unsigned 20-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 1048575)")))
+
+(define_constraint "Q"
+  "A shift QI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 7)")))
+
+(define_constraint "R"
+  "A shift HI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 15)")))
+
+(define_constraint "S"
+  "A shift SI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 31)")))
diff -uprN orig/gcc/config/cr16/cr16.c mod/gcc/config/cr16/cr16.c
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-05-20 16:26:26.000000000 +0530
@@ -0,0 +1,2212 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Structure for stack computations.  */
+
+/* variable definitions in the struture
+   args_size             Number of bytes saved on the stack for local 
+			 variables
+
+   reg_size		 Number of bytes saved on the stack for 
+			 non-scratch registers
+
+   total_size 		 The sum of 2 sizes: locals vars and padding byte 
+			 for saving the registers. Used in expand_prologue() 
+			 and expand_epilogue()
+
+   last_reg_to_save      Will hold the number of the last register the 
+			 prologue saves, -1 if no register is saved
+
+   save_regs[16]	 Each object in the array is a register number. 
+			 Mark 1 for registers that need to be saved
+
+   num_regs		 Number of registers saved
+
+   initialized		 Non-zero if frame size already calculated, not 
+			 used yet
+
+   function_makes_calls  Does the function make calls ? not used yet.  */
+
+struct cr16_frame_info
+{
+  unsigned long var_size;
+  unsigned long args_size;
+  unsigned int  reg_size;
+  unsigned long total_size;
+  long          last_reg_to_save;
+  long          save_regs[FIRST_PSEUDO_REGISTER];
+  int           num_regs;
+  int           initialized;
+  int           function_makes_calls;
+};
+
+/* Current frame information calculated by cr16_compute_frame_size.  */
+static struct cr16_frame_info current_frame_info;
+
+/* Static Variables.  */
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* TARGETM Function Prototypes and forward declarations  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
+static bool cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+static bool cr16_legitimate_constant_p   (enum machine_mode, rtx);
+static rtx cr16_function_value (const_tree, const_tree, bool);
+static rtx cr16_libcall_value (enum machine_mode, const_rtx);
+static bool cr16_function_value_regno_p (const unsigned int);
+static bool cr16_legitimate_address_p (enum machine_mode, rtx, bool);
+static void cr16_print_operand (FILE *, rtx, int);
+static void cr16_print_operand_address (FILE *, rtx);
+static int cr16_address_cost (rtx, bool);
+static int cr16_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
+static int cr16_memory_move_cost (enum machine_mode, reg_class_t, bool);
+
+/* Stack layout and calling conventions.  */
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P    cr16_legitimate_constant_p
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P     cr16_legitimate_address_p
+
+/* Returning function value.  */
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE cr16_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE cr16_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
+
+/* printing the values.  */
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND cr16_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
+
+/* Table of machine attributes.  */
+static const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity }.  */
+  {"interrupt", 0, 0, false, true, true, NULL, false},
+  {NULL, 0, 0, false, false, false, NULL, false}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS 
+       || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, 
+		      int size ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture");
+	}
+      else
+	error ("invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array current_frame_info.save_regs and the variable 
+   current_frame_info.reg_size. The index of current_frame_info.save_regs 
+   is numbers of register, each will get 1 if we need to save it in the 
+   current function, 0 if not. current_frame_info.reg_size is the total sum 
+   of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  current_frame_info.last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  current_frame_info.reg_size = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (fixed_regs[regno])
+	{
+	  current_frame_info.save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    current_frame_info.save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    current_frame_info.save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  current_frame_info.save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (current_frame_info.save_regs[regno] == 1)
+      {
+	current_frame_info.last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
+	else
+	  current_frame_info.reg_size += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  current_frame_info.var_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = current_frame_info.var_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  current_frame_info.var_size += padding_locals;
+  current_frame_info.total_size = current_frame_info.var_size 
+			   + (ACCUMULATE_OUTGOING_ARGS
+			    ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use current_frame_info.reg_size.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use current_frame_info.var_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size 
+	    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
+        return 0;
+ 
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  if ((TARGET_INT32)
+      && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
+     return 0;
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Returns register number for function return value.*/
+static inline unsigned int
+cr16_ret_register (void)
+{
+  return 0;
+}
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, cr16_ret_register ());
+}
+
+/* Returning function value.  */
+
+/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.  */
+static bool
+cr16_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   library function returns a value of mode MODE.  */
+static rtx
+cr16_libcall_value (enum machine_mode mode,
+                   const_rtx func ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   function returns a value of data type VALTYPE.  */
+static rtx
+cr16_function_value (const_tree type,
+                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE(type), cr16_ret_register ());
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  cum->last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!cum->last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+     C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+     C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+     NOTE: @BRO is added using unspec:BRO
+     NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of TARGET_LEGITIMATE_ADDRESS_P.  */
+static bool
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, bool strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "index + register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\ncr16 address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /* CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9.  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+
+/* Implement `TARGET_REGISTER_MOVE_COST'.  */
+static int
+cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                        reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
+{
+  return (to != GENERAL_REGS ? 8
+          : 2);
+}
+
+/* Implement `TARGET_MEMORY_MOVE_COST'.  */
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+static int
+cr16_memory_move_cost (enum machine_mode mode,
+                       reg_class_t rclass ATTRIBUTE_UNUSED,
+                       bool in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+static void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "unspec!!");
+	  switch (XINT (x, 1))
+	    {
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+static void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "unspec 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of current_frame_info.save_regs[], going from 0 until 
+     current_frame_info.last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= current_frame_info.last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) 
+	     && (i <= current_frame_info.last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!current_frame_info.save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* POP.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
+    {
+      if (current_frame_info.save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = current_frame_info.last_reg_to_save + 1;
+  to = current_frame_info.last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = current_frame_info.last_reg_to_save; i >= 0;)
+    {
+      if (!current_frame_info.save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && current_frame_info.save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (SImode, dwarf,
+					REG_NOTES (insn));
+}
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
+    return;
+
+  if (current_frame_info.last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue
+			(GEN_INT (current_frame_info.reg_size)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
+			&& (current_frame_info.reg_size 
+			 == CR16_UNITS_PER_DWORD));
+  
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (current_frame_info.last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static bool
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return
+	  || cfun->has_nonlocal_label || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+   Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P. In cr16c treat legitimize float 
+   constant as an immediate operand.  */
+static bool
+cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			    rtx x ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+void
+notice_update_cc (rtx exp)
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
+
+/* Helper function for md file. This function is used to emit arithmetic 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_add_sub_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi0_op[2] ;
+  rtx hi1_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
+  hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
+  hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
+
+  if (num == 0)
+    {
+        output_asm_insn ("addd\t%1, %0", lo_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("subd\t%1, %0", lo_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else
+    return "";
+
+}
+
+
+/* Helper function for md file. This function is used to emit logical 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_logical_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
+  if (num == 0)
+    {
+        output_asm_insn ("andd\t%1, %0", lo_op) ;
+        output_asm_insn ("andd\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("ord\t%1, %0", lo_op) ;
+        output_asm_insn ("ord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 2)
+    {
+        output_asm_insn ("xord\t%1, %0", lo_op) ;
+        output_asm_insn ("xord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else
+    return "";
+}
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
diff -uprN orig/gcc/config/cr16/cr16.h mod/gcc/config/cr16/cr16.h
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-05-20 16:16:16.000000000 +0530
@@ -0,0 +1,591 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+  }                                        \
+while (0)
+#endif
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+   values must be in memory.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+  (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Macros to check the range of integers . These macros were used across
+   the port, majorly in constraints.md, predicates.md files. */
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+#define IN_RANGE_P(VALUE, LOW, HIGH)                            \
+  ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))           \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+#define IN_RAN(VALUE, LOW, HIGH)                             \
+  (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))       \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0)
+
+/* This check is for sbit/cbit instruction.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+  int last_parm_in_reg;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#endif /* End of GCC_CR16_H.  */
diff -uprN orig/gcc/config/cr16/cr16-libgcc.s mod/gcc/config/cr16/cr16-libgcc.s
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,568 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
diff -uprN orig/gcc/config/cr16/cr16.md mod/gcc/config/cr16/cr16.md
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-05-20 16:29:51.000000000 +0530
@@ -0,0 +1,1271 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+;;  Register numbers
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates & Constraints
+(include "predicates.md")
+(include "constraints.md")
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+   (UNSPEC_RETURN_ADDR          5)
+  ]
+)
+
+;; Attributes
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+;;  Code Macro Definitions
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;; Arithmetic Instuction  Patterns
+;;
+;; Addition insns.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0")
+		 (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 0);
+  "
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+		 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
+  ""
+  "addd\t%2, %0"
+  [(set_attr "length" "2,2,4,4,6")]
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "addw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+		 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "addb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(minus:DI (match_operand:DI 1 "register_operand" "")
+		  (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(minus:DI (match_operand:DI 1 "register_operand" "0")
+		  (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 1);
+  "
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,0")
+		  (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
+  ""
+  "subd\t%2, %0"
+  [(set_attr "length" "4,6")]
+)
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+		  (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "subw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(minus:QI (match_operand:QI 1 "register_operand" "0,0")
+		  (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "subb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Multiply and Accumulate Instructions
+(define_insn "smachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macsw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "umachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macuw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_set_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Logical Instructions - and
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(and:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 0);
+  "
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(and:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - or 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ior:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 1);
+  "
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - xor 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(xor:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 2);
+  "
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "xord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(xor:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(not:DI (match_operand:DI 1 "register_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "register_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
+  ""
+  "ashub\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c")
+	(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
+  ""
+  "ashuw\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
+  ""
+  "ashud\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "ashrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
+  ""
+  "ashub\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
+  ""
+  "ashuw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
+  ""
+  "ashud\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashub\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashuw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrdi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "ashud\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "reg_or_int_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "lshrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_operand" "Q")))]
+  ""
+  "lshb\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_operand" "R")))]
+  ""
+  "lshw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_operand" "S")))]
+  ""
+  "lshd\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshb\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "lshd\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "general_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "nonmemory_operand" "")))
+    (clobber (match_scratch:HI 2 "=r"))] ) ]
+  ""
+  "")
+
+;;  Scond Instructions
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 2 "register_operand" "")
+		 (match_operand:CR16IM 3 "nonmemory_operand" "")))
+   (set (match_operand:HI 0 "register_operand")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  ""
+)
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
+  ""
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "sCOND_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  "s%d1\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "jump_return"
+  [(parallel
+    [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
+     (return)])]
+  "reload_completed"
+  "jump\t(ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
+      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      {
+	operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
+        return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+      }
+  }
+  [(set_attr "length" "6")]
+)
+
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+              (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop\t"
+)
+
+;; PIC
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
diff -uprN orig/gcc/config/cr16/cr16.opt mod/gcc/config/cr16/cr16.opt
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,51 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2010 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
diff -uprN orig/gcc/config/cr16/cr16-protos.h mod/gcc/config/cr16/cr16-protos.h
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,100 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+#endif /* RTX_CODE.  */
+
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+extern const char *cr16_emit_add_sub_di (rtx *, int);
+extern const char *cr16_emit_logical_di (rtx *, int);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
diff -uprN orig/gcc/config/cr16/divmodhi3.c mod/gcc/config/cr16/divmodhi3.c
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
diff -uprN orig/gcc/config/cr16/predicates.md mod/gcc/config/cr16/predicates.md
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-05-20 16:27:09.000000000 +0530
@@ -0,0 +1,224 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;;  Predicates
+
+;; Predicates for sbit/cbit instructions
+;; bit operand used for the generation of bit insn generation
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Predicates for shift instructions
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0;
+})
+
+;; Predicates for jump/call instructions
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+(define_predicate "hard_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) <= 15")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Helper predicate 
+(define_predicate "reg_or_int_operand"
+  (ior (match_code "const_int")
+       (match_operand 0 "register_operand")))
+
+;;
+;;
+;; Atithmetic/logical predicates
+
+;; QI Helper
+(define_predicate "arith_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) 
+                || (INTVAL (op) != 11))) ? 1 : 0 ; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "reg_qi_int_operand"
+  (ior (match_operand 0 "arith_qi_operand")
+       (match_operand 0 "register_operand")))
+
+;; HI Helper
+(define_predicate "arith_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "reg_hi_int_operand"
+  (ior (match_operand 0 "arith_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "reg_si_int_operand"
+  (ior (match_operand 0 "const_int_operand")
+       (match_operand 0 "register_operand")))
+
+;;
+;; Shift predicates
+
+;; QI Helper
+(define_predicate "shift_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_qi_int_operand"
+  (ior (match_operand 0 "shift_qi_operand")
+       (match_operand 0 "register_operand")))
+;; HI Helper
+(define_predicate "shift_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_hi_int_operand"
+  (ior (match_operand 0 "shift_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "shift_si_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_si_int_operand"
+  (ior (match_operand 0 "shift_si_operand")
+       (match_operand 0 "register_operand")))
diff -uprN orig/gcc/config/cr16/t-cr16 mod/gcc/config/cr16/t-cr16
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,58 @@
+# CR16 Target Makefile
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+LIB2ADDEH = $(srcdir)/config/cr16/unwind-dw2-cr16.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-c.c
+
+
+MULTILIB_OPTIONS     = fPIC mint32 
+MULTILIB_DIRNAMES    = far-pic int32 
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
diff -uprN orig/gcc/config/cr16/unwind-dw2-cr16.c mod/gcc/config/cr16/unwind-dw2-cr16.c
--- orig/gcc/config/cr16/unwind-dw2-cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2-cr16.c	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,1597 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2008, 2009, 2010  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
+#endif
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  void *reg[DWARF_FRAME_REGISTERS+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[DWARF_FRAME_REGISTERS+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+  unsigned u2 __attribute__ ((mode (HI)));
+  unsigned u4 __attribute__ ((mode (SI)));
+  unsigned u8 __attribute__ ((mode (DI)));
+  signed s2 __attribute__ ((mode (HI)));
+  signed s4 __attribute__ ((mode (SI)));
+  signed s8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+
+static inline int
+read_1u (const void *p) { return *(const unsigned char *) p; }
+
+static inline int
+read_1s (const void *p) { return *(const signed char *) p; }
+
+static inline int
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
+
+static inline int
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
+
+static inline unsigned int
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
+
+static inline int
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
+
+static inline unsigned long
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
+
+static inline unsigned long
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return context->flags & EXTENDED_CONTEXT_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  void *ptr;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  ptr = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) ptr;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) ptr;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+      return;
+    }
+  ptr = context->reg[index];
+    if ( size == sizeof(_Unwind_Word) )
+      * (_Unwind_Word *) ptr = val;
+    else {
+      typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
+      gcc_assert (index + 1  <  (int) sizeof(dwarf_reg_size_table));
+      * (_CR16_Unwind_Word *) ptr = val & 0xffff ;  /* low 16-bit.  */
+      ptr = context->reg[index + 1];
+      * (_CR16_Unwind_Word *) ptr = val >> 16 ;  /* high 16-bit.  */
+         }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+		    _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
+
+  context->by_value[index] = 1;
+  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+#endif
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* Immediately following the augmentation are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
+   onto the stack to start.  */
+
+static _Unwind_Word
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
+		  struct _Unwind_Context *context, _Unwind_Word initial)
+{
+  _Unwind_Word stack[64];	/* ??? Assume this is enough.  */
+  int stack_elt;
+
+  stack[0] = initial;
+  stack_elt = 1;
+
+  while (op_ptr < op_end)
+    {
+      enum dwarf_location_atom op = *op_ptr++;
+      _Unwind_Word result;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      switch (op)
+	{
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	  result = op - DW_OP_lit0;
+	  break;
+
+	case DW_OP_addr:
+	  result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
+	  op_ptr += sizeof (void *);
+	  break;
+
+	case DW_OP_GNU_encoded_addr:
+	  {
+	    _Unwind_Ptr presult;
+	    op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+	    result = presult;
+	  }
+	  break;
+
+	case DW_OP_const1u:
+	  result = read_1u (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const1s:
+	  result = read_1s (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const2u:
+	  result = read_2u (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const2s:
+	  result = read_2s (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const4u:
+	  result = read_4u (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const4s:
+	  result = read_4s (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const8u:
+	  result = read_8u (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_const8s:
+	  result = read_8s (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_constu:
+	  op_ptr = read_uleb128 (op_ptr, &utmp);
+	  result = (_Unwind_Word)utmp;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &stmp);
+	  result = (_Unwind_Sword)stmp;
+	  break;
+
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+	  result = _Unwind_GetGR (context, op - DW_OP_reg0);
+	  break;
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  result = _Unwind_GetGR (context, reg);
+	  break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+	  break;
+	case DW_OP_bregx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+	  break;
+
+	case DW_OP_dup:
+	  gcc_assert (stack_elt);
+	  result = stack[stack_elt - 1];
+	  break;
+
+	case DW_OP_drop:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+	  goto no_push;
+
+	case DW_OP_pick:
+	  offset = *op_ptr++;
+	  gcc_assert (offset < stack_elt - 1);
+	  result = stack[stack_elt - 1 - offset];
+	  break;
+
+	case DW_OP_over:
+	  gcc_assert (stack_elt >= 2);
+	  result = stack[stack_elt - 2];
+	  break;
+
+	case DW_OP_swap:
+	  {
+	    _Unwind_Word t;
+	    gcc_assert (stack_elt >= 2);
+	    t = stack[stack_elt - 1];
+	    stack[stack_elt - 1] = stack[stack_elt - 2];
+	    stack[stack_elt - 2] = t;
+	    goto no_push;
+	  }
+
+	case DW_OP_rot:
+	  {
+	    _Unwind_Word t1, t2, t3;
+
+	    gcc_assert (stack_elt >= 3);
+	    t1 = stack[stack_elt - 1];
+	    t2 = stack[stack_elt - 2];
+	    t3 = stack[stack_elt - 3];
+	    stack[stack_elt - 1] = t2;
+	    stack[stack_elt - 2] = t3;
+	    stack[stack_elt - 3] = t1;
+	    goto no_push;
+	  }
+
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	case DW_OP_abs:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_plus_uconst:
+	  /* Unary operations.  */
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  result = stack[stack_elt];
+
+	  switch (op)
+	    {
+	    case DW_OP_deref:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		result = (_Unwind_Ptr) read_pointer (ptr);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		switch (*op_ptr++)
+		  {
+		  case 1:
+		    result = read_1u (ptr);
+		    break;
+		  case 2:
+		    result = read_2u (ptr);
+		    break;
+		  case 4:
+		    result = read_4u (ptr);
+		    break;
+		  case 8:
+		    result = read_8u (ptr);
+		    break;
+		  default:
+		    gcc_unreachable ();
+		  }
+	      }
+	      break;
+
+	    case DW_OP_abs:
+	      if ((_Unwind_Sword) result < 0)
+		result = -result;
+	      break;
+	    case DW_OP_neg:
+	      result = -result;
+	      break;
+	    case DW_OP_not:
+	      result = ~result;
+	      break;
+	    case DW_OP_plus_uconst:
+	      op_ptr = read_uleb128 (op_ptr, &utmp);
+	      result += (_Unwind_Word)utmp;
+	      break;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_le:
+	case DW_OP_ge:
+	case DW_OP_eq:
+	case DW_OP_lt:
+	case DW_OP_gt:
+	case DW_OP_ne:
+	  {
+	    /* Binary operations.  */
+	    _Unwind_Word first, second;
+	    gcc_assert (stack_elt >= 2);
+	    stack_elt -= 2;
+
+	    second = stack[stack_elt];
+	    first = stack[stack_elt + 1];
+
+	    switch (op)
+	      {
+	      case DW_OP_and:
+		result = second & first;
+		break;
+	      case DW_OP_div:
+		result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+		break;
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		result = second % first;
+		break;
+	      case DW_OP_mul:
+		result = second * first;
+		break;
+	      case DW_OP_or:
+		result = second | first;
+		break;
+	      case DW_OP_plus:
+		result = second + first;
+		break;
+	      case DW_OP_shl:
+		result = second << first;
+		break;
+	      case DW_OP_shr:
+		result = second >> first;
+		break;
+	      case DW_OP_shra:
+		result = (_Unwind_Sword) second >> first;
+		break;
+	      case DW_OP_xor:
+		result = second ^ first;
+		break;
+	      case DW_OP_le:
+		result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ge:
+		result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_eq:
+		result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+		break;
+	      case DW_OP_lt:
+		result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+		break;
+	      case DW_OP_gt:
+		result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ne:
+		result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  }
+	  break;
+
+	case DW_OP_skip:
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_bra:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  if (stack[stack_elt] != 0)
+	    op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_nop:
+	  goto no_push;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* Decode DWARF 2 call frame information. Takes pointers the
+   instruction sequence to decode, current register information and
+   CIE info, and the PC range to evaluate.  */
+
+static void
+execute_cfa_program (const unsigned char *insn_ptr,
+		     const unsigned char *insn_end,
+		     struct _Unwind_Context *context,
+		     _Unwind_FrameState *fs)
+{
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
+	      (_Unwind_Word)reg2;
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
+
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_GNU_window_save:
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  for (reg = 16; reg < 32; ++reg)
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	    }
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#else
+      return _URC_END_OF_STACK;
+#endif
+    }
+
+  fs->pc = context->bases.func;
+
+  cie = get_cie (fde);
+  insn = extract_cie_info (cie, context, fs);
+  if (insn == NULL)
+    /* CIE contained unknown augmentation.  */
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* First decode all the insns in the CIE.  */
+  end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  context.flags = EXTENDED_CONTEXT_BIT;
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
+
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+	{
+	case REG_SAVED_REG:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+	  break;
+	default:
+	  state_in->reg_or_offset[reg] = 0;
+	  break;
+	}
+    }
+
+  state_in->cfa_offset = fs.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+		     _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef EH_RETURN_STACKADJ_RTX
+  /* Special handling here: Many machines do not use a frame pointer,
+     and track the CFA only through offsets from the stack pointer from
+     one frame to the next.  In this case, the stack pointer is never
+     stored, so it has no saved address in the context.  What we do
+     have is the CFA from the previous stack frame.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+	const unsigned char *exp = fs->regs.cfa_exp;
+	_uleb128_t len;
+
+	exp = read_uleb128 (exp, &len);
+	cfa = (void *) (_Unwind_Ptr)
+	  execute_stack_op (exp, exp + len, &orig_context, 0);
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  context->cfa = cfa;
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
+    switch (fs->regs.reg[i].how)
+      {
+      case REG_UNSAVED:
+      case REG_UNDEFINED:
+	break;
+
+      case REG_SAVED_OFFSET:
+	_Unwind_SetGRPtr (context, i,
+			  (void *) (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_REG:
+	if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+	  _Unwind_SetGRValue (context, i,
+			      _Unwind_GetGR (&orig_context,
+					     fs->regs.reg[i].loc.reg));
+	else
+	  _Unwind_SetGRPtr (context, i,
+			    _Unwind_GetGRPtr (&orig_context,
+					      fs->regs.reg[i].loc.reg));
+	break;
+
+      case REG_SAVED_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRPtr (context, i, (void *) val);
+	}
+	break;
+
+      case REG_SAVED_VAL_OFFSET:
+	_Unwind_SetGRValue (context, i,
+			    (_Unwind_Internal_Ptr)
+			    (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_VAL_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRValue (context, i, val);
+	}
+	break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+    context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      /* Do any necessary initialization to access arbitrary stack frames. \
+	 On the SPARC, this means flushing the register windows.  */	   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context,
+		   void *outer_cfa, void *outer_ra)
+{
+  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  _Unwind_FrameState fs;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#if __GTHREADS
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
+	&& dwarf_reg_size_table[0] == 0)
+      init_dwarf_reg_size_table ();
+  }
+#else
+  if (dwarf_reg_size_table[0] == 0)
+    init_dwarf_reg_size_table ();
+#endif
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.cfa_offset -= context->args_size ;
+  uw_update_context_1 (context, &fs);
+
+  /* If the return address column was saved in a register in the
+     initialization context, then we can't see it in the given
+     call frame data.  So have the initialization context tell us.  */
+  context->ra = __builtin_extract_return_addr (outer_ra);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+  asm ("");
+}
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+
+#define uw_install_context(CURRENT, TARGET)                              \
+  do                                                                     \
+    {                                                                    \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
+      handler = (void*)( ( (unsigned)handler ) >> 1 ) ;                  \
+      __builtin_eh_return (offset, handler);                             \
+    }                                                                    \
+  while (0)
+
+
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+	{
+	  _Unwind_Word w;
+	  _Unwind_Ptr p;
+	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	    {
+	      w = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &w, sizeof (_Unwind_Word));
+	    }
+	  else
+	    {
+	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      p = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &p, sizeof (_Unwind_Ptr));
+	    }
+	}
+      else if (t && c && t != c)
+	memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
+      if (STACK_GROWS_DOWNWARD)
+	return target_cfa - current->cfa + target->args_size;
+      else
+	return current->cfa - target_cfa - target->args_size;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (STACK_GROWS_DOWNWARD)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff -uprN orig/gcc/config/cr16/unwind-dw2.h mod/gcc/config/cr16/unwind-dw2.h
--- orig/gcc/config/cr16/unwind-dw2.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2.h	2011-05-20 15:17:13.000000000 +0530
@@ -0,0 +1,87 @@
+/* DWARF2 frame unwind data structure.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* A target can override (perhaps for backward compatibility) how
+   many dwarf2 columns are unwound.  */
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* The result of interpreting the frame unwind info for a frame.
+   This is all symbolic at this point, as none of the values can
+   be resolved until the target pc is located.  */
+typedef struct
+{
+  /* Each register save state can be described in terms of a CFA slot,
+     another register, or a location expression.  */
+  struct frame_state_reg_info
+  {
+    struct {
+      union {
+	_Unwind_Word reg;
+	_Unwind_Sword offset;
+	const unsigned char *exp;
+      } loc;
+      enum {
+	REG_UNSAVED,
+	REG_SAVED_OFFSET,
+	REG_SAVED_REG,
+	REG_SAVED_EXP,
+	REG_SAVED_VAL_OFFSET,
+	REG_SAVED_VAL_EXP,
+	REG_UNDEFINED
+      } how;
+    } reg[DWARF_FRAME_REGISTERS+1];
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct frame_state_reg_info *prev;
+
+    /* The CFA can be described in terms of a reg+offset or a
+       location expression.  */
+    _Unwind_Sword cfa_offset;
+    _Unwind_Word cfa_reg;
+    const unsigned char *cfa_exp;
+    enum {
+      CFA_UNSET,
+      CFA_REG_OFFSET,
+      CFA_EXP
+    } cfa_how;
+  } regs;
+
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Sword data_align;
+  _Unwind_Word code_align;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+} _Unwind_FrameState;
+
diff -uprN orig/gcc/config.gcc mod/gcc/config.gcc
--- orig/gcc/config.gcc	2011-05-10 22:10:55.000000000 +0530
+++ mod/gcc/config.gcc	2011-05-20 15:17:32.000000000 +0530
@@ -926,6 +926,12 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+        tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} cr16/t-cr16 "
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        use_collect2=no
+        ;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
diff -uprN orig/gcc/doc/extend.texi mod/gcc/doc/extend.texi
--- orig/gcc/doc/extend.texi	2011-05-05 05:04:37.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-05-20 15:17:35.000000000 +0530
@@ -2551,7 +2551,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
diff -uprN orig/gcc/doc/install.texi mod/gcc/doc/install.texi
--- orig/gcc/doc/install.texi	2011-05-11 23:58:14.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-05-20 15:17:36.000000000 +0530
@@ -3205,6 +3205,29 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
diff -uprN orig/gcc/doc/invoke.texi mod/gcc/doc/invoke.texi
--- orig/gcc/doc/invoke.texi	2011-05-14 15:09:38.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-05-20 15:17:36.000000000 +0530
@@ -497,6 +497,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32 -mbit-ops
+-mdata-model=@var{model}}
+
 @emph{Darwin Options}
 @gccoptlist{-all_load  -allowable_client  -arch  -arch_errors_fatal @gol
 -arch_only  -bind_at_load  -bundle  -bundle_loader @gol
@@ -9951,6 +9957,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * Darwin Options::
 * DEC Alpha Options::
 * DEC Alpha/VMS Options::
@@ -10726,6 +10733,46 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mbit-ops
+@opindex mbit-ops
+Generates sbit/cbit instructions for bit manipulations.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near},
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
 @node Darwin Options
 @subsection Darwin Options
 @cindex Darwin options
diff -uprN orig/gcc/doc/md.texi mod/gcc/doc/md.texi
--- orig/gcc/doc/md.texi	2011-05-05 05:04:37.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-05-20 15:17:36.000000000 +0530
@@ -1775,6 +1775,40 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item Hewlett-Packard PA-RISC---@file{config/pa/pa.h}
 @table @code
 @item a
diff -uprN orig/libgcc/config/cr16/crti.S mod/libgcc/config/cr16/crti.S
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-05-20 16:40:32.000000000 +0530
@@ -0,0 +1,54 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
diff -uprN orig/libgcc/config/cr16/crtlibid.S mod/libgcc/config/cr16/crtlibid.S
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-05-20 16:40:53.000000000 +0530
@@ -0,0 +1,28 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
diff -uprN orig/libgcc/config/cr16/crtn.S mod/libgcc/config/cr16/crtn.S
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-05-20 16:40:41.000000000 +0530
@@ -0,0 +1,44 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
diff -uprN orig/libgcc/config/cr16/t-cr16 mod/libgcc/config/cr16/t-cr16
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-05-20 15:16:40.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
diff -uprN orig/libgcc/config.host mod/libgcc/config.host
--- orig/libgcc/config.host	2011-03-23 01:28:18.000000000 +0530
+++ mod/libgcc/config.host	2011-05-20 15:16:40.000000000 +0530
@@ -79,6 +79,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+	;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -237,6 +239,10 @@ bfin*-linux-uclibc*)
 	;;
 bfin*-*)
         ;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none)
 	extra_parts="crtbegin.o crtend.o"
 	;;
diff -uprN orig/libstdc++-v3/configure mod/libstdc++-v3/configure
--- orig/libstdc++-v3/configure	2011-04-10 21:50:42.000000000 +0530
+++ mod/libstdc++-v3/configure	2011-05-20 15:16:31.000000000 +0530
@@ -26492,6 +26492,9 @@ case "${host}" in
     # This is a freestanding configuration; there is nothing to do here.
     ;;
 
+  cr16-*-*)
+    ;;
+
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
     SECTION_FLAGS='-ffunction-sections -fdata-sections'

[-- Attachment #3: unwind.diff --]
[-- Type: application/octet-stream, Size: 2686 bytes --]

3c3
<    2008, 2009, 2010  Free Software Foundation, Inc.
---
>    2008, 2009, 2010, 2011  Free Software Foundation, Inc.
39a40,43
> #ifdef HAVE_SYS_SDT_H
> #include <sys/sdt.h>
> #endif
> 
210a215
> 
212c217,222
<     if ( size == sizeof(_Unwind_Word) )
---
> 
>   if (size == sizeof(_Unwind_Ptr))
>     * (_Unwind_Ptr *) ptr = val;
>   else
>     {
>       gcc_assert (size == sizeof(_Unwind_Word));
214,220c224
<     else {
<       typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
<       gcc_assert (index + 1  <  (int) sizeof(dwarf_reg_size_table));
<       * (_CR16_Unwind_Word *) ptr = val & 0xffff ;  /* low 16-bit.  */
<       ptr = context->reg[index + 1];
<       * (_CR16_Unwind_Word *) ptr = val >> 16 ;  /* high 16-bit.  */
<          }
---
>     }
359c363,372
<   /* Immediately following the augmentation are the code and
---
>   /* After the augmentation resp. pointer for "eh" augmentation
>      follows for CIE version >= 4 address size byte and
>      segment size byte.  */
>   if (__builtin_expect (cie->version >= 4, 0))
>     {
>       if (p[0] != sizeof (void *) || p[1] != 0)
> 	return NULL;
>       p += 2;
>     }
>   /* Immediately following this are the code and
1406d1418
<     context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
1467c1479,1480
<   fs.regs.cfa_offset -= context->args_size ;
---
>   fs.regs.cfa_offset = 0;
> 
1486a1500,1504
>   /* We only want to use stap probes starting with v3.  Earlier
>      versions added too much startup cost.  */
> #if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
>   STAP_PROBE2 (libgcc, unwind, cfa, handler);
> #else
1487a1506
> #endif
1494,1502c1513,1520
< 
< #define uw_install_context(CURRENT, TARGET)                              \
<   do                                                                     \
<     {                                                                    \
<       long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
<       void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
<       handler = (void*)( ( (unsigned)handler ) >> 1 ) ;                  \
<       __builtin_eh_return (offset, handler);                             \
<     }                                                                    \
---
> #define uw_install_context(CURRENT, TARGET)				\
>   do									\
>     {									\
>       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
>       void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
>       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
>       __builtin_eh_return (offset, handler);				\
>     }									\
1505,1506d1522
< 
< 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-05-20 13:59   ` Sumanth Gundapaneni
@ 2011-05-20 17:07     ` Joseph S. Myers
  2011-05-30 15:44       ` Sumanth Gundapaneni
                         ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Joseph S. Myers @ 2011-05-20 17:07 UTC (permalink / raw)
  To: Sumanth Gundapaneni; +Cc: gcc-patches, rth, Jayant R. Sonar

On Fri, 20 May 2011, Sumanth Gundapaneni wrote:

> > There is no such target as target-mudflap,
> The configure file is altered as per your suggestion.

Please remove the remaining toplevel configure changes from the patch.

I moved the code disabling libgcj for particular targets out of the 
general case over targets, into a separate case statement - and removed 
most of it by simply disabling Java for targets without a libffi port.  
You don't have a libffi port, so Java is automatically disabled.  With my 
toplevel cleanups, it's a lot less likely that a new port is going to need 
toplevel configure changes at all.

If you want to enable GDB for some targets but not others, that's not a 
matter for a GCC-port patch; such a toplevel change would best be sent in 
the context of a GDB port submission.  Because port submissions are large 
patches, it's always good to split out separable pieces like that anyway.

> >The libstdc++-v3 changes also seem suspicious.  
> The configure files of libstdc++-v3 are changed as advised.  

Now you seem to have a stray change to the generated file 
libstdc++-v3/configure, with no corresponding source file change.  That's 
always wrong; such files should only ever be changes by regeneration from 
the corresponding sources.  Again, you can probably just eliminate this 
change and make the patch smaller.

> >I'm still not satisfied with the forked version of the unwind code.  
> >Please show a diff of what the minimum changes would be to the 
> I have attached diff file (unwind.diff) for your reference. Please
> go through it. As explicated before the CR16's programming memory 

I said "a diff of what the minimum changes would be to the 
target-independent unwind-dw2-* files for CR16 to work with those files 
based on behavior in those files being conditioned as needed on target 
macros defined by CR16", not a raw diff between two files, but the changes 
appear small enough that it certainly looks like you should be able to 
define a few target macros (in a file in libgcc/config/cr16 listed in 
libgcc_tm_file) and make the code in unwind-dw2-* use those macros, 
instead of having separate copies of the files.


Since you first submitted the port, a file contrib/config-list.mk has been 
added to support all-targets builds, to help detect if a target stops 
building cleanly.  You should add the new target cr16-elf to this file.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-05-20 17:07     ` Joseph S. Myers
@ 2011-05-30 15:44       ` Sumanth Gundapaneni
  2011-06-09 10:15       ` Sumanth Gundapaneni
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-05-30 15:44 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, rth, Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 3475 bytes --]

Hi Joseph and Richard,

Thanks for your time in reviewing the CR16 port and once again I am
grateful for your valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications
as suggested by Joseph in his previous mail.

For your kind information, I am providing the recent posts regarding
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html
Third post   : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg00624.html
Fourth post  : http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01441.html

Please review the patch and let me know if there should be any
modifications in it.

Joseph, please go through my explanation for your comments.

>Please remove the remaining top level configure changes from the patch.

The top level configure changes have been removed as advised.


>Now you seem to have a stray change to the generated file
>libstdc++-v3/configure. Again, you can probably just eliminate this

The configure changes in libtsdc++-v3 are removed too and you can find
the same in the updated patch.


>and make the code in unwind-dw2-* use those macros,
>instead of having separate copies of the files.

A new file unwind-helper.h file is created in libgcc/config/cr16 directory
as per your suggestion and defined a few macros in this newly defined file
which are getting called from gcc/unwind-dw2.c. Please review the same
and do let me know for further modifications, if any. We have identified
issues related to exception handling using prints in unwind code and
will debug the same to a greater extent in near future with further
development of GNU based tools.


>Since you first submitted the port, a file contrib/config-list.mk

"cr16-elf" is added to config-list.mk file.


gcc/ChangeLog:
--------------
2011-05-28      Sumanth G <sumanth.gundapaneni@kpitcummins.com>
                Jayant R Sonar <jayant.sonar@kpitcummins.com>

        * config.gcc: Add cr16-* support.

        * doc/extend.texi: Document cr16 extensions.
        * doc/install.texi: Document cr16 install.
        * doc/invoke.texi: Document cr16 options.
        * doc/md.texi: Document cr16 constraints.

        * config/cr16/cr16.c: New file.
        * config/cr16/cr16.h: New file.
        * config/cr16/cr16.md: New file.
        * config/cr16/cr16.opt: New file.
        * config/cr16/cr16-libgcc.s: New file.
        * config/cr16/cr16-protos.h: New file.

        * config/cr16/divmodhi3.c: New file.
        * config/cr16/predicates.md: New file.
        * config/cr16/constraints.md: New file.
        * config/cr16/t-cr16: New file.

libgcc/ChangeLog:
-----------------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
                Jayant R Sonar <jayant.sonar@kpitcummins.com>

        * config.host: Add National Semiconductor CR16 target (cr16-*-*).
        * config/cr16/crti.S: New file.
        * config/cr16/crtlibid.S: New file.
        * config/cr16/crtn.S: New file.
        * config/cr16/t-cr16: New file.
        * config/cr16/unwind-helper.h: New file.

contrib/ChangeLog:
----------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
                Jayant R Sonar <jayant.sonar@kpitcummins.com>

        * config-list.mk: Add National Semiconductor CR16 target.

Thanks in advance,
Sumanth G,
PUNE (India).


[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 173284 bytes --]

--- orig/contrib/config-list.mk	2011-05-05 07:17:47.000000000 +0530
+++ mod/contrib/config-list.mk	2011-05-30 17:16:35.000000000 +0530
@@ -17,7 +17,7 @@ LIST = alpha-linux-gnu alpha-freebsd6 al
   arm-linux-androideabi arm-uclinux_eabi arm-ecos-elf arm-eabi \
   arm-symbianelf arm-rtems arm-elf arm-wince-pe avr-rtems avr-elf \
   bfin-elf bfin-uclinux bfin-linux-uclibc bfin-rtems bfin-openbsd \
-  cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
+  cr16-elf cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
   fr30-elf frv-elf frv-linux h8300-elf h8300-rtems hppa-linux-gnu \
   hppa-linux-gnuOPT-enable-sjlj-exceptions=yes hppa64-linux-gnu \
   hppa2.0-hpux10.1 hppa64-hpux11.3 \
--- orig/gcc/config/cr16/constraints.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/constraints.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,81 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;; Constraints
+;; Register constraints
+(define_register_constraint "b" "NOSP_REGS"
+  "@no sp registers")
+
+(define_register_constraint "c" "SHORT_REGS"
+  "@short registers")
+
+(define_register_constraint "d" "LONG_REGS"
+  "@long registers")
+
+;; Integer constraints.
+(define_constraint "I"
+  "A signed 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "J"
+  "A signed 5-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)")))
+
+(define_constraint "K"
+  "A signed 6-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)")))
+
+(define_constraint "L"
+  "A unsigned 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "M"
+  "A unsigned and customized  4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) || (ival != 11)))  ")))
+
+(define_constraint "N"
+  "A signed 16-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -32768, 32767)")))
+
+(define_constraint "O"
+  "A unsigned 20-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 1048575)")))
+
+(define_constraint "Q"
+  "A shift QI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 7)")))
+
+(define_constraint "R"
+  "A shift HI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 15)")))
+
+(define_constraint "S"
+  "A shift SI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 31)")))
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,2212 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Structure for stack computations.  */
+
+/* variable definitions in the struture
+   args_size             Number of bytes saved on the stack for local 
+			 variables
+
+   reg_size		 Number of bytes saved on the stack for 
+			 non-scratch registers
+
+   total_size 		 The sum of 2 sizes: locals vars and padding byte 
+			 for saving the registers. Used in expand_prologue() 
+			 and expand_epilogue()
+
+   last_reg_to_save      Will hold the number of the last register the 
+			 prologue saves, -1 if no register is saved
+
+   save_regs[16]	 Each object in the array is a register number. 
+			 Mark 1 for registers that need to be saved
+
+   num_regs		 Number of registers saved
+
+   initialized		 Non-zero if frame size already calculated, not 
+			 used yet
+
+   function_makes_calls  Does the function make calls ? not used yet.  */
+
+struct cr16_frame_info
+{
+  unsigned long var_size;
+  unsigned long args_size;
+  unsigned int  reg_size;
+  unsigned long total_size;
+  long          last_reg_to_save;
+  long          save_regs[FIRST_PSEUDO_REGISTER];
+  int           num_regs;
+  int           initialized;
+  int           function_makes_calls;
+};
+
+/* Current frame information calculated by cr16_compute_frame_size.  */
+static struct cr16_frame_info current_frame_info;
+
+/* Static Variables.  */
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* TARGETM Function Prototypes and forward declarations  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
+static bool cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+static bool cr16_legitimate_constant_p   (enum machine_mode, rtx);
+static rtx cr16_function_value (const_tree, const_tree, bool);
+static rtx cr16_libcall_value (enum machine_mode, const_rtx);
+static bool cr16_function_value_regno_p (const unsigned int);
+static bool cr16_legitimate_address_p (enum machine_mode, rtx, bool);
+static void cr16_print_operand (FILE *, rtx, int);
+static void cr16_print_operand_address (FILE *, rtx);
+static int cr16_address_cost (rtx, bool);
+static int cr16_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
+static int cr16_memory_move_cost (enum machine_mode, reg_class_t, bool);
+
+/* Stack layout and calling conventions.  */
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P    cr16_legitimate_constant_p
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P     cr16_legitimate_address_p
+
+/* Returning function value.  */
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE cr16_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE cr16_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
+
+/* printing the values.  */
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND cr16_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
+
+/* Table of machine attributes.  */
+static const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity }.  */
+  {"interrupt", 0, 0, false, true, true, NULL, false},
+  {NULL, 0, 0, false, false, false, NULL, false}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS 
+       || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, 
+		      int size ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture");
+	}
+      else
+	error ("invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array current_frame_info.save_regs and the variable 
+   current_frame_info.reg_size. The index of current_frame_info.save_regs 
+   is numbers of register, each will get 1 if we need to save it in the 
+   current function, 0 if not. current_frame_info.reg_size is the total sum 
+   of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  current_frame_info.last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  current_frame_info.reg_size = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (fixed_regs[regno])
+	{
+	  current_frame_info.save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    current_frame_info.save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    current_frame_info.save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  current_frame_info.save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (current_frame_info.save_regs[regno] == 1)
+      {
+	current_frame_info.last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
+	else
+	  current_frame_info.reg_size += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  current_frame_info.var_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = current_frame_info.var_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  current_frame_info.var_size += padding_locals;
+  current_frame_info.total_size = current_frame_info.var_size 
+			   + (ACCUMULATE_OUTGOING_ARGS
+			    ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use current_frame_info.reg_size.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use current_frame_info.var_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size 
+	    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
+        return 0;
+ 
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  if ((TARGET_INT32)
+      && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
+     return 0;
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Returns register number for function return value.*/
+static inline unsigned int
+cr16_ret_register (void)
+{
+  return 0;
+}
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, cr16_ret_register ());
+}
+
+/* Returning function value.  */
+
+/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.  */
+static bool
+cr16_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   library function returns a value of mode MODE.  */
+static rtx
+cr16_libcall_value (enum machine_mode mode,
+                   const_rtx func ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   function returns a value of data type VALTYPE.  */
+static rtx
+cr16_function_value (const_tree type,
+                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE(type), cr16_ret_register ());
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  cum->last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!cum->last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+     C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+     C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+     NOTE: @BRO is added using unspec:BRO
+     NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of TARGET_LEGITIMATE_ADDRESS_P.  */
+static bool
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, bool strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "index + register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\ncr16 address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /* CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9.  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+
+/* Implement `TARGET_REGISTER_MOVE_COST'.  */
+static int
+cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                        reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
+{
+  return (to != GENERAL_REGS ? 8
+          : 2);
+}
+
+/* Implement `TARGET_MEMORY_MOVE_COST'.  */
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+static int
+cr16_memory_move_cost (enum machine_mode mode,
+                       reg_class_t rclass ATTRIBUTE_UNUSED,
+                       bool in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+static void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "unspec!!");
+	  switch (XINT (x, 1))
+	    {
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+static void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "unspec 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of current_frame_info.save_regs[], going from 0 until 
+     current_frame_info.last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= current_frame_info.last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) 
+	     && (i <= current_frame_info.last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!current_frame_info.save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* POP.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
+    {
+      if (current_frame_info.save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = current_frame_info.last_reg_to_save + 1;
+  to = current_frame_info.last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = current_frame_info.last_reg_to_save; i >= 0;)
+    {
+      if (!current_frame_info.save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && current_frame_info.save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (SImode, dwarf,
+					REG_NOTES (insn));
+}
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
+    return;
+
+  if (current_frame_info.last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue
+			(GEN_INT (current_frame_info.reg_size)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
+			&& (current_frame_info.reg_size 
+			 == CR16_UNITS_PER_DWORD));
+  
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (current_frame_info.last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static bool
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return
+	  || cfun->has_nonlocal_label || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+   Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P. In cr16c treat legitimize float 
+   constant as an immediate operand.  */
+static bool
+cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			    rtx x ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+void
+notice_update_cc (rtx exp)
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
+
+/* Helper function for md file. This function is used to emit arithmetic 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_add_sub_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi0_op[2] ;
+  rtx hi1_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
+  hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
+  hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
+
+  if (num == 0)
+    {
+        output_asm_insn ("addd\t%1, %0", lo_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("subd\t%1, %0", lo_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else
+    return "";
+
+}
+
+
+/* Helper function for md file. This function is used to emit logical 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_logical_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
+  if (num == 0)
+    {
+        output_asm_insn ("andd\t%1, %0", lo_op) ;
+        output_asm_insn ("andd\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("ord\t%1, %0", lo_op) ;
+        output_asm_insn ("ord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 2)
+    {
+        output_asm_insn ("xord\t%1, %0", lo_op) ;
+        output_asm_insn ("xord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else
+    return "";
+}
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,591 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+  }                                        \
+while (0)
+#endif
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+   values must be in memory.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+  (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Macros to check the range of integers . These macros were used across
+   the port, majorly in constraints.md, predicates.md files. */
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+#define IN_RANGE_P(VALUE, LOW, HIGH)                            \
+  ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))           \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+#define IN_RAN(VALUE, LOW, HIGH)                             \
+  (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))       \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0)
+
+/* This check is for sbit/cbit instruction.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+  int last_parm_in_reg;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#endif /* End of GCC_CR16_H.  */
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,568 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,1271 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+;;  Register numbers
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates & Constraints
+(include "predicates.md")
+(include "constraints.md")
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+   (UNSPEC_RETURN_ADDR          5)
+  ]
+)
+
+;; Attributes
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+;;  Code Macro Definitions
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;; Arithmetic Instuction  Patterns
+;;
+;; Addition insns.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0")
+		 (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 0);
+  "
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+		 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
+  ""
+  "addd\t%2, %0"
+  [(set_attr "length" "2,2,4,4,6")]
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "addw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+		 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "addb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(minus:DI (match_operand:DI 1 "register_operand" "")
+		  (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(minus:DI (match_operand:DI 1 "register_operand" "0")
+		  (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 1);
+  "
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,0")
+		  (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
+  ""
+  "subd\t%2, %0"
+  [(set_attr "length" "4,6")]
+)
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+		  (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "subw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(minus:QI (match_operand:QI 1 "register_operand" "0,0")
+		  (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "subb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Multiply and Accumulate Instructions
+(define_insn "smachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macsw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "umachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macuw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_set_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Logical Instructions - and
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(and:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 0);
+  "
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(and:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - or 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ior:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 1);
+  "
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - xor 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(xor:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 2);
+  "
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "xord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(xor:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(not:DI (match_operand:DI 1 "register_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "register_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
+  ""
+  "ashub\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c")
+	(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
+  ""
+  "ashuw\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
+  ""
+  "ashud\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "ashrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
+  ""
+  "ashub\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
+  ""
+  "ashuw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
+  ""
+  "ashud\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashub\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashuw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrdi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "ashud\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "reg_or_int_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "lshrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_operand" "Q")))]
+  ""
+  "lshb\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_operand" "R")))]
+  ""
+  "lshw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_operand" "S")))]
+  ""
+  "lshd\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshb\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "lshd\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "general_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "nonmemory_operand" "")))
+    (clobber (match_scratch:HI 2 "=r"))] ) ]
+  ""
+  "")
+
+;;  Scond Instructions
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 2 "register_operand" "")
+		 (match_operand:CR16IM 3 "nonmemory_operand" "")))
+   (set (match_operand:HI 0 "register_operand")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  ""
+)
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
+  ""
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "sCOND_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  "s%d1\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "jump_return"
+  [(parallel
+    [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
+     (return)])]
+  "reload_completed"
+  "jump\t(ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
+      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      {
+	operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
+        return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+      }
+  }
+  [(set_attr "length" "6")]
+)
+
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+              (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop\t"
+)
+
+;; PIC
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,51 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2011 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,100 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+#endif /* RTX_CODE.  */
+
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+extern const char *cr16_emit_add_sub_di (rtx *, int);
+extern const char *cr16_emit_logical_di (rtx *, int);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,224 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;;  Predicates
+
+;; Predicates for sbit/cbit instructions
+;; bit operand used for the generation of bit insn generation
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Predicates for shift instructions
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0;
+})
+
+;; Predicates for jump/call instructions
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+(define_predicate "hard_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) <= 15")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Helper predicate 
+(define_predicate "reg_or_int_operand"
+  (ior (match_code "const_int")
+       (match_operand 0 "register_operand")))
+
+;;
+;;
+;; Atithmetic/logical predicates
+
+;; QI Helper
+(define_predicate "arith_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) 
+                || (INTVAL (op) != 11))) ? 1 : 0 ; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "reg_qi_int_operand"
+  (ior (match_operand 0 "arith_qi_operand")
+       (match_operand 0 "register_operand")))
+
+;; HI Helper
+(define_predicate "arith_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "reg_hi_int_operand"
+  (ior (match_operand 0 "arith_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "reg_si_int_operand"
+  (ior (match_operand 0 "const_int_operand")
+       (match_operand 0 "register_operand")))
+
+;;
+;; Shift predicates
+
+;; QI Helper
+(define_predicate "shift_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_qi_int_operand"
+  (ior (match_operand 0 "shift_qi_operand")
+       (match_operand 0 "register_operand")))
+;; HI Helper
+(define_predicate "shift_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_hi_int_operand"
+  (ior (match_operand 0 "shift_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "shift_si_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_si_int_operand"
+  (ior (match_operand 0 "shift_si_operand")
+       (match_operand 0 "register_operand")))
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,54 @@
+# CR16 Target Makefile
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+MULTILIB_OPTIONS     = fPIC mint32 
+MULTILIB_DIRNAMES    = far-pic int32 
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
--- orig/gcc/config.gcc	2011-05-28 13:32:57.000000000 +0530
+++ mod/gcc/config.gcc	2011-05-30 17:16:35.000000000 +0530
@@ -929,6 +929,13 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+	tm_file="elfos.h ${tm_file}"
+	tmake_file="${tmake_file} cr16/t-cr16 "
+	libgcc_tm_file="${libgcc_tm_file} cr16/unwind-helper.h"
+	extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+	use_collect2=no
+	;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
--- orig/gcc/doc/extend.texi	2011-05-25 22:48:29.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-05-30 17:16:35.000000000 +0530
@@ -2551,7 +2551,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
--- orig/gcc/doc/install.texi	2011-05-23 16:42:25.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-05-30 17:16:35.000000000 +0530
@@ -3199,6 +3199,29 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
--- orig/gcc/doc/invoke.texi	2011-05-25 16:30:14.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-05-30 17:16:35.000000000 +0530
@@ -497,6 +497,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32 -mbit-ops
+-mdata-model=@var{model}}
+
 @emph{Darwin Options}
 @gccoptlist{-all_load  -allowable_client  -arch  -arch_errors_fatal @gol
 -arch_only  -bind_at_load  -bundle  -bundle_loader @gol
@@ -9984,6 +9990,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * Darwin Options::
 * DEC Alpha Options::
 * DEC Alpha/VMS Options::
@@ -10759,6 +10766,46 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mbit-ops
+@opindex mbit-ops
+Generates sbit/cbit instructions for bit manipulations.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near},
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
 @node Darwin Options
 @subsection Darwin Options
 @cindex Darwin options
--- orig/gcc/doc/md.texi	2011-05-05 05:04:37.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-05-30 17:16:35.000000000 +0530
@@ -1775,6 +1775,40 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item Hewlett-Packard PA-RISC---@file{config/pa/pa.h}
 @table @code
 @item a
--- orig/gcc/unwind-dw2.c	2011-03-15 01:17:58.000000000 +0530
+++ mod/gcc/unwind-dw2.c	2011-05-30 17:16:35.000000000 +0530
@@ -219,8 +219,12 @@ _Unwind_SetGR (struct _Unwind_Context *c
     * (_Unwind_Ptr *) ptr = val;
   else
     {
+#if defined (__CR16__)
+      CR16_UW_SETGR(ptr,val,size,index,context);	
+#else
       gcc_assert (size == sizeof(_Unwind_Word));
       * (_Unwind_Word *) ptr = val;
+#endif
     }
 }
 
@@ -1416,6 +1420,9 @@ uw_update_context (struct _Unwind_Contex
        can change from frame to frame.  */
     context->ra = __builtin_extract_return_addr
       (_Unwind_GetPtr (context, fs->retaddr_column));
+#if defined( __CR16__ )
+    context->ra = CR16_UW_CONTEXT(context->ra) ;
+#endif
 }
 
 static void
@@ -1476,7 +1483,11 @@ uw_init_context_1 (struct _Unwind_Contex
   _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
   fs.regs.cfa_how = CFA_REG_OFFSET;
   fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+#if defined( __CR16__ )
+  fs.regs.cfa_offset -= CR16_ARGS_SIZE(context);
+#else
   fs.regs.cfa_offset = 0;
+#endif
 
   uw_update_context_1 (context, &fs);
 
@@ -1510,6 +1521,18 @@ _Unwind_DebugHook (void *cfa __attribute
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
 
+#if defined (__CR16__)
+#define uw_install_context(CURRENT, TARGET)				\
+  do									\
+    {									\
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      CR16_UW_CONTEXT(handler);						\
+      _Unwind_DebugHook ((TARGET)->cfa, handler);			\
+      __builtin_eh_return (offset, handler);				\
+    }									\
+  while (0)
+#else
 #define uw_install_context(CURRENT, TARGET)				\
   do									\
     {									\
@@ -1519,6 +1542,7 @@ _Unwind_DebugHook (void *cfa __attribute
       __builtin_eh_return (offset, handler);				\
     }									\
   while (0)
+#endif
 
 static long
 uw_install_context_1 (struct _Unwind_Context *current,
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,54 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,28 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,44 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
--- orig/libgcc/config/cr16/unwind-helper.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/unwind-helper.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,51 @@
+/* Header file for CR16 unwind support.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Helper macro to load the correct PC value from RA register.  */
+#if defined (__CR16__)
+#define CR16_UW_CONTEXT(HANDLER)	\
+  (void*)( ( (unsigned)HANDLER ) >> 1 ) ;
+
+/* Helper macro in uw_init_context_1 to calculate curent 
+   frame cfa offset.  */
+#define CR16_ARGS_SIZE(CONTEXT)	\
+  CONTEXT->args_size;
+
+/* Helper routine of _Unwind_SetGR for CR16.  */
+#define CR16_UW_SETGR(PTR,VAL,SIZE,INDEX,CONTEXT)	\
+  do							\
+    {							\
+      if ( SIZE == sizeof(_Unwind_Word) )		\
+	* (_Unwind_Word *) PTR = VAL ;			\
+      else						\
+	{						\
+	  typedef unsigned _CR16_Unwind_Word 		\
+			     __attribute__((__mode__(__word__)));\
+	  gcc_assert (INDEX + 1  <  (int) sizeof(dwarf_reg_size_table));  \
+	  * (_CR16_Unwind_Word *) PTR = VAL & 0xffff; 	\
+	  PTR = CONTEXT->reg[INDEX + 1];     		\
+	  * (_CR16_Unwind_Word *) PTR = VAL >> 16;  	\
+	}							\
+    } while(0)  
+#endif
--- orig/libgcc/config.host	2011-03-23 01:28:18.000000000 +0530
+++ mod/libgcc/config.host	2011-05-30 17:16:35.000000000 +0530
@@ -79,6 +79,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+	;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -237,6 +239,10 @@ bfin*-linux-uclibc*)
 	;;
 bfin*-*)
         ;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none)
 	extra_parts="crtbegin.o crtend.o"
 	;;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-05-20 17:07     ` Joseph S. Myers
  2011-05-30 15:44       ` Sumanth Gundapaneni
@ 2011-06-09 10:15       ` Sumanth Gundapaneni
  2011-06-28  8:32       ` Sumanth Gundapaneni
  2011-07-15  7:54       ` Sumanth Gundapaneni
  3 siblings, 0 replies; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-06-09 10:15 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, rth, Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 3820 bytes --]

PING: For review

Hi,
 
I can understand people are busy and if in case you overlook
my previous mail , please review the patch attached with this
mail. For explanations, please view the mail below.

Thanks in advance,
Sumanth G,
PUNE (India).

===== Begin Message ======
-----Original Message-----
From: Sumanth Gundapaneni 
Sent: Monday, May 30, 2011 6:57 PM
To: 'Joseph Myers'
Cc: gcc-patches@gcc.gnu.org; rth@redhat.com; Jayant R. Sonar
Subject: RE: CR16 Port addition

Hi Joseph and Richard,

Thanks for your time in reviewing the CR16 port and once again I am 
grateful for your valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications 
as suggested by Joseph in his previous mail.

For your kind information, I am providing the recent posts regarding 
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html  
Third post   : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg00624.html
Fourth post  : http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01441.html 

Please review the patch and let me know if there should be any 
modifications in it.

Joseph, please go through my explanation for your comments.

>Please remove the remaining top level configure changes from the patch.

The top level configure changes have been removed as advised.


>Now you seem to have a stray change to the generated file 
>libstdc++-v3/configure. Again, you can probably just eliminate this 

The configure changes in libtsdc++-v3 are removed too and you can find 
the same in the updated patch.


>and make the code in unwind-dw2-* use those macros, 
>instead of having separate copies of the files.

A new file unwind-helper.h file is created in libgcc/config/cr16 directory 
as per your suggestion and defined a few macros in this newly defined file 
which are getting called from gcc/unwind-dw2.c. Please review the same 
and do let me know for further modifications, if any. We have identified 
issues related to exception handling using prints in unwind code and 
will debug the same to a greater extent in near future with further 
development of GNU based tools.


>Since you first submitted the port, a file contrib/config-list.mk

"cr16-elf" is added to config-list.mk file.


gcc/ChangeLog:
--------------
2011-05-28	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/constraints.md: New file.
	* config/cr16/t-cr16: New file.

libgcc/ChangeLog:
-----------------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-helper.h: New file.
	
contrib/ChangeLog:
----------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config-list.mk: Add National Semiconductor CR16 target.
   
Thanks in advance,
Sumanth G,
PUNE (India).

===== End Message ======


[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 173284 bytes --]

--- orig/contrib/config-list.mk	2011-05-05 07:17:47.000000000 +0530
+++ mod/contrib/config-list.mk	2011-05-30 17:16:35.000000000 +0530
@@ -17,7 +17,7 @@ LIST = alpha-linux-gnu alpha-freebsd6 al
   arm-linux-androideabi arm-uclinux_eabi arm-ecos-elf arm-eabi \
   arm-symbianelf arm-rtems arm-elf arm-wince-pe avr-rtems avr-elf \
   bfin-elf bfin-uclinux bfin-linux-uclibc bfin-rtems bfin-openbsd \
-  cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
+  cr16-elf cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
   fr30-elf frv-elf frv-linux h8300-elf h8300-rtems hppa-linux-gnu \
   hppa-linux-gnuOPT-enable-sjlj-exceptions=yes hppa64-linux-gnu \
   hppa2.0-hpux10.1 hppa64-hpux11.3 \
--- orig/gcc/config/cr16/constraints.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/constraints.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,81 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;; Constraints
+;; Register constraints
+(define_register_constraint "b" "NOSP_REGS"
+  "@no sp registers")
+
+(define_register_constraint "c" "SHORT_REGS"
+  "@short registers")
+
+(define_register_constraint "d" "LONG_REGS"
+  "@long registers")
+
+;; Integer constraints.
+(define_constraint "I"
+  "A signed 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "J"
+  "A signed 5-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)")))
+
+(define_constraint "K"
+  "A signed 6-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)")))
+
+(define_constraint "L"
+  "A unsigned 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "M"
+  "A unsigned and customized  4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) || (ival != 11)))  ")))
+
+(define_constraint "N"
+  "A signed 16-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -32768, 32767)")))
+
+(define_constraint "O"
+  "A unsigned 20-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 1048575)")))
+
+(define_constraint "Q"
+  "A shift QI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 7)")))
+
+(define_constraint "R"
+  "A shift HI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 15)")))
+
+(define_constraint "S"
+  "A shift SI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 31)")))
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,2212 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Structure for stack computations.  */
+
+/* variable definitions in the struture
+   args_size             Number of bytes saved on the stack for local 
+			 variables
+
+   reg_size		 Number of bytes saved on the stack for 
+			 non-scratch registers
+
+   total_size 		 The sum of 2 sizes: locals vars and padding byte 
+			 for saving the registers. Used in expand_prologue() 
+			 and expand_epilogue()
+
+   last_reg_to_save      Will hold the number of the last register the 
+			 prologue saves, -1 if no register is saved
+
+   save_regs[16]	 Each object in the array is a register number. 
+			 Mark 1 for registers that need to be saved
+
+   num_regs		 Number of registers saved
+
+   initialized		 Non-zero if frame size already calculated, not 
+			 used yet
+
+   function_makes_calls  Does the function make calls ? not used yet.  */
+
+struct cr16_frame_info
+{
+  unsigned long var_size;
+  unsigned long args_size;
+  unsigned int  reg_size;
+  unsigned long total_size;
+  long          last_reg_to_save;
+  long          save_regs[FIRST_PSEUDO_REGISTER];
+  int           num_regs;
+  int           initialized;
+  int           function_makes_calls;
+};
+
+/* Current frame information calculated by cr16_compute_frame_size.  */
+static struct cr16_frame_info current_frame_info;
+
+/* Static Variables.  */
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* TARGETM Function Prototypes and forward declarations  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
+static bool cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+static bool cr16_legitimate_constant_p   (enum machine_mode, rtx);
+static rtx cr16_function_value (const_tree, const_tree, bool);
+static rtx cr16_libcall_value (enum machine_mode, const_rtx);
+static bool cr16_function_value_regno_p (const unsigned int);
+static bool cr16_legitimate_address_p (enum machine_mode, rtx, bool);
+static void cr16_print_operand (FILE *, rtx, int);
+static void cr16_print_operand_address (FILE *, rtx);
+static int cr16_address_cost (rtx, bool);
+static int cr16_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
+static int cr16_memory_move_cost (enum machine_mode, reg_class_t, bool);
+
+/* Stack layout and calling conventions.  */
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P    cr16_legitimate_constant_p
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P     cr16_legitimate_address_p
+
+/* Returning function value.  */
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE cr16_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE cr16_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
+
+/* printing the values.  */
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND cr16_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
+
+/* Table of machine attributes.  */
+static const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity }.  */
+  {"interrupt", 0, 0, false, true, true, NULL, false},
+  {NULL, 0, 0, false, false, false, NULL, false}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS 
+       || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, 
+		      int size ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture");
+	}
+      else
+	error ("invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array current_frame_info.save_regs and the variable 
+   current_frame_info.reg_size. The index of current_frame_info.save_regs 
+   is numbers of register, each will get 1 if we need to save it in the 
+   current function, 0 if not. current_frame_info.reg_size is the total sum 
+   of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  current_frame_info.last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  current_frame_info.reg_size = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (fixed_regs[regno])
+	{
+	  current_frame_info.save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    current_frame_info.save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    current_frame_info.save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  current_frame_info.save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (current_frame_info.save_regs[regno] == 1)
+      {
+	current_frame_info.last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
+	else
+	  current_frame_info.reg_size += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  current_frame_info.var_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = current_frame_info.var_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  current_frame_info.var_size += padding_locals;
+  current_frame_info.total_size = current_frame_info.var_size 
+			   + (ACCUMULATE_OUTGOING_ARGS
+			    ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use current_frame_info.reg_size.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use current_frame_info.var_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size 
+	    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
+        return 0;
+ 
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  if ((TARGET_INT32)
+      && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
+     return 0;
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Returns register number for function return value.*/
+static inline unsigned int
+cr16_ret_register (void)
+{
+  return 0;
+}
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, cr16_ret_register ());
+}
+
+/* Returning function value.  */
+
+/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.  */
+static bool
+cr16_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   library function returns a value of mode MODE.  */
+static rtx
+cr16_libcall_value (enum machine_mode mode,
+                   const_rtx func ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   function returns a value of data type VALTYPE.  */
+static rtx
+cr16_function_value (const_tree type,
+                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE(type), cr16_ret_register ());
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  cum->last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!cum->last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+     C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+     C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+     NOTE: @BRO is added using unspec:BRO
+     NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of TARGET_LEGITIMATE_ADDRESS_P.  */
+static bool
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, bool strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "index + register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\ncr16 address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /* CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9.  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+
+/* Implement `TARGET_REGISTER_MOVE_COST'.  */
+static int
+cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                        reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
+{
+  return (to != GENERAL_REGS ? 8
+          : 2);
+}
+
+/* Implement `TARGET_MEMORY_MOVE_COST'.  */
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+static int
+cr16_memory_move_cost (enum machine_mode mode,
+                       reg_class_t rclass ATTRIBUTE_UNUSED,
+                       bool in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+static void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "unspec!!");
+	  switch (XINT (x, 1))
+	    {
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+static void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "unspec 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of current_frame_info.save_regs[], going from 0 until 
+     current_frame_info.last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= current_frame_info.last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) 
+	     && (i <= current_frame_info.last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!current_frame_info.save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* POP.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
+    {
+      if (current_frame_info.save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = current_frame_info.last_reg_to_save + 1;
+  to = current_frame_info.last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = current_frame_info.last_reg_to_save; i >= 0;)
+    {
+      if (!current_frame_info.save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && current_frame_info.save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (SImode, dwarf,
+					REG_NOTES (insn));
+}
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
+    return;
+
+  if (current_frame_info.last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue
+			(GEN_INT (current_frame_info.reg_size)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
+			&& (current_frame_info.reg_size 
+			 == CR16_UNITS_PER_DWORD));
+  
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (current_frame_info.last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static bool
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return
+	  || cfun->has_nonlocal_label || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+   Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P. In cr16c treat legitimize float 
+   constant as an immediate operand.  */
+static bool
+cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			    rtx x ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+void
+notice_update_cc (rtx exp)
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
+
+/* Helper function for md file. This function is used to emit arithmetic 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_add_sub_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi0_op[2] ;
+  rtx hi1_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
+  hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
+  hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
+
+  if (num == 0)
+    {
+        output_asm_insn ("addd\t%1, %0", lo_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("subd\t%1, %0", lo_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else
+    return "";
+
+}
+
+
+/* Helper function for md file. This function is used to emit logical 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_logical_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
+  if (num == 0)
+    {
+        output_asm_insn ("andd\t%1, %0", lo_op) ;
+        output_asm_insn ("andd\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("ord\t%1, %0", lo_op) ;
+        output_asm_insn ("ord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 2)
+    {
+        output_asm_insn ("xord\t%1, %0", lo_op) ;
+        output_asm_insn ("xord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else
+    return "";
+}
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,591 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+  }                                        \
+while (0)
+#endif
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+   values must be in memory.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+  (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Macros to check the range of integers . These macros were used across
+   the port, majorly in constraints.md, predicates.md files. */
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+#define IN_RANGE_P(VALUE, LOW, HIGH)                            \
+  ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))           \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+#define IN_RAN(VALUE, LOW, HIGH)                             \
+  (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))       \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0)
+
+/* This check is for sbit/cbit instruction.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+  int last_parm_in_reg;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#endif /* End of GCC_CR16_H.  */
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,568 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,1271 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+;;  Register numbers
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates & Constraints
+(include "predicates.md")
+(include "constraints.md")
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+   (UNSPEC_RETURN_ADDR          5)
+  ]
+)
+
+;; Attributes
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+;;  Code Macro Definitions
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;; Arithmetic Instuction  Patterns
+;;
+;; Addition insns.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0")
+		 (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 0);
+  "
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+		 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
+  ""
+  "addd\t%2, %0"
+  [(set_attr "length" "2,2,4,4,6")]
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "addw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+		 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "addb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(minus:DI (match_operand:DI 1 "register_operand" "")
+		  (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(minus:DI (match_operand:DI 1 "register_operand" "0")
+		  (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 1);
+  "
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,0")
+		  (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
+  ""
+  "subd\t%2, %0"
+  [(set_attr "length" "4,6")]
+)
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+		  (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "subw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(minus:QI (match_operand:QI 1 "register_operand" "0,0")
+		  (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "subb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Multiply and Accumulate Instructions
+(define_insn "smachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macsw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "umachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macuw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_set_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Logical Instructions - and
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(and:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 0);
+  "
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(and:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - or 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ior:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 1);
+  "
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - xor 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(xor:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 2);
+  "
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "xord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(xor:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(not:DI (match_operand:DI 1 "register_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "register_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
+  ""
+  "ashub\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c")
+	(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
+  ""
+  "ashuw\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
+  ""
+  "ashud\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "ashrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
+  ""
+  "ashub\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
+  ""
+  "ashuw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
+  ""
+  "ashud\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashub\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashuw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrdi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "ashud\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "reg_or_int_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "lshrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_operand" "Q")))]
+  ""
+  "lshb\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_operand" "R")))]
+  ""
+  "lshw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_operand" "S")))]
+  ""
+  "lshd\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshb\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "lshd\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "general_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "nonmemory_operand" "")))
+    (clobber (match_scratch:HI 2 "=r"))] ) ]
+  ""
+  "")
+
+;;  Scond Instructions
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 2 "register_operand" "")
+		 (match_operand:CR16IM 3 "nonmemory_operand" "")))
+   (set (match_operand:HI 0 "register_operand")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  ""
+)
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
+  ""
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "sCOND_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  "s%d1\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "jump_return"
+  [(parallel
+    [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
+     (return)])]
+  "reload_completed"
+  "jump\t(ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
+      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      {
+	operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
+        return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+      }
+  }
+  [(set_attr "length" "6")]
+)
+
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+              (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop\t"
+)
+
+;; PIC
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,51 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2011 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,100 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+#endif /* RTX_CODE.  */
+
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+extern const char *cr16_emit_add_sub_di (rtx *, int);
+extern const char *cr16_emit_logical_di (rtx *, int);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,224 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;;  Predicates
+
+;; Predicates for sbit/cbit instructions
+;; bit operand used for the generation of bit insn generation
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Predicates for shift instructions
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0;
+})
+
+;; Predicates for jump/call instructions
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+(define_predicate "hard_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) <= 15")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Helper predicate 
+(define_predicate "reg_or_int_operand"
+  (ior (match_code "const_int")
+       (match_operand 0 "register_operand")))
+
+;;
+;;
+;; Atithmetic/logical predicates
+
+;; QI Helper
+(define_predicate "arith_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) 
+                || (INTVAL (op) != 11))) ? 1 : 0 ; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "reg_qi_int_operand"
+  (ior (match_operand 0 "arith_qi_operand")
+       (match_operand 0 "register_operand")))
+
+;; HI Helper
+(define_predicate "arith_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "reg_hi_int_operand"
+  (ior (match_operand 0 "arith_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "reg_si_int_operand"
+  (ior (match_operand 0 "const_int_operand")
+       (match_operand 0 "register_operand")))
+
+;;
+;; Shift predicates
+
+;; QI Helper
+(define_predicate "shift_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_qi_int_operand"
+  (ior (match_operand 0 "shift_qi_operand")
+       (match_operand 0 "register_operand")))
+;; HI Helper
+(define_predicate "shift_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_hi_int_operand"
+  (ior (match_operand 0 "shift_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "shift_si_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_si_int_operand"
+  (ior (match_operand 0 "shift_si_operand")
+       (match_operand 0 "register_operand")))
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,54 @@
+# CR16 Target Makefile
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+MULTILIB_OPTIONS     = fPIC mint32 
+MULTILIB_DIRNAMES    = far-pic int32 
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
--- orig/gcc/config.gcc	2011-05-28 13:32:57.000000000 +0530
+++ mod/gcc/config.gcc	2011-05-30 17:16:35.000000000 +0530
@@ -929,6 +929,13 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+	tm_file="elfos.h ${tm_file}"
+	tmake_file="${tmake_file} cr16/t-cr16 "
+	libgcc_tm_file="${libgcc_tm_file} cr16/unwind-helper.h"
+	extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+	use_collect2=no
+	;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
--- orig/gcc/doc/extend.texi	2011-05-25 22:48:29.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-05-30 17:16:35.000000000 +0530
@@ -2551,7 +2551,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
--- orig/gcc/doc/install.texi	2011-05-23 16:42:25.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-05-30 17:16:35.000000000 +0530
@@ -3199,6 +3199,29 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
--- orig/gcc/doc/invoke.texi	2011-05-25 16:30:14.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-05-30 17:16:35.000000000 +0530
@@ -497,6 +497,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32 -mbit-ops
+-mdata-model=@var{model}}
+
 @emph{Darwin Options}
 @gccoptlist{-all_load  -allowable_client  -arch  -arch_errors_fatal @gol
 -arch_only  -bind_at_load  -bundle  -bundle_loader @gol
@@ -9984,6 +9990,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * Darwin Options::
 * DEC Alpha Options::
 * DEC Alpha/VMS Options::
@@ -10759,6 +10766,46 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mbit-ops
+@opindex mbit-ops
+Generates sbit/cbit instructions for bit manipulations.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near},
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
 @node Darwin Options
 @subsection Darwin Options
 @cindex Darwin options
--- orig/gcc/doc/md.texi	2011-05-05 05:04:37.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-05-30 17:16:35.000000000 +0530
@@ -1775,6 +1775,40 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item Hewlett-Packard PA-RISC---@file{config/pa/pa.h}
 @table @code
 @item a
--- orig/gcc/unwind-dw2.c	2011-03-15 01:17:58.000000000 +0530
+++ mod/gcc/unwind-dw2.c	2011-05-30 17:16:35.000000000 +0530
@@ -219,8 +219,12 @@ _Unwind_SetGR (struct _Unwind_Context *c
     * (_Unwind_Ptr *) ptr = val;
   else
     {
+#if defined (__CR16__)
+      CR16_UW_SETGR(ptr,val,size,index,context);	
+#else
       gcc_assert (size == sizeof(_Unwind_Word));
       * (_Unwind_Word *) ptr = val;
+#endif
     }
 }
 
@@ -1416,6 +1420,9 @@ uw_update_context (struct _Unwind_Contex
        can change from frame to frame.  */
     context->ra = __builtin_extract_return_addr
       (_Unwind_GetPtr (context, fs->retaddr_column));
+#if defined( __CR16__ )
+    context->ra = CR16_UW_CONTEXT(context->ra) ;
+#endif
 }
 
 static void
@@ -1476,7 +1483,11 @@ uw_init_context_1 (struct _Unwind_Contex
   _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
   fs.regs.cfa_how = CFA_REG_OFFSET;
   fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+#if defined( __CR16__ )
+  fs.regs.cfa_offset -= CR16_ARGS_SIZE(context);
+#else
   fs.regs.cfa_offset = 0;
+#endif
 
   uw_update_context_1 (context, &fs);
 
@@ -1510,6 +1521,18 @@ _Unwind_DebugHook (void *cfa __attribute
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
 
+#if defined (__CR16__)
+#define uw_install_context(CURRENT, TARGET)				\
+  do									\
+    {									\
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      CR16_UW_CONTEXT(handler);						\
+      _Unwind_DebugHook ((TARGET)->cfa, handler);			\
+      __builtin_eh_return (offset, handler);				\
+    }									\
+  while (0)
+#else
 #define uw_install_context(CURRENT, TARGET)				\
   do									\
     {									\
@@ -1519,6 +1542,7 @@ _Unwind_DebugHook (void *cfa __attribute
       __builtin_eh_return (offset, handler);				\
     }									\
   while (0)
+#endif
 
 static long
 uw_install_context_1 (struct _Unwind_Context *current,
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,54 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,28 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,44 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
--- orig/libgcc/config/cr16/unwind-helper.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/unwind-helper.h	2011-05-30 17:16:35.000000000 +0530
@@ -0,0 +1,51 @@
+/* Header file for CR16 unwind support.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Helper macro to load the correct PC value from RA register.  */
+#if defined (__CR16__)
+#define CR16_UW_CONTEXT(HANDLER)	\
+  (void*)( ( (unsigned)HANDLER ) >> 1 ) ;
+
+/* Helper macro in uw_init_context_1 to calculate curent 
+   frame cfa offset.  */
+#define CR16_ARGS_SIZE(CONTEXT)	\
+  CONTEXT->args_size;
+
+/* Helper routine of _Unwind_SetGR for CR16.  */
+#define CR16_UW_SETGR(PTR,VAL,SIZE,INDEX,CONTEXT)	\
+  do							\
+    {							\
+      if ( SIZE == sizeof(_Unwind_Word) )		\
+	* (_Unwind_Word *) PTR = VAL ;			\
+      else						\
+	{						\
+	  typedef unsigned _CR16_Unwind_Word 		\
+			     __attribute__((__mode__(__word__)));\
+	  gcc_assert (INDEX + 1  <  (int) sizeof(dwarf_reg_size_table));  \
+	  * (_CR16_Unwind_Word *) PTR = VAL & 0xffff; 	\
+	  PTR = CONTEXT->reg[INDEX + 1];     		\
+	  * (_CR16_Unwind_Word *) PTR = VAL >> 16;  	\
+	}							\
+    } while(0)  
+#endif
--- orig/libgcc/config.host	2011-03-23 01:28:18.000000000 +0530
+++ mod/libgcc/config.host	2011-05-30 17:16:35.000000000 +0530
@@ -79,6 +79,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+	;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -237,6 +239,10 @@ bfin*-linux-uclibc*)
 	;;
 bfin*-*)
         ;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none)
 	extra_parts="crtbegin.o crtend.o"
 	;;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-05-20 17:07     ` Joseph S. Myers
  2011-05-30 15:44       ` Sumanth Gundapaneni
  2011-06-09 10:15       ` Sumanth Gundapaneni
@ 2011-06-28  8:32       ` Sumanth Gundapaneni
  2011-07-15  7:54       ` Sumanth Gundapaneni
  3 siblings, 0 replies; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-06-28  8:32 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, rth, Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 3830 bytes --]

PING 2: For review
Hi,
    I have updated the patch to the latest snapshot .i.e.
gcc-4.7-20110625. Please go through the attached patch and
you can view the explanations for the earlier communication
below.

Thanks in advance,
Sumanth G,
PUNE (India).
   
===== Begin Message ======
-----Original Message-----
From: Sumanth Gundapaneni 
Sent: Monday, May 30, 2011 6:57 PM
To: 'Joseph Myers'
Cc: gcc-patches@gcc.gnu.org; rth@redhat.com; Jayant R. Sonar
Subject: RE: CR16 Port addition

Hi Joseph and Richard,

Thanks for your time in reviewing the CR16 port and once again I am 
grateful for your valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications 
as suggested by Joseph in his previous mail.

For your kind information, I am providing the recent posts regarding 
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html  
Third post   : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg00624.html
Fourth post  : http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01441.html 

Please review the patch and let me know if there should be any 
modifications in it.

Joseph, please go through my explanation for your comments.

>Please remove the remaining top level configure changes from the patch.

The top level configure changes have been removed as advised.


>Now you seem to have a stray change to the generated file 
>libstdc++-v3/configure. Again, you can probably just eliminate this 

The configure changes in libtsdc++-v3 are removed too and you can find 
the same in the updated patch.


>and make the code in unwind-dw2-* use those macros, 
>instead of having separate copies of the files.

A new file unwind-helper.h file is created in libgcc/config/cr16 directory 
as per your suggestion and defined a few macros in this newly defined file 
which are getting called from gcc/unwind-dw2.c. Please review the same 
and do let me know for further modifications, if any. We have identified 
issues related to exception handling using prints in unwind code and 
will debug the same to a greater extent in near future with further 
development of GNU based tools.


>Since you first submitted the port, a file contrib/config-list.mk

"cr16-elf" is added to config-list.mk file.


gcc/ChangeLog:
--------------
2011-05-28	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/constraints.md: New file.
	* config/cr16/t-cr16: New file.

libgcc/ChangeLog:
-----------------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-helper.h: New file.
	
contrib/ChangeLog:
----------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config-list.mk: Add National Semiconductor CR16 target.
   
Thanks in advance,
Sumanth G,
PUNE (India).

===== End Message ======


[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 173900 bytes --]

--- orig/contrib/config-list.mk	2011-05-05 07:17:47.000000000 +0530
+++ mod/contrib/config-list.mk	2011-06-28 12:35:26.000000000 +0530
@@ -17,7 +17,7 @@ LIST = alpha-linux-gnu alpha-freebsd6 al
   arm-linux-androideabi arm-uclinux_eabi arm-ecos-elf arm-eabi \
   arm-symbianelf arm-rtems arm-elf arm-wince-pe avr-rtems avr-elf \
   bfin-elf bfin-uclinux bfin-linux-uclibc bfin-rtems bfin-openbsd \
-  cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
+  cr16-elf cris-elf cris-linux crisv32-elf crisv32-linux fido-elf \
   fr30-elf frv-elf frv-linux h8300-elf h8300-rtems hppa-linux-gnu \
   hppa-linux-gnuOPT-enable-sjlj-exceptions=yes hppa64-linux-gnu \
   hppa2.0-hpux10.1 hppa64-hpux11.3 \
--- orig/gcc/config/cr16/constraints.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/constraints.md	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,81 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;; Constraints
+;; Register constraints
+(define_register_constraint "b" "NOSP_REGS"
+  "@no sp registers")
+
+(define_register_constraint "c" "SHORT_REGS"
+  "@short registers")
+
+(define_register_constraint "d" "LONG_REGS"
+  "@long registers")
+
+;; Integer constraints.
+(define_constraint "I"
+  "A signed 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "J"
+  "A signed 5-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)")))
+
+(define_constraint "K"
+  "A signed 6-bit immediate."
+  (and (match_code "const_int")
+       (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)")))
+
+(define_constraint "L"
+  "A unsigned 4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)")))
+
+(define_constraint "M"
+  "A unsigned and customized  4-bit immediate."
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) || (ival != 11)))  ")))
+
+(define_constraint "N"
+  "A signed 16-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, -32768, 32767)")))
+
+(define_constraint "O"
+  "A unsigned 20-bit immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 1048575)")))
+
+(define_constraint "Q"
+  "A shift QI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 7)")))
+
+(define_constraint "R"
+  "A shift HI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 15)")))
+
+(define_constraint "S"
+  "A shift SI immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE_P (ival, 0, 31)")))
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,2214 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Structure for stack computations.  */
+
+/* variable definitions in the struture
+   args_size             Number of bytes saved on the stack for local 
+			 variables
+
+   reg_size		 Number of bytes saved on the stack for 
+			 non-scratch registers
+
+   total_size 		 The sum of 2 sizes: locals vars and padding byte 
+			 for saving the registers. Used in expand_prologue() 
+			 and expand_epilogue()
+
+   last_reg_to_save      Will hold the number of the last register the 
+			 prologue saves, -1 if no register is saved
+
+   save_regs[16]	 Each object in the array is a register number. 
+			 Mark 1 for registers that need to be saved
+
+   num_regs		 Number of registers saved
+
+   initialized		 Non-zero if frame size already calculated, not 
+			 used yet
+
+   function_makes_calls  Does the function make calls ? not used yet.  */
+
+struct cr16_frame_info
+{
+  unsigned long var_size;
+  unsigned long args_size;
+  unsigned int  reg_size;
+  unsigned long total_size;
+  long          last_reg_to_save;
+  long          save_regs[FIRST_PSEUDO_REGISTER];
+  int           num_regs;
+  int           initialized;
+  int           function_makes_calls;
+};
+
+/* Current frame information calculated by cr16_compute_frame_size.  */
+static struct cr16_frame_info current_frame_info;
+
+/* Static Variables.  */
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* TARGETM Function Prototypes and forward declarations  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
+static bool cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (cumulative_args_t, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (cumulative_args_t, enum machine_mode,
+                                      const_tree, bool);
+static bool cr16_legitimate_constant_p   (enum machine_mode, rtx);
+static rtx cr16_function_value (const_tree, const_tree, bool);
+static rtx cr16_libcall_value (enum machine_mode, const_rtx);
+static bool cr16_function_value_regno_p (const unsigned int);
+static bool cr16_legitimate_address_p (enum machine_mode, rtx, bool);
+static void cr16_print_operand (FILE *, rtx, int);
+static void cr16_print_operand_address (FILE *, rtx);
+static int cr16_address_cost (rtx, bool);
+static int cr16_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
+static int cr16_memory_move_cost (enum machine_mode, reg_class_t, bool);
+
+/* Stack layout and calling conventions.  */
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P    cr16_legitimate_constant_p
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P     cr16_legitimate_address_p
+
+/* Returning function value.  */
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE cr16_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE cr16_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
+
+/* printing the values.  */
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND cr16_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
+
+/* Table of machine attributes.  */
+static const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity }.  */
+  {"interrupt", 0, 0, false, true, true, NULL, false},
+  {NULL, 0, 0, false, false, false, NULL, false}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS 
+       || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, 
+		      int size ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture");
+	}
+      else
+	error ("invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array current_frame_info.save_regs and the variable 
+   current_frame_info.reg_size. The index of current_frame_info.save_regs 
+   is numbers of register, each will get 1 if we need to save it in the 
+   current function, 0 if not. current_frame_info.reg_size is the total sum 
+   of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  current_frame_info.last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  current_frame_info.reg_size = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (fixed_regs[regno])
+	{
+	  current_frame_info.save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    current_frame_info.save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    current_frame_info.save_regs[regno] = 1;
+	  else
+	    current_frame_info.save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  current_frame_info.save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (current_frame_info.save_regs[regno] == 1)
+      {
+	current_frame_info.last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
+	else
+	  current_frame_info.reg_size += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  current_frame_info.var_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = current_frame_info.var_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  current_frame_info.var_size += padding_locals;
+  current_frame_info.total_size = current_frame_info.var_size 
+			   + (ACCUMULATE_OUTGOING_ARGS
+			    ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use current_frame_info.reg_size.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use current_frame_info.var_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (current_frame_info.reg_size + current_frame_info.var_size 
+	    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
+        return 0;
+ 
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  if ((TARGET_INT32)
+      && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
+     return 0;
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Returns register number for function return value.*/
+static inline unsigned int
+cr16_ret_register (void)
+{
+  return 0;
+}
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, cr16_ret_register ());
+}
+
+/* Returning function value.  */
+
+/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.  */
+static bool
+cr16_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   library function returns a value of mode MODE.  */
+static rtx
+cr16_libcall_value (enum machine_mode mode,
+                   const_rtx func ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, cr16_ret_register ());
+}
+
+/* Create an RTX representing the place where a
+   function returns a value of data type VALTYPE.  */
+static rtx
+cr16_function_value (const_tree type,
+                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE(type), cr16_ret_register ());
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS *cum, const_tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  cum->last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  cum->last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!cum->last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+     C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+     C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+     NOTE: @BRO is added using unspec:BRO
+     NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of TARGET_LEGITIMATE_ADDRESS_P.  */
+static bool
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, bool strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "index + register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\ncr16 address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /* CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9.  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+
+/* Implement `TARGET_REGISTER_MOVE_COST'.  */
+static int
+cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                        reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
+{
+  return (to != GENERAL_REGS ? 8
+          : 2);
+}
+
+/* Implement `TARGET_MEMORY_MOVE_COST'.  */
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+static int
+cr16_memory_move_cost (enum machine_mode mode,
+                       reg_class_t rclass ATTRIBUTE_UNUSED,
+                       bool in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+static void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "unspec!!");
+	  switch (XINT (x, 1))
+	    {
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+static void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "unspec 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of current_frame_info.save_regs[], going from 0 until 
+     current_frame_info.last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= current_frame_info.last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) 
+	     && (i <= current_frame_info.last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!current_frame_info.save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* POP.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
+    {
+      if (current_frame_info.save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = current_frame_info.last_reg_to_save + 1;
+  to = current_frame_info.last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = current_frame_info.last_reg_to_save; i >= 0;)
+    {
+      if (!current_frame_info.save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && current_frame_info.save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (SImode, dwarf,
+					REG_NOTES (insn));
+}
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
+    return;
+
+  if (current_frame_info.last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue
+			(GEN_INT (current_frame_info.reg_size)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
+			&& (current_frame_info.reg_size 
+			 == CR16_UNITS_PER_DWORD));
+  
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (current_frame_info.total_size > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (current_frame_info.total_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (current_frame_info.last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return 
+			     (GEN_INT (current_frame_info.reg_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static bool
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return
+	  || cfun->has_nonlocal_label || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+   Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P. In cr16c treat legitimize float 
+   constant as an immediate operand.  */
+static bool
+cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			    rtx x ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+void
+notice_update_cc (rtx exp)
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
+
+/* Helper function for md file. This function is used to emit arithmetic 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_add_sub_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi0_op[2] ;
+  rtx hi1_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
+  hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
+  hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
+
+  if (num == 0)
+    {
+        output_asm_insn ("addd\t%1, %0", lo_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("addcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("subd\t%1, %0", lo_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi0_op) ;
+        output_asm_insn ("subcw\t%1, %0", hi1_op) ;
+        return "";
+    }
+  else
+    return "";
+
+}
+
+
+/* Helper function for md file. This function is used to emit logical 
+   DI instructions. The argument "num" decides which instruction to be
+   printed.  */
+const char *
+cr16_emit_logical_di (rtx *operands, int num)
+{
+
+  rtx lo_op[2] ;
+  rtx hi_op[2] ;
+
+  lo_op[0] = gen_lowpart (SImode, operands[0]);
+  hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
+
+  lo_op[1] = gen_lowpart (SImode, operands[2]);
+  hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
+  if (num == 0)
+    {
+        output_asm_insn ("andd\t%1, %0", lo_op) ;
+        output_asm_insn ("andd\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 1)
+    {
+        output_asm_insn ("ord\t%1, %0", lo_op) ;
+        output_asm_insn ("ord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else if (num == 2)
+    {
+        output_asm_insn ("xord\t%1, %0", lo_op) ;
+        output_asm_insn ("xord\t%1, %0", hi_op) ;
+        return "";
+    }
+  else
+    return "";
+}
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,591 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+  }                                        \
+while (0)
+#endif
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+   values must be in memory.  */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+  (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Macros to check the range of integers . These macros were used across
+   the port, majorly in constraints.md, predicates.md files. */
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+#define IN_RANGE_P(VALUE, LOW, HIGH)                            \
+  ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))           \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+#define IN_RAN(VALUE, LOW, HIGH)                             \
+  (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW))       \
+   && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0)
+
+/* This check is for sbit/cbit instruction.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+  int last_parm_in_reg;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#endif /* End of GCC_CR16_H.  */
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,568 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,1271 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+;;  Register numbers
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates & Constraints
+(include "predicates.md")
+(include "constraints.md")
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+   (UNSPEC_RETURN_ADDR          5)
+  ]
+)
+
+;; Attributes
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+;;  Code Macro Definitions
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;; Arithmetic Instuction  Patterns
+;;
+;; Addition insns.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0")
+		 (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 0);
+  "
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+		 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
+  ""
+  "addd\t%2, %0"
+  [(set_attr "length" "2,2,4,4,6")]
+)
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "addw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+		 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "addb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(minus:DI (match_operand:DI 1 "register_operand" "")
+		  (match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(minus:DI (match_operand:DI 1 "register_operand" "0")
+		  (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_add_sub_di (operands, 1);
+  "
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,0")
+		  (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
+  ""
+  "subd\t%2, %0"
+  [(set_attr "length" "4,6")]
+)
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+		  (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "subw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(minus:QI (match_operand:QI 1 "register_operand" "0,0")
+		  (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
+  ""
+  "subb\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+;;
+;;  Multiply and Accumulate Instructions
+(define_insn "smachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macsw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "umachisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI
+	 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+		  (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))
+	 (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_MAC"
+  "macuw\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_set_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=m")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
+  )]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Logical Instructions - and
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(and:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 0);
+  "
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(and:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - or 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ior:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 1);
+  "
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;  Logical Instructions - xor 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if ((GET_CODE (operands[2]) != REG))
+	{
+	  operands[2] = force_reg (DImode, operands[2]);
+	}
+    }
+)
+
+(define_insn "xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(xor:DI (match_operand:DI 1 "register_operand" "%0")
+		(match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "*
+    return cr16_emit_logical_di (operands, 2);
+  "
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+		(match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
+  ""
+  "xord\t%2, %0"
+  [(set_attr "length" "2,2,4,6")]
+)
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c,c")
+	(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+		(match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,2,4")]
+)
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c,c")
+	(xor:QI (match_operand:QI 1 "register_operand" "%0,0,0")
+		(match_operand:QI 2 "reg_hi_int_operand" "c,M,N")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,2,2")]
+)
+
+;;
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(not:DI (match_operand:DI 1 "register_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "register_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "register_operand" "=c,c")
+	(ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,I")))]
+  ""
+  "ashub\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand" "=c,c")
+	(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "c,J")))]
+  ""
+  "ashuw\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+		   (match_operand:QI 2 "nonmemory_operand" "r,K")))]
+  ""
+  "ashud\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "ashrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
+  ""
+  "ashub\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
+  ""
+  "ashuw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_imm_operand" "i")))]
+  ""
+  "ashud\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashub\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "ashuw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashrdi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "ashud\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "register_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
+			 (match_operand:QI 2 "reg_or_int_operand" "")))]
+  ""
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+	{
+	  /* If the constant is not in range, try placing it in a reg */
+	  if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg(QImode, operands[2]);
+	}
+
+      if (GET_CODE (operands[2]) != CONST_INT)
+	operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+    }
+)
+
+(define_insn "lshrqi3_imm_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_qi_operand" "Q")))]
+  ""
+  "lshb\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_imm_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_hi_operand" "R")))]
+  ""
+  "lshw\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_imm_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (match_operand:QI 2 "shift_si_operand" "S")))]
+  ""
+  "lshd\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrqi3_neg_insn"
+  [(set (match_operand:QI 0 "register_operand" "=c")
+	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshb\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrhi3_neg_insn"
+  [(set (match_operand:HI 0 "register_operand" "=c")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
+  ""
+  "lshw\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshrsi3_neg_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+		     (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "lshd\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "general_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "nonmemory_operand" "")))
+    (clobber (match_scratch:HI 2 "=r"))] ) ]
+  ""
+  "")
+
+;;  Scond Instructions
+(define_expand "cstore<mode>4"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 2 "register_operand" "")
+		 (match_operand:CR16IM 3 "nonmemory_operand" "")))
+   (set (match_operand:HI 0 "register_operand")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  ""
+)
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
+  ""
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "sCOND_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(match_operator:HI 1 "ordered_comparison_operator"
+	[(cc0) (const_int 0)]))]
+  ""
+  "s%d1\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "jump_return"
+  [(parallel
+    [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
+     (return)])]
+  "reload_completed"
+  "jump\t(ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
+      return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      {
+	operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
+        return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";	
+      }
+  }
+  [(set_attr "length" "6")]
+)
+
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+              (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop\t"
+)
+
+;; PIC
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,51 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2011 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,100 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+#endif /* RTX_CODE.  */
+
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+extern const char *cr16_emit_add_sub_di (rtx *, int);
+extern const char *cr16_emit_logical_di (rtx *, int);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,224 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+;;  Predicates
+
+;; Predicates for sbit/cbit instructions
+;; bit operand used for the generation of bit insn generation
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Predicates for shift instructions
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0;
+})
+
+;; Predicates for jump/call instructions
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+(define_predicate "hard_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) <= 15")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Helper predicate 
+(define_predicate "reg_or_int_operand"
+  (ior (match_code "const_int")
+       (match_operand 0 "register_operand")))
+
+;;
+;;
+;; Atithmetic/logical predicates
+
+;; QI Helper
+(define_predicate "arith_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) 
+                || (INTVAL (op) != 11))) ? 1 : 0 ; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "reg_qi_int_operand"
+  (ior (match_operand 0 "arith_qi_operand")
+       (match_operand 0 "register_operand")))
+
+;; HI Helper
+(define_predicate "arith_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "reg_hi_int_operand"
+  (ior (match_operand 0 "arith_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "reg_si_int_operand"
+  (ior (match_operand 0 "const_int_operand")
+       (match_operand 0 "register_operand")))
+
+;;
+;; Shift predicates
+
+;; QI Helper
+(define_predicate "shift_qi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; 
+})
+
+;;QI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_qi_int_operand"
+  (ior (match_operand 0 "shift_qi_operand")
+       (match_operand 0 "register_operand")))
+;; HI Helper
+(define_predicate "shift_hi_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; 
+})
+
+;;HI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_hi_int_operand"
+  (ior (match_operand 0 "shift_hi_operand")
+       (match_operand 0 "register_operand")))
+
+;; SI Helper
+(define_predicate "shift_si_operand"
+   (match_code "const_int")
+{
+        return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; 
+})
+
+;;SI Reg, subreg(reg) or const_int.
+(define_predicate "shift_reg_si_int_operand"
+  (ior (match_operand 0 "shift_si_operand")
+       (match_operand 0 "register_operand")))
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-06-28 12:34:34.000000000 +0530
@@ -0,0 +1,54 @@
+# CR16 Target Makefile
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+MULTILIB_OPTIONS     = fPIC mint32 
+MULTILIB_DIRNAMES    = far-pic int32 
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
--- orig/gcc/config.gcc	2011-06-22 22:31:17.000000000 +0530
+++ mod/gcc/config.gcc	2011-06-28 12:33:58.000000000 +0530
@@ -332,6 +332,9 @@ frv*)	cpu_type=frv
 moxie*)	cpu_type=moxie
 	target_has_targetm_common=no
 	;;
+cr16-*-*)
+	target_has_targetm_common=no
+	;;
 fido-*-*)
 	cpu_type=m68k
 	extra_headers=math-68881.h
@@ -970,6 +973,13 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+        tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} cr16/t-cr16 "
+        libgcc_tm_file="${libgcc_tm_file} cr16/unwind-helper.h"
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        use_collect2=no
+        ;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
--- orig/gcc/doc/extend.texi	2011-06-21 19:46:39.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-06-28 12:34:06.000000000 +0530
@@ -2551,7 +2551,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
--- orig/gcc/doc/install.texi	2011-06-22 15:27:02.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-06-28 12:34:06.000000000 +0530
@@ -3218,6 +3218,29 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
--- orig/gcc/doc/invoke.texi	2011-06-22 15:27:02.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-06-28 12:34:06.000000000 +0530
@@ -505,6 +505,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32 -mbit-ops
+-mdata-model=@var{model}}
+
 @emph{Darwin Options}
 @gccoptlist{-all_load  -allowable_client  -arch  -arch_errors_fatal @gol
 -arch_only  -bind_at_load  -bundle  -bundle_loader @gol
@@ -10087,6 +10093,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * Darwin Options::
 * DEC Alpha Options::
 * DEC Alpha/VMS Options::
@@ -10878,6 +10885,46 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mbit-ops
+@opindex mbit-ops
+Generates sbit/cbit instructions for bit manipulations.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near},
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
 @node Darwin Options
 @subsection Darwin Options
 @cindex Darwin options
--- orig/gcc/doc/md.texi	2011-06-21 23:00:54.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-06-28 12:34:06.000000000 +0530
@@ -1778,6 +1778,41 @@ A memory address based on Y or Z pointer
 Constant integer 4
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item Hewlett-Packard PA-RISC---@file{config/pa/pa.h}
 @table @code
 @item a
--- orig/gcc/unwind-dw2.c	2011-06-04 00:00:39.000000000 +0530
+++ mod/gcc/unwind-dw2.c	2011-06-28 12:34:00.000000000 +0530
@@ -219,8 +219,12 @@ _Unwind_SetGR (struct _Unwind_Context *c
     * (_Unwind_Ptr *) ptr = val;
   else
     {
+#if defined (__CR16__)
+      CR16_UW_SETGR(ptr,val,size,index,context);
+#else
       gcc_assert (size == sizeof(_Unwind_Word));
       * (_Unwind_Word *) ptr = val;
+#endif
     }
 }
 
@@ -1414,6 +1418,9 @@ uw_update_context (struct _Unwind_Contex
        can change from frame to frame.  */
     context->ra = __builtin_extract_return_addr
       (_Unwind_GetPtr (context, fs->retaddr_column));
+#if defined (__CR16__)
+    context->ra = CR16_UW_CONTEXT(context->ra) ;
+#endif
 }
 
 static void
@@ -1474,7 +1481,11 @@ uw_init_context_1 (struct _Unwind_Contex
   _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
   fs.regs.cfa_how = CFA_REG_OFFSET;
   fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+#if defined (__CR16__)
+  fs.regs.cfa_offset -= CR16_ARGS_SIZE(context);
+#else
   fs.regs.cfa_offset = 0;
+#endif
 
   uw_update_context_1 (context, &fs);
 
@@ -1508,6 +1519,18 @@ _Unwind_DebugHook (void *cfa __attribute
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
 
+#if defined (__CR16__)
+#define uw_install_context(CURRENT, TARGET)                             \
+  do                                                                    \
+    {                                                                   \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));         \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);        \
+      CR16_UW_CONTEXT(handler);                                         \
+      _Unwind_DebugHook ((TARGET)->cfa, handler);                       \
+      __builtin_eh_return (offset, handler);                            \
+    }                                                                   \
+  while (0)
+#else
 #define uw_install_context(CURRENT, TARGET)				\
   do									\
     {									\
@@ -1517,6 +1540,7 @@ _Unwind_DebugHook (void *cfa __attribute
       __builtin_eh_return (offset, handler);				\
     }									\
   while (0)
+#endif
 
 static long
 uw_install_context_1 (struct _Unwind_Context *current,
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-06-28 12:33:42.000000000 +0530
@@ -0,0 +1,54 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-06-28 12:33:42.000000000 +0530
@@ -0,0 +1,28 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-06-28 12:33:42.000000000 +0530
@@ -0,0 +1,44 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-06-28 12:33:42.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
--- orig/libgcc/config/cr16/unwind-helper.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/unwind-helper.h	2011-06-28 12:33:42.000000000 +0530
@@ -0,0 +1,51 @@
+/* Header file for CR16 unwind support.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Helper macro to load the correct PC value from RA register.  */
+#if defined (__CR16__)
+#define CR16_UW_CONTEXT(HANDLER)	\
+  (void*)( ( (unsigned)HANDLER ) >> 1 ) ;
+
+/* Helper macro in uw_init_context_1 to calculate curent 
+   frame cfa offset.  */
+#define CR16_ARGS_SIZE(CONTEXT)	\
+  CONTEXT->args_size;
+
+/* Helper routine of _Unwind_SetGR for CR16.  */
+#define CR16_UW_SETGR(PTR,VAL,SIZE,INDEX,CONTEXT)	\
+  do							\
+    {							\
+      if ( SIZE == sizeof(_Unwind_Word) )		\
+	* (_Unwind_Word *) PTR = VAL ;			\
+      else						\
+	{						\
+	  typedef unsigned _CR16_Unwind_Word 		\
+			     __attribute__((__mode__(__word__)));\
+	  gcc_assert (INDEX + 1  <  (int) sizeof(dwarf_reg_size_table));  \
+	  * (_CR16_Unwind_Word *) PTR = VAL & 0xffff; 	\
+	  PTR = CONTEXT->reg[INDEX + 1];     		\
+	  * (_CR16_Unwind_Word *) PTR = VAL >> 16;  	\
+	}							\
+    } while(0)  
+#endif
--- orig/libgcc/config.host	2011-06-14 17:50:08.000000000 +0530
+++ mod/libgcc/config.host	2011-06-28 12:33:41.000000000 +0530
@@ -85,6 +85,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+        ;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -294,6 +296,10 @@ bfin*-linux-uclibc*)
 	;;
 bfin*-*)
         ;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none)
 	extra_parts="crtbegin.o crtend.o"
 	;;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2011-05-20 17:07     ` Joseph S. Myers
                         ` (2 preceding siblings ...)
  2011-06-28  8:32       ` Sumanth Gundapaneni
@ 2011-07-15  7:54       ` Sumanth Gundapaneni
  3 siblings, 0 replies; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-07-15  7:54 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, rth, Jayant R. Sonar

PING 3: For review
Hi,
    Please review the attached patch and you can view the 
explanations for the earlier communication below.

NOTE: From now on , Jayant (Jayant.Sonar@kpitcummins.com) will be 
posting the patches related to CR16. Please feel free to contact him 
if you need any information related to the patches posted. 

Thanks in advance,
Sumanth G,
PUNE (India).

===== Begin Message ======
-----Original Message-----
From: Sumanth Gundapaneni
Sent: Monday, May 30, 2011 6:57 PM
To: 'Joseph Myers'
Cc: gcc-patches@gcc.gnu.org; rth@redhat.com; Jayant R. Sonar
Subject: RE: CR16 Port addition

Hi Joseph and Richard,

Thanks for your time in reviewing the CR16 port and once again I am grateful for your valuable suggestions.

Please find attached the patch "cr16-gcc.patch" which contains modifications as suggested by Joseph in his previous mail.

For your kind information, I am providing the recent posts regarding
CR16 patches.
Initial post : http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01676.html
Second post  : http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00803.html  
Third post   : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg00624.html
Fourth post  : http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01441.html 

Please review the patch and let me know if there should be any modifications in it.

Joseph, please go through my explanation for your comments.

>Please remove the remaining top level configure changes from the patch.

The top level configure changes have been removed as advised.


>Now you seem to have a stray change to the generated file
>libstdc++-v3/configure. Again, you can probably just eliminate this

The configure changes in libtsdc++-v3 are removed too and you can find 
the same in the updated patch.


>and make the code in unwind-dw2-* use those macros, 
>instead of having separate copies of the files.

A new file unwind-helper.h file is created in libgcc/config/cr16 directory 
as per your suggestion and defined a few macros in this newly defined file 
which are getting called from gcc/unwind-dw2.c. Please review the same 
and do let me know for further modifications, if any. We have identified 
issues related to exception handling using prints in unwind code and 
will debug the same to a greater extent in near future with further 
development of GNU based tools.


>Since you first submitted the port, a file contrib/config-list.mk

"cr16-elf" is added to config-list.mk file.


gcc/ChangeLog:
--------------
2011-05-28	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/constraints.md: New file.
	* config/cr16/t-cr16: New file.

libgcc/ChangeLog:
-----------------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-helper.h: New file.
	
contrib/ChangeLog:
----------
2011-05-28  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config-list.mk: Add National Semiconductor CR16 target.
   
Thanks in advance,
Sumanth G,
PUNE (India).

===== End Message ======


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: CR16 Port addition
  2011-01-13  9:06 Sumanth Gundapaneni
@ 2011-01-14 18:54 ` Richard Henderson
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2011-01-14 18:54 UTC (permalink / raw)
  To: Sumanth Gundapaneni; +Cc: Joseph Myers, gcc-patches, Jayant R. Sonar

> +/* Initialize 'targetm' variable which contains pointers to functions 
> +   and data relating to the target machine.  */
> +struct gcc_target targetm = TARGET_INITIALIZER;

Not a requirement, but as a comment:

I find it much cleaner to move the target initializer to the end
of the file, which avoids the need for forward delcarations of 
the functions that are placed within.

I know there is a lot of variation in this among ports, but this
is something that ought to get cleaned up in the future.

> +cr16_class_likely_spilled_p (reg_class_t rclass)
> +{
> +  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS \

Trailing \.  Left over from macro-to-function conversion?

> +  /* To avoid gen_rtx_SUBREG ICE. SI gets splitted to two HIs where 
> +     validate_subreg is invalid with the second HI having offset 2
> +     .Offset applicable to big endian machines.  */
> +  flag_split_wide_types = 0;

I would really like to know more about this.

> +  /* If EH, disable optimization GCSE.  */
> +  if (flag_exceptions)
> +    flag_gcse = 0;

Why?  It works for other targets.

> +/* Compute values for the array save_regs and the variable sum_regs.
> +   The index of save_regs is numbers of register, each will get 1 if we 
> +   need to save it in the current function, 0 if not.  sum_regs is the 
> +   total sum of the registers being saved.  */
> +static void
> +cr16_compute_save_regs (void)
...
> +/* Compute the size of the local area and the size to be adjusted by the
> +   prologue and epilogue.  */
> +static void
> +cr16_compute_frame (void)

I would be very much happier if these functions did not store their results
into global variables.  Consider using a structure, like struct ix86_frame
is used in the i386 port.

> +  if ((mode == Pmode) && (regno == 11))
> +    return 0;

Is there a symbolic name for 11?

> +cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
> +		   const_tree type, bool named ATTRIBUTE_UNUSED)
> +{
> +  last_parm_in_reg = 0;

Using a global here is definitely wrong.  If you need to store extra
data, then store it in the CUMULATIVE_ARGS structure.  Though in this
case I think all you need to do is share some code between function_arg
and function_arg_advance.

> +      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))

s/(tree) 0/NULL_TREE/g

> +/* Constraint for bit instructions.  */
> +#define OK_FOR_Z(OP) \
> +  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
> +   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
> +   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
> +       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
> +       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
...
> +(define_predicate "bit_operand"
> +  (match_code "mem")
> +{
> +  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
> +})

These should be merged, since OK_FOR_Z isn't used elsewhere.

I don't see a constraints.md file?  Or any of the legacy macros for
that matter.  Did the file get forgotten in the patch?

> +  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")

The constraint here is almost certainly wrong.  It should be only "=Z".
If you're having problems with this, it means you havn't properly
defined the Z constraint with define_memory_constraint.

> +;; Register operand to avoid subreg with offset byte offset 2 
> +(define_predicate "reg_operand"
> +  (match_operand 0 "register_operand")
> +{
> +  if (GET_CODE(op) == SUBREG
> +      && (REGNO(SUBREG_REG(op)) > 11
> +          && REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
> +      && SUBREG_BYTE(op) != 0)
> +    return 0;    
> +    return 1;
> +})

This is wrong.  This issue should be handled with CANNOT_CHANGE_MODE_CLASS,
and not with random hacks across the rest of the port.

> +(define_expand "adddi3"
> +  [(set (match_operand:DI 0 "reg_operand" "")
> +	(plus:DI (match_operand:DI 1 "reg_operand" "")
> +		 (match_operand:DI 2 "reg_operand" "")))]
> +  ""
> +  {
> +    if ((GET_CODE (operands[2]) != REG) )
> +      {
> +	operands[2] = force_reg (DImode, operands[2]);
> +      }
> +  }

You should trust the predicates to do the right thing.  You
have constrained operands[2] to be a reg_operand.  Why are
you then checking that it's not a REG?

Indeed, once that's fixed there's no reason not to simply
merge your adddi3 expander with the adddi3_insn pattern.

> +	(plus:SI (mult:SI (sz_xtnd:SI (match_operand:HI 1 "reg_operand" "%r"))
> +			  (sz_xtnd:SI (match_operand:HI 2 "reg_operand" "r")))

% should be used only when the constraints of the two operands
are different.  Otherwise you're just wasting time in reload
making it examine both possibilities.

> +  [(set (match_operand:HI 0 "reg_operand" "=r,=r")
> +	(mult:HI (match_operand:HI 1 "register_and_valid_subreg_byte_operand" "%0,0")
> +		 (match_operand:HI 2 "nonmemory_operand" "r,i")))]

Extra = in operand 0.

> +(define_expand "andhi3"
> +  [(set (match_operand:HI 0 "reg_operand" "")
> +	(and:HI (match_operand:HI 1 "reg_operand" "")
> +		(match_operand:HI 2 "nonmemory_operand" "")))]
> +  ""
> +  "
> +{
> +  if ((GET_CODE (operands[1]) == SUBREG 
> +       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
> +   && (GET_CODE (operands[2]) == SUBREG
> +       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
> +    FAIL;
> +}")
> +

What is this for?  Disallowing subregs of pseudos?!?

> +;;T -  prints upper half
> +;;U -  prints lower half
> +(define_insn "anddi3"
> +  [(set (match_operand:DI 0 "reg_operand" "=r")
> +	(and:DI (match_operand:DI 1 "reg_operand" "%0")
> +		(match_operand:DI 2 "nonmemory_operand" "r")))]
> +  ""
> +  "andd\t%T2,%T0\;andd\t%U2,%U0"
> +)

You'd be better off without this, and let the compiler generate
it itself from two SImode ands.  Likewise with the rest of the
logical arithmetic.

> +; (DI, DF) move
> +(define_insn "*mov<mode>_double"
> +  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
> +	(match_operand:DOUBLE 1 "gen_operand" "r, <iFD>, m, r"))]
> +  "register_operand (operands[0], DImode) 
> +   || register_operand (operands[0], DFmode)
> +   || register_operand (operands[1], DImode)
> +   || register_operand (operands[1], DFmode)"

This whole pattern has got to get cleaned up.  The best way to do so
is to delete it, and let the generic bits of the compiler handle this
itself via subreg decomposition.  Of course, this requires that you
fix the subreg problems that you're having rather than papering over.

> +(define_insn "cbranch<mode>4"
> +  [(set (pc)
> +	(if_then_else (match_operator 0 "ordered_comparison_operator"
> +		      [(match_operand:CR16IM 1 "register_operand" "r,r")
> +		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
> +		       (label_ref (match_operand 3 "" ""))
> +                      (pc)))
> +   (clobber (cc0))]
> +  ""
> +  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
> +  [(set_attr "length" "6,6")]
> +)
> +
> +(define_expand "cmp<mode>"
> +  [(parallel [(set (cc0)
> +    (compare (match_operand:CR16IM 0 "register_operand" "")
> +	     (match_operand:CR16IM 1 "register_operand" "")))
> +   (clobber (match_scratch:HI 2 "=r"))]) ]
> +   ""
> +   "")
> +
> +(define_insn "*cmp<mode>_insn"
> +  [(set (cc0)
> +	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
> +		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))
> +   (clobber (match_scratch:HI 2 "=r,r")) ]
> +  ""                  
> +  "cmp<tIsa>\t%1, %0"
> +  [(set_attr "length" "2,4")]
> +)

I'm not sure I understand the logic here.  If you have a cbranch insn,
which you never split, I'm not sure why you'd need a cmp pattern at all.

> +(define_insn "indirect_jump_return"
> +  [(parallel
> +    [(set (pc)
> +	  (reg:SI RA_REGNUM))
> +   (return)])
> +  ]
...
> +(define_insn "interrupt_return"
> +  [(parallel
> +    [(unspec_volatile [(const_int 0)] 0)
> +   (return)])]
...
> +(define_insn "push_for_prologue"
> +  [(parallel
> +    [(set (reg:SI SP_REGNUM)
> +	  (minus:SI (reg:SI SP_REGNUM)
> +		    (match_operand:SI 0 "immediate_operand" "i")))])]
...
> +(define_insn "pop_and_popret_return"
> +  [(parallel
> +    [(set (reg:SI SP_REGNUM)
> +	  (plus:SI (reg:SI SP_REGNUM)
> +		   (match_operand:SI 0 "immediate_operand" "i")))
> +     (use (reg:SI RA_REGNUM))
> +     (return)])

Extra parallel.  It's implicit in define_insn.

> +(define_expand "call"
> +  [(call (match_operand:QI 0 "memory_operand" "")
> +	 (match_operand 1 "" ""))]
> +  ""
...
> +(define_expand "cr16_call"
> +  [(parallel
> +    [(call (match_operand:QI 0 "memory_operand" "")
> +	   (match_operand 1 "" ""))
> +   (clobber (reg:SI RA_REGNUM))])]

These can be trivially merged.

> +;;  Nop
> +(define_insn "nop"
> +  [(const_int 0)]
> +  ""
> +  ""
> +)

Nop really needs to output something.  It's used to make sure
various line numbers are distinct addresses at -O0 -g.

> +;; Shared FLAT
> +(define_insn "unspec_library_offset"
> +  [(const_int UNSPEC_LIBRARY_OFFSET)]
> +  ""
> +  "push \t$2, r0;\n\tmovd \t$__current_shared_library_r12_offset_, (r1,r0);\n\tloadd \t[r12]0(r1,r0), (r12);\n\tpop \t$2, r0\n\t"
> +  [(set_attr "length" "12")]
> +)
> +
> +(define_insn "unspec_sh_lib_push_r12"
> +  [(const_int UNSPEC_SH_LIB_PUSH_R12)]
> +  ""
> +  "push \t$2, r12"
> +  [(set_attr "length" "2")]
> +)
> +
> +(define_insn "unspec_sh_lib_pop_r12"
> +  [(const_int UNSPEC_SH_LIB_POP_R12)]
> +  ""
> +  "pop \t$2, r12"
> +  [(set_attr "length" "2")]
> +)

Huh?


r~

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
@ 2011-01-13  9:06 Sumanth Gundapaneni
  2011-01-14 18:54 ` Richard Henderson
  0 siblings, 1 reply; 13+ messages in thread
From: Sumanth Gundapaneni @ 2011-01-13  9:06 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 2225 bytes --]

Hi Joseph,

Thanks for review and suggestions.

Please find attached the patch "cr16-gcc.patch" which contains 
modifications as suggested in your review mail.

A mail had already been posted at the following link which addressed 
the comments as per your suggestions.
"http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01931.html"

However, we have not yet received any replies for the above mail.
Please review the patch and let me know if there should be any 
modifications in it.

gcc/ChangeLog:
--------------
2011-01-13	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-dw2-cr16.c: New file.
	* config/cr16/unwind-dw2.h: New file. 

libgcc/ChangeLog:
-----------------
2011-01-13  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.host: Add National Semiconductor CR16 target (cr16-*-*).
	* config/cr16/crti.S: New file.
	* config/cr16/crtlibid.S: New file.
	* config/cr16/crtn.S: New file.
	* config/cr16/t-cr16: New file.
		
libstdc++-v3/ChangeLog:
-----------------------
2011-01-13  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	*configure: Add National Semiconductor CR16 target (cr16-*-*).		
	*crossconfig.m4 : Add support for National Semiconductor CR16 target.

ChangeLog:
----------
2011-01-13  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* configure.ac: Add National Semiconductor CR16 target.
	* configure: Regenerate
   
Thanks in advance,
Sumanth G,
PUNE (India).  

[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 217416 bytes --]

diff -uprN orig/configure mod/configure
--- orig/configure	2010-12-21 20:00:26.000000000 +0530
+++ mod/configure	2011-01-12 17:39:57.000000000 +0530
@@ -3239,8 +3239,13 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
-    ;;
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
+    ;;	
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
     case "${target}" in
diff -uprN orig/configure.ac mod/configure.ac
--- orig/configure.ac	2010-12-21 19:58:26.000000000 +0530
+++ mod/configure.ac	2011-01-12 17:36:41.000000000 +0530
@@ -699,7 +699,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
     ;;
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
diff -uprN orig/gcc/config/cr16/cr16.c mod/gcc/config/cr16/cr16.c
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2011-01-12 17:39:04.000000000 +0530
@@ -0,0 +1,2267 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Static Variables.  */
+
+/* Nonzero if the last param processed is passed in a register.  */
+static int last_parm_in_reg;
+
+/* Will hold the number of the last register the prologue saves, -1 if no
+   register is saved.  */
+static int last_reg_to_save;
+
+/* Each object in the array is a register number. Mark 1 for registers that
+   need to be saved.  */
+static int save_regs[FIRST_PSEUDO_REGISTER];
+
+/* Number of bytes saved on the stack for non-scratch registers.  */
+static int sum_regs = 0;
+
+/* Number of bytes saved on the stack for local variables.  */
+static int local_vars_size;
+
+/* The sum of 2 sizes: locals vars and padding byte for saving the registers.
+   Used in expand_prologue () and expand_epilogue ().  */
+static int size_for_adjusting_sp;
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* Nonzero if -mshared-library-id was given.  */
+static int cr16_lib_id_given;
+
+/* Global Variables.  */
+
+/* Specify the identification number of the library being built.  */
+const char *cr16_library_id_string = "__current_shared_library_r12_offset_";
+
+/* Table of machine attributes.  */
+const struct attribute_spec cr16_attribute_table[];
+
+/* TARGETM Function Prototypes.  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
+static int cr16_address_cost (rtx);
+static int cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+
+/* Stack layout and calling conventions.  */
+
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+
+const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  {"interrupt", 0, 0, false, true, true, NULL},
+  {NULL, 0, 0, false, false, false, NULL}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+		       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, CR16_STRUCT_VALUE_REGNUM);
+}
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS \
+       || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, int size)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* To avoid gen_rtx_SUBREG ICE. SI gets splitted to two HIs where 
+     validate_subreg is invalid with the second HI having offset 2
+     .Offset applicable to big endian machines.  */
+  flag_split_wide_types = 0;
+
+  /* If EH, disable optimization GCSE.  */
+  if (flag_exceptions)
+    flag_gcse = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture.");
+	}
+      else
+	error ("Invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+  /* Library identification.  */
+  if (cr16_lib_id_given && !TARGET_ID_SHARED_LIBRARY)
+    error ("-mshared-library-id= specified without -mid-shared-library");
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    flag_pic = FAR_PIC;
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array save_regs and the variable sum_regs.
+   The index of save_regs is numbers of register, each will get 1 if we 
+   need to save it in the current function, 0 if not.  sum_regs is the 
+   total sum of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  sum_regs = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (!TARGET_ID_SHARED_LIBRARY &&
+      FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (TARGET_ID_SHARED_LIBRARY && PIC_OFFSET_TABLE_REGNUM == regno)
+	{
+	  save_regs[regno] = 1;
+	  continue;
+	}
+      else if (fixed_regs[regno])
+	{
+	  save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    save_regs[regno] = 1;
+	  else
+	    save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (save_regs[regno] == 1)
+      {
+	last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  sum_regs += CR16_UNITS_PER_DWORD;
+	else
+	  sum_regs += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  local_vars_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = local_vars_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  local_vars_size += padding_locals;
+  size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS
+					     ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use sum_regs.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use local_vars_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (sum_regs + local_vars_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (sum_regs + local_vars_size + (ACCUMULATE_OUTGOING_ARGS
+					  ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  if (regno < 15)
+    return NOSP_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((mode == Pmode) && (regno == 11))
+    return 0;
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/*Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+NOTE: @BRO is added using unspec:BRO
+NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+  rtx pic_ref;
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	  pic_ref = reg;
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	  pic_ref = reg;
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of got_operand.  */
+rtx
+got_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_got_addr (reg, orig));
+  return reg;
+}
+
+/* Implementation of bro_operand.  */
+rtx
+bro_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_bro_addr (reg, orig));
+  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+  return reg;
+}
+
+/* Implementation of GO_IF_LEGITIMATE_ADDRESS.  */
+int
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, int strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "Invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "Absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "Register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "Register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "Index + Register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\nCR16 Address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /*
+     CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9
+  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+
+int
+cr16_memory_move_cost (enum machine_mode mode,
+		       enum reg_class class ATTRIBUTE_UNUSED,
+		       int in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (class, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+
+    case 'L':
+    case 'M':
+    case 'H':
+      /* Print the  DImode values.  */
+      if (GET_CODE (x) == REG)
+	{
+	  if (LONG_REG_P (REGNO (x)))
+	    fprintf (file, "identified an  error L0");
+	  else if (code == 'L')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+		     reg_names[REGNO (x)]);
+	  else if (code == 'M')
+	    fprintf (file, "%s", reg_names[REGNO (x) + 2]);
+	  else if (code == 'H')
+	    fprintf (file, "%s", reg_names[REGNO (x) + 3]);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  fprintf (file, "$");
+	  if (code == 'L')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 32) & 0xffffffff);
+	  else if (code == 'M')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 16) & 0xffff);
+	  else if (code == 'H')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX, (INTVAL (x)) & 0xffff);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else
+	output_operand_lossage ("invalid operand");
+
+      return;
+    case 'T':
+    case 'U':
+      if (GET_CODE (x) == REG)
+	{
+	  if (LONG_REG_P (REGNO (x)))
+	    fprintf (file, "identified an  error T0");
+	  else if (code == 'T')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+		     reg_names[REGNO (x)]);
+	  else if (code == 'U')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 3],
+		     reg_names[REGNO (x) + 2]);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  fprintf (file, "$");
+	  if (code == 'T')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 32) & 0xffffffff);
+	  else if (code == 'U')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x)) & 0xffffffff);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else
+	output_operand_lossage ("invalid operand");
+
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "UNSPEC!!");
+	  switch (XINT (x, 1))
+	    {
+	    case UNSPEC_LIBRARY_OFFSET:
+	      inform (input_location, "UNSPEC_LIBRARY_OFFSET!!!");
+	      fprintf (file, "%s", cr16_library_id_string);
+	      return;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "UNSPEC 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+void
+cr16_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
+			   rtx tmp_reg, unsigned HOST_WIDE_INT * offset_p)
+{
+  rtx addr, mem;
+  unsigned HOST_WIDE_INT offset = *offset_p;
+
+  /* Load.  */
+  addr = plus_constant (src, offset);
+  mem = adjust_automodify_address (srcbase, SImode, addr, offset);
+  emit_move_insn (tmp_reg, mem);
+
+  /* Store.  */
+  addr = plus_constant (dst, offset);
+  mem = adjust_automodify_address (dstbase, SImode, addr, offset);
+  emit_move_insn (mem, tmp_reg);
+
+  *offset_p = offset + 4;
+}
+
+int
+cr16_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
+{
+  unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
+  HOST_WIDE_INT align = 0;
+
+  rtx src, dst;
+  rtx tmp_reg;
+
+  if (GET_CODE (align_exp) == CONST_INT)
+    {				/* Only if aligned.  */
+      align = INTVAL (align_exp);
+      if (align & 3)
+	return 0;
+    }
+
+  if (GET_CODE (count_exp) == CONST_INT)
+    {				/* No more than 16 SImode moves.  */
+      count = INTVAL (count_exp);
+      if (count > 64)
+	return 0;
+    }
+
+  tmp_reg = gen_reg_rtx (SImode);
+
+  /* Create psrs for the src and dest pointers.  */
+  dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
+  if (dst != XEXP (dstbase, 0))
+    dstbase = replace_equiv_address_nv (dstbase, dst);
+  src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
+  if (src != XEXP (srcbase, 0))
+    srcbase = replace_equiv_address_nv (srcbase, src);
+
+  offset = 0;
+
+  /* Emit SImode moves.  */
+  si_moves = count >> 2;
+  for (i = 0; i < si_moves; i++)
+    cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
+
+  /* Special cases.  */
+  if (count & 3)
+    {
+      offset = count - 4;
+      cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg,
+				 &offset);
+    }
+
+  gcc_assert (offset == count);
+
+  return 1;
+}
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of save_regs[], going from 0 until last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) && (i <= last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* pop.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= last_reg_to_save; ++i)
+    {
+      if (save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = last_reg_to_save + 1;
+  to = last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = last_reg_to_save; i >= 0;)
+    {
+      if (!save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+					REG_NOTES (insn));
+}
+
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((size_for_adjusting_sp + sum_regs) == 0)
+    return;
+
+  if (last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    emit_insn (gen_unspec_library_offset ());
+
+  if (size_for_adjusting_sp > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-size_for_adjusting_sp)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+  rtx return_reg;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
+			&& (sum_regs == CR16_UNITS_PER_DWORD));
+
+  /* Return register.  */
+  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);
+
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (size_for_adjusting_sp > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (size_for_adjusting_sp)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_indirect_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static int
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* Implement TARGET_HANDLE_OPTION.  */
+static bool
+cr16_handle_option (size_t code, const char *arg, int value)
+{
+  switch (code)
+    {
+    case OPT_mshared_library_id_:
+      if (value > MAX_LIBRARY_ID)
+	error ("-mshared-library-id=%s is not between 0"
+	       " and %d", arg, MAX_LIBRARY_ID);
+      cr16_lib_id_given = 1;
+      return true;
+
+    default:
+      return true;
+    }
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION cr16_handle_option
+
+void
+notice_update_cc (exp)
+     rtx exp;
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+rtx
+gen_compare_reg (code, x, y)
+     enum rtx_code code;
+     rtx x, y;
+{
+  enum machine_mode mode;
+
+  mode = GET_MODE (x);
+
+  /* For floating point compare insns, a call is generated so don't
+     do anything here.  */
+
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return cc0_rtx;
+
+  emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
+			  gen_rtx_COMPARE (VOIDmode,
+					   force_reg (mode, x),
+					   force_reg (mode, y))));
+  return cc0_rtx;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
diff -uprN orig/gcc/config/cr16/cr16.h mod/gcc/config/cr16/cr16.h
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2011-01-12 17:39:04.000000000 +0530
@@ -0,0 +1,691 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES         	\
+  {                                 	\
+    GENERAL_REGS, LIM_REG_CLASSES  	\
+  }
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+    if (TARGET_ID_SHARED_LIBRARY)          \
+      builtin_define ("__ID_SHARED_LIB__"); \
+  }                                        \
+while (0)
+#endif
+
+#define TARGET_VERSION fputs (" (CR16/ELF)", stderr);
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+/* Maximum number of library ids we permit.  */
+#define MAX_LIBRARY_ID 255
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Order of allocation of registers. Need to experiment on it
+   to for effective code density.  */
+#define REG_ALLOC_ORDER {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+   (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define REG_CLASS_FROM_LETTER(C)    \
+  ((C) == 'b' ? NOSP_REGS :         \
+   (C) == 't' ? SHORT_REGS :        \
+   (C) == 'p' ? LONG_REGS :         \
+   NO_REGS)
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+
+#define CHECK_64_BIT_ADD_SUB_DI(imm) 	\
+  (((((long long) imm >> 47) & 0x1) && (((long long)imm >> 63) \
+       & 0x1))? 0 : 1)
+
+/* The letters I, J, K, L in a register constraint string
+   can be used to stand for particular ranges of immediate operands.
+   This macro defines what the ranges are.
+   C is the letter, and VALUE is a constant value.
+   Return 1 if VALUE is in the range specified by C.
+   I : signed 4 bit immediate
+   J : signed 5 bit immediate
+   K : signed 6 bit immediate
+   L : unsigned 4 bit immediate  
+   M : signed 32 bit immediate  
+   N : check for 64-bit add/sub instructions.  */
+#define CONST_OK_FOR_LETTER_P(VALUE, C)                \
+   ((C) == 'I' ? SIGNED_INT_FITS_N_BITS (VALUE, 4) :   \
+    (C) == 'J' ? SIGNED_INT_FITS_N_BITS (VALUE, 5) :   \
+    (C) == 'K' ? SIGNED_INT_FITS_N_BITS (VALUE, 6) :   \
+    (C) == 'L' ? UNSIGNED_INT_FITS_N_BITS (VALUE, 4):  \
+    (C) == 'M' ? SIGNED_INT_FITS_N_BITS (VALUE,32) :   \
+    (C) == 'N' ? CHECK_64_BIT_ADD_SUB_DI (VALUE) : 0)
+
+/*To print Logical DI3 patterns.  */
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
+  (CODE == 'L' || CODE == 'M' || CODE == 'H'|| CODE == 'U')
+
+/* Similar, but for floating constants, and defining letters G and H.
+   Here VALUE is the CONST_DOUBLE rtx itself.  
+   G : Float constant that can fit in 4 bits.
+   H : Not defined.  */
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
+  ((C) == 'G' ? cr16_const_double_ok (VALUE) : 0)
+
+/* Constraint for bit instructions.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Returning function value.  */
+
+/* On the CR16, the return value is in R0.  */
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+    gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
+
+#define LIBCALL_VALUE(MODE)     gen_rtx_REG (MODE, 0)
+
+#define FUNCTION_VALUE_REGNO_P(N)   ((N) == 0)
+
+#define CR16_STRUCT_VALUE_REGNUM  0
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("Profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 1))       \
+    goto LABEL;                                   \
+}
+#else /* not REG_OK_STRICT.  */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 0))       \
+    goto LABEL;                                   \
+}
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P.
+   In cr16c treat legitimize float constant as an immediate operand.  */
+#define LEGITIMATE_CONSTANT_P(X)  1
+
+/* Relative costs of operations.  */
+#define MEMORY_MOVE_COST(MODE, CLASS, IN) \
+  cr16_memory_move_cost (MODE, CLASS, IN)
+
+/* Moving to processor register flushes pipeline - thus asymmetric.  */
+#define REGISTER_MOVE_COST(MODE, FROM, TO) ((TO != GENERAL_REGS) ? 8 : 2)
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+#define PRINT_OPERAND(STREAM, X, CODE) \
+  cr16_print_operand (STREAM, X, CODE)
+
+#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
+  cr16_print_operand_address (STREAM, ADDR)
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
+  (CODE == 'L' || CODE == 'M' || CODE == 'H'|| CODE == 'U')
+
+
+#endif /* End of GCC_CR16_H.  */
diff -uprN orig/gcc/config/cr16/cr16-libgcc.s mod/gcc/config/cr16/cr16-libgcc.s
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2011-01-12 17:49:13.000000000 +0530
@@ -0,0 +1,578 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
diff -uprN orig/gcc/config/cr16/cr16.md mod/gcc/config/cr16/cr16.md
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2011-01-12 17:46:49.000000000 +0530
@@ -0,0 +1,1127 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>. 
+
+
+;;  Register numbers
+
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates
+
+(include "predicates.md")
+
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+  ]
+)
+
+;; Attributes
+
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+
+(define_mode_iterator ALLMT  [QI HI SI SF])
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+
+(define_mode_attr IJK       [(QI "I") (HI "J") (SI "K")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+
+;;  Code Macro Definitions
+
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[3]) < 0 || INTVAL (operands[3]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	   emit_insn (gen_set_bithi (operands[0], operands[2]));
+	   DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+;;; In operand %s1, 's' will be evaluated to bit number to set
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+ )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+;; In operand %r1, 'r' will be evaluated to bit number to reset
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i")))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Addition Instructions
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "reg_operand" "")
+	(plus:DI (match_operand:DI 1 "reg_operand" "")
+		 (match_operand:DI 2 "reg_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG) )
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(plus:DI (match_operand:DI 1 "reg_operand" "%0")
+		 (match_operand:DI 2 "reg_operand" "r")))]
+  ""
+  "addd\t%L2,%L0\;addcw\t%M2,%M0\;addcw\t%H2,%H0"
+)
+
+(define_insn "add<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,r")
+	(plus:CR16IM (match_operand:CR16IM 1 "reg_operand" "%0,0")
+		     (match_operand:CR16IM 2 "nonmemory_operand" "r,i")))]
+  ""
+  "add<tIsa>\t%2, %0"
+)
+
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "reg_operand" "")
+	(minus:DI (match_operand:DI 1 "reg_operand" "")
+		  (match_operand:DI 2 "reg_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "reg_operand" "=r,r")
+	(minus:DI (match_operand:DI 1 "reg_operand" "0,0")
+		  (match_operand:DI 2 "reg_operand" "r,i")))]
+  ""
+  "subd\t%L2,%L0\;subcw\t%M2,%M0\;subcw\t%H2,%H0"
+  [(set_attr "length" "8")]
+)
+
+(define_insn "sub<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,r")
+	(minus:CR16IM (match_operand:CR16IM 1 "reg_operand" "0,0")
+		      (match_operand:CR16IM 2 "nonmemory_operand" "r,i")))]
+  ""
+  "sub<tIsa>\t%2, %0"
+  [(set_attr "length" "2,<lImmArith>")]
+)
+
+;;  Multiply and Accumulate Instructions
+(define_insn "<sPat>madhisi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r")
+	(plus:SI (mult:SI (sz_xtnd:SI (match_operand:HI 1 "reg_operand" "%r"))
+			  (sz_xtnd:SI (match_operand:HI 2 "reg_operand" "r")))
+		 (match_operand:SI 3 "reg_operand" "0")))]
+  "TARGET_MAC"
+  "mac<sPat>w\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "reg_operand" "=r,=r")
+	(mult:HI (match_operand:HI 1 "register_and_valid_subreg_byte_operand" "%0,0")
+		 (match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+; Only mulsb exists, therefore no use of mode and code macros
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "reg_operand" "=r")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "reg_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Logical Instructions - and
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(and:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "andhi3"
+  [(set (match_operand:HI 0 "reg_operand" "")
+	(and:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG 
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+
+(define_insn "andhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(and:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(and:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T -  prints upper half
+;;U -  prints lower half
+(define_insn "anddi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(and:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "andd\t%T2,%T0\;andd\t%U2,%U0"
+)
+
+;;  Logical Instructions - or
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(ior:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "iorhi3"
+  [(set (match_operand:HI 0 "reg_operand" "")
+	(ior:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG 
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG 
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+
+(define_insn "iorhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(ior:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,4")]
+) 
+
+(define_insn "iorsi3" 
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(ior:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T - prints upper half
+;;U - prints lower half
+(define_insn "iordi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(ior:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "ord\t%T2,%T0\;ord\t%U2,%U0"
+)
+
+;;  Logical Instructions - xor
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(xor:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "xorhi3"
+  [(set (match_operand:HI 0 "reg_operand" "") 
+	(xor:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+ 
+(define_insn "xorhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(xor:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(xor:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""   
+  "xord\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T - prints upper half
+;;U - prints lower half
+(define_insn "xordi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(xor:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "xord\t%T2,%T0\;xord\t%U2,%U0"
+)
+
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "reg_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "reg_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "reg_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "reg_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(not:DI (match_operand:DI 1 "reg_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashl<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,=r")
+	(ashift:CR16IM (match_operand:CR16IM 1 "reg_operand" "0,0")
+		       (match_operand:QI 2 "nonmemory_operand" "r,<IJK>")))]
+  ""
+  "ashu<tIsa>\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if (GET_CODE (operands[2]) == CONST_INT)
+      {
+	/* If the constant is not in range, try placing it in a reg.  */
+	if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg (QImode, operands[2]);
+      }
+
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }
+)
+
+(define_insn "ashr<mode>3_imm_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (match_operand:QI 2 "shift_<mode>_imm_operand" "i")))]
+  ""
+  "ashu<tIsa>\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashr<mode>3_neg_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (neg:QI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "ashu<tIsa>\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if (GET_CODE (operands[2]) == CONST_INT)
+      {
+	/* If the constant is not in range, try placing it in a reg.  */
+	if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg (QImode, operands[2]);
+      }
+
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }
+)
+
+(define_insn "lshr<mode>3_imm_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (match_operand:QI 2 "shift_<mode>_imm_operand" "i")))]
+  ""
+  "lsh<tIsa>\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshr<mode>3_neg_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (neg:QI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "lsh<tIsa>\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "gen_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "gen_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "gen_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "gen_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "register_operand" "")))
+   (clobber (match_scratch:HI 2 "=r"))]) ]
+   ""
+   "")
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))
+   (clobber (match_scratch:HI 2 "=r,r")) ]
+  ""                  
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      return "bal (ra), %b0";
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      return "bal (ra), %b1";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  ""
+)
+
+;; PIC
+                                                                                                                             
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+                                                                                                                             
+                                                                                                                            
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
+
+;; Shared FLAT
+(define_insn "unspec_library_offset"
+  [(const_int UNSPEC_LIBRARY_OFFSET)]
+  ""
+  "push \t$2, r0;\n\tmovd \t$__current_shared_library_r12_offset_, (r1,r0);\n\tloadd \t[r12]0(r1,r0), (r12);\n\tpop \t$2, r0\n\t"
+  [(set_attr "length" "12")]
+)
+
+(define_insn "unspec_sh_lib_push_r12"
+  [(const_int UNSPEC_SH_LIB_PUSH_R12)]
+  ""
+  "push \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "unspec_sh_lib_pop_r12"
+  [(const_int UNSPEC_SH_LIB_POP_R12)]
+  ""
+  "pop \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
diff -uprN orig/gcc/config/cr16/cr16.opt mod/gcc/config/cr16/cr16.opt
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2011-01-12 17:39:04.000000000 +0530
@@ -0,0 +1,59 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2010 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
+mid-shared-library
+Target Report Mask(ID_SHARED_LIBRARY)
+Enabled ID based shared library
+
+mshared-library-id=
+Target RejectNegative Joined UInteger Var(cr16_library_id)
+ID of shared library to build
+
diff -uprN orig/gcc/config/cr16/cr16-protos.h mod/gcc/config/cr16/cr16-protos.h
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2011-01-12 17:39:04.000000000 +0530
@@ -0,0 +1,110 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_legitimate_address_p (enum machine_mode, rtx, int);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+/* Instruction output.  */
+extern void cr16_print_operand (FILE *, rtx, int);
+extern void cr16_print_operand_address (FILE *, rtx);
+extern void cr16_expand_movmem_single (rtx, rtx, rtx, rtx, rtx,
+				       unsigned HOST_WIDE_INT *);
+extern int cr16_expand_movmem (rtx, rtx, rtx, rtx);
+extern rtx got_operand (rtx, enum machine_mode);
+extern rtx bro_operand (rtx, enum machine_mode);
+
+#endif /* RTX_CODE.  */
+
+/* Routines to compute costs.  */
+extern int cr16_memory_move_cost (enum machine_mode, enum reg_class, int);
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
diff -uprN orig/gcc/config/cr16/divmodhi3.c mod/gcc/config/cr16/divmodhi3.c
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2011-01-12 17:54:47.000000000 +0530
@@ -0,0 +1,115 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
diff -uprN orig/gcc/config/cr16/predicates.md mod/gcc/config/cr16/predicates.md
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2011-01-12 17:39:04.000000000 +0530
@@ -0,0 +1,191 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+
+;;  Predicates
+
+;; Equality operator
+(define_special_predicate "equality_operator"
+  (match_code "eq,ne"))
+
+;; Zero operand
+(define_predicate "zero_operand"
+  (match_code "const_int")
+{
+  HOST_WIDE_INT value = INTVAL (op);
+  return value == 0;
+})
+
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Register operand to avoid subreg with offset byte offset 2 
+(define_predicate "reg_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE(op) == SUBREG
+      && (REGNO(SUBREG_REG(op)) > 11
+          && REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+      && SUBREG_BYTE(op) != 0)
+    return 0;    
+    return 1;
+})
+
+;; General operand to avoid subreg with offset byte offset 2 
+(define_predicate "gen_operand"
+  (match_operand 0 "general_operand")
+{
+  if (GET_CODE(op) == SUBREG
+      && (REGNO(SUBREG_REG(op)) > 11
+          && REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+      && SUBREG_BYTE(op) != 0)
+    return 0;    
+    return 1;
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
+})
+
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 5)) ? 1 : 0;
+})
+
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 24)) ? 1 : 0;
+})
+
+;; CR16C/C+ does not have capability to address
+;; higher bytes of a register. Therefore, reject a register
+;; operand that has non-zero subreg byte
+(define_predicate "register_and_valid_subreg_byte_operand"
+  (match_operand 0 "register_operand")
+{
+  if ((GET_CODE(op) == SUBREG)
+       && (REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+       && (SUBREG_BYTE(op) != 0))
+    return 0;
+    return 1;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+
diff -uprN orig/gcc/config/cr16/t-cr16 mod/gcc/config/cr16/t-cr16
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2011-01-12 17:59:50.000000000 +0530
@@ -0,0 +1,73 @@
+# CR16 Target Makefile
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+LIB2ADDEH = $(srcdir)/config/cr16/unwind-dw2-cr16.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-c.c
+
+#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+#$(T)crti.o: $(srcdir)/config/cr16/crti.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.s
+
+#$(T)crtn.o: $(srcdir)/config/cr16/crtn.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.s
+
+#$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.s $(GCC_PASSES)
+#	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+#	  -c -o $(T)crtlibid.o \
+#	  -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.s
+
+MULTILIB_OPTIONS     = fPIC mint32 mid-shared-library
+MULTILIB_DIRNAMES    = far-pic int32 mid-shared-library
+MULTILIB_EXCEPTIONS  = fno-PIC/mid-shared-library
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
diff -uprN orig/gcc/config/cr16/unwind-dw2-cr16.c mod/gcc/config/cr16/unwind-dw2-cr16.c
--- orig/gcc/config/cr16/unwind-dw2-cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2-cr16.c	2011-01-12 17:54:58.000000000 +0530
@@ -0,0 +1,1597 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2008, 2009, 2010  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
+#endif
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  void *reg[DWARF_FRAME_REGISTERS+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[DWARF_FRAME_REGISTERS+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+  unsigned u2 __attribute__ ((mode (HI)));
+  unsigned u4 __attribute__ ((mode (SI)));
+  unsigned u8 __attribute__ ((mode (DI)));
+  signed s2 __attribute__ ((mode (HI)));
+  signed s4 __attribute__ ((mode (SI)));
+  signed s8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+
+static inline int
+read_1u (const void *p) { return *(const unsigned char *) p; }
+
+static inline int
+read_1s (const void *p) { return *(const signed char *) p; }
+
+static inline int
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
+
+static inline int
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
+
+static inline unsigned int
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
+
+static inline int
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
+
+static inline unsigned long
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
+
+static inline unsigned long
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return context->flags & EXTENDED_CONTEXT_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  void *ptr;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  ptr = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) ptr;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) ptr;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+      return;
+    }
+  ptr = context->reg[index];
+    if ( size == sizeof(_Unwind_Word) )
+      * (_Unwind_Word *) ptr = val;
+    else {
+      typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
+      gcc_assert (index + 1  <  (int) sizeof(dwarf_reg_size_table));
+      * (_CR16_Unwind_Word *) ptr = val & 0xffff ;  /* low 16-bit.  */
+      ptr = context->reg[index + 1];
+      * (_CR16_Unwind_Word *) ptr = val >> 16 ;  /* high 16-bit.  */
+         }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+		    _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
+
+  context->by_value[index] = 1;
+  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+#endif
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* Immediately following the augmentation are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
+   onto the stack to start.  */
+
+static _Unwind_Word
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
+		  struct _Unwind_Context *context, _Unwind_Word initial)
+{
+  _Unwind_Word stack[64];	/* ??? Assume this is enough.  */
+  int stack_elt;
+
+  stack[0] = initial;
+  stack_elt = 1;
+
+  while (op_ptr < op_end)
+    {
+      enum dwarf_location_atom op = *op_ptr++;
+      _Unwind_Word result;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      switch (op)
+	{
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	  result = op - DW_OP_lit0;
+	  break;
+
+	case DW_OP_addr:
+	  result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
+	  op_ptr += sizeof (void *);
+	  break;
+
+	case DW_OP_GNU_encoded_addr:
+	  {
+	    _Unwind_Ptr presult;
+	    op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+	    result = presult;
+	  }
+	  break;
+
+	case DW_OP_const1u:
+	  result = read_1u (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const1s:
+	  result = read_1s (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const2u:
+	  result = read_2u (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const2s:
+	  result = read_2s (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const4u:
+	  result = read_4u (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const4s:
+	  result = read_4s (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const8u:
+	  result = read_8u (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_const8s:
+	  result = read_8s (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_constu:
+	  op_ptr = read_uleb128 (op_ptr, &utmp);
+	  result = (_Unwind_Word)utmp;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &stmp);
+	  result = (_Unwind_Sword)stmp;
+	  break;
+
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+	  result = _Unwind_GetGR (context, op - DW_OP_reg0);
+	  break;
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  result = _Unwind_GetGR (context, reg);
+	  break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+	  break;
+	case DW_OP_bregx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+	  break;
+
+	case DW_OP_dup:
+	  gcc_assert (stack_elt);
+	  result = stack[stack_elt - 1];
+	  break;
+
+	case DW_OP_drop:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+	  goto no_push;
+
+	case DW_OP_pick:
+	  offset = *op_ptr++;
+	  gcc_assert (offset < stack_elt - 1);
+	  result = stack[stack_elt - 1 - offset];
+	  break;
+
+	case DW_OP_over:
+	  gcc_assert (stack_elt >= 2);
+	  result = stack[stack_elt - 2];
+	  break;
+
+	case DW_OP_swap:
+	  {
+	    _Unwind_Word t;
+	    gcc_assert (stack_elt >= 2);
+	    t = stack[stack_elt - 1];
+	    stack[stack_elt - 1] = stack[stack_elt - 2];
+	    stack[stack_elt - 2] = t;
+	    goto no_push;
+	  }
+
+	case DW_OP_rot:
+	  {
+	    _Unwind_Word t1, t2, t3;
+
+	    gcc_assert (stack_elt >= 3);
+	    t1 = stack[stack_elt - 1];
+	    t2 = stack[stack_elt - 2];
+	    t3 = stack[stack_elt - 3];
+	    stack[stack_elt - 1] = t2;
+	    stack[stack_elt - 2] = t3;
+	    stack[stack_elt - 3] = t1;
+	    goto no_push;
+	  }
+
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	case DW_OP_abs:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_plus_uconst:
+	  /* Unary operations.  */
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  result = stack[stack_elt];
+
+	  switch (op)
+	    {
+	    case DW_OP_deref:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		result = (_Unwind_Ptr) read_pointer (ptr);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		switch (*op_ptr++)
+		  {
+		  case 1:
+		    result = read_1u (ptr);
+		    break;
+		  case 2:
+		    result = read_2u (ptr);
+		    break;
+		  case 4:
+		    result = read_4u (ptr);
+		    break;
+		  case 8:
+		    result = read_8u (ptr);
+		    break;
+		  default:
+		    gcc_unreachable ();
+		  }
+	      }
+	      break;
+
+	    case DW_OP_abs:
+	      if ((_Unwind_Sword) result < 0)
+		result = -result;
+	      break;
+	    case DW_OP_neg:
+	      result = -result;
+	      break;
+	    case DW_OP_not:
+	      result = ~result;
+	      break;
+	    case DW_OP_plus_uconst:
+	      op_ptr = read_uleb128 (op_ptr, &utmp);
+	      result += (_Unwind_Word)utmp;
+	      break;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_le:
+	case DW_OP_ge:
+	case DW_OP_eq:
+	case DW_OP_lt:
+	case DW_OP_gt:
+	case DW_OP_ne:
+	  {
+	    /* Binary operations.  */
+	    _Unwind_Word first, second;
+	    gcc_assert (stack_elt >= 2);
+	    stack_elt -= 2;
+
+	    second = stack[stack_elt];
+	    first = stack[stack_elt + 1];
+
+	    switch (op)
+	      {
+	      case DW_OP_and:
+		result = second & first;
+		break;
+	      case DW_OP_div:
+		result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+		break;
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		result = second % first;
+		break;
+	      case DW_OP_mul:
+		result = second * first;
+		break;
+	      case DW_OP_or:
+		result = second | first;
+		break;
+	      case DW_OP_plus:
+		result = second + first;
+		break;
+	      case DW_OP_shl:
+		result = second << first;
+		break;
+	      case DW_OP_shr:
+		result = second >> first;
+		break;
+	      case DW_OP_shra:
+		result = (_Unwind_Sword) second >> first;
+		break;
+	      case DW_OP_xor:
+		result = second ^ first;
+		break;
+	      case DW_OP_le:
+		result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ge:
+		result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_eq:
+		result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+		break;
+	      case DW_OP_lt:
+		result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+		break;
+	      case DW_OP_gt:
+		result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ne:
+		result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  }
+	  break;
+
+	case DW_OP_skip:
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_bra:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  if (stack[stack_elt] != 0)
+	    op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_nop:
+	  goto no_push;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* Decode DWARF 2 call frame information. Takes pointers the
+   instruction sequence to decode, current register information and
+   CIE info, and the PC range to evaluate.  */
+
+static void
+execute_cfa_program (const unsigned char *insn_ptr,
+		     const unsigned char *insn_end,
+		     struct _Unwind_Context *context,
+		     _Unwind_FrameState *fs)
+{
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
+	      (_Unwind_Word)reg2;
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
+
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_GNU_window_save:
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  for (reg = 16; reg < 32; ++reg)
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	    }
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#else
+      return _URC_END_OF_STACK;
+#endif
+    }
+
+  fs->pc = context->bases.func;
+
+  cie = get_cie (fde);
+  insn = extract_cie_info (cie, context, fs);
+  if (insn == NULL)
+    /* CIE contained unknown augmentation.  */
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* First decode all the insns in the CIE.  */
+  end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  context.flags = EXTENDED_CONTEXT_BIT;
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
+
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+	{
+	case REG_SAVED_REG:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+	  break;
+	default:
+	  state_in->reg_or_offset[reg] = 0;
+	  break;
+	}
+    }
+
+  state_in->cfa_offset = fs.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+		     _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef EH_RETURN_STACKADJ_RTX
+  /* Special handling here: Many machines do not use a frame pointer,
+     and track the CFA only through offsets from the stack pointer from
+     one frame to the next.  In this case, the stack pointer is never
+     stored, so it has no saved address in the context.  What we do
+     have is the CFA from the previous stack frame.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+	const unsigned char *exp = fs->regs.cfa_exp;
+	_uleb128_t len;
+
+	exp = read_uleb128 (exp, &len);
+	cfa = (void *) (_Unwind_Ptr)
+	  execute_stack_op (exp, exp + len, &orig_context, 0);
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  context->cfa = cfa;
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
+    switch (fs->regs.reg[i].how)
+      {
+      case REG_UNSAVED:
+      case REG_UNDEFINED:
+	break;
+
+      case REG_SAVED_OFFSET:
+	_Unwind_SetGRPtr (context, i,
+			  (void *) (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_REG:
+	if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+	  _Unwind_SetGRValue (context, i,
+			      _Unwind_GetGR (&orig_context,
+					     fs->regs.reg[i].loc.reg));
+	else
+	  _Unwind_SetGRPtr (context, i,
+			    _Unwind_GetGRPtr (&orig_context,
+					      fs->regs.reg[i].loc.reg));
+	break;
+
+      case REG_SAVED_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRPtr (context, i, (void *) val);
+	}
+	break;
+
+      case REG_SAVED_VAL_OFFSET:
+	_Unwind_SetGRValue (context, i,
+			    (_Unwind_Internal_Ptr)
+			    (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_VAL_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRValue (context, i, val);
+	}
+	break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+    context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      /* Do any necessary initialization to access arbitrary stack frames. \
+	 On the SPARC, this means flushing the register windows.  */	   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context,
+		   void *outer_cfa, void *outer_ra)
+{
+  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  _Unwind_FrameState fs;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#if __GTHREADS
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
+	&& dwarf_reg_size_table[0] == 0)
+      init_dwarf_reg_size_table ();
+  }
+#else
+  if (dwarf_reg_size_table[0] == 0)
+    init_dwarf_reg_size_table ();
+#endif
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.cfa_offset -= context->args_size ;
+  uw_update_context_1 (context, &fs);
+
+  /* If the return address column was saved in a register in the
+     initialization context, then we can't see it in the given
+     call frame data.  So have the initialization context tell us.  */
+  context->ra = __builtin_extract_return_addr (outer_ra);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+  asm ("");
+}
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+
+#define uw_install_context(CURRENT, TARGET)                              \
+  do                                                                     \
+    {                                                                    \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
+      handler = (void*)( ( (unsigned)handler ) >> 1 ) ;                  \
+      __builtin_eh_return (offset, handler);                             \
+    }                                                                    \
+  while (0)
+
+
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+	{
+	  _Unwind_Word w;
+	  _Unwind_Ptr p;
+	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	    {
+	      w = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &w, sizeof (_Unwind_Word));
+	    }
+	  else
+	    {
+	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      p = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &p, sizeof (_Unwind_Ptr));
+	    }
+	}
+      else if (t && c && t != c)
+	memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
+      if (STACK_GROWS_DOWNWARD)
+	return target_cfa - current->cfa + target->args_size;
+      else
+	return current->cfa - target_cfa - target->args_size;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (STACK_GROWS_DOWNWARD)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff -uprN orig/gcc/config/cr16/unwind-dw2.h mod/gcc/config/cr16/unwind-dw2.h
--- orig/gcc/config/cr16/unwind-dw2.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2.h	2011-01-12 17:55:04.000000000 +0530
@@ -0,0 +1,87 @@
+/* DWARF2 frame unwind data structure.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* A target can override (perhaps for backward compatibility) how
+   many dwarf2 columns are unwound.  */
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* The result of interpreting the frame unwind info for a frame.
+   This is all symbolic at this point, as none of the values can
+   be resolved until the target pc is located.  */
+typedef struct
+{
+  /* Each register save state can be described in terms of a CFA slot,
+     another register, or a location expression.  */
+  struct frame_state_reg_info
+  {
+    struct {
+      union {
+	_Unwind_Word reg;
+	_Unwind_Sword offset;
+	const unsigned char *exp;
+      } loc;
+      enum {
+	REG_UNSAVED,
+	REG_SAVED_OFFSET,
+	REG_SAVED_REG,
+	REG_SAVED_EXP,
+	REG_SAVED_VAL_OFFSET,
+	REG_SAVED_VAL_EXP,
+	REG_UNDEFINED
+      } how;
+    } reg[DWARF_FRAME_REGISTERS+1];
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct frame_state_reg_info *prev;
+
+    /* The CFA can be described in terms of a reg+offset or a
+       location expression.  */
+    _Unwind_Sword cfa_offset;
+    _Unwind_Word cfa_reg;
+    const unsigned char *cfa_exp;
+    enum {
+      CFA_UNSET,
+      CFA_REG_OFFSET,
+      CFA_EXP
+    } cfa_how;
+  } regs;
+
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Sword data_align;
+  _Unwind_Word code_align;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+} _Unwind_FrameState;
+
diff -uprN orig/gcc/config.gcc mod/gcc/config.gcc
--- orig/gcc/config.gcc	2010-12-21 19:58:41.000000000 +0530
+++ mod/gcc/config.gcc	2011-01-12 17:37:14.000000000 +0530
@@ -926,6 +926,12 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+        tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} cr16/t-cr16 "
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        use_collect2=no
+        ;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
diff -uprN orig/gcc/doc/extend.texi mod/gcc/doc/extend.texi
--- orig/gcc/doc/extend.texi	2010-12-21 19:58:53.000000000 +0530
+++ mod/gcc/doc/extend.texi	2011-01-12 17:37:20.000000000 +0530
@@ -2545,7 +2545,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, CRX, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, CRX, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
diff -uprN orig/gcc/doc/install.texi mod/gcc/doc/install.texi
--- orig/gcc/doc/install.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/install.texi	2011-01-12 17:37:20.000000000 +0530
@@ -3185,6 +3185,33 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
diff -uprN orig/gcc/doc/invoke.texi mod/gcc/doc/invoke.texi
--- orig/gcc/doc/invoke.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2011-01-12 17:37:20.000000000 +0530
@@ -500,6 +500,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32
+-mdata-model=@var{model}}
+
 @emph{CRX Options}
 @gccoptlist{-mmac -mpush-args}
 
@@ -9885,6 +9891,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * CRX Options::
 * Darwin Options::
 * DEC Alpha Options::
@@ -10713,6 +10720,43 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near}, 
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
+
 @node CRX Options
 @subsection CRX Options
 @cindex CRX Options
diff -uprN orig/gcc/doc/md.texi mod/gcc/doc/md.texi
--- orig/gcc/doc/md.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/md.texi	2011-01-12 17:37:20.000000000 +0530
@@ -1775,6 +1775,40 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item CRX Architecture---@file{config/crx/crx.h}
 @table @code
 
diff -uprN orig/libgcc/config/cr16/crti.S mod/libgcc/config/cr16/crti.S
--- orig/libgcc/config/cr16/crti.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crti.S	2011-01-12 17:56:52.000000000 +0530
@@ -0,0 +1,55 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.file   "crti.o"
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
diff -uprN orig/libgcc/config/cr16/crtlibid.S mod/libgcc/config/cr16/crtlibid.S
--- orig/libgcc/config/cr16/crtlibid.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtlibid.S	2011-01-12 17:57:06.000000000 +0530
@@ -0,0 +1,29 @@
+# Provide a weak definition of the library ID, for the benefit of certain
+# configure scripts.	 
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+	.file   "crtlibid.o"
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
diff -uprN orig/libgcc/config/cr16/crtn.S mod/libgcc/config/cr16/crtn.S
--- orig/libgcc/config/cr16/crtn.S	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/crtn.S	2011-01-12 17:56:58.000000000 +0530
@@ -0,0 +1,45 @@
+# Specialized code needed to support construction and destruction of
+# file-scope objects in C++ and Java code, and to support exception handling.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.file   "crtn.o"
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
diff -uprN orig/libgcc/config/cr16/t-cr16 mod/libgcc/config/cr16/t-cr16
--- orig/libgcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/libgcc/config/cr16/t-cr16	2011-01-12 18:17:40.000000000 +0530
@@ -0,0 +1,14 @@
+# Assemble startup files.
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.S
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtlibid.o -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.S
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.S $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.S
diff -uprN orig/libgcc/config.host mod/libgcc/config.host
--- orig/libgcc/config.host	2010-12-21 19:58:26.000000000 +0530
+++ mod/libgcc/config.host	2011-01-12 17:36:42.000000000 +0530
@@ -79,6 +79,8 @@ avr-*-*)
 bfin*-*)
 	cpu_type=bfin
 	;;
+cr16-*-*)
+	;;
 fido-*-*)
 	cpu_type=m68k
 	;;
@@ -250,6 +252,10 @@ cris-*-linux* | crisv32-*-linux*)
 	;;
 crx-*-elf)
 	;;
+cr16-*-*)
+        extra_parts="crtbegin.o crtend.o crti.o crtn.o crtlibid.o"
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 fido-*-elf)
 	;;
 fr30-*-elf)
diff -uprN orig/libstdc++-v3/configure mod/libstdc++-v3/configure
--- orig/libstdc++-v3/configure	2010-12-21 20:00:22.000000000 +0530
+++ mod/libstdc++-v3/configure	2011-01-12 17:39:53.000000000 +0530
@@ -26431,6 +26431,9 @@ case "${host}" in
   arm*-*-symbianelf*)
     # This is a freestanding configuration; there is nothing to do here.
     ;;
+  
+  cr16-*-*)
+    ;;
 
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
diff -uprN orig/libstdc++-v3/crossconfig.m4 mod/libstdc++-v3/crossconfig.m4
--- orig/libstdc++-v3/crossconfig.m4	2010-12-21 20:00:21.000000000 +0530
+++ mod/libstdc++-v3/crossconfig.m4	2011-01-12 17:39:52.000000000 +0530
@@ -8,7 +8,10 @@ case "${host}" in
   arm*-*-symbianelf*)
     # This is a freestanding configuration; there is nothing to do here.
     ;;
-
+  cr16-*-*)
+    # SiTel
+    #     ;;
+ 
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
     SECTION_FLAGS='-ffunction-sections -fdata-sections'

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: CR16 Port addition
  2010-12-22 13:25 ` Joseph S. Myers
@ 2010-12-29 15:32   ` Sumanth Gundapaneni
  0 siblings, 0 replies; 13+ messages in thread
From: Sumanth Gundapaneni @ 2010-12-29 15:32 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, Jayant R. Sonar

Hi Joseph,

Thanks for your detailed review and useful suggestions.

>> Files built for the target need to have the exception wording 
>> referencing COPYING.RUNTIME, not no exception as here ...

>> ... or the old GPLv2 exception as here.  Please check all libgcc
>> sources in this patch for appropriate license exception wording.

The concerned files have been modified as per GPLv3.

>> In general, if possible files built for the target should be under 
>> libgcc/config not gcc/config with makefile rules under 
>> libgcc/config as well.

The files have been moved to libgcc/config.

>> Could you clarify how these source files are related to the main 
>> target-independent unwind-dw2* files 

The following link was referenced while implementing CPP Exception 
Handling for CR16. http://gcc.gnu.org/wiki/Dwarf2EHNewbiesHowto
As per the link, required changes were implemented to handle 
exceptions in C++.

However, the CR16's programming memory is 2-byte aligned and the least
significant bit of PC is always zero. The Return Address (RA) register 
always saves the value of PC right shifted by 1(PC >> 1). This 
conversion seems broken at some places during unwinding which results 
in terminate() function  being called.
 
These files were added to help fix this problem. However, we have not yet
completely solved this problem. If we are able to fix this without major 
modifications, we will move these files back in which case customized
unwind files would not be needed.

>> No, never send such a patch to gcc-patches.  Any such changes must 
>> go to config-patches 
>> GCC should not have any local changes, and the GCC and src 
>> repositories should be kept in sync.

Fortunately, config.git has cr16 target added long time back. 


Thanks and Regards,
Sumanth G


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: CR16 Port addition
  2010-12-22 11:58 Sumanth Gundapaneni
@ 2010-12-22 13:25 ` Joseph S. Myers
  2010-12-29 15:32   ` Sumanth Gundapaneni
  0 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2010-12-22 13:25 UTC (permalink / raw)
  To: Sumanth Gundapaneni; +Cc: gcc-patches, Jayant R. Sonar

On Wed, 22 Dec 2010, Sumanth Gundapaneni wrote:

> 	* config/cr16/cr16-libgcc.s: New file.

Files built for the target need to have the exception wording referencing 
COPYING.RUNTIME, not no exception as here ...

> 	* config/cr16/crti.s: New file.

 ... or the old GPLv2 exception as here.  Please check all libgcc sources 
in this patch for appropriate license exception wording.

In general, if possible files built for the target should be under 
libgcc/config not gcc/config with makefile rules under libgcc/config as 
well.  At least crt* files can probably go there.

> 	* config/cr16/unwind-dw2-cr16.c: New file.
> 	* config/cr16/unwind-dw2.h: New file. 

Could you clarify how these source files are related to the main 
target-independent unwind-dw2* files, and, if they are based on them in 
some way, why you need a target-specific version, how you have kept it up 
to date with all changes to the target-independent version since you first 
forked it, and how you plan to keep it up to date in future?

> 2010-12-21  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
> 		Jayant R Sonar <jayant.sonar@kpitcummins.com>
> 
> 	* config.sub: Add National Semiconductor CR16 target.

No, never send such a patch to gcc-patches.  Any such changes must go to 
config-patches (preferably against the latest config.git, including 
testcases).  Once they are in config.git, you can import the latest 
versions of config.sub and config.guess into the gcc and src repositories 
without needing separate approval - but the only changes to those files in 
GCC should be imports of unmodified versions from config.git; GCC should 
not have any local changes, and the GCC and src repositories should be 
kept in sync.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* CR16 Port addition
@ 2010-12-22 11:58 Sumanth Gundapaneni
  2010-12-22 13:25 ` Joseph S. Myers
  0 siblings, 1 reply; 13+ messages in thread
From: Sumanth Gundapaneni @ 2010-12-22 11:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jayant R. Sonar

[-- Attachment #1: Type: text/plain, Size: 2886 bytes --]

Hi,

Please find the attached patch "cr16-gcc.patch" that adds compiler 
support for National Semiconductor's CR16 Architecture.
	
The following link provides an insight into previous attempts,
http://gcc.gnu.org/ml/gcc-patches/2007-09/msg01806.html

These sources have been updated and enhanced to suit latest version
of gcc branch.

The binutils and gdb-sim support were added at the following links
http://sourceware.org/ml/binutils/2007-06/msg00260.html
http://sourceware.org/ml/gdb-patches/2008-02/msg00253.html

Newlib support for this target was added recently by KPIT and 
the patches have been accepted in latest sources,
http://sourceware.org/ml/newlib/2010/msg00596.html

CR16 target port characteristics:
         | Characteristics 
Target   | HMSLQNFICBD lqrcpfgmbdates
---------+---------------------------
cr16     |    L  FI    l  cp g         

The CR16 compiler has been validated against gcc-testsuite. I will 
submit the results to gcc-testsuite mailing list soon.

Please review the patch and let me know if there should be any 
modifications in it.

gcc/ChangeLog:
--------------
2010-12-21	Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>
		
	* config.gcc: Add cr16-* support.

	* doc/extend.texi: Document cr16 extensions.
	* doc/install.texi: Document cr16 install.
	* doc/invoke.texi: Document cr16 options.
	* doc/md.texi: Document cr16 constraints.

	* config/cr16/cr16.c: New file.
	* config/cr16/cr16.h: New file.
	* config/cr16/cr16.md: New file.
	* config/cr16/cr16.opt: New file.
	* config/cr16/cr16-libgcc.s: New file.
	* config/cr16/cr16-protos.h: New file.
	* config/cr16/crti.s: New file.
	* config/cr16/crtlibid.s: New file.
	* config/cr16/crtn.s: New file.
	* config/cr16/divmodhi3.c: New file.
	* config/cr16/predicates.md: New file.
	* config/cr16/t-cr16: New file.
	* config/cr16/unwind-dw2-cr16.c: New file.
	* config/cr16/unwind-dw2.h: New file. 

libgcc/ChangeLog:
-----------------
2010-12-21  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	*config.host: Add National Semiconductor CR16 target (cr16-*-*).
		
libstdc++-v3/ChangeLog:
-----------------------
2010-12-21  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	*configure: Add National Semiconductor CR16 target (cr16-*-*).		
	*crossconfig.m4 : Add support for National Semiconductor CR16 target.

ChangeLog:
----------
2010-12-21  Sumanth G <sumanth.gundapaneni@kpitcummins.com>
		Jayant R Sonar <jayant.sonar@kpitcummins.com>

	* config.sub: Add National Semiconductor CR16 target.
	* configure.ac: Add National Semiconductor CR16 target.
	* configure: Regenerate
   
Thanks in advance,
Sumanth G,
KPIT Cummins Infosystems Limited,
PUNE (India).  

[-- Attachment #2: cr16-gcc.patch --]
[-- Type: application/octet-stream, Size: 217075 bytes --]

diff -uprN -x'*.orig' -x'*.rej' orig/config.sub mod/config.sub
--- orig/config.sub	2010-12-21 20:00:23.000000000 +0530
+++ mod/config.sub	2010-12-21 18:56:46.000000000 +0530
@@ -529,6 +529,10 @@ case $basic_machine in
 		basic_machine=c38-convex
 		os=-bsd
 		;;
+	cr16)
+                basic_machine=cr16-unknown
+                os=-elf
+                ;;
 	cray | j90)
 		basic_machine=j90-cray
 		os=-unicos
@@ -537,7 +541,7 @@ case $basic_machine in
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16)
+	cr16c)
 		basic_machine=cr16-unknown
 		os=-elf
 		;;
diff -uprN -x'*.orig' -x'*.rej' orig/configure mod/configure
--- orig/configure	2010-12-21 20:00:26.000000000 +0530
+++ mod/configure	2010-12-21 18:56:46.000000000 +0530
@@ -3239,8 +3239,13 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
-    ;;
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
+    ;;	
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
     case "${target}" in
diff -uprN -x'*.orig' -x'*.rej' orig/configure.ac mod/configure.ac
--- orig/configure.ac	2010-12-21 19:58:26.000000000 +0530
+++ mod/configure.ac	2010-12-21 18:56:46.000000000 +0530
@@ -699,7 +699,12 @@ case "${target}" in
     noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj} gcc gdb newlib"
     ;;
   cr16-*-*)
-    noconfigdirs="$noconfigdirs ${libgcj} gdb"
+    case "${target_alias}" in
+      cr16-uclinux)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj}";;
+      *)
+        noconfigdirs="$noconfigdirs target-mudflap ${libgcj} gdb";;
+    esac
     ;;
   cris-*-* | crisv32-*-*)
     unsupported_languages="$unsupported_languages java"
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.c mod/gcc/config/cr16/cr16.c
--- orig/gcc/config/cr16/cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.c	2010-12-22 12:09:15.000000000 +0530
@@ -0,0 +1,2267 @@
+/* Output routines for CR16 processor.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+  
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+ 
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-codes.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "recog.h"
+#include "expr.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "basic-block.h"
+#include "target.h"
+#include "target-def.h"
+#include "df.h"
+
+/* Definitions.  */
+
+/* Maximum number of register used for passing parameters.  */
+#define MAX_REG_FOR_PASSING_ARGS  6
+
+/* Minimum number register used for passing parameters.  */
+#define MIN_REG_FOR_PASSING_ARGS  2
+
+/* The maximum count of words supported in the assembly of the architecture in
+   a push/pop instruction.  */
+#define MAX_COUNT  8
+
+/* Predicate is true if the current function is a 'noreturn' function, 
+   i.e. it is qualified as volatile.  */
+#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
+
+/* Predicate that holds when we need to save registers even for 'noreturn'
+   functions, to accomodate for unwinding.  */
+#define MUST_SAVE_REGS_P() \
+  (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
+
+/* Nonzero if the rtx X is a signed const int of n bits.  */
+#define RTX_SIGNED_INT_FITS_N_BITS(X,n)                \
+  ((GET_CODE (X) == CONST_INT                          \
+   && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Nonzero if the rtx X is an unsigned const int of n bits.  */
+#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n)               \
+  ((GET_CODE (X) == CONST_INT                            \
+   && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
+
+/* Static Variables.  */
+
+/* Nonzero if the last param processed is passed in a register.  */
+static int last_parm_in_reg;
+
+/* Will hold the number of the last register the prologue saves, -1 if no
+   register is saved.  */
+static int last_reg_to_save;
+
+/* Each object in the array is a register number. Mark 1 for registers that
+   need to be saved.  */
+static int save_regs[FIRST_PSEUDO_REGISTER];
+
+/* Number of bytes saved on the stack for non-scratch registers.  */
+static int sum_regs = 0;
+
+/* Number of bytes saved on the stack for local variables.  */
+static int local_vars_size;
+
+/* The sum of 2 sizes: locals vars and padding byte for saving the registers.
+   Used in expand_prologue () and expand_epilogue ().  */
+static int size_for_adjusting_sp;
+
+/* Data model that was supplied by user via command line option
+   This will be overridden in case of invalid combination
+   of core and data model options are supplied.  */
+static enum data_model_type data_model = DM_DEFAULT;
+
+/* Nonzero if -mshared-library-id was given.  */
+static int cr16_lib_id_given;
+
+/* Global Variables.  */
+
+/* Specify the identification number of the library being built.  */
+const char *cr16_library_id_string = "__current_shared_library_r12_offset_";
+
+/* Table of machine attributes.  */
+const struct attribute_spec cr16_attribute_table[];
+
+/* TARGETM Function Prototypes.  */
+static rtx cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+				  int incoming ATTRIBUTE_UNUSED);
+static bool cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
+static int cr16_address_cost (rtx);
+static int cr16_frame_pointer_required (void);
+static bool cr16_can_eliminate (const int, const int);
+static rtx cr16_legitimize_address (rtx, rtx, enum machine_mode);
+static enum machine_mode cr16_unwind_word_mode (void);
+static void cr16_conditional_register_usage (void);
+static void cr16_override_options (void);
+static bool cr16_class_likely_spilled_p (reg_class_t);
+static int  cr16_return_pops_args (tree, tree, int);
+static rtx cr16_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+                             const_tree, bool);
+static void cr16_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+                                      const_tree, bool);
+
+/* Stack layout and calling conventions.  */
+
+#undef  TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX     	cr16_struct_value_rtx
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY     	cr16_return_in_memory
+
+/* Relative costs of operations.  */
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST 		cr16_address_cost
+
+/* Target-specific uses of '__attribute__'.  */
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE 		cr16_attribute_table
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+/* EH related.  */
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE		cr16_unwind_word_mode
+
+/* Override Options.  */
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE  	cr16_override_options 
+
+/* Conditional register usuage.  */
+#undef TARGET_CONDITIONAL_REGISTER_USAGE 
+#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
+
+/* Controlling register spills.  */
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
+
+/* Passing function arguments.  */
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cr16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
+#undef TARGET_RETURN_POPS_ARGS
+#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED	cr16_frame_pointer_required
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE 		cr16_can_eliminate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS 	cr16_legitimize_address
+
+const struct attribute_spec cr16_attribute_table[] = {
+  /* ISRs have special prologue and epilogue requirements.  */
+  {"interrupt", 0, 0, false, true, true, NULL},
+  {NULL, 0, 0, false, false, false, NULL}
+};
+
+/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
+   .?byte directive along with @c is not understood by assembler.
+   Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
+   as TARGET_ASM_ALIGNED_xx_OP.  */
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP 	TARGET_ASM_ALIGNED_HI_OP
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP 	TARGET_ASM_ALIGNED_SI_OP
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
+
+/* Initialize 'targetm' variable which contains pointers to functions 
+   and data relating to the target machine.  */
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Target hook implementations.  */
+
+/* Implements hook TARGET_STRUCT_VALUE_RTX.  */
+static rtx
+cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+		       int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, CR16_STRUCT_VALUE_REGNUM);
+}
+
+/* Implements hook TARGET_RETURN_IN_MEMORY.  */
+static bool
+cr16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+  if (TYPE_MODE (type) == BLKmode)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      return ((size == -1) || (size > 8));
+    }
+  else
+    return false;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+
+static bool
+cr16_class_likely_spilled_p (reg_class_t rclass)
+{
+  if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS \
+       || (rclass) == GENERAL_REGS)
+    return true;
+
+  return false;
+}
+
+static int
+cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                      tree funtype ATTRIBUTE_UNUSED, int size)
+{
+  return 0;
+}
+
+/* Returns true if data model selected via command line option
+   is same as function argument.  */
+bool
+cr16_is_data_model (enum data_model_type model)
+{
+  return (model == data_model);
+}
+
+/* Parse relevant options and override.  */
+static void
+cr16_override_options (void)
+{
+  /* Disable -fdelete-null-pointer-checks option for CR16 target.
+     Programs which rely on NULL pointer dereferences _not_ halting the 
+     program may not work properly with this option. So disable this 
+     option.  */
+  flag_delete_null_pointer_checks = 0;
+
+  /* To avoid gen_rtx_SUBREG ICE. SI gets splitted to two HIs where 
+     validate_subreg is invalid with the second HI having offset 2
+     .Offset applicable to big endian machines.  */
+  flag_split_wide_types = 0;
+
+  /* If EH, disable optimization GCSE.  */
+  if (flag_exceptions)
+    flag_gcse = 0;
+
+  /* If -fpic option, data_model == DM_FAR.  */
+  if (flag_pic == NEAR_PIC)
+    {
+      data_model = DM_FAR;
+    }
+
+  /* The only option we want to examine is data model option.  */
+  if (cr16_data_model)
+    {
+      if (strcmp (cr16_data_model, "medium") == 0)
+	data_model = DM_DEFAULT;
+      else if (strcmp (cr16_data_model, "near") == 0)
+	data_model = DM_NEAR;
+      else if (strcmp (cr16_data_model, "far") == 0)
+	{
+	  if (TARGET_CR16CP)
+	    data_model = DM_FAR;
+	  else
+	    error ("data-model=far not valid for cr16c architecture.");
+	}
+      else
+	error ("Invalid data model option -mdata-model=%s", cr16_data_model);
+    }
+  else
+    data_model = DM_DEFAULT;
+
+  /* Library identification.  */
+  if (cr16_lib_id_given && !TARGET_ID_SHARED_LIBRARY)
+    error ("-mshared-library-id= specified without -mid-shared-library");
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    flag_pic = FAR_PIC;
+
+}
+
+/* Implements the macro  TARGET_CONDITIONAL_REGISTER_USAGE.  */
+static void
+cr16_conditional_register_usage (void)
+{
+  if (flag_pic)
+    {
+      fixed_regs[12] = call_used_regs[12] = 1;
+    }
+}
+
+/* Stack layout and calling conventions routines.  */
+
+/* Return nonzero if the current function being compiled is an interrupt
+   function as specified by the "interrupt" attribute.  */
+int
+cr16_interrupt_function_p (void)
+{
+  tree attributes;
+
+  attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+  return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
+}
+
+/* Compute values for the array save_regs and the variable sum_regs.
+   The index of save_regs is numbers of register, each will get 1 if we 
+   need to save it in the current function, 0 if not.  sum_regs is the 
+   total sum of the registers being saved.  */
+static void
+cr16_compute_save_regs (void)
+{
+  unsigned int regno;
+
+  /* Initialize here so in case the function is no-return it will be -1.  */
+  last_reg_to_save = -1;
+
+  /* Initialize the number of bytes to be saved. */
+  sum_regs = 0;
+
+  /* No need to save any registers if the function never returns.  */
+  if (!TARGET_ID_SHARED_LIBRARY &&
+      FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
+    return;
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (TARGET_ID_SHARED_LIBRARY && PIC_OFFSET_TABLE_REGNUM == regno)
+	{
+	  save_regs[regno] = 1;
+	  continue;
+	}
+      else if (fixed_regs[regno])
+	{
+	  save_regs[regno] = 0;
+	  continue;
+	}
+
+      /* If this reg is used and not call-used (except RA), save it.  */
+      if (cr16_interrupt_function_p ())
+	{
+	  if (!current_function_is_leaf && call_used_regs[regno])
+	    /* This is a volatile reg in a non-leaf interrupt routine - save 
+	       it for the sake of its sons.  */
+	    save_regs[regno] = 1;
+	  else if (df_regs_ever_live_p (regno))
+	    /* This reg is used - save it.  */
+	    save_regs[regno] = 1;
+	  else
+	    /* This reg is not used, and is not a volatile - don't save.  */
+	    save_regs[regno] = 0;
+	}
+      else
+	{
+	  /* If this reg is used and not call-used (except RA), save it.  */
+	  if (df_regs_ever_live_p (regno)
+	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
+	    save_regs[regno] = 1;
+	  else
+	    save_regs[regno] = 0;
+	}
+    }
+
+  /* Save registers so the exception handler can modify them.  */
+  if (crtl->calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0;; ++i)
+	{
+	  regno = EH_RETURN_DATA_REGNO (i);
+	  if (INVALID_REGNUM == regno)
+	    break;
+	  save_regs[regno] = 1;
+	}
+    }
+
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (save_regs[regno] == 1)
+      {
+	last_reg_to_save = regno;
+	if (regno >= CR16_FIRST_DWORD_REGISTER)
+	  sum_regs += CR16_UNITS_PER_DWORD;
+	else
+	  sum_regs += UNITS_PER_WORD;
+      }
+}
+
+/* Compute the size of the local area and the size to be adjusted by the
+   prologue and epilogue.  */
+static void
+cr16_compute_frame (void)
+{
+  /* For aligning the local variables.  */
+  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+  int padding_locals;
+
+  /* Padding needed for each element of the frame.  */
+  local_vars_size = get_frame_size ();
+
+  /* Align to the stack alignment.  */
+  padding_locals = local_vars_size % stack_alignment;
+  if (padding_locals)
+    padding_locals = stack_alignment - padding_locals;
+
+  local_vars_size += padding_locals;
+  size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS
+					     ? crtl->outgoing_args_size : 0);
+}
+
+/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET.  */
+int
+cr16_initial_elimination_offset (int from, int to)
+{
+  /* Compute this since we need to use sum_regs.  */
+  cr16_compute_save_regs ();
+
+  /* Compute this since we need to use local_vars_size.  */
+  cr16_compute_frame ();
+
+  if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
+    return (sum_regs + local_vars_size);
+  else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
+    return (sum_regs + local_vars_size + (ACCUMULATE_OUTGOING_ARGS
+					  ? crtl->outgoing_args_size : 0));
+  else
+    gcc_unreachable ();
+}
+
+/* Register Usage.  */
+
+/* Return the class number of the smallest class containing reg number REGNO.
+   This could be a conditional expression or could index an array.  */
+enum reg_class
+cr16_regno_reg_class (int regno)
+{
+  if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
+    return SHORT_REGS;
+
+  if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
+    return LONG_REGS;
+
+  if (regno < 15)
+    return NOSP_REGS;
+
+  return NO_REGS;
+}
+
+/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+int
+cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if ((mode == Pmode) && (regno == 11))
+    return 0;
+  if (mode == DImode || mode == DFmode)
+    {
+      if ((regno > 8) || (regno & 1))
+	return 0;
+      return 1;
+    }
+
+  /* CC can only hold CCmode values.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    return 0;
+  return 1;
+}
+
+/* Passing function arguments.  */
+
+/* If enough param regs are available for passing the param of type TYPE return
+   the number of registers needed else 0.  */
+static int
+enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
+		       enum machine_mode mode)
+{
+  int type_size;
+  int remaining_size;
+
+  if (mode != BLKmode)
+    type_size = GET_MODE_BITSIZE (mode);
+  else
+    type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+  remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
+				    - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
+				    1);
+
+  /* Any variable which is too big to pass in two registers, will pass on
+     stack.  */
+  if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
+    return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
+
+  return 0;
+}
+
+/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+static rtx
+cr16_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+		   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  last_parm_in_reg = 0;
+
+  /* function_arg () is called with this type just after all the args have 
+     had their registers assigned. The rtx that function_arg returns from 
+     this type is supposed to pass to 'gen_call' but currently it is not 
+     implemented (see macro GEN_CALL).  */
+  if (type == void_type_node)
+    return NULL_RTX;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return NULL_RTX;
+
+  if (mode == BLKmode)
+    {
+      /* Enable structures that need padding bytes at the end to pass to a
+         function in registers.  */
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
+    return NULL_RTX;
+  else
+    {
+      if (enough_regs_for_param (cum, type, mode) != 0)
+	{
+	  last_parm_in_reg = 1;
+	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	}
+    }
+
+  return NULL_RTX;
+}
+
+/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h.  */
+void
+cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
+			   rtx libfunc ATTRIBUTE_UNUSED)
+{
+  tree param, next_param;
+
+  cum->ints = 0;
+
+  /* Determine if this function has variable arguments.  This is indicated by
+     the last argument being 'void_type_mode' if there are no variable
+     arguments.  Change here for a different vararg.  */
+  for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+       param != (tree) 0; param = next_param)
+    {
+      next_param = TREE_CHAIN (param);
+      if ((next_param == (tree) 0) && (TREE_VALUE (param) != void_type_node))
+	{
+	  cum->ints = -1;
+	  return;
+	}
+    }
+}
+
+/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
+static void
+cr16_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+			   const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  /* l holds the number of registers required.  */
+  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+
+  /* If the parameter isn't passed on a register don't advance cum.  */
+  if (!last_parm_in_reg)
+    return;
+
+  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+    return;
+
+  if ((mode == SImode) || (mode == HImode)
+      || (mode == QImode) || (mode == DImode))
+    {
+      if (l <= 1)
+	cum->ints += 1;
+      else
+	cum->ints += l;
+    }
+  else if ((mode == SFmode) || (mode == DFmode))
+    cum->ints += l;
+  else if ((mode) == BLKmode)
+    {
+      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+	cum->ints += l;
+    }
+  return;
+}
+
+/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
+   Return nonzero if N is a register used for passing parameters.  */
+int
+cr16_function_arg_regno_p (int n)
+{
+  return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
+}
+
+/* Addressing modes. 
+   Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
+   defined in cr16.h.  */
+
+/* Helper function to check if is a valid base register that can
+   hold address.  */
+static int
+cr16_addr_reg_p (rtx addr_reg)
+{
+  rtx reg;
+
+  if (REG_P (addr_reg))
+    reg = addr_reg;
+  else if ((GET_CODE (addr_reg) == SUBREG)
+	   && REG_P (SUBREG_REG (addr_reg))
+	   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
+	       <= UNITS_PER_WORD))
+    reg = SUBREG_REG (addr_reg);
+  else
+    return FALSE;
+
+  if (GET_MODE (reg) != Pmode)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Helper functions: Created specifically for decomposing operand of CONST
+   Recursively look into expression x for code or data symbol.
+   The function expects the expression to contain combination of 
+   SYMBOL_REF, CONST_INT, (PLUS or MINUS)
+   LABEL_REF, CONST_INT, (PLUS or MINUS)
+   SYMBOL_REF
+   LABEL_REF
+   All other combinations will result in code = -1 and data = ILLEGAL_DM
+   code data
+   -1   ILLEGAL_DM   The expression did not contain SYMBOL_REF or LABEL_REF
+    0   DM_FAR       SYMBOL_REF was found and it was far data reference. 
+    0   DM_DEFAULT   SYMBOL_REF was found and it was medium data reference. 
+    1   ILLEGAL_DM   LABEL_REF was found. 
+    2   ILLEGAL_DM   SYMBOL_REF was found and it was function reference.  */
+void
+cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
+		      bool treat_as_const)
+{
+  *code = -1;
+  *data = ILLEGAL_DM;
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
+      /* 2 indicates func sym.  */
+      if (*code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    *data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    *data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing 
+		   the qualifier. This call is (may be)
+		   made by cr16_print_operand_address.  */
+		*data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		*data = ILLEGAL_DM;
+	    }
+	}
+      return;
+
+    case LABEL_REF:
+      /* 1 - indicates non-function symbol.  */
+      *code = 1;
+      return;
+
+    case PLUS:
+    case MINUS:
+      /* Look into the tree nodes.  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+	cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
+      return;
+    default:
+      return;
+    }
+}
+
+/* Decompose Address
+   This function decomposes the address returns the type of address
+   as defined in enum cr16_addrtype.  It also fills the parameter *out.
+   The decomposed address can be used for two purposes.  One to 
+   check if the address is valid and second to print the address
+   operand.
+
+   Following tables list valid address supported in CR16C/C+ architectures.
+   Legend: 
+   aN : Absoulte address N-bit address
+   R  : One 16-bit register
+   RP : Consecutive two 16-bit registers or one 32-bit register
+   I  : One 32-bit register
+   dispN : Signed displacement of N-bits
+
+   ----Code addresses----
+   Branch operands:
+   disp9        : CR16_ABSOLUTE       (disp)
+   disp17       : CR16_ABSOLUTE       (disp)
+   disp25       : CR16_ABSOLUTE       (disp)
+   RP + disp25  : CR16_REGP_REL       (base, disp)
+
+   Jump operands:
+   RP           : CR16_REGP_REL       (base, disp=0)
+   a24          : CR16_ABSOLUTE       (disp)
+
+   ----Data addresses----
+   a20          : CR16_ABSOLUTE       (disp)                near (1M)
+   a24          : CR16_ABSOLUTE       (disp)                medium  (16M)
+   R  + d20     : CR16_REG_REL        (base,  disp)         near (1M+64K)
+   RP + d4      : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d16     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   RP + d20     : CR16_REGP_REL       (base,  disp)         far  (4G)
+   I            : *** Valid but port does not support this
+   I  + a20     : *** Valid but port does not support this
+   I  + RP + d14: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+   I  + RP + d20: CR16_INDEX_REGP_REL (base,  index, disp)  far  (4G)
+
+   Decomposing Data model in case of absolute address.
+
+   Target Option             Address type Resultant Data ref type
+   ----------------------    ------------ -----------------------
+   CR16_TARGET_MODEL_NEAR    ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_NEAR    ABS24        Invalid
+   CR16_TARGET_MODEL_NEAR    IMM32        Invalid
+
+   CR16_TARGET_MODEL_MEDIUM  ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_MEDIUM  ABS24        DM_FAR
+   CR16_TARGET_MODEL_MEDIUM  IMM32        Invalid
+
+   CR16_TARGET_MODEL_FAR     ABS20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     IMM20        DM_DEFAULT
+   CR16_TARGET_MODEL_FAR     ABS24        DM_FAR
+   CR16_TARGET_MODEL_FAR     IMM32        DM_FAR.  */
+enum cr16_addrtype
+cr16_decompose_address (rtx addr, struct cr16_address *out,
+			bool debug_print, bool treat_as_const)
+{
+  rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
+  enum data_model_type data = ILLEGAL_DM;
+  int code = -1;
+  enum cr16_addrtype retval = CR16_INVALID;
+
+  switch (GET_CODE (addr))
+    {
+    case CONST_INT:
+      /* Absolute address (known at compile time).  */
+      code = 0;
+      if (debug_print)
+	fprintf (stderr, "\ncode:%d", code);
+      disp = addr;
+
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	}
+
+      if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+	{
+	  data = DM_DEFAULT;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  retval = CR16_ABSOLUTE;
+	}
+      else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
+	{
+	  if (!CR16_TARGET_DATA_NEAR)
+	    {
+	      data = DM_FAR;
+	      if (debug_print)
+		fprintf (stderr, "\ndata:%d", data);
+	      retval = CR16_ABSOLUTE;
+	    }
+	  else
+	    return CR16_INVALID;	/* ABS24 is not support in NEAR model.  */
+	}
+      else
+	return CR16_INVALID;
+      break;
+
+    case CONST:
+      /* A CONST is an expression of PLUS or MINUS with 
+         CONST_INT, SYMBOL_REF or LABEL_REF. This is the
+         result of assembly-time arithmetic computation.  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* Call the helper function to check the validity.  */
+      cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
+      if ((code == 0) && (data == ILLEGAL_DM))
+	/* CONST is not valid code or data address.  */
+	return CR16_INVALID;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	  fprintf (stderr, "\ndata:%d", data);
+	}
+      break;
+
+    case LABEL_REF:
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* 1 - indicates non-function symbol.  */
+      code = 1;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      break;
+
+    case SYMBOL_REF:
+      /* Absolute address (known at link time).  */
+      retval = CR16_ABSOLUTE;
+      disp = addr;
+      /* This is a code address if symbol_ref is a function.  */
+      /* 2 indicates func sym.  */
+      code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\ndisp:");
+	  debug_rtx (disp);
+	  fprintf (stderr, "\ncode:%d", code);
+	}
+      /* If not function ref then check if valid data ref.  */
+      if (code == 0)
+	{
+	  if (CR16_TARGET_DATA_NEAR)
+	    data = DM_DEFAULT;
+	  else if (CR16_TARGET_DATA_MEDIUM)
+	    data = DM_FAR;
+	  else if (CR16_TARGET_DATA_FAR)
+	    {
+	      if (treat_as_const)
+		/* This will be used only for printing the 
+		   qualifier. This call is (may be) made
+		   by cr16_print_operand_address.  */
+		data = DM_FAR;
+	      else
+		/* This call is (may be) made by 
+		   cr16_legitimate_address_p.  */
+		return CR16_INVALID;
+	    }
+	  else
+	    data = DM_DEFAULT;
+	}
+      if (debug_print)
+	fprintf (stderr, "\ndata:%d", data);
+      break;
+
+    case REG:
+    case SUBREG:
+      /* Register relative address.  */
+      /* Assume REG fits in a single register.  */
+      retval = CR16_REG_REL;
+      if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
+	if (!LONG_REG_P (REGNO (addr)))
+	  /* REG will result in reg pair.  */
+	  retval = CR16_REGP_REL;
+      base = addr;
+      if (debug_print)
+	{
+	  fprintf (stderr, "\nbase:");
+	  debug_rtx (base);
+	}
+      break;
+
+    case PLUS:
+      switch (GET_CODE (XEXP (addr, 0)))
+	{
+	case REG:
+	case SUBREG:
+	  /* REG + DISP20.  */
+	  /* All Reg relative addresses having a displacement needs 
+	     to fit in 20-bits.  */
+	  disp = XEXP (addr, 1);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\ndisp:");
+	      debug_rtx (disp);
+	    }
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case CONST_INT:
+	      /* Shall fit in 20-bits.  */
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	      code = 0;
+	      if (debug_print)
+		fprintf (stderr, "\ncode:%d", code);
+	      break;
+
+	    case UNSPEC:
+	      inform (input_location, "UNSPEC 2!!");
+	      switch (XINT (XEXP (addr, 1), 1))
+		{
+		case UNSPEC_LIBRARY_OFFSET:
+		  inform (input_location, "UNSPEC_LIBRARY_OFFSET 2!!!");
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	      break;
+
+	    case LABEL_REF:
+	    case SYMBOL_REF:
+	    case CONST:
+	      /* This is also a valid expression for address.
+	         However, we cannot ascertain if the resultant
+	         displacement will be valid 20-bit value.  Therefore, 
+	         lets not allow such an expression for now.  This will 
+	         be updated when  we find a way to validate this 
+	         expression as legitimate address. 
+	         Till then fall through CR16_INVALID.  */
+	    default:
+	      return CR16_INVALID;
+	    }
+
+	  /* Now check if REG can fit into single or pair regs.  */
+	  retval = CR16_REG_REL;
+	  base = XEXP (addr, 0);
+	  if (debug_print)
+	    {
+	      fprintf (stderr, "\nbase:");
+	      debug_rtx (base);
+	    }
+	  if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
+	    {
+	      if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
+		/* REG will result in reg pair.  */
+		retval = CR16_REGP_REL;
+	    }
+	  break;
+
+	case PLUS:
+	  /* Valid expr: 
+	     plus
+	     /\
+	     /  \
+	     plus idx
+	     /\
+	     /  \
+	     reg  const_int
+
+	     Check if the operand 1 is valid index register.  */
+	  data = ILLEGAL_DM;
+	  if (debug_print)
+	    fprintf (stderr, "\ndata:%d", data);
+	  switch (GET_CODE (XEXP (addr, 1)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
+		return CR16_INVALID;
+	      /* OK. REG is a valid index register.  */
+	      index = XEXP (addr, 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\nindex:");
+		  debug_rtx (index);
+		}
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Check if operand 0 of operand 0 is REGP.  */
+	  switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
+	    {
+	    case REG:
+	    case SUBREG:
+	      /* Now check if REG is a REGP and not in LONG regs.  */
+	      if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
+		  > BITS_PER_WORD)
+		{
+		  if (REGNO (XEXP (XEXP (addr, 0), 0))
+		      >= CR16_FIRST_DWORD_REGISTER)
+		    return CR16_INVALID;
+		  base = XEXP (XEXP (addr, 0), 0);
+		  if (debug_print)
+		    {
+		      fprintf (stderr, "\nbase:");
+		      debug_rtx (base);
+		    }
+		}
+	      else
+		return CR16_INVALID;
+	      break;
+	    default:
+	      return CR16_INVALID;
+	    }
+	  /* Now check if the operand 1 of operand 0 is const_int.  */
+	  if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+	    {
+	      disp = XEXP (XEXP (addr, 0), 1);
+	      if (debug_print)
+		{
+		  fprintf (stderr, "\ndisp:");
+		  debug_rtx (disp);
+		}
+	      if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
+		return CR16_INVALID;
+	    }
+	  else
+	    return CR16_INVALID;
+	  retval = CR16_INDEX_REGP_REL;
+	  break;
+	default:
+	  return CR16_INVALID;
+	}
+      break;
+
+    default:
+      return CR16_INVALID;
+    }
+
+  /* Check if the base and index registers are valid.  */
+  if (base && !(cr16_addr_reg_p (base)))
+    return CR16_INVALID;
+  if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
+    return CR16_INVALID;
+  if (index && !(REG_OK_FOR_INDEX_P (index)))
+    return CR16_INVALID;
+
+  /* Write the decomposition to out parameter.  */
+  out->base = base;
+  out->disp = disp;
+  out->index = index;
+  out->data = data;
+  out->code = code;
+
+  return retval;
+}
+
+/* Return non-zero value if 'x' is legitimate PIC operand
+   when generating PIC code.  */
+int
+legitimate_pic_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return 0;
+      break;
+    case LABEL_REF:
+      return 0;
+      break;
+    case CONST:
+      /* REVISIT: Use something like symbol_referenced_p.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+	  && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	      || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+	return 0;
+      break;
+    case MEM:
+      return legitimate_pic_operand_p (XEXP (x, 0));
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/*Convert a non-PIC address in `orig' to a PIC address in `reg'.
+
+     Input            Output (-f pic)        Output (-f PIC)
+     orig             reg
+                                                                                                                             
+C1   symbol           symbol@BRO (r12)        symbol@GOT (r12)
+                                                                                                                             
+C2   symbol + offset  symbol+offset@BRO (r12) symbol+offset@GOT (r12)
+                                                                                                                             
+NOTE: @BRO is added using unspec:BRO
+NOTE: @GOT is added using unspec:GOT.  */
+rtx
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+			rtx reg)
+{
+  rtx pic_ref;
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF.  */
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	reg = gen_reg_rtx (Pmode);
+
+      if (flag_pic == NEAR_PIC)
+	{
+	  /* Unspec to handle -fpic option.  */
+	  emit_insn (gen_unspec_bro_addr (reg, orig));
+	  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+	  pic_ref = reg;
+	}
+      else if (flag_pic == FAR_PIC)
+	{
+	  /* Unspec to handle -fPIC option.  */
+	  emit_insn (gen_unspec_got_addr (reg, orig));
+	  pic_ref = reg;
+	}
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      /* To handle (symbol + offset).  */
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (can_create_pseudo_p ());
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+				       base == reg ? 0 : reg);
+
+      /* REVISIT: Optimize for const-offsets.  */
+      emit_insn (gen_addsi3 (reg, base, offset));
+
+      return reg;
+    }
+  return orig;
+}
+
+/* Implementation of got_operand.  */
+rtx
+got_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_got_addr (reg, orig));
+  return reg;
+}
+
+/* Implementation of bro_operand.  */
+rtx
+bro_operand (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  rtx reg;
+  reg = gen_reg_rtx (Pmode);
+  emit_insn (gen_unspec_bro_addr (reg, orig));
+  emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+  return reg;
+}
+
+/* Implementation of GO_IF_LEGITIMATE_ADDRESS.  */
+int
+cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			   rtx addr, int strict)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr,
+	       "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d",
+	       GET_MODE_NAME (mode), strict);
+      debug_rtx (addr);
+    }
+  addrtype = cr16_decompose_address (addr, &address,
+				     (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      const char *typestr;
+
+      switch (addrtype)
+	{
+	case CR16_INVALID:
+	  typestr = "Invalid";
+	  break;
+	case CR16_ABSOLUTE:
+	  typestr = "Absolute";
+	  break;
+	case CR16_REG_REL:
+	  typestr = "Register relative";
+	  break;
+	case CR16_REGP_REL:
+	  typestr = "Register pair relative";
+	  break;
+	case CR16_INDEX_REGP_REL:
+	  typestr = "Index + Register pair relative";
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      fprintf (stderr, "\nCR16 Address type: %s\n", typestr);
+    }
+
+  if (addrtype == CR16_INVALID)
+    return FALSE;
+
+  if (strict)
+    {
+      if (address.base
+	  && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Base register not strict\n");
+	  return FALSE;
+	}
+      if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
+	{
+	  if (TARGET_DEBUG_ADDR)
+	    fprintf (stderr, "Index register not strict\n");
+	  return FALSE;
+	}
+    }
+
+  /* Return true if addressing mode is register relative.  */
+  if (flag_pic)
+    {
+      if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
+	return TRUE;
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Routines to compute costs.  */
+
+/* Return cost of the memory address x.  */
+static int
+cr16_address_cost (rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+  int cost = 2;
+
+  addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
+
+  gcc_assert (addrtype != CR16_INVALID);
+
+  /*
+     CR16_ABSOLUTE            : 3
+     CR16_REG_REL  (disp !=0) : 4
+     CR16_REG_REL  (disp ==0) : 5
+     CR16_REGP_REL (disp !=0) : 6
+     CR16_REGP_REL (disp ==0) : 7
+     CR16_INDEX_REGP_REL (disp !=0) : 8
+     CR16_INDEX_REGP_REL (disp ==0) : 9
+  */
+  switch (addrtype)
+    {
+    case CR16_ABSOLUTE:
+      cost += 1;
+      break;
+    case CR16_REGP_REL:
+      cost += 2;
+      /* Fall through.  */
+    case CR16_REG_REL:
+      cost += 3;
+      if (address.disp)
+	cost -= 1;
+      break;
+    case CR16_INDEX_REGP_REL:
+      cost += 7;
+      if (address.disp)
+	cost -= 1;
+    default:
+      break;
+    }
+
+  if (TARGET_DEBUG_ADDR)
+    {
+      fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
+      debug_rtx (addr);
+    }
+
+  return cost;
+}
+
+/* Return the cost of moving data of mode MODE between a register of class
+   CLASS and memory; IN is zero if the value is to be written to memory,
+   nonzero if it is to be read in. This cost is relative to those in
+   REGISTER_MOVE_COST.  */
+
+int
+cr16_memory_move_cost (enum machine_mode mode,
+		       enum reg_class class ATTRIBUTE_UNUSED,
+		       int in ATTRIBUTE_UNUSED)
+{
+  /* One LD or ST takes twice the time of a simple reg-reg move.  */
+  if (reg_classes_intersect_p (class, GENERAL_REGS))
+    return (4 * HARD_REGNO_NREGS (0, mode));
+  else
+    return (100);
+}
+
+/* Instruction output.  */
+
+/* Check if a const_double is ok for cr16 store-immediate instructions.  */
+int
+cr16_const_double_ok (rtx op)
+{
+  if (GET_MODE (op) == SFmode)
+    {
+      REAL_VALUE_TYPE r;
+      long l;
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      REAL_VALUE_TO_TARGET_SINGLE (r, l);
+      return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
+    }
+
+  return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
+	  (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
+}
+
+/* Returns bit position of first 0 or 1 bit.
+   It is safe to assume val as 16-bit wide.  */
+int
+cr16_operand_bit_pos (int val, int bitval)
+{
+  int i;
+  if (bitval == 0)
+    val = ~val;
+
+  for (i = 0; i < 16; i++)
+    if (val & (1 << i))
+      break;
+  return i;
+}
+
+/* Implements the macro PRINT_OPERAND defined in cr16.h.  */
+void
+cr16_print_operand (FILE * file, rtx x, int code)
+{
+  int ptr_dereference = 0;
+
+  switch (code)
+    {
+    case 'd':
+      {
+	const char *cr16_cmp_str;
+	switch (GET_CODE (x))
+	  {
+	    /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
+	       -> swap all non symmetric ops.  */
+	  case EQ:
+	    cr16_cmp_str = "eq";
+	    break;
+	  case NE:
+	    cr16_cmp_str = "ne";
+	    break;
+	  case GT:
+	    cr16_cmp_str = "lt";
+	    break;
+	  case GTU:
+	    cr16_cmp_str = "lo";
+	    break;
+	  case LT:
+	    cr16_cmp_str = "gt";
+	    break;
+	  case LTU:
+	    cr16_cmp_str = "hi";
+	    break;
+	  case GE:
+	    cr16_cmp_str = "le";
+	    break;
+	  case GEU:
+	    cr16_cmp_str = "ls";
+	    break;
+	  case LE:
+	    cr16_cmp_str = "ge";
+	    break;
+	  case LEU:
+	    cr16_cmp_str = "hs";
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	fprintf (file, "%s", cr16_cmp_str);
+	return;
+      }
+    case '$':
+      putc ('$', file);
+      return;
+
+    case 'p':
+      if (GET_CODE (x) == REG)
+	{
+	  /* For Push instructions, we should not print register pairs.  */
+	  fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+	}
+      break;
+
+    case 'b':
+      /* Print the immediate address for bal 
+         'b' is used instead of 'a' to avoid compiler calling
+         the GO_IF_LEGITIMATE_ADDRESS which cannot
+         perform checks on const_int code addresses as it
+         assumes all const_int are data addresses.  */
+      fprintf (file, "0x%lx", INTVAL (x));
+      return;
+
+    case 'r':
+      /* Print bit position of first 0.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
+      return;
+
+    case 's':
+      /* Print bit position of first 1.  */
+      fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
+      return;
+
+    case 'L':
+    case 'M':
+    case 'H':
+      /* Print the  DImode values.  */
+      if (GET_CODE (x) == REG)
+	{
+	  if (LONG_REG_P (REGNO (x)))
+	    fprintf (file, "identified an  error L0");
+	  else if (code == 'L')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+		     reg_names[REGNO (x)]);
+	  else if (code == 'M')
+	    fprintf (file, "%s", reg_names[REGNO (x) + 2]);
+	  else if (code == 'H')
+	    fprintf (file, "%s", reg_names[REGNO (x) + 3]);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  fprintf (file, "$");
+	  if (code == 'L')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 32) & 0xffffffff);
+	  else if (code == 'M')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 16) & 0xffff);
+	  else if (code == 'H')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX, (INTVAL (x)) & 0xffff);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else
+	output_operand_lossage ("invalid operand");
+
+      return;
+    case 'T':
+    case 'U':
+      if (GET_CODE (x) == REG)
+	{
+	  if (LONG_REG_P (REGNO (x)))
+	    fprintf (file, "identified an  error T0");
+	  else if (code == 'T')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+		     reg_names[REGNO (x)]);
+	  else if (code == 'U')
+	    fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 3],
+		     reg_names[REGNO (x) + 2]);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
+	{
+	  fprintf (file, "$");
+	  if (code == 'T')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x) >> 32) & 0xffffffff);
+	  else if (code == 'U')
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (INTVAL (x)) & 0xffffffff);
+	  else
+	    output_operand_lossage ("invalid operand");
+	}
+      else
+	output_operand_lossage ("invalid operand");
+
+      return;
+    case 'g':
+      /* 'g' is used for implicit mem: dereference.  */
+      ptr_dereference = 1;
+    case 'f':
+    case 0:
+      /* default.  */
+      switch (GET_CODE (x))
+	{
+	case REG:
+	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
+	    {
+	      if (LONG_REG_P (REGNO (x)))
+		fprintf (file, "(%s)", reg_names[REGNO (x)]);
+	      else
+		fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
+			 reg_names[REGNO (x)]);
+	    }
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (x)]);
+	  return;
+
+	case MEM:
+	  output_address (XEXP (x, 0));
+	  return;
+
+	case CONST_DOUBLE:
+	  {
+	    REAL_VALUE_TYPE r;
+	    long l;
+
+	    REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+	    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+
+	    fprintf (file, "$0x%lx", l);
+	    return;
+	  }
+	case CONST_INT:
+	  {
+	    fprintf (file, "$%ld", INTVAL (x));
+	    return;
+	  }
+	case UNSPEC:
+	  inform (input_location, "UNSPEC!!");
+	  switch (XINT (x, 1))
+	    {
+	    case UNSPEC_LIBRARY_OFFSET:
+	      inform (input_location, "UNSPEC_LIBRARY_OFFSET!!!");
+	      fprintf (file, "%s", cr16_library_id_string);
+	      return;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	default:
+	  if (!ptr_dereference)
+	    {
+	      putc ('$', file);
+	    }
+	  cr16_print_operand_address (file, x);
+	  return;
+	}
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h.  */
+
+void
+cr16_print_operand_address (FILE * file, rtx addr)
+{
+  enum cr16_addrtype addrtype;
+  struct cr16_address address;
+
+  /* Decompose the address. Also ask it to treat address as constant.  */
+  addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
+
+  if (address.disp && GET_CODE (address.disp) == UNSPEC)
+    {
+      inform (input_location, "UNSPEC 3 (%d)!!!", addrtype);
+      debug_rtx (addr);
+    }
+
+  switch (addrtype)
+    {
+    case CR16_REG_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
+      break;
+
+    case CR16_ABSOLUTE:
+      if (address.disp)
+	output_addr_const (file, address.disp);
+      else
+	fprintf (file, "0");
+      break;
+
+    case CR16_INDEX_REGP_REL:
+      fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
+      /* Fall through.  */
+    case CR16_REGP_REL:
+      if (address.disp)
+	{
+	  if (GET_CODE (address.disp) == UNSPEC)
+	    cr16_print_operand (file, address.disp, 0);
+	  else
+	    output_addr_const (file, address.disp);
+	}
+      else
+	fprintf (file, "0");
+      fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
+	       reg_names[REGNO (address.base)]);
+      break;
+    default:
+      debug_rtx (addr);
+      gcc_unreachable ();
+    }
+  /* Add qualifiers to the address expression that was just printed.  */
+  if (flag_pic < NEAR_PIC && address.code == 0)
+    {
+      if (address.data == DM_FAR)
+	/* Addr contains SYMBOL_REF & far data ptr.  */
+	fprintf (file, "@l");
+      else if (address.data == DM_DEFAULT)
+	/* Addr contains SYMBOL_REF & medium data ptr.  */
+	fprintf (file, "@m");
+      /* Addr contains SYMBOL_REF & medium data ptr.  */
+      else if (address.data == DM_NEAR)
+	/* Addr contains SYMBOL_REF & near data ptr.  */
+	fprintf (file, "@s");
+    }
+  else if (flag_pic == NEAR_PIC
+	   && (address.code == 0) && (address.data == DM_FAR
+				      || address.data == DM_DEFAULT
+				      || address.data == DM_NEAR))
+    {
+      fprintf (file, "@l");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 2)
+    {
+      fprintf (file, "pic");
+    }
+  else if (flag_pic == NEAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cpic");
+    }
+
+  else if (flag_pic == FAR_PIC && address.code == 2)
+    {
+      /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
+         address ! GOTc tells assembler this symbol is a text-address 
+         This needs to be fixed in such a way that this offset is done 
+         only in the case where an address is being used for indirect jump
+         or call. Determining the potential usage of loadd is of course not
+         possible always. Eventually, this has to be fixed in the 
+         processor.  */
+      fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+  else if (flag_pic == FAR_PIC && address.code == 1)
+    {
+      fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+
+  else if (flag_pic == FAR_PIC &&
+	   (address.data == DM_FAR || address.data == DM_DEFAULT
+	    || address.data == DM_NEAR))
+    {
+      fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
+}
+
+/* Machine description helper functions.  */
+void
+cr16_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
+			   rtx tmp_reg, unsigned HOST_WIDE_INT * offset_p)
+{
+  rtx addr, mem;
+  unsigned HOST_WIDE_INT offset = *offset_p;
+
+  /* Load.  */
+  addr = plus_constant (src, offset);
+  mem = adjust_automodify_address (srcbase, SImode, addr, offset);
+  emit_move_insn (tmp_reg, mem);
+
+  /* Store.  */
+  addr = plus_constant (dst, offset);
+  mem = adjust_automodify_address (dstbase, SImode, addr, offset);
+  emit_move_insn (mem, tmp_reg);
+
+  *offset_p = offset + 4;
+}
+
+int
+cr16_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
+{
+  unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
+  HOST_WIDE_INT align = 0;
+
+  rtx src, dst;
+  rtx tmp_reg;
+
+  if (GET_CODE (align_exp) == CONST_INT)
+    {				/* Only if aligned.  */
+      align = INTVAL (align_exp);
+      if (align & 3)
+	return 0;
+    }
+
+  if (GET_CODE (count_exp) == CONST_INT)
+    {				/* No more than 16 SImode moves.  */
+      count = INTVAL (count_exp);
+      if (count > 64)
+	return 0;
+    }
+
+  tmp_reg = gen_reg_rtx (SImode);
+
+  /* Create psrs for the src and dest pointers.  */
+  dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
+  if (dst != XEXP (dstbase, 0))
+    dstbase = replace_equiv_address_nv (dstbase, dst);
+  src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
+  if (src != XEXP (srcbase, 0))
+    srcbase = replace_equiv_address_nv (srcbase, src);
+
+  offset = 0;
+
+  /* Emit SImode moves.  */
+  si_moves = count >> 2;
+  for (i = 0; i < si_moves; i++)
+    cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
+
+  /* Special cases.  */
+  if (count & 3)
+    {
+      offset = count - 4;
+      cr16_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg,
+				 &offset);
+    }
+
+  gcc_assert (offset == count);
+
+  return 1;
+}
+
+/* Called from cr16.md. The return value depends on the parameter push_or_pop:
+   When push_or_pop is zero -> string for push instructions of prologue.
+   When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
+   Relies on the assumptions:
+   1. RA is the last register to be saved.
+   2. The maximal value of the counter is MAX_COUNT.  */
+char *
+cr16_prepare_push_pop_string (int push_or_pop)
+{
+  /* j is the number of registers being saved, takes care that there won't be
+     more than 8 in one push/pop instruction.  */
+
+  /* For the register mask string.  */
+  static char one_inst_str[50];
+
+  /* i is the index of save_regs[], going from 0 until last_reg_to_save.  */
+  int i, start_reg;
+  int word_cnt;
+  int print_ra;
+  char *return_str;
+
+  /* For reversing on the push instructions if there are more than one.  */
+  char *temp_str;
+
+  return_str = (char *) xmalloc (160);
+  temp_str = (char *) xmalloc (160);
+
+  /* Initialize.  */
+  memset (return_str, 0, 3);
+
+  i = 0;
+  while (i <= last_reg_to_save)
+    {
+      /* Prepare mask for one instruction.  */
+      one_inst_str[0] = 0;
+
+      /* To count number of words in one instruction.  */
+      word_cnt = 0;
+      start_reg = i;
+      print_ra = 0;
+      while ((word_cnt < MAX_COUNT) && (i <= last_reg_to_save))
+	{
+	  /* For each non consecutive save register, 
+	     a new instruction shall be generated.  */
+	  if (!save_regs[i])
+	    {
+	      /* Move to next reg and break.  */
+	      ++i;
+	      break;
+	    }
+
+	  if (i == RETURN_ADDRESS_REGNUM)
+	    print_ra = 1;
+	  else
+	    {
+	      /* Check especially if adding 2 does not cross the MAX_COUNT.  */
+	      if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
+		  >= MAX_COUNT)
+		break;
+	      /* Increase word count by 2 for long registers except RA.   */
+	      word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
+	    }
+	  ++i;
+	}
+
+      /* No need to generate any instruction as
+         no register or RA needs to be saved.  */
+      if ((word_cnt == 0) && (print_ra == 0))
+	continue;
+
+      /* Now prepare the instruction operands.  */
+      if (word_cnt > 0)
+	{
+	  sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
+	  if (print_ra)
+	    strcat (one_inst_str, ", ra");
+	}
+      else
+	strcat (one_inst_str, "ra");
+
+      if (push_or_pop == 1)
+	{
+	  /* Pop instruction.  */
+	  if (print_ra && !cr16_interrupt_function_p ()
+	      && !crtl->calls_eh_return)
+	    /* Print popret if RA is saved and its not a interrupt 
+	       function.  */
+	    strcpy (temp_str, "\n\tpopret\t");
+	  else
+	    strcpy (temp_str, "\n\tpop\t");
+
+	  strcat (temp_str, one_inst_str);
+
+	  /* Add the pop instruction list.  */
+	  strcat (return_str, temp_str);
+	}
+      else
+	{
+	  /* Push instruction.  */
+	  strcpy (temp_str, "\n\tpush\t");
+	  strcat (temp_str, one_inst_str);
+
+	  /* We need to reverse the order of the instructions if there
+	     are more than one. (since the pop will not be reversed in 
+	     the epilogue.  */
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+
+    }
+
+  if (push_or_pop == 1)
+    {
+      /* pop.  */
+      if (cr16_interrupt_function_p ())
+	strcat (return_str, "\n\tretx\n");
+      else if (crtl->calls_eh_return)
+	{
+	  /* Add stack adjustment before returning to exception handler
+	     NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5,r4).  */
+	  strcat (return_str, "\n\taddd\t (r5,r4), (sp)\t\n");
+	  strcat (return_str, "\n\tjump\t (ra)\n");
+
+	  /* But before anything else, undo the adjustment addition done in
+	     cr16_expand_epilogue ().  */
+	  strcpy (temp_str, "\n\tsubd\t (r5,r4), (sp)\t\n");
+	  strcat (temp_str, return_str);
+	  strcpy (return_str, temp_str);
+	}
+      else if (!FUNC_IS_NORETURN_P (current_function_decl)
+	       && !(save_regs[RETURN_ADDRESS_REGNUM]))
+	strcat (return_str, "\n\tjump\t (ra)\n");
+    }
+
+  /* Skip the newline and the tab in the start of return_str.  */
+  return_str += 2;
+  return return_str;
+}
+
+
+/* Generate DWARF2 annotation for multi-push instruction.  */
+static void
+cr16_create_dwarf_for_multi_push (rtx insn)
+{
+  rtx dwarf, reg, tmp;
+  int i, j, from, to, word_cnt, dwarf_par_index, inc;
+  enum machine_mode mode;
+  int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
+
+  for (i = 0; i <= last_reg_to_save; ++i)
+    {
+      if (save_regs[i])
+	{
+	  ++num_regs;
+	  if (i < CR16_FIRST_DWORD_REGISTER)
+	    total_push_bytes += 2;
+	  else
+	    total_push_bytes += 4;
+	}
+    }
+
+  if (!num_regs)
+    return;
+
+  dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+  dwarf_par_index = num_regs;
+
+  from = last_reg_to_save + 1;
+  to = last_reg_to_save;
+  word_cnt = 0;
+
+  for (i = last_reg_to_save; i >= 0;)
+    {
+      if (!save_regs[i] || 0 == i || split_here)
+	{
+	  /* This block of regs is pushed in one instruction.  */
+	  if (0 == i && save_regs[i])
+	    from = 0;
+
+	  for (j = to; j >= from; --j)
+	    {
+	      if (j < CR16_FIRST_DWORD_REGISTER)
+		{
+		  mode = HImode;
+		  inc = 1;
+		}
+	      else
+		{
+		  mode = SImode;
+		  inc = 2;
+		}
+	      reg = gen_rtx_REG (mode, j);
+	      offset += 2 * inc;
+	      tmp = gen_rtx_SET (VOIDmode,
+				 gen_frame_mem (mode,
+						plus_constant
+						(stack_pointer_rtx,
+						 total_push_bytes - offset)),
+				 reg);
+	      RTX_FRAME_RELATED_P (tmp) = 1;
+	      XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
+	    }
+	  from = i;
+	  to = --i;
+	  split_here = 0;
+	  word_cnt = 0;
+	  continue;
+	}
+
+      if (i != RETURN_ADDRESS_REGNUM)
+	{
+	  inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
+	  if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
+	    {
+	      split_here = 1;
+	      from = i;
+	      continue;
+	    }
+	  word_cnt += inc;
+	}
+
+      from = i--;
+    }
+
+  tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
+		     gen_rtx_PLUS (SImode, stack_pointer_rtx,
+				   GEN_INT (-offset)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, 0) = tmp;
+
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+					REG_NOTES (insn));
+}
+
+
+/*
+CompactRISC CR16 Architecture stack layout:
+
+     0 +---------------------
+    |
+    .
+    .
+    |
+    +==================== Sp (x) = Ap (x+1)
+      A | Args for functions
+      | | called by X and      Dynamically
+      | | Dynamic allocations  allocated and
+      | | (alloca, variable    deallocated
+  Stack | length arrays).
+  grows +-------------------- Fp (x)
+  down| | Local variables of X
+  ward| +--------------------
+      | | Regs saved for X-1
+      | +==================== Sp (x-1) = Ap (x)
+    | Args for func X
+    | pushed by X-1
+    +-------------------- Fp (x-1)
+    |
+    |
+    V
+*/
+void
+cr16_expand_prologue (void)
+{
+  rtx insn;
+
+  cr16_compute_frame ();
+  cr16_compute_save_regs ();
+
+  /* If there is no need in push and adjustment to sp, return.  */
+  if ((size_for_adjusting_sp + sum_regs) == 0)
+    return;
+
+  if (last_reg_to_save != -1)
+    {
+      /* If there are registers to push.  */
+      insn = emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));
+      cr16_create_dwarf_for_multi_push (insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (TARGET_ID_SHARED_LIBRARY)
+    emit_insn (gen_unspec_library_offset ());
+
+  if (size_for_adjusting_sp > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (-size_for_adjusting_sp)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (frame_pointer_needed)
+    {
+      /* Initialize the frame pointer with the value of the stack pointer
+         pointing now to the locals.  */
+      insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+    }
+}
+
+/* Generate insn that updates the stack for local variables and padding 
+   for registers we save.   - Generate the appropriate return insn.  */
+void
+cr16_expand_epilogue (void)
+{
+  rtx insn;
+  rtx return_reg;
+
+  /* Nonzero if we need to return and pop only RA. This will generate a
+     different insn. This differentiate is for the peepholes for call as 
+     last statement in function.  */
+  int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
+			&& (sum_regs == CR16_UNITS_PER_DWORD));
+
+  /* Return register.  */
+  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);
+
+  if (frame_pointer_needed)
+    {
+      /* Restore the stack pointer with the frame pointers value.  */
+      insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+    }
+
+  if (size_for_adjusting_sp > 0)
+    {
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    GEN_INT (size_for_adjusting_sp)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (crtl->calls_eh_return)
+    {
+      /* Add this here so that (r5,r4) is actually loaded with the adjustment
+         value; otherwise, the load might be optimized away...
+         NOTE: remember to subtract the adjustment before popping the regs
+         and add it back before returning.  */
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				    EH_RETURN_STACKADJ_RTX));
+    }
+
+  if (cr16_interrupt_function_p ())
+    {
+      insn = emit_jump_insn (gen_interrupt_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (crtl->calls_eh_return)
+    {
+      /* Special case, pop what's necessary, adjust SP and jump to (RA).  */
+      insn = emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (last_reg_to_save == -1)
+    /* Nothing to pop.  */
+    /* Don't output jump for interrupt routine, only retx.  */
+    emit_jump_insn (gen_indirect_jump_return ());
+  else if (only_popret_RA)
+    {
+      insn = emit_jump_insn (gen_popret_RA_return ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else
+    {
+      insn = emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+}
+
+/* Implements FRAME_POINTER_REQUIRED.  */
+static int
+cr16_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca || crtl->calls_eh_return);
+}
+
+static bool
+cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
+}
+
+
+/* Implement TARGET_HANDLE_OPTION.  */
+static bool
+cr16_handle_option (size_t code, const char *arg, int value)
+{
+  switch (code)
+    {
+    case OPT_mshared_library_id_:
+      if (value > MAX_LIBRARY_ID)
+	error ("-mshared-library-id=%s is not between 0"
+	       " and %d", arg, MAX_LIBRARY_ID);
+      cr16_lib_id_given = 1;
+      return true;
+
+    default:
+      return true;
+    }
+}
+
+
+/* A C compound statement that attempts to replace X with
+   a valid memory address for an operand of mode MODE. WIN
+   will be a C statement label elsewhere in the code.
+   X will always be the result of a call to break_out_memory_refs (),
+   and OLDX will be the operand that was given to that function to
+   produce X.
+   The code generated by this macro should not alter the
+   substructure of X.  If it transforms X into a more legitimate form, 
+   it should assign X (which will always be a C variable) a new value.  */
+static rtx
+cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return legitimize_pic_address (orig_x, mode, NULL_RTX);
+  else
+    return x;
+}
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION cr16_handle_option
+
+void
+notice_update_cc (exp)
+     rtx exp;
+{
+  if (GET_CODE (exp) == SET)
+    {
+      /* Jumps do not alter the cc's.  */
+      if (SET_DEST (exp) == pc_rtx)
+	return;
+
+      /* Moving register or memory into a register:
+         it doesn't alter the cc's, but it might invalidate
+         the RTX's which we remember the cc's came from.
+         (Note that moving a constant 0 or 1 MAY set the cc's).  */
+      if (REG_P (SET_DEST (exp))
+	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+	{
+	  return;
+	}
+
+      /* Moving register into memory doesn't alter the cc's.
+         It may invalidate the RTX's which we remember the cc's came from.  */
+      if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+	{
+	  return;
+	}
+
+    }
+
+  CC_STATUS_INIT;
+  return;
+}
+
+rtx
+gen_compare_reg (code, x, y)
+     enum rtx_code code;
+     rtx x, y;
+{
+  enum machine_mode mode;
+
+  mode = GET_MODE (x);
+
+  /* For floating point compare insns, a call is generated so don't
+     do anything here.  */
+
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return cc0_rtx;
+
+  emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
+			  gen_rtx_COMPARE (VOIDmode,
+					   force_reg (mode, x),
+					   force_reg (mode, y))));
+  return cc0_rtx;
+}
+
+static enum machine_mode
+cr16_unwind_word_mode (void)
+{
+  return SImode;
+}
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.h mod/gcc/config/cr16/cr16.h
--- orig/gcc/config/cr16/cr16.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.h	2010-12-22 12:06:09.000000000 +0530
@@ -0,0 +1,691 @@
+/* Definitions of target machine for GNU compiler, for CR16.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+   
+#ifndef GCC_CR16_H
+#define GCC_CR16_H
+
+#define OBJECT_FORMAT_ELF
+
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES         	\
+  {                                 	\
+    GENERAL_REGS, LIM_REG_CLASSES  	\
+  }
+
+/* Controlling the driver.  */
+
+/* The GNU C++ standard library requires that these macros be defined.  */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef  MATH_LIBRARY
+#define MATH_LIBRARY ""
+
+#undef  LIB_SPEC
+#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \
+%{msim*:%{!T*:-Tsim.ld}} \
+%{!T*:%{!msim*: %{-Telf32cr16.x}}} "
+
+
+
+/* Run-time target specification.  */
+#ifndef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS()          \
+do                                         \
+  {                                        \
+    builtin_define ("__CR__");             \
+    builtin_define ("__CR16__");           \
+    builtin_define ("__CR16C__");          \
+    if (TARGET_CR16CP)                     \
+      builtin_define ("__CR16CP__");       \
+    else                                   \
+      builtin_define ("__CR16CSTD__");     \
+    if (CR16_TARGET_DATA_NEAR)             \
+      builtin_define ("__DATA_NEAR__");    \
+    if (CR16_TARGET_DATA_MEDIUM)           \
+      builtin_define ("__DATA_MEDIUM__");  \
+    if (CR16_TARGET_DATA_FAR)              \
+      builtin_define ("__DATA_FAR__");     \
+    if (TARGET_INT32)                      \
+      builtin_define ("__INT32__");         \
+    if (TARGET_ID_SHARED_LIBRARY)          \
+      builtin_define ("__ID_SHARED_LIB__"); \
+  }                                        \
+while (0)
+#endif
+
+#define TARGET_VERSION fputs (" (CR16/ELF)", stderr);
+
+/* Force the generation of dwarf .debug_frame sections even if not
+   compiling -g.  This guarantees that we can unwind the stack.  */
+#define DWARF2_FRAME_INFO 1
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Generate .file/.loc directives, so that the assembler generates the
+   line table.  */
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+/* Maximum number of library ids we permit.  */
+#define MAX_LIBRARY_ID 255
+
+#define CR16_TARGET_DATA_NEAR   cr16_is_data_model (DM_NEAR)
+#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT)
+#define CR16_TARGET_DATA_FAR    cr16_is_data_model (DM_FAR)
+
+/* Storage layout.  */
+#define BITS_BIG_ENDIAN     0
+
+#define BYTES_BIG_ENDIAN    0
+
+#define WORDS_BIG_ENDIAN    0
+
+#define UNITS_PER_WORD      2
+
+/* Units per 32-bit (DWORD).  */
+#define CR16_UNITS_PER_DWORD 4
+
+#define POINTER_SIZE        32
+
+#define PARM_BOUNDARY       16
+
+#define STACK_BOUNDARY      (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY))
+
+#define FUNCTION_BOUNDARY  (!optimize_size ? BIGGEST_ALIGNMENT : BITS_PER_WORD)
+
+/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based 
+   where as CR16C is proprietary internal bus architecture.  */
+#define BIGGEST_ALIGNMENT   ((TARGET_CR16CP) ? 32 : 16)
+
+#define MAX_FIXED_MODE_SIZE 64
+
+/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster.  */
+#define DATA_ALIGNMENT(TYPE, ALIGN)             \
+  (((TREE_CODE (TYPE) == ARRAY_TYPE)            \
+     && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \
+     && ((ALIGN) < BITS_PER_WORD))               \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+/* In CR16 strings are word-aligne; strcpy from constants will be faster.  */
+#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN)                            \
+  (((TREE_CODE (CONSTANT) == STRING_CST) && ((ALIGN) < BITS_PER_WORD)) \
+     ? (BITS_PER_WORD) : (ALIGN))
+
+#define STRICT_ALIGNMENT 0
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Layout of source language data types.  */
+#define INT_TYPE_SIZE       (TARGET_INT32 ? 32 : 16)
+
+#define SHORT_TYPE_SIZE     16
+
+#define LONG_TYPE_SIZE      32
+
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE     32
+
+#define DOUBLE_TYPE_SIZE    64
+
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE           "long unsigned int"
+
+#define PTRDIFF_TYPE        "long int"
+
+#define WCHAR_TYPE          "short unsigned int"
+
+#define WCHAR_TYPE_SIZE     16
+
+/* By default, the C++ compiler will use the lowest bit of the pointer
+   to function to indicate a pointer-to-member-function points to a
+   virtual member function.  However, in CR architecture FUNCTION_BOUNDARY
+   indicates function addresses are always even, but function pointers can be
+   odd (after right-shifting them when loading them into a register), and the
+   default doesn't work.  In that case, the lowest bit of the delta
+   field will be used (the remainder of the field is shifted to the left).  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION     ptrmemfunc_vbit_in_delta
+
+/* Register usage.  */
+
+/* First 32-bit register is R12.  */
+#define CR16_FIRST_DWORD_REGISTER   12
+
+#define FIRST_PSEUDO_REGISTER       16
+
+/* 1 for registers that have pervasive standard uses
+   and are not available for the register allocator.
+   On the CR16, only the stack pointer (r15) is such.  */
+#define FIXED_REGISTERS                               \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  0,  1                                 \
+  }      
+
+/* 1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ 
+   On the CR16, calls clobbers r0-r6 (scratch registers), 
+   ra (the return address) and sp (the stack pointer).  */
+#define CALL_USED_REGISTERS                           \
+  {                                                   \
+  /* r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10.  */ \
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,        \
+  /* r11 r12 r13 ra  sp.  */                          \
+    0,  0,  0,  1,  1                                 \
+  }
+
+/* Order of allocation of registers. Need to experiment on it
+   to for effective code density.  */
+#define REG_ALLOC_ORDER {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+
+/* Returns 1 if the register is longer than word size, 0 otherwise.  */
+#define LONG_REG_P(REGNO)                                                    \
+  (HARD_REGNO_NREGS (REGNO,                                                  \
+  		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
+  					  (BITS_PER_WORD, MODE_INT)))        \
+   		      == 1)
+
+#define HARD_REGNO_NREGS(REGNO, MODE)                                        \
+ ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                       \
+  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
+  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+
+/* Nonzero if it is permissible to store a value of mode @var{mode} in hard
+   register number @var{regno} (or in several registers starting with that
+   one).  On the CR16 architecture, all registers can hold all modes,
+   except that double precision floats (and double ints) must fall on
+   even-register boundaries.  */ 
+#define HARD_REGNO_MODE_OK(REGNO, MODE) cr16_hard_regno_mode_ok (REGNO, MODE)
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+   notice_update_cc ((EXP))
+
+/* Interrupt functions can only use registers that have already been 
+   saved by the prologue, even if they would normally be call-clobbered 
+   Check if sizes are same and then check if it is possible to rename.  */
+#define HARD_REGNO_RENAME_OK(SRC, DEST)                 \
+   (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST)))
+
+/* Exception handling stuff.  */
+
+/*To ensure correct dwarf unwinding.  */
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse")))
+
+#define gen_rtx_RA	gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM)
+
+/* Use (r8,r7) and (r10,r9) to pass exception handling information.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM)
+
+#define DWARF2_UNWIND_INFO 1
+
+/* (r5,r4) holds a stack adjustment for returning to a handler.  */
+#define EH_RETURN_STACKADJ_RTX 		gen_rtx_REG (Pmode, 4)
+
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -4))
+
+#define INCOMING_RETURN_ADDR_RTX	gen_rtx_RA
+
+#define DWARF_FRAME_RETURN_COLUMN	\
+  DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM)
+
+#define INCOMING_FRAME_SP_OFFSET		0	
+#define FRAME_POINTER_CFA_OFFSET(FNDECL)	0	
+
+/* A C expression whose value is RTL representing the value of the return
+   address for the frame COUNT steps up from the current frame.  */
+#define RETURN_ADDR_RTX(COUNT, FRAME) 			  		\
+  (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
+		:  const0_rtx
+
+#define MODES_TIEABLE_P(MODE1, MODE2)  \
+  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+
+enum reg_class
+{
+  NO_REGS,
+  SHORT_REGS,
+  LONG_REGS,
+  NOSP_REGS,
+  DOUBLE_BASE_REGS,
+  GENERAL_REGS,
+  ALL_REGS,
+  LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES	\
+  {			\
+    "NO_REGS",		\
+    "SHORT_REGS",	\
+    "LONG_REGS",	\
+    "NOSP_REGS",	\
+    "DOUBLE_BASE_REGS",	\
+    "GENERAL_REGS",	\
+    "ALL_REGS"		\
+  }
+
+#define REG_CLASS_CONTENTS			     		\
+  {						     		\
+    {0x00000000}, /* NO_REGS		             */  	\
+    {0x00000FFF}, /* SHORT_REGS 	: 0 - 11     */   	\
+    {0x0000F000}, /* LONG_REGS 		: 12 - 15    */  	\
+    {0x00007FFF}, /* NOSP_REGS 		: 0 - 14     */   	\
+    {0x0000F555}, /* DOUBLE_BASE_REGS   : 2,4,6,8,10 */  	\
+    {0x0000FFFF}, /* GENERAL_REGS	: 0 - 15     */  	\
+    {0x0000FFFF}  /* ALL_REGS 		: 0 - 15     */  	\
+  }
+
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P  hook_bool_mode_true 
+
+#define REGNO_REG_CLASS(REGNO)  cr16_regno_reg_class (REGNO)
+
+#define BASE_REG_CLASS      GENERAL_REGS
+
+#define MODE_BASE_REG_CLASS(MODE) \
+  (GET_MODE_SIZE (MODE) <= 4 ?  (BASE_REG_CLASS) :  (DOUBLE_BASE_REGS))
+
+#define INDEX_REG_CLASS      LONG_REGS
+
+#define REG_CLASS_FROM_LETTER(C)    \
+  ((C) == 'b' ? NOSP_REGS :         \
+   (C) == 't' ? SHORT_REGS :        \
+   (C) == 'p' ? LONG_REGS :         \
+   NO_REGS)
+
+#define CR16_REGNO_OK_FOR_BASE_P(REGNO)                \
+  (((REGNO) < FIRST_PSEUDO_REGISTER)                   \
+   || (reg_renumber && ((unsigned) reg_renumber[REGNO] \
+                        < FIRST_PSEUDO_REGISTER)))
+
+/* Use even-numbered reg for 64-bit accesses.  */
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)	  \
+	(CR16_REGNO_OK_FOR_BASE_P(REGNO)  &&	  \
+	  ((GET_MODE_SIZE (MODE) > 4  &&  	  \
+	     (REGNO) < CR16_FIRST_DWORD_REGISTER)\
+	     ? (0 == ((REGNO) & 1)) \
+	     : 1))
+
+/* TODO: For now lets not support index addressing mode.  */
+#define REGNO_OK_FOR_INDEX_P(REGNO)        \
+  (((REGNO >= CR16_FIRST_DWORD_REGISTER)  \
+     && ((REGNO) < FIRST_PSEUDO_REGISTER)) \
+   || (reg_renumber                        \
+       && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \
+            && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)))\
+  )
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+/* The maximum number of consecutive registers of class CLASS needed to
+   hold a value of mode MODE.
+   On the CompactRISC architecture, the size of MODE in words.
+   The size of MODE in double words for the class LONG_REGS.
+
+   The following check assumes if the class is not LONG_REGS, then
+   all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are 
+   short.  We may have to check if this can cause any degradation in 
+   performance.  */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+  (CLASS == LONG_REGS \
+   ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+#define SIGNED_INT_FITS_N_BITS(imm, N)           \
+  ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1)))       \
+      && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0)
+
+#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
+  (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0)
+
+
+#define CHECK_64_BIT_ADD_SUB_DI(imm) 	\
+  (((((long long) imm >> 47) & 0x1) && (((long long)imm >> 63) \
+       & 0x1))? 0 : 1)
+
+/* The letters I, J, K, L in a register constraint string
+   can be used to stand for particular ranges of immediate operands.
+   This macro defines what the ranges are.
+   C is the letter, and VALUE is a constant value.
+   Return 1 if VALUE is in the range specified by C.
+   I : signed 4 bit immediate
+   J : signed 5 bit immediate
+   K : signed 6 bit immediate
+   L : unsigned 4 bit immediate  
+   M : signed 32 bit immediate  
+   N : check for 64-bit add/sub instructions.  */
+#define CONST_OK_FOR_LETTER_P(VALUE, C)                \
+   ((C) == 'I' ? SIGNED_INT_FITS_N_BITS (VALUE, 4) :   \
+    (C) == 'J' ? SIGNED_INT_FITS_N_BITS (VALUE, 5) :   \
+    (C) == 'K' ? SIGNED_INT_FITS_N_BITS (VALUE, 6) :   \
+    (C) == 'L' ? UNSIGNED_INT_FITS_N_BITS (VALUE, 4):  \
+    (C) == 'M' ? SIGNED_INT_FITS_N_BITS (VALUE,32) :   \
+    (C) == 'N' ? CHECK_64_BIT_ADD_SUB_DI (VALUE) : 0)
+
+/*To print Logical DI3 patterns.  */
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
+  (CODE == 'L' || CODE == 'M' || CODE == 'H'|| CODE == 'U')
+
+/* Similar, but for floating constants, and defining letters G and H.
+   Here VALUE is the CONST_DOUBLE rtx itself.  
+   G : Float constant that can fit in 4 bits.
+   H : Not defined.  */
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
+  ((C) == 'G' ? cr16_const_double_ok (VALUE) : 0)
+
+/* Constraint for bit instructions.  */
+#define OK_FOR_Z(OP) \
+  ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \
+   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \
+       && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT))
+
+/* Stack layout and calling conventions.  */
+#define STACK_GROWS_DOWNWARD
+
+#define STARTING_FRAME_OFFSET   0
+
+#define STACK_POINTER_REGNUM    15
+
+#define FRAME_POINTER_REGNUM    13
+
+#define ARG_POINTER_REGNUM      12
+
+#define STATIC_CHAIN_REGNUM     1
+
+#define RETURN_ADDRESS_REGNUM   14
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+#define ELIMINABLE_REGS                            \
+  {                                                \
+    { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
+    { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM}, \
+    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
+  }
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)              \
+  do                                                              \
+    {                                                             \
+      (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO));  \
+    }                                                             \
+  while (0)
+
+/* Passing function arguments.  */
+
+#define ACCUMULATE_OUTGOING_ARGS 0
+
+#define PUSH_ARGS 1
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+#ifndef CUMULATIVE_ARGS
+struct cumulative_args
+{
+  int ints;
+};
+
+#define CUMULATIVE_ARGS struct cumulative_args
+#endif
+
+/* On the CR16 architecture, Varargs routines should receive their parameters 
+   on the stack.  */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+
+#define FUNCTION_ARG_REGNO_P(REGNO)  cr16_function_arg_regno_p (REGNO)
+
+/* Returning function value.  */
+
+/* On the CR16, the return value is in R0.  */
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+    gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
+
+#define LIBCALL_VALUE(MODE)     gen_rtx_REG (MODE, 0)
+
+#define FUNCTION_VALUE_REGNO_P(N)   ((N) == 0)
+
+#define CR16_STRUCT_VALUE_REGNUM  0
+
+/* Generating code for profiling - NOT IMPLEMENTED.  */
+#undef  FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO)      \
+{                                               \
+  sorry ("Profiler support for CR16");        \
+}
+
+/* Trampolines for nested functions - NOT SUPPORTED.  */
+#define TRAMPOLINE_SIZE    16
+
+/* ADDRESSING MODES.  */
+
+#define CONSTANT_ADDRESS_P(X)       \
+  (GET_CODE (X) == LABEL_REF        \
+   || GET_CODE (X) == SYMBOL_REF    \
+   || GET_CODE (X) == CONST         \
+   || GET_CODE (X) == CONST_INT)
+
+#define MAX_REGS_PER_ADDRESS    2
+
+#define HAVE_POST_INCREMENT     0
+#define HAVE_POST_DECREMENT     0
+#define HAVE_POST_MODIFY_DISP   0
+#define HAVE_POST_MODIFY_REG    0
+
+#ifdef REG_OK_STRICT
+#define CR16_REG_OK_FOR_BASE_P(X)	CR16_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	\
+  REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE)
+#define REG_OK_FOR_INDEX_P(X)   REGNO_OK_FOR_INDEX_P (REGNO (X))
+#else /* not REG_OK_STRICT.  */
+#define CR16_REG_OK_FOR_BASE_P(X)	1
+#define REG_MODE_OK_FOR_BASE_P(X, MODE)	1
+#define REG_OK_FOR_INDEX_P(X)   1
+#endif /* not REG_OK_STRICT.  */
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 1))       \
+    goto LABEL;                                   \
+}
+#else /* not REG_OK_STRICT.  */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)    \
+{                                                   \
+  if (cr16_legitimate_address_p (MODE, X, 0))       \
+    goto LABEL;                                   \
+}
+#endif /* not REG_OK_STRICT.  */
+
+/* Go to LABEL if ADDR (a legitimate address expression) has 
+   an effect that depends on the machine mode it is used for.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Nonzero if X is a legitimate constant for an immediate
+   operand on the target machine.  You can assume that X
+   satisfies CONSTANT_P.
+   In cr16c treat legitimize float constant as an immediate operand.  */
+#define LEGITIMATE_CONSTANT_P(X)  1
+
+/* Relative costs of operations.  */
+#define MEMORY_MOVE_COST(MODE, CLASS, IN) \
+  cr16_memory_move_cost (MODE, CLASS, IN)
+
+/* Moving to processor register flushes pipeline - thus asymmetric.  */
+#define REGISTER_MOVE_COST(MODE, FROM, TO) ((TO != GENERAL_REGS) ? 8 : 2)
+/* Assume best case (branch predicted).  */
+#define BRANCH_COST(speed_p, predictable_p)       2
+
+#define SLOW_BYTE_ACCESS  1
+
+/* It is as good or better to call a constant function address than to
+   call an address kept in a register.  */
+#define NO_FUNCTION_CSE
+
+/* Dividing the output into sections.  */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP  "\t.section\t.bss"
+
+/* Position independent code (PIC).  */
+/* NEAR_PIC for -fpic option.  */
+
+#define NEAR_PIC 1
+                                      
+/* FAR_PIC for -fPIC option.  */                                                                                       
+
+#define FAR_PIC  2
+
+#define PIC_OFFSET_TABLE_REGNUM  12
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)       
+
+/* Assembler format.  */
+
+/* Character to start a comment.  */
+#define ASM_COMMENT_START "#"
+
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
+
+#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)   \
+  do                                            \
+    {                                           \
+      const char *rn = XSTR (SYMBOL, 0);        \
+      assemble_name (STREAM, rn);               \
+      if (SYMBOL_REF_FUNCTION_P (SYMBOL))       \
+      {                                         \
+        fprintf ((STREAM), "@c");               \
+      }                                         \
+    }                                           \
+  while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON   "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF  "#NO_APP\n"
+
+/* Switch into a generic section.  */
+#define TARGET_ASM_NAMED_SECTION	default_elf_asm_named_section
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP		"\t.section\t.init"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP		"\t.section\t.fini"
+
+/* Instruction output.  */
+
+#define REGISTER_NAMES                                     \
+  {                                                        \
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "ra",  "sp"  \
+  }
+
+#define PRINT_OPERAND(STREAM, X, CODE) \
+  cr16_print_operand (STREAM, X, CODE)
+
+#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
+  cr16_print_operand_address (STREAM, ADDR)
+
+/* Output of dispatch tables.  */
+
+/* Revisit. No PC relative case as label expressions are not 
+   properly supported in binutils else we could have done this:
+   #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0).  */
+#define CASE_VECTOR_PC_RELATIVE 0
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)    \
+  ((GET_MODE (BODY) == QImode)                              \
+   ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL)                                   \
+   : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n",         \
+              VALUE, REL))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+  asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE))
+
+/* Alignment in assembler file.  */
+
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+  asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
+
+/* Miscellaneous parameters.  */
+
+#define CASE_VECTOR_MODE  Pmode
+
+#define MOVE_MAX 4
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
+
+#define STORE_FLAG_VALUE  1
+
+#define Pmode SImode
+
+#define FUNCTION_MODE QImode
+
+/* Define this boolean macro(s) to indicate whether or not your architecture
+   has (un)conditional branches that can span all of memory.  It is used in
+   conjunction with an optimization that partitions hot and cold basic blocks
+   into separate sections of the executable.
+   CR16 contains branch instructions that span whole address space.  */
+#define HAS_LONG_COND_BRANCH    1
+#define HAS_LONG_UNCOND_BRANCH  1
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
+  (CODE == 'L' || CODE == 'M' || CODE == 'H'|| CODE == 'U')
+
+
+#endif /* End of GCC_CR16_H.  */
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16-libgcc.s mod/gcc/config/cr16/cr16-libgcc.s
--- orig/gcc/config/cr16/cr16-libgcc.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-libgcc.s	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,573 @@
+/* Libgcc Target specific implementation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef  L_mulsi3
+	.text
+	.align  4
+	.globl  ___mulsi3
+___mulsi3:
+	movw    r4,r0
+	movw    r2,r1
+	/* Extended multiplication between the 2 lower words */
+	muluw   r1,(r1,r0)
+
+	/* Multiply the lower word of each parameter  */  
+	mulw    r2,r5   
+    
+	/* With the higher word of the other  */
+	mulw    r3,r4     
+  
+	/* Add products to the higher part of the final result  */
+	addw    r4,r1       
+	addw    r5,r1
+	jump    (ra)
+#endif
+
+
+#ifdef L_divdi3
+	.text
+	.align 4
+	.globl ___divdi3
+
+___divdi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd   12(sp), (r1, r0)
+	loadd   16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   20(sp), (r5, r4)
+	loadd   24(sp), (r7, r6)
+	
+	/* Set neg to 0 */
+	movw $0, r10
+	
+	subd $16, (sp)
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $0, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	addd	$16, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret $4, r7, ra
+#endif
+
+#ifdef L_lshrdi3
+	.text
+	.align 4
+	.globl ___lshrdi3
+
+___lshrdi3:
+	push	$3, r7
+
+	/* Load parameters from stack in this order */
+	movw r2, r6		/* Number of shifts */
+	loadd	6(sp), (r1, r0)	/* Low bits */
+	loadd	10(sp), (r3, r2)/* High bits */
+
+	xorw $-1, r6		/* Invert number of shifts */
+	addw $1, r6		/* Add 1 by number of shifts */
+
+	movw r6, r7		/* Copy number of shifts */
+
+	tbit $15, r6		/* Test if number is negative */
+	bfs L2			/* If negative jump to L2 */
+
+	movd (r1, r0), (r9, r8)	/* Copy low bits */
+
+	subw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the right to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $32, r6		/* If number of shifts is higher than 31 */
+	blt L1			/* Shift by moving */
+
+	lshd r6, (r3, r2)	/* Shift high bits */
+	lshd r6, (r1, r0)	/* Shift low bits */
+	addd (r9, r8), (r3, r2)	/* Add overflow to the high bits */
+	popret	$3, r7		/* Return */
+
+L1:	movd $0, (r1, r0)	/* Reset low bit */
+	movd (r9, r8), (r3, r2)	/* Add the overflow from the low bit */
+	popret	$3, r7		/* Return */
+
+L2:	movd (r3, r2), (r9, r8)	/* Copy high bits */
+
+	addw $32, r7		/* Calc how many bits will overflow */
+	/* Shift the temp low bit to the left to see the overflowing bits  */
+	lshd r7, (r9, r8)	
+
+	cmpw $-32, r6		/* If number of shifts is lower than -31 */
+	bgt L3			/* Shift by moving */
+
+	lshd r6, (r1, r0)	/* Shift low bits */
+	lshd r6, (r3, r2)	/* Shift high bits */
+	addd (r9, r8), (r1, r0)	/* Add overflow to the low bits */
+	popret	$3, r7		/* Return */
+	
+L3:	movd $0, (r3, r2)	/* Reset the high bit */
+	movd (r9, r8), (r1, r0)	/* Add the overflow from the high bit */
+	popret	$3, r7		/* Return */
+#endif
+
+#ifdef L_moddi3
+	.text
+	.align 4
+	.globl ___moddi3
+
+___moddi3:
+	push	$4, r7, ra
+
+#  ifdef __ID_SHARED_LIB__
+	push	$2, r12
+	movd	$__current_shared_library_r12_offset_, (r1,r0)
+	loadd	[r12]0(r1,r0), (r12)
+#  endif
+
+	/* Param #1 Long Long low bit first */
+	loadd	12(sp), (r1, r0)
+	loadd	16(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	20(sp), (r5, r4)
+	loadd	24(sp), (r7, r6)
+	
+	subd	$18, (sp)
+
+	/* Set neg to 0 */
+	storw $0, 16(sp)
+	
+	movd	$-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L4
+
+	/* Invert param1 and neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	storw $1, 16(sp)
+	bcc L4			/* If no carry occurred go to L4 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L4:	stord (r1, r0), 0(sp)
+	stord (r3, r2), 4(sp)
+	
+	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L5
+
+	/* Invert param2 and neg */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	bcc L5			/* If no carry occurred go to L5 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+
+L5:	stord (r5, r4), 8(sp)
+	stord (r7, r6), 12(sp)
+	movw $1, r2
+
+	/* Call udivmoddi3 */
+#ifdef __PIC__
+	loadd	___udivmoddi3@cGOT(r12), (r1,r0)
+	jal	(r1,r0)
+#else
+	bal (ra), ___udivmoddi3
+#endif
+
+	/* If (neg) */
+	loadw 16(sp), r10	/* Load neg from stack */
+	addd	$18, (sp)
+	cmpw $0, r10		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of ures with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of ures with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of ures */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of ures */
+Lexit__:
+#  ifdef __ID_SHARED_LIB__
+	pop	$2, r12
+#  endif
+	popret	$4, r7, ra
+#endif
+
+#ifdef L_muldi3
+	.text
+	.align 4
+	.globl ___muldi3
+
+___muldi3:
+	push	$2, r13
+	push	$7, r7
+	/* Param #1 Long Long low bit first */
+	loadd   18(sp), (r1, r0)
+	loadd   22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd   26(sp), (r5, r4)
+	loadd   30(sp), (r7, r6)
+
+	/* Clear r13, r12 */	
+	movd $0, (r12)	
+	movd $0, (r13)
+
+	/* Set neg */
+	movw $0, r10
+
+	/* Compare if param1 is greater than 0 */	
+	cmpw $0, r3
+	ble L1
+
+	/* Invert param1 and neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of param 1 with temp */
+	xord (r9, r8), (r3, r2)	/* Xor high bits of param 1 with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of param 1 */
+	xorw $1, r10		/* Invert neg */
+	bcc L1			/* If no carry occurred go to L1 */
+	addd $1, (r3, r2)	/* Add 1 to high bits of param 1 */
+
+L1:	/* Compare if param2 is greater than 0 */	
+	cmpw $0, r7
+	ble L2	
+	
+	/* Invert param2 and neg */
+	movd $-1, (r9, r8)	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r5, r4)	/* Xor low bits of param 2 with temp */
+	xord (r9, r8), (r7, r6)	/* Xor high bits of param 2 with temp */
+	addd $1, (r5, r4)	/* Add 1 to low bits of param 2 */
+	xorw $1, r10		/* Invert neg */
+	bcc L2			/* If no carry occurred go to L2 */
+	addd $1, (r7, r6)	/* Add 1 to high bits of param 2 */
+	
+L2:	storw r10, 18(sp)	/* Store neg to stack so we can use r10 */
+
+	/* B*D */
+	/* Bl*Dl */
+	macuw r0, r4, (r12)	/* Multiply r0 and r4 and add to r12 */
+		
+	/* Bh*Dl */
+	movd $0, (r9, r8)	/* Clear r9, r8 */
+	macuw r1, r4, (r9, r8)	/* Multiply Bh*Dl and add result to (r9, r8) */
+	movw r9,  r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	movw $0, r11		/* Clear r11 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L3			/* If no carry occurred go to L3 */
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L3:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+		
+	/* Bl*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r5, (r9, r8)	/* Multiply r0 and r5 and stor in (r9, r8) */
+	movw r9, r10		/* Shift left: r9 to r10 */
+	lshd $16, (r9, r8)	/* Shift left: r8 to r9 */
+	addd (r9, r8), (r12)	/* Add (r9, r8) to r12 */
+	bcc L4			/* If no carry occurred go to L4 */ 
+	addd $1, (r13)		/* If carry occurred add 1 to r13 */
+
+L4:	addd (r11, r10), (r13)	/* Add (r11, r10) to r13 */
+
+	/* Bh*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r1, r5, (r9, r8)	/* Multiply r1 and r5 and add to r13 */
+	addd (r9, r8), (r13)	/* Add (r9, r8) to result */
+
+	/* A*D */
+	/* Al*Dl */
+	movd $0, (r11, r10)	/* Clear (r11, r10) */
+	macuw r2, r4, (r11, r10)/* Multiply r2 and r4 and add to (r11, r10) */
+	
+	addd (r13), (r11, r10)	/* Copy r13 to (r11, r10) */
+
+	/* Al*Dh */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r2, r5, (r9, r8)	/* Multiply r2 and r5 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+	
+	/* Ah*Dl */
+	muluw r3, (r5, r4)	/* Multiply r3 and r4 and stor in (r5, r4) */
+	addw r4, r11		/* Add r4 to r11 */
+
+	/* B*C */
+	/* Bl*Cl */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r6, (r9, r8)	/* Multiply r0 and r6 and add to (r9, r8) */
+	addd (r9, r8), (r11, r10)/* Add (r9, r8) to result */
+
+	/* Bl*Ch */
+	movd $0, (r9, r8)	/* Clear (r9, r8) */
+	macuw r0, r7, (r9, r8)	/* Multiply r0 and r7 and add to (r9, r8) */
+	addw r8, r11		/* Add r8 to r11 */
+
+	loadw 18(sp), r8	/* Load neg from stack */
+
+	/* Bh*Cl */
+	muluw r1, (r7, r6)	/* Multiply r1 and r6 and stor in (r7, r6) */
+	addw r6, r11		/* Add r6 to r11 */
+
+E1:	movd (r11, r10), (r3, r2)
+	movd (r12), (r1, r0)	
+
+	/* If (neg) */
+	cmpw $0, r8		/* Compare 0 with neg */
+	beq	Lexit__
+	
+	/* Neg = -Neg */
+	movd $-1, (r9, r8) 	/* Temp set to FFFFFFFF */
+	xord (r9, r8), (r1, r0)	/* Xor low bits of result with temp */
+	xord (r9, r8), (r3, r2) /* Xor high bits of result with temp */
+	addd $1, (r1, r0)	/* Add 1 to low bits of result */
+	bcc	Lexit__
+	addd $1, (r3, r2)	/* Add 1 to high bit of result */
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_negdi2
+	.text
+	.align 4
+	.globl ___negdi2
+
+___negdi2:
+	/* Load parameter from the registers in this order */
+	loadd 0(sp), (r1, r0)
+	loadd 4(sp), (r3, r2)
+	
+	movd $-1, (r6, r5)	/* Set temp to FFFFFFFF */
+	xord (r6, r5), (r1, r0)	/* Xor low bits with temp */
+	xord (r6, r5), (r3, r2)	/* Xor high bits with temp */
+	addd $1, (r1, r0)	/* Add one */
+	jcc (ra)
+	addd $1, (r3, r2)	/* Add the carry to the high bits */
+	jump (ra)
+#endif
+
+#ifdef L_udivdi3
+	.text
+	.align 4
+	.globl ___udivdi3
+
+___udivdi3:
+	movw $0, r2
+	br ___udivmoddi3
+#endif
+
+#ifdef L_udivmoddi3
+	.text
+	.align 4
+	.globl ___udivmoddi3
+
+___udivmoddi3:
+	push	$2, r13
+	push	$7, r7
+
+	/* Param #1 Long Long low bit first */
+	loadd	18(sp), (r1, r0)
+	storw	r2, 18(sp)	/* Store modulo on stack */
+	loadd	22(sp), (r3, r2)
+
+	/* Param #2 Long Long low bit first */
+	loadd	26(sp), (r5, r4)
+	loadd	30(sp), (r7, r6)
+
+	/* Set ures to 0 */
+	movd $0, (r13)
+	movd $0, (r12)
+	
+	cmpd (r12), (r5, r4)
+	beq LE
+
+L5:	movd $1, (r9, r8)	/* Store 1 in low bits from bit */
+	movd $0, (r11, r10)	/* Store 0 in high bits from bit */
+	
+L6:	/* While (den < num && (!den & (1LL<<63))) */
+	/* Compare high bits from param 1 and param 2 */
+	cmpd (r7, r6), (r3, r2)	
+	bhi L10			/* If param 2 is greater go to L10 */
+	bne L8			/* If param 1 is greater go to L8 */
+	cmpd (r5, r4), (r1, r0)	/* Compare low bits from param 1 and param 2 */
+	/*  If param 2 is greater or the same go to L1 */
+	bhs L10			 
+
+L8:	/* Check if most significant bit of param 2 is set */
+	tbit $15, r7		
+	bfs L10			/* If PSR is set go to L10 */
+
+	/* Shift bit */
+	lshd $1, (r11, r10)	/* Shift left: high bits of bit */ 
+	/* Check if most significant bit of bit is set */
+	tbit $15, r9		
+	lshd $1, (r9, r8)	/* Shift left: low bits of bit */
+	bfs L28			/* If PSR is set go to L28 */
+
+L9:	/* Shift b */
+	lshd $1, (r7, r6)	/* Shift left: high bits of param 2 */
+	/* Check if most significant bit of param 2 is set */
+	tbit $15, r5		
+	lshd $1, (r5, r4)	/* Shift left: low bits of param 2 */
+	bfc L6			/* If PSR is set go to L6 */
+	addw $1, r6		/* Add 1 to the highest bits of b */
+	br L6			/* Go to L6 */
+	
+L10:	/* While (bit) */
+	cmpd $0, (r11, r10)	
+	bne L11
+	cmpd $0, (r9, r8)
+	beq E1
+
+L11:	/* If (num >= den) */
+	cmpd (r3, r2), (r7, r6)	/* Compare high bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+	bne L12			/* If not equal go to L12 */	
+	cmpd (r1, r0), (r5, r4)	/* Compare low bits of param 1 and param 2 */
+	blo L15			/* If param 1 lower than param 2 go to L15 */
+
+L12:	/* Ures |= bit */
+	ord (r11, r10), (r13)
+	ord (r9, r8), (r12)	
+
+	/* Num -= den */
+	subd (r7, r6), (r3, r2) /* Subtract highest 32 bits from each other */
+	subd (r5, r4), (r1, r0)	/* Subtract lowest 32 bits from each other */
+	bcc L15			/* If no carry occurred go to L15 */
+	subd $1, (r3, r2)	/* Subtract the carry */
+
+	
+L15:	/* Shift bit to the right */
+	lshd $-1, (r9, r8)	/* Shift right: low bits of bit */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r10		
+	lshd $-1, (r11, r10)	/* Shift right: high bits of bit */
+	bfs L18			/* If PSR is set go to L18 */
+
+L17:	/* Shift param#2 to the right */
+	lshd $-1, (r5, r4)	/* Shift right: low bits of param 2 */
+	/* Check if least significant bit of high bits is set */
+	tbit $0, r6		
+	lshd $-1, (r7, r6)	/* Shift right: high bits of param 2 */
+	bfc L10			/* If PSR is not set go to L10 */
+	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r5		
+	br L10			/* Go to L10 */
+
+
+L18:	/* Or with 0x8000 to set most significant bit */
+	orw $32768, r9		
+	br L17
+
+
+L28: 	/* Left shift bit */
+	addw $1, r10		/* Add 1 to highest bits of bit */
+	br L9			/* Go to L9 */
+
+LE:	cmpd (r12), (r7, r6)
+	bne L5
+	excp dvz
+	br	Lexit__
+
+E1:	loadw	18(sp), r4
+	cmpw $0, r4
+	bne	Lexit__
+
+	/* Return result */
+	movd (r12), (r1, r0)
+	movd (r13), (r3, r2)
+Lexit__:
+	pop	$7, r7
+	popret	$2, r13
+#endif
+
+#ifdef L_umoddi3
+	.text
+	.align 4
+	.globl ___umoddi3
+
+___umoddi3:
+	movw $1, r2
+	br ___udivmoddi3
+#endif
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.md mod/gcc/config/cr16/cr16.md
--- orig/gcc/config/cr16/cr16.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.md	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,1127 @@
+;; GCC machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+
+;;  Register numbers
+
+(define_constants
+  [(SP_REGNUM 15); Stack pointer
+   (RA_REGNUM 14); Return address
+  ]
+)
+
+;; Predicates
+
+(include "predicates.md")
+
+
+;; UNSPEC usage
+(define_constants
+  [(UNSPEC_PIC_ADDR             0)
+   (UNSPEC_PIC_LOAD_ADDR        1)
+   (UNSPEC_LIBRARY_OFFSET       2)
+   (UNSPEC_SH_LIB_PUSH_R12      3)
+   (UNSPEC_SH_LIB_POP_R12       4)
+  ]
+)
+
+;; Attributes
+
+(define_attr "length" "" (const_int 2))
+
+(define_asm_attributes
+  [(set_attr "length" "2")]
+)
+
+;;  Mode Macro Definitions
+
+(define_mode_iterator ALLMT  [QI HI SI SF])
+(define_mode_iterator CR16IM [QI HI SI])
+(define_mode_iterator LONG   [SI SF])
+(define_mode_iterator ALLMTD [QI HI SI SF DI DF])
+(define_mode_iterator DOUBLE [DI DF])
+(define_mode_iterator SHORT  [QI HI])
+
+(define_mode_attr tIsa      [(QI "b") (HI "w") (SI "d") (SF "d")])
+
+(define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
+(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
+
+(define_mode_attr IJK       [(QI "I") (HI "J") (SI "K")])
+(define_mode_attr iF        [(QI "i") (HI "i") (SI "i") (SF "F")])
+(define_mode_attr iFD       [(DI "i") (DF "F")])
+(define_mode_attr LL        [(QI "L") (HI "L")])
+
+(define_mode_attr shImmBits	[(QI "3") (HI "4") (SI "5")])
+
+; In QI mode we push 2 bytes instead of 1 byte.
+(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
+; tpush will be used to generate the 'number of registers to push' in the 
+; push instruction.
+(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
+
+
+;;  Code Macro Definitions
+
+(define_code_iterator sz_xtnd [ sign_extend       zero_extend])
+(define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
+(define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
+(define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
+(define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
+
+(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
+
+;;  Bit Set/Clear Instructions
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "memory_operand" "")
+		      (match_operand 1 "immediate_operand" "")
+		      (match_operand 2 "immediate_operand" ""))
+	(match_operand 3 "immediate_operand" ""))]
+  "TARGET_BIT_OPS"
+  {
+    if (INTVAL (operands[1]) != 1)
+      FAIL;
+    if (INTVAL (operands[3]) < 0 || INTVAL (operands[3]) > 15)
+      FAIL;
+    if (INTVAL (operands[3]) == 1)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_set_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	   emit_insn (gen_set_bithi (operands[0], operands[2]));
+	   DONE;
+	  }
+      }
+    if (INTVAL (operands[3]) == 0)
+      {
+	if (GET_MODE (operands[0]) == QImode)
+	  {
+	    emit_insn (gen_clr_bitqi (operands[0], operands[2]));
+	    DONE;
+	  }
+	else if (GET_MODE (operands[0]) == HImode)
+	  {
+	    emit_insn (gen_clr_bithi (operands[0], operands[2]));
+	    DONE;
+	  }
+      }
+  }
+)
+
+;;; In operand %s1, 's' will be evaluated to bit number to set
+(define_insn "set_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 1))]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "clr_bit<mode>"
+  [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
+			    (const_int 1)
+			    (match_operand 1 "immediate_operand" "i"))
+	(const_int 0))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t%1,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "set_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")
+	(ior:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "one_bit_operand" "i"))
+ )]
+  "TARGET_BIT_OPS"
+  "sbit<tIsa>\t$%s1,%0"
+  [(set_attr "length" "2")]
+)
+
+;; In operand %r1, 'r' will be evaluated to bit number to reset
+(define_insn "clear_bit<mode>_mem"
+  [(set (match_operand:SHORT 0 "bit_operand" "=mZ")
+	(and:SHORT (match_dup 0)
+		   (match_operand:SHORT 1 "rev_one_bit_operand" "i")))]
+  "TARGET_BIT_OPS"
+  "cbit<tIsa>\t$%r1,%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Addition Instructions
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "reg_operand" "")
+	(plus:DI (match_operand:DI 1 "reg_operand" "")
+		 (match_operand:DI 2 "reg_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG) )
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "adddi3_insn"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(plus:DI (match_operand:DI 1 "reg_operand" "%0")
+		 (match_operand:DI 2 "reg_operand" "r")))]
+  ""
+  "addd\t%L2,%L0\;addcw\t%M2,%M0\;addcw\t%H2,%H0"
+)
+
+(define_insn "add<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,r")
+	(plus:CR16IM (match_operand:CR16IM 1 "reg_operand" "%0,0")
+		     (match_operand:CR16IM 2 "nonmemory_operand" "r,i")))]
+  ""
+  "add<tIsa>\t%2, %0"
+)
+
+;;  Subtract Instructions
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "reg_operand" "")
+	(minus:DI (match_operand:DI 1 "reg_operand" "")
+		  (match_operand:DI 2 "reg_operand" "")))]
+  ""
+  {
+    if ((GET_CODE (operands[2]) != REG))
+      {
+	operands[2] = force_reg (DImode, operands[2]);
+      }
+  }
+)
+
+(define_insn "subdi3_insn"
+  [(set (match_operand:DI 0 "reg_operand" "=r,r")
+	(minus:DI (match_operand:DI 1 "reg_operand" "0,0")
+		  (match_operand:DI 2 "reg_operand" "r,i")))]
+  ""
+  "subd\t%L2,%L0\;subcw\t%M2,%M0\;subcw\t%H2,%H0"
+  [(set_attr "length" "8")]
+)
+
+(define_insn "sub<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,r")
+	(minus:CR16IM (match_operand:CR16IM 1 "reg_operand" "0,0")
+		      (match_operand:CR16IM 2 "nonmemory_operand" "r,i")))]
+  ""
+  "sub<tIsa>\t%2, %0"
+  [(set_attr "length" "2,<lImmArith>")]
+)
+
+;;  Multiply and Accumulate Instructions
+(define_insn "<sPat>madhisi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r")
+	(plus:SI (mult:SI (sz_xtnd:SI (match_operand:HI 1 "reg_operand" "%r"))
+			  (sz_xtnd:SI (match_operand:HI 2 "reg_operand" "r")))
+		 (match_operand:SI 3 "reg_operand" "0")))]
+  "TARGET_MAC"
+  "mac<sPat>w\t%1, %2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Multiply Instructions
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "reg_operand" "=r,=r")
+	(mult:HI (match_operand:HI 1 "register_and_valid_subreg_byte_operand" "%0,0")
+		 (match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "mulw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+; Only mulsb exists, therefore no use of mode and code macros
+(define_insn "mulqihi3"
+  [(set (match_operand:HI 0 "reg_operand" "=r")
+	(mult:HI (sign_extend:HI (match_operand:QI 1 "reg_operand" "%0"))
+		 (sign_extend:HI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "mulsb\t%2, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Logical Instructions - and
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(and:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "andhi3"
+  [(set (match_operand:HI 0 "reg_operand" "")
+	(and:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG 
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+
+(define_insn "andhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(and:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(and:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "andd\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T -  prints upper half
+;;U -  prints lower half
+(define_insn "anddi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(and:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "andd\t%T2,%T0\;andd\t%U2,%U0"
+)
+
+;;  Logical Instructions - or
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(ior:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "orb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "iorhi3"
+  [(set (match_operand:HI 0 "reg_operand" "")
+	(ior:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG 
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG 
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+
+(define_insn "iorhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(ior:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "orw\t%2, %0"
+  [(set_attr "length" "2,4")]
+) 
+
+(define_insn "iorsi3" 
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(ior:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "ord\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T - prints upper half
+;;U - prints lower half
+(define_insn "iordi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(ior:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "ord\t%T2,%T0\;ord\t%U2,%U0"
+)
+
+;;  Logical Instructions - xor
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "reg_operand" "=r,r")
+	(xor:QI (match_operand:QI 1 "reg_operand" "%0,0")
+		(match_operand:QI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "xorb\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_expand "xorhi3"
+  [(set (match_operand:HI 0 "reg_operand" "") 
+	(xor:HI (match_operand:HI 1 "reg_operand" "")
+		(match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if ((GET_CODE (operands[1]) == SUBREG
+       && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && (GET_CODE (operands[2]) == SUBREG
+       && REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER))
+    FAIL;
+}")
+ 
+(define_insn "xorhi3_1"
+  [(set (match_operand:HI 0 "reg_operand" "=r,r")
+	(xor:HI (match_operand:HI 1 "reg_operand" "%0,0")
+		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  ""
+  "xorw\t%2, %0"
+  [(set_attr "length" "2,4")]
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "reg_operand" "=r,r")
+	(xor:SI (match_operand:SI 1 "reg_operand" "%0,0")
+		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  ""   
+  "xord\t%2, %0"
+  [(set_attr "length" "2,6")]
+)
+
+;;T - prints upper half
+;;U - prints lower half
+(define_insn "xordi3"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(xor:DI (match_operand:DI 1 "reg_operand" "%0")
+		(match_operand:DI 2 "nonmemory_operand" "r")))]
+  ""
+  "xord\t%T2,%T0\;xord\t%U2,%U0"
+)
+
+;;  Sign and Zero Extend Instructions
+(define_insn "<szPat>extendhisi2"
+  [(set (match_operand:SI 0 "reg_operand" "=r")
+	(sz_xtnd:SI (match_operand:HI 1 "reg_operand" "r")))]
+  ""
+  "mov<szIsa>w\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "<szPat>extendqihi2"
+  [(set (match_operand:HI 0 "reg_operand" "=r")
+	(sz_xtnd:HI (match_operand:QI 1 "reg_operand" "r")))]
+  ""
+  "mov<szIsa>b\t%1, %0"
+  [(set_attr "length" "4")]
+)
+
+;;  One's Complement
+(define_insn "one_cmpldi2"
+  [(set (match_operand:DI 0 "reg_operand" "=r")
+	(not:DI (match_operand:DI 1 "reg_operand" "0")))]
+  ""
+  {
+     rtx xoperand ;
+     int reg0 = REGNO (operands[0]);
+
+     xoperand = gen_rtx_REG (SImode, reg0 + 2);
+     output_asm_insn ("xord\t$-1, %0", operands);
+     output_asm_insn ("xord\t$-1, %0", &xoperand);
+     return "" ;
+  }
+  [(set_attr "length" "12")]
+)
+
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(not:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")))]
+  ""
+  "xor<tIsa>\t$-1, %0"
+  [(set_attr "length" "2")]
+)
+
+;;  Arithmetic Left and Right Shift Instructions
+(define_insn "ashl<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r,=r")
+	(ashift:CR16IM (match_operand:CR16IM 1 "reg_operand" "0,0")
+		       (match_operand:QI 2 "nonmemory_operand" "r,<IJK>")))]
+  ""
+  "ashu<tIsa>\t%2, %0"
+  [(set_attr "length" "2,2")]
+)
+
+(define_expand "ashr<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if (GET_CODE (operands[2]) == CONST_INT)
+      {
+	/* If the constant is not in range, try placing it in a reg.  */
+	if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg (QImode, operands[2]);
+      }
+
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }
+)
+
+(define_insn "ashr<mode>3_imm_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (match_operand:QI 2 "shift_<mode>_imm_operand" "i")))]
+  ""
+  "ashu<tIsa>\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "ashr<mode>3_neg_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(ashiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (neg:QI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "ashu<tIsa>\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+(define_expand "lshr<mode>3"
+  [(set (match_operand:CR16IM 0 "reg_operand" "")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "")
+			 (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+  {
+    if (GET_CODE (operands[2]) == CONST_INT)
+      {
+	/* If the constant is not in range, try placing it in a reg.  */
+	if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (operands[2]),<shImmBits>))
+	  operands[2] = copy_to_mode_reg (QImode, operands[2]);
+      }
+
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }
+)
+
+(define_insn "lshr<mode>3_imm_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (match_operand:QI 2 "shift_<mode>_imm_operand" "i")))]
+  ""
+  "lsh<tIsa>\t$%n2, %0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "lshr<mode>3_neg_insn"
+  [(set (match_operand:CR16IM 0 "reg_operand" "=r")
+	(lshiftrt:CR16IM (match_operand:CR16IM 1 "reg_operand" "0")
+			 (neg:QI (match_operand:QI 2 "reg_operand" "r"))))]
+  ""
+  "lsh<tIsa>\t%2,%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Move Instructions
+
+;; Move any non-immediate operand 0 to a general operand 1.
+;; This applies only before starting the reload process
+;; Operand 0 is not a register operand of type mode MODE
+;; If Operand 0 is a push operand of type mode MODE
+;; then, if Operand 1 is a non-SP register
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; else
+;; if Operand 1 is either register or 4-bit immediate constant
+;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
+;; endif
+;; endif
+;;
+;; What does copy_to_mode_reg (mode, rtx val) do?
+;; Copy the value into new temp reg and return the reg where the
+;; mode of the new reg is always mode MODE when value is constant
+;;
+;; Why should copy_to_mode_reg be called?
+;; All sorts of move are nor supported by CR16. Therefore, 
+;; when unsupported move is encountered, the additional instructions 
+;; will be introduced for the purpose.
+;;
+;; A new move insn is inserted for Op 1 when one of the following
+;; conditions is met.
+;; Case 1:  Op 0 is push_operand
+;;          Op 1 is SP register
+;;
+;; Case 2:  Op 0 is not push_operand
+;;          Op 1 is neither register nor unsigned 4-bit immediate
+
+(define_expand "mov<mode>"
+  [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
+	(match_operand:ALLMTD 1 "gen_operand" ""))]
+  ""
+  {
+    if (!(reload_in_progress || reload_completed))
+      {
+	/* Only if Op0 is a register operand.  */
+	if (!register_operand (operands[0], <MODE>mode))
+	  {
+	    if (push_operand (operands[0], <MODE>mode)) 
+	      {
+		/* Use copy_to_mode_reg only if the register needs 
+		to be pushed is SP as CR16 does not support pushing SP.  */
+		if (!nosp_reg_operand (operands[1], <MODE>mode))
+		  operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+	      }
+	    else
+	      {
+		/* Use copy_to_mode_reg if op1 is not register operand
+		   subject to conditions inside.  */
+		if (!register_operand (operands[1], <MODE>mode))
+		  {
+		    /* CR16 does not support moving immediate to SI or SF 
+		       type memory.  */
+		    if (<MODE>mode == SImode || <MODE>mode == SFmode ||
+			<MODE>mode == DImode || <MODE>mode == DFmode)
+		      operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		    else
+		      /* moving imm4 is supported by CR16 instruction.  */
+		      if (!u4bits_operand (operands[1], <MODE>mode))
+			operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+		  }
+	       }
+	  }
+
+	  /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
+	  if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
+	    {
+	      operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
+	    }
+      }
+  }
+)
+
+; ALLMT     : QI,HI,SI,SF
+; pushCnstr : Push constraints 
+;                QI : X
+;             HI,SI,SF,DI,DF : <
+; b         : All non-sp registers
+; tpush     : Push count
+;                QI,HI : 1
+;                SI,SF : 2
+;                DI,DF : 4
+(define_insn "push<mode>_internal"
+  [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
+	(match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
+  ""
+  "push\t$<tpush>,%p1"
+  [(set_attr "length" "2")]
+)
+
+; (DI, DF) move
+(define_insn "*mov<mode>_double"
+  [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DOUBLE 1 "gen_operand" "r, <iFD>, m, r"))]
+  "register_operand (operands[0], DImode) 
+   || register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DImode)
+   || register_operand (operands[1], DFmode)"
+  {
+    if (0 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]);
+      int reg1 = REGNO (operands[1]);
+
+      xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+      xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
+      if ((reg1 + 2) != reg0)
+	{
+	  output_asm_insn ("movd\t%1, %0", operands);
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	}
+      else
+	{
+	  output_asm_insn ("movd\t%1, %0", xoperands);
+	  output_asm_insn ("movd\t%1, %0", operands);
+	}}
+
+    else if (1 == which_alternative) {
+      rtx lo_operands[2] ;
+      rtx hi_operands[2] ;
+
+      lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+      lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 0);
+      hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
+		       VOIDmode == GET_MODE (operands[1])
+		       ? DImode  : GET_MODE (operands[1]), 4);
+      output_asm_insn ("movd\t%1, %0", lo_operands);
+      output_asm_insn ("movd\t%1, %0", hi_operands);}
+
+    else if (2 == which_alternative) {
+      rtx xoperands[2] ;
+      int reg0 = REGNO (operands[0]), reg1 = -2 ;
+      rtx addr ;
+
+	if (MEM_P (operands[1]))
+	  addr = XEXP (operands[1], 0);
+	else
+	  addr = NULL_RTX ;
+	switch (GET_CODE (addr))
+	  {
+	    case REG:
+	    case SUBREG:
+	      reg1 = REGNO (addr);
+	      break ;
+	    case PLUS:
+	      switch (GET_CODE (XEXP (addr, 0))) {
+		case REG:
+		case SUBREG:
+		  reg1 = REGNO (XEXP (addr, 0));
+		  break ;
+		case PLUS:
+		  reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
+		  break ;
+		default:
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
+		  debug_rtx (addr);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
+		  debug_rtx (operands[1]);
+		  inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
+		  break ;}
+	      break ;
+	    default:
+	      break ;
+	  }
+
+	xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
+	xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
+	gcc_assert ((reg0 + 1) != reg1);
+	if (reg0 != reg1  &&  (reg1 + 1) != reg0)
+	  {
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	  }
+	else
+	  {
+	    output_asm_insn ("loadd\t%1, %0", xoperands);
+	    output_asm_insn ("loadd\t%1, %0", operands);
+	  }}
+    else
+      {
+	rtx xoperands[2] ;
+	xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
+	xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+	output_asm_insn ("stord\t%1, %0", operands);
+   	output_asm_insn ("stord\t%1, %0", xoperands);
+      }
+    return "" ;
+  }
+  [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
+)
+
+; All long (SI, SF) register move, load and store operations
+; The print_operand will take care of printing the register pair 
+; when mode is SI/SF and register is in SHORT_REGS
+(define_insn "*mov<mode>_long"
+  [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:LONG 1 "gen_operand" "r, <iF>, m, r"))]
+  "register_operand (operands[0], <MODE>mode)
+   || register_operand (operands[1], <MODE>mode)"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+; All short (QI, HI) register move, load and store operations
+(define_insn "*mov<mode>_short"
+  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
+	(match_operand:SHORT 1 "gen_operand" "r, <iF>, m, r, <LL>"))]
+  "(register_operand (operands[0], <MODE>mode))
+    || (store_operand (operands[0], <MODE>mode)
+	&& (register_operand (operands[1], <MODE>mode)
+	    || u4bits_operand (operands[1], <MODE>mode)))"
+  "@
+  mov<tIsa>\t%1, %0
+  mov<tIsa>\t%1, %0
+  load<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0
+  stor<tIsa>\t%1, %0"
+  [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
+)
+
+;;  Compare Instructions
+
+; Instruction generated compares the operands in reverse order
+; Therefore, while printing the asm, the reverse of the
+; compare condition shall be printed.
+(define_insn "cbranch<mode>4"
+  [(set (pc)
+	(if_then_else (match_operator 0 "ordered_comparison_operator"
+		      [(match_operand:CR16IM 1 "register_operand" "r,r")
+		       (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
+		       (label_ref (match_operand 3 "" ""))
+                      (pc)))
+   (clobber (cc0))]
+  ""
+  "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
+  [(set_attr "length" "6,6")]
+)
+
+(define_expand "cmp<mode>"
+  [(parallel [(set (cc0)
+    (compare (match_operand:CR16IM 0 "register_operand" "")
+	     (match_operand:CR16IM 1 "register_operand" "")))
+   (clobber (match_scratch:HI 2 "=r"))]) ]
+   ""
+   "")
+
+(define_insn "*cmp<mode>_insn"
+  [(set (cc0)
+	(compare (match_operand:CR16IM 0 "register_operand" "r,r")
+		 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))
+   (clobber (match_scratch:HI 2 "=r,r")) ]
+  ""                  
+  "cmp<tIsa>\t%1, %0"
+  [(set_attr "length" "2,4")]
+)
+
+;;  Jumps and Branches
+(define_insn "indirect_jump_return"
+  [(parallel
+    [(set (pc)
+	  (reg:SI RA_REGNUM))
+   (return)])
+  ]
+  "reload_completed"
+  "jump\t (ra)"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "indirect_jump"
+  [(set (pc)
+	(match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
+  ""
+  "@
+  jump\t%0
+  br\t%a0"
+  [(set_attr "length" "2,6")]
+)
+
+(define_insn "interrupt_return"
+  [(parallel
+    [(unspec_volatile [(const_int 0)] 0)
+   (return)])]
+  ""
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "14")]
+)
+
+(define_insn "jump_to_imm"
+  [(set (pc)
+	(match_operand 0 "jump_imm_operand" "i"))]
+  ""
+  "br\t%c0"
+  [(set_attr "length" "6")]
+)
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "br\t%l0"
+  [(set_attr "length" "6")]
+)
+
+;;  Function Prologue and Epilogue
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  {
+    cr16_expand_prologue ();
+    DONE;
+  }
+)
+
+(define_insn "push_for_prologue"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (minus:SI (reg:SI SP_REGNUM)
+		    (match_operand:SI 0 "immediate_operand" "i")))])]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (0);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  {
+    cr16_expand_epilogue ();
+    DONE;
+  }
+)
+
+(define_insn "pop_and_popret_return"
+  [(parallel
+    [(set (reg:SI SP_REGNUM)
+	  (plus:SI (reg:SI SP_REGNUM)
+		   (match_operand:SI 0 "immediate_operand" "i")))
+     (use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  {
+    return cr16_prepare_push_pop_string (1);
+  }
+  [(set_attr "length" "4")]
+)
+
+(define_insn "popret_RA_return"
+  [(parallel
+    [(use (reg:SI RA_REGNUM))
+     (return)])
+  ]
+  "reload_completed"
+  "popret\tra"
+  [(set_attr "length" "2")]
+)
+
+;;  Table Jump
+(define_insn "tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref:SI (match_operand 1 "" "")))]
+  "!flag_pic"
+  "jump\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Instructions
+
+(define_expand "call"
+  [(call (match_operand:QI 0 "memory_operand" "")
+	 (match_operand 1 "" ""))]
+  ""
+  {
+    if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
+      {
+	operands[0] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      }
+    else
+      emit_call_insn (gen_cr16_call (operands[0], operands[1]));
+      DONE;
+  }
+)
+
+(define_expand "cr16_call"
+  [(parallel
+    [(call (match_operand:QI 0 "memory_operand" "")
+	   (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_insn_branch_pic"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "loadd\t%g0, %2 \n\tjal %2";
+    else
+      return "jal %2";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_insn_branch"
+  [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[0]) != CONST_INT)
+      return "bal (ra), %a0";
+    else
+      return "bal (ra), %b0";
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_insn_jump"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	 (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "+r"))]
+  ""
+  "jal\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;  Call Value Instructions
+
+(define_expand "call_value"
+  [(set (match_operand 0 "general_operand" "")
+	(call (match_operand:QI 1 "memory_operand" "")
+	      (match_operand 2 "" "")))]
+  ""
+  {
+    if (flag_pic && !legitimate_pic_operand_p (operands[1]))
+      {
+	operands[1] = gen_const_mem (QImode,
+	legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+      }
+    else
+	emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cr16_call_value"
+  [(parallel
+    [(set (match_operand 0 "general_operand" "")
+	  (call (match_operand 1 "memory_operand" "")
+		(match_operand 2 "" "")))
+     (clobber (reg:SI RA_REGNUM))])]
+  ""
+  ""
+)
+
+(define_insn "cr16_call_value_insn_branch_pic"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == FAR_PIC"
+  {
+    if (GET_CODE (operands[1]) != CONST_INT)
+      return "loadd\t%g1, %3 \n\tjal %3";
+    else
+      return "jal %3";
+  }
+  [(set_attr "length" "8")]
+)
+
+(define_insn "cr16_call_value_insn_branch"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  "flag_pic == 0 || flag_pic == NEAR_PIC"
+  {
+    /* Print the immediate address for bal 
+       'b' is used instead of 'a' to avoid compiler calling
+       the GO_IF_LEGITIMATE_ADDRESS which cannot
+       perform checks on const_int code addresses as it
+       assumes all const_int are data addresses.
+    */
+    if (GET_CODE (operands[1]) != CONST_INT) 
+      return "bal (ra), %a1";
+    else
+      return "bal (ra), %b1";	
+  }
+  [(set_attr "length" "6")]
+)
+
+(define_insn "cr16_call_value_insn_jump"
+  [(set (match_operand 0 "" "=g")
+	(call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+	      (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "+r"))]
+  ""
+  "jal\t%1"
+  [(set_attr "length" "2")]
+)
+
+;;  Nop
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  ""
+)
+
+;; PIC
+                                                                                                                             
+/* When generating pic, we need to load the symbol offset into a register.
+   So that the optimizer does not confuse this with a normal symbol load
+   we use an unspec.  The offset will be loaded from a constant pool entry,
+   since that is the only type of relocation we can use.  */
+                                                                                                                            
+(define_insn "unspec_bro_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
+  ""
+  "movd \t%f1, %0"
+  [(set_attr "length" "4")]
+)
+                                                                                                                             
+                                                                                                                            
+(define_insn "unspec_got_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
+  ""
+  "loadd \t%g1, %0"
+  [(set_attr "length" "6")]
+)
+
+;; Shared FLAT
+(define_insn "unspec_library_offset"
+  [(const_int UNSPEC_LIBRARY_OFFSET)]
+  ""
+  "push \t$2, r0;\n\tmovd \t$__current_shared_library_r12_offset_, (r1,r0);\n\tloadd \t[r12]0(r1,r0), (r12);\n\tpop \t$2, r0\n\t"
+  [(set_attr "length" "12")]
+)
+
+(define_insn "unspec_sh_lib_push_r12"
+  [(const_int UNSPEC_SH_LIB_PUSH_R12)]
+  ""
+  "push \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "unspec_sh_lib_pop_r12"
+  [(const_int UNSPEC_SH_LIB_POP_R12)]
+  ""
+  "pop \t$2, r12"
+  [(set_attr "length" "2")]
+)
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16.opt mod/gcc/config/cr16/cr16.opt
--- orig/gcc/config/cr16/cr16.opt	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16.opt	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,59 @@
+; Options for the National Semiconductor CR16 port of the compiler.
+; Copyright (C) 2010 Free Software Foundation, Inc.
+; Contributed by KPIT Cummins Infosystems Limited.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+msim
+Target
+-msim   Use simulator runtime
+
+mbit-ops
+Target Report Mask(BIT_OPS)
+Generate SBIT, CBIT instructions
+
+mmac
+Target Report Mask(MAC)
+Support multiply accumulate instructions
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdata-model=
+Target RejectNegative JoinedOrMissing Var(cr16_data_model)
+Treat data references as near, far or medium. medium is default
+
+mcr16c
+Target RejectNegative Mask(CR16C)
+Generate code for CR16C architecture
+
+mcr16cplus
+Target RejectNegative InverseMask(CR16C,CR16CP)
+Generate code for CR16C+ architecture (Default)
+
+mint32
+Target RejectNegative Mask(INT32)
+Treat integers as 32-bit.
+
+mid-shared-library
+Target Report Mask(ID_SHARED_LIBRARY)
+Enabled ID based shared library
+
+mshared-library-id=
+Target RejectNegative Joined UInteger Var(cr16_library_id)
+ID of shared library to build
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/cr16-protos.h mod/gcc/config/cr16/cr16-protos.h
--- orig/gcc/config/cr16/cr16-protos.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/cr16-protos.h	2010-12-22 12:56:55.000000000 +0530
@@ -0,0 +1,110 @@
+/* Prototypes for exported functions defined in cr16.c
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CR16_PROTOS_H
+#define GCC_CR16_PROTOS_H
+
+/* Register usage.  */
+extern enum reg_class cr16_regno_reg_class (int);
+extern int cr16_hard_regno_mode_ok (int regno, enum machine_mode);
+
+/* Passing function arguments.  */
+extern int cr16_function_arg_regno_p (int);
+#ifdef TREE_CODE
+
+#ifdef RTX_CODE
+
+extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+
+#endif /* RTX_CODE.  */
+
+#endif /* TREE_CODE.  */
+
+/* Enumeration giving the various data models we support.  */
+enum data_model_type
+{
+  DM_DEFAULT,		/* Default data model (in CR16C/C+ - up to 16M).  */
+  DM_NEAR,		/* Near data model    (in CR16C/C+ - up to 1M).  */
+  DM_FAR,		/* Far data model     (in CR16C+   - up to 4G)
+			   (in CR16C    - up to 16M).  */
+  ILLEGAL_DM		/* Illegal data model.  */
+};
+
+#ifdef RTX_CODE
+
+/* Addressing Modes.  */
+struct cr16_address
+{
+  rtx base;	 	/* Base register: Any register or register pair.  */
+  rtx index;		/* Index register: If one is present.  */
+  rtx disp;		/* Displacement or Absolute address.  */
+  enum data_model_type data;	/* data ref type.  */
+  int code;		/* Whether the address is code address. 
+			   0 - data, 1 - code label, 2 - function label.  */
+};
+
+enum cr16_addrtype
+{
+  CR16_INVALID,
+  CR16_REG_REL,
+  CR16_REGP_REL,
+  CR16_INDEX_REGP_REL,
+  CR16_ABSOLUTE
+};
+
+extern void notice_update_cc PARAMS ((rtx));
+extern int cr16_operand_bit_pos (int val, int bitval);
+extern void cr16_decompose_const (rtx x, int *code,
+				  enum data_model_type *data,
+				  bool treat_as_const);
+extern enum cr16_addrtype cr16_decompose_address (rtx addr,
+						  struct cr16_address *out,
+						  bool debug_print,
+						  bool treat_as_const);
+extern int cr16_legitimate_address_p (enum machine_mode, rtx, int);
+extern int cr16_const_double_ok (rtx op);
+extern int legitimate_pic_operand_p (rtx);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+
+/* Instruction output.  */
+extern void cr16_print_operand (FILE *, rtx, int);
+extern void cr16_print_operand_address (FILE *, rtx);
+extern void cr16_expand_movmem_single (rtx, rtx, rtx, rtx, rtx,
+				       unsigned HOST_WIDE_INT *);
+extern int cr16_expand_movmem (rtx, rtx, rtx, rtx);
+extern rtx got_operand (rtx, enum machine_mode);
+extern rtx bro_operand (rtx, enum machine_mode);
+
+#endif /* RTX_CODE.  */
+
+/* Routines to compute costs.  */
+extern int cr16_memory_move_cost (enum machine_mode, enum reg_class, int);
+
+/* Prologue/Epilogue functions.  */
+extern int cr16_initial_elimination_offset (int, int);
+extern char *cr16_prepare_push_pop_string (int);
+extern void cr16_expand_prologue (void);
+extern void cr16_expand_epilogue (void);
+
+/* Handling the "interrupt" attribute.  */
+extern int cr16_interrupt_function_p (void);
+extern bool cr16_is_data_model (enum data_model_type);
+
+#endif /* Not GCC_CR16_PROTOS_H.  */ 
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/crti.s mod/gcc/config/cr16/crti.s
--- orig/gcc/config/cr16/crti.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/crti.s	2010-12-22 12:57:16.000000000 +0530
@@ -0,0 +1,58 @@
+/* Specialized code needed to support construction and destruction of
+   file-scope objects in C++ and Java code, and to support exception handling.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+ 
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* This file just supplies function prologues for the .init and .fini
+   sections.  It is linked in before crtbegin.o.  */
+
+	.file   "crti.o"
+	.ident  "GNU C crti.o"
+
+	.section .init
+	.globl  __init
+	.type   __init,@function
+__init:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+
+	.section .fini
+	.globl  __fini
+	.type   __fini,@function
+__fini:
+#if defined (__ID_SHARED_LIB__)
+	push	$2, r12, ra
+	movd    $__current_shared_library_r12_offset_, (r1,r0)
+	loadd   [r12]0(r1,r0), (r12)
+#else
+        push	ra
+#endif
+	
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/crtlibid.s mod/gcc/config/cr16/crtlibid.s
--- orig/gcc/config/cr16/crtlibid.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/crtlibid.s	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,32 @@
+/* Provide a weak definition of the library ID, for the benefit of certain
+   configure scripts.	 
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+ 
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+	.file   "crtlibid.o"
+	.ident  "GNU C crtlibid.o"
+
+.weak __current_shared_library_r12_offset_
+.set __current_shared_library_r12_offset_, 0
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/crtn.s mod/gcc/config/cr16/crtn.s
--- orig/gcc/config/cr16/crtn.s	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/crtn.s	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,47 @@
+/* Specialized code needed to support construction and destruction of
+   file-scope objects in C++ and Java code, and to support exception handling.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+ 
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* This file supplies function epilogues for the .init and .fini sections.
+  It is linked in after all other files.  */
+
+	.file   "crtn.o"
+	.ident  "GNU C crtn.o"
+
+	.section .init
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
+	.section .fini
+#if defined (__ID_SHARED_LIB__)
+	popret	$2, r12, ra
+#else
+	popret	ra
+#endif
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/divmodhi3.c mod/gcc/config/cr16/divmodhi3.c
--- orig/gcc/config/cr16/divmodhi3.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/divmodhi3.c	2010-12-22 12:56:31.000000000 +0530
@@ -0,0 +1,110 @@
+/* Libgcc Target specific implementation - Emulating div and mod.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by KPIT Cummins Infosystems Limited.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+	 
+
+/* Emulate the division and modulus operation.  */
+
+unsigned short
+udivmodhi4 (unsigned short num, unsigned short den, short modwanted)
+{
+  unsigned short bit = 1;
+  unsigned short res = 0;
+
+  while (den < num && bit && !(den & (1 << 15)))
+    {
+      den <<= 1;
+      bit <<= 1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>= 1;
+      den >>= 1;
+    }
+
+  if (modwanted)
+    return num;
+  return res;
+}
+
+short
+__divhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__modhi3 (short a, short b)
+{
+  short neg = 0;
+  short res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+short
+__udivhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+short
+__umodhi3 (short a, short b)
+{
+  return udivmodhi4 (a, b, 1);
+}
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/predicates.md mod/gcc/config/cr16/predicates.md
--- orig/gcc/config/cr16/predicates.md	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/predicates.md	2010-12-22 12:54:56.000000000 +0530
@@ -0,0 +1,191 @@
+;; Predicates of machine description for CR16.
+;; Copyright (C) 2010 Free Software Foundation, Inc.
+;; Contributed by KPIT Cummins Infosystems Limited.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  
+
+
+;;  Predicates
+
+;; Equality operator
+(define_special_predicate "equality_operator"
+  (match_code "eq,ne"))
+
+;; Zero operand
+(define_predicate "zero_operand"
+  (match_code "const_int")
+{
+  HOST_WIDE_INT value = INTVAL (op);
+  return value == 0;
+})
+
+(define_predicate "bit_operand"
+  (match_code "mem")
+{
+  return ((GET_CODE (op) == MEM && OK_FOR_Z (op)));
+})
+
+;; Register operand to avoid subreg with offset byte offset 2 
+(define_predicate "reg_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE(op) == SUBREG
+      && (REGNO(SUBREG_REG(op)) > 11
+          && REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+      && SUBREG_BYTE(op) != 0)
+    return 0;    
+    return 1;
+})
+
+;; General operand to avoid subreg with offset byte offset 2 
+(define_predicate "gen_operand"
+  (match_operand 0 "general_operand")
+{
+  if (GET_CODE(op) == SUBREG
+      && (REGNO(SUBREG_REG(op)) > 11
+          && REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+      && SUBREG_BYTE(op) != 0)
+    return 0;    
+    return 1;
+})
+
+;; Unsigned 4-bits constant int or double value.
+(define_predicate "u4bits_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    return cr16_const_double_ok (op);
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
+})
+
+;; Immediate operand predicate for count in shift operations.
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a qi mode operand.
+(define_predicate "shift_qi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 3)) ? 1 : 0;
+})
+
+;; Immediate shall be 4-bits in case operand to be operated on
+;; is a hi mode operand.
+(define_predicate "shift_hi_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
+})
+
+;; Immediate shall be 3-bits in case operand to be operated on
+;; is a si mode operand.
+(define_predicate "shift_si_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 5)) ? 1 : 0;
+})
+
+;; Jump immediate cannot be more than 24-bits
+(define_predicate "jump_imm_operand"
+  (match_code "const_int")
+{
+  return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 24)) ? 1 : 0;
+})
+
+;; Call immediate cannot be more than 24-bits
+(define_predicate "call_imm_operand"
+  (match_operand 0 "immediate_operand")
+{
+  if (GET_CODE (op) != CONST_INT) return 1;
+    return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 24)) ? 1 : 0;
+})
+
+;; CR16C/C+ does not have capability to address
+;; higher bytes of a register. Therefore, reject a register
+;; operand that has non-zero subreg byte
+(define_predicate "register_and_valid_subreg_byte_operand"
+  (match_operand 0 "register_operand")
+{
+  if ((GET_CODE(op) == SUBREG)
+       && (REGNO(SUBREG_REG(op)) < FIRST_PSEUDO_REGISTER)
+       && (SUBREG_BYTE(op) != 0))
+    return 0;
+    return 1;
+})
+
+;; Operand is register or 4-bit immediate operand
+(define_predicate "reg_or_u4bits_operand"
+  (ior (match_operand 0 "u4bits_operand")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a register or symbol reference
+(define_predicate "reg_or_sym_operand"
+  (ior (match_code "symbol_ref")
+       (match_operand 0 "register_operand")))
+
+;; Operand is a non stack pointer register
+(define_predicate "nosp_reg_operand"
+  (and (match_operand 0 "register_operand")
+       (match_test "REGNO (op) != SP_REGNUM")))
+
+;; Operand is a memory reference and
+;; not a push operand.
+(define_predicate "store_operand"
+  (and (match_operand 0 "memory_operand")
+       (not (match_operand 0 "push_operand"))))
+
+;; Operand is a constant integer where
+;; only one bit is set to 1.
+(define_predicate "one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = INTVAL (op);
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+;; Operand is a constant integer where
+;; only one bit is set to 0.
+(define_predicate "rev_one_bit_operand"
+  (match_code "const_int")
+{
+  unsigned int val;
+
+  val = ~INTVAL (op); /* Invert and use.  */
+  if (mode == QImode) 
+    val &= 0xff;
+  else if (mode == HImode)
+    val &= 0xffff;
+  else
+    gcc_unreachable();
+
+  if (val != 0)
+    return (val & (val - 1)) == 0; /* true if only one bit is set.  */
+  else
+    return 0;
+})
+
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/t-cr16 mod/gcc/config/cr16/t-cr16
--- orig/gcc/config/cr16/t-cr16	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/t-cr16	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,73 @@
+# CR16 Target Makefile
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# Contributed by KPIT Cummins Infosystems Limited.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.     
+
+LIB1ASMSRC = cr16/cr16-libgcc.s
+LIB1ASMFUNCS =	_mulsi3 _lshrdi3 _muldi3 _divdi3 _udivdi3 _udivmoddi3 \
+		_umoddi3 _moddi3
+
+LIB2FUNCS_EXTRA = \
+	$(srcdir)/config/cr16/divmodhi3.c  \
+	$(srcdir)/config/udivmodsi4.c \
+	$(srcdir)/config/udivmod.c   \
+	$(srcdir)/config/divmod.c 
+
+LIB2ADDEH = $(srcdir)/config/cr16/unwind-dw2-cr16.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-c.c
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+
+$(T)crti.o: $(srcdir)/config/cr16/crti.s $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	  -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/cr16/crti.s
+
+$(T)crtn.o: $(srcdir)/config/cr16/crtn.s $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	  -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/cr16/crtn.s
+
+$(T)crtlibid.o: $(srcdir)/config/cr16/crtlibid.s $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	  -c -o $(T)crtlibid.o \
+	  -x assembler-with-cpp $(srcdir)/config/cr16/crtlibid.s
+
+MULTILIB_OPTIONS     = fPIC mint32 mid-shared-library
+MULTILIB_DIRNAMES    = far-pic int32 mid-shared-library
+MULTILIB_EXCEPTIONS  = fno-PIC/mid-shared-library
+MULTILIB_MATCHES     =
+MULTILIB_EXTRA_OPTS  = mcr16cplus mdata-model=far
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# We want fine grained libraries, so use the new code.
+# to build the floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#define SMALL_MACHINE' >> fp-bit.c
+	echo '#define CMPtype HItype' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define SMALL_MACHINE' >> dp-bit.c
+	echo '#define CMPtype HItype' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/unwind-dw2-cr16.c mod/gcc/config/cr16/unwind-dw2-cr16.c
--- orig/gcc/config/cr16/unwind-dw2-cr16.c	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2-cr16.c	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,1597 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2008, 2009, 2010  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
+#endif
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  void *reg[DWARF_FRAME_REGISTERS+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[DWARF_FRAME_REGISTERS+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+  unsigned u2 __attribute__ ((mode (HI)));
+  unsigned u4 __attribute__ ((mode (SI)));
+  unsigned u8 __attribute__ ((mode (DI)));
+  signed s2 __attribute__ ((mode (HI)));
+  signed s4 __attribute__ ((mode (SI)));
+  signed s8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+
+static inline int
+read_1u (const void *p) { return *(const unsigned char *) p; }
+
+static inline int
+read_1s (const void *p) { return *(const signed char *) p; }
+
+static inline int
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
+
+static inline int
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
+
+static inline unsigned int
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
+
+static inline int
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
+
+static inline unsigned long
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
+
+static inline unsigned long
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return context->flags & EXTENDED_CONTEXT_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  void *ptr;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  ptr = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) ptr;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) ptr;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+      return;
+    }
+  ptr = context->reg[index];
+    if ( size == sizeof(_Unwind_Word) )
+      * (_Unwind_Word *) ptr = val;
+    else {
+      typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
+      gcc_assert (index + 1  <  (int) sizeof(dwarf_reg_size_table));
+      * (_CR16_Unwind_Word *) ptr = val & 0xffff ;  /* low 16-bit.  */
+      ptr = context->reg[index + 1];
+      * (_CR16_Unwind_Word *) ptr = val >> 16 ;  /* high 16-bit.  */
+         }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+		    _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
+
+  context->by_value[index] = 1;
+  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+#endif
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* Immediately following the augmentation are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
+   onto the stack to start.  */
+
+static _Unwind_Word
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
+		  struct _Unwind_Context *context, _Unwind_Word initial)
+{
+  _Unwind_Word stack[64];	/* ??? Assume this is enough.  */
+  int stack_elt;
+
+  stack[0] = initial;
+  stack_elt = 1;
+
+  while (op_ptr < op_end)
+    {
+      enum dwarf_location_atom op = *op_ptr++;
+      _Unwind_Word result;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      switch (op)
+	{
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	  result = op - DW_OP_lit0;
+	  break;
+
+	case DW_OP_addr:
+	  result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
+	  op_ptr += sizeof (void *);
+	  break;
+
+	case DW_OP_GNU_encoded_addr:
+	  {
+	    _Unwind_Ptr presult;
+	    op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+	    result = presult;
+	  }
+	  break;
+
+	case DW_OP_const1u:
+	  result = read_1u (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const1s:
+	  result = read_1s (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const2u:
+	  result = read_2u (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const2s:
+	  result = read_2s (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const4u:
+	  result = read_4u (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const4s:
+	  result = read_4s (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const8u:
+	  result = read_8u (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_const8s:
+	  result = read_8s (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_constu:
+	  op_ptr = read_uleb128 (op_ptr, &utmp);
+	  result = (_Unwind_Word)utmp;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &stmp);
+	  result = (_Unwind_Sword)stmp;
+	  break;
+
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+	  result = _Unwind_GetGR (context, op - DW_OP_reg0);
+	  break;
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  result = _Unwind_GetGR (context, reg);
+	  break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+	  break;
+	case DW_OP_bregx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+	  break;
+
+	case DW_OP_dup:
+	  gcc_assert (stack_elt);
+	  result = stack[stack_elt - 1];
+	  break;
+
+	case DW_OP_drop:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+	  goto no_push;
+
+	case DW_OP_pick:
+	  offset = *op_ptr++;
+	  gcc_assert (offset < stack_elt - 1);
+	  result = stack[stack_elt - 1 - offset];
+	  break;
+
+	case DW_OP_over:
+	  gcc_assert (stack_elt >= 2);
+	  result = stack[stack_elt - 2];
+	  break;
+
+	case DW_OP_swap:
+	  {
+	    _Unwind_Word t;
+	    gcc_assert (stack_elt >= 2);
+	    t = stack[stack_elt - 1];
+	    stack[stack_elt - 1] = stack[stack_elt - 2];
+	    stack[stack_elt - 2] = t;
+	    goto no_push;
+	  }
+
+	case DW_OP_rot:
+	  {
+	    _Unwind_Word t1, t2, t3;
+
+	    gcc_assert (stack_elt >= 3);
+	    t1 = stack[stack_elt - 1];
+	    t2 = stack[stack_elt - 2];
+	    t3 = stack[stack_elt - 3];
+	    stack[stack_elt - 1] = t2;
+	    stack[stack_elt - 2] = t3;
+	    stack[stack_elt - 3] = t1;
+	    goto no_push;
+	  }
+
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	case DW_OP_abs:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_plus_uconst:
+	  /* Unary operations.  */
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  result = stack[stack_elt];
+
+	  switch (op)
+	    {
+	    case DW_OP_deref:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		result = (_Unwind_Ptr) read_pointer (ptr);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		switch (*op_ptr++)
+		  {
+		  case 1:
+		    result = read_1u (ptr);
+		    break;
+		  case 2:
+		    result = read_2u (ptr);
+		    break;
+		  case 4:
+		    result = read_4u (ptr);
+		    break;
+		  case 8:
+		    result = read_8u (ptr);
+		    break;
+		  default:
+		    gcc_unreachable ();
+		  }
+	      }
+	      break;
+
+	    case DW_OP_abs:
+	      if ((_Unwind_Sword) result < 0)
+		result = -result;
+	      break;
+	    case DW_OP_neg:
+	      result = -result;
+	      break;
+	    case DW_OP_not:
+	      result = ~result;
+	      break;
+	    case DW_OP_plus_uconst:
+	      op_ptr = read_uleb128 (op_ptr, &utmp);
+	      result += (_Unwind_Word)utmp;
+	      break;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_le:
+	case DW_OP_ge:
+	case DW_OP_eq:
+	case DW_OP_lt:
+	case DW_OP_gt:
+	case DW_OP_ne:
+	  {
+	    /* Binary operations.  */
+	    _Unwind_Word first, second;
+	    gcc_assert (stack_elt >= 2);
+	    stack_elt -= 2;
+
+	    second = stack[stack_elt];
+	    first = stack[stack_elt + 1];
+
+	    switch (op)
+	      {
+	      case DW_OP_and:
+		result = second & first;
+		break;
+	      case DW_OP_div:
+		result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+		break;
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		result = second % first;
+		break;
+	      case DW_OP_mul:
+		result = second * first;
+		break;
+	      case DW_OP_or:
+		result = second | first;
+		break;
+	      case DW_OP_plus:
+		result = second + first;
+		break;
+	      case DW_OP_shl:
+		result = second << first;
+		break;
+	      case DW_OP_shr:
+		result = second >> first;
+		break;
+	      case DW_OP_shra:
+		result = (_Unwind_Sword) second >> first;
+		break;
+	      case DW_OP_xor:
+		result = second ^ first;
+		break;
+	      case DW_OP_le:
+		result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ge:
+		result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_eq:
+		result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+		break;
+	      case DW_OP_lt:
+		result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+		break;
+	      case DW_OP_gt:
+		result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ne:
+		result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  }
+	  break;
+
+	case DW_OP_skip:
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_bra:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  if (stack[stack_elt] != 0)
+	    op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_nop:
+	  goto no_push;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* Decode DWARF 2 call frame information. Takes pointers the
+   instruction sequence to decode, current register information and
+   CIE info, and the PC range to evaluate.  */
+
+static void
+execute_cfa_program (const unsigned char *insn_ptr,
+		     const unsigned char *insn_end,
+		     struct _Unwind_Context *context,
+		     _Unwind_FrameState *fs)
+{
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
+	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
+	      (_Unwind_Word)reg2;
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
+
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_VAL_EXP;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_GNU_window_save:
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  for (reg = 16; reg < 32; ++reg)
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	    }
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+	    = REG_SAVED_OFFSET;
+	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#else
+      return _URC_END_OF_STACK;
+#endif
+    }
+
+  fs->pc = context->bases.func;
+
+  cie = get_cie (fde);
+  insn = extract_cie_info (cie, context, fs);
+  if (insn == NULL)
+    /* CIE contained unknown augmentation.  */
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* First decode all the insns in the CIE.  */
+  end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  context.flags = EXTENDED_CONTEXT_BIT;
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
+
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+	{
+	case REG_SAVED_REG:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+	  break;
+	default:
+	  state_in->reg_or_offset[reg] = 0;
+	  break;
+	}
+    }
+
+  state_in->cfa_offset = fs.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+		     _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef EH_RETURN_STACKADJ_RTX
+  /* Special handling here: Many machines do not use a frame pointer,
+     and track the CFA only through offsets from the stack pointer from
+     one frame to the next.  In this case, the stack pointer is never
+     stored, so it has no saved address in the context.  What we do
+     have is the CFA from the previous stack frame.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+	const unsigned char *exp = fs->regs.cfa_exp;
+	_uleb128_t len;
+
+	exp = read_uleb128 (exp, &len);
+	cfa = (void *) (_Unwind_Ptr)
+	  execute_stack_op (exp, exp + len, &orig_context, 0);
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  context->cfa = cfa;
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
+    switch (fs->regs.reg[i].how)
+      {
+      case REG_UNSAVED:
+      case REG_UNDEFINED:
+	break;
+
+      case REG_SAVED_OFFSET:
+	_Unwind_SetGRPtr (context, i,
+			  (void *) (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_REG:
+	if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+	  _Unwind_SetGRValue (context, i,
+			      _Unwind_GetGR (&orig_context,
+					     fs->regs.reg[i].loc.reg));
+	else
+	  _Unwind_SetGRPtr (context, i,
+			    _Unwind_GetGRPtr (&orig_context,
+					      fs->regs.reg[i].loc.reg));
+	break;
+
+      case REG_SAVED_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRPtr (context, i, (void *) val);
+	}
+	break;
+
+      case REG_SAVED_VAL_OFFSET:
+	_Unwind_SetGRValue (context, i,
+			    (_Unwind_Internal_Ptr)
+			    (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_VAL_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRValue (context, i, val);
+	}
+	break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+    context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      /* Do any necessary initialization to access arbitrary stack frames. \
+	 On the SPARC, this means flushing the register windows.  */	   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context,
+		   void *outer_cfa, void *outer_ra)
+{
+  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  _Unwind_FrameState fs;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#if __GTHREADS
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
+	&& dwarf_reg_size_table[0] == 0)
+      init_dwarf_reg_size_table ();
+  }
+#else
+  if (dwarf_reg_size_table[0] == 0)
+    init_dwarf_reg_size_table ();
+#endif
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.cfa_offset -= context->args_size ;
+  uw_update_context_1 (context, &fs);
+
+  /* If the return address column was saved in a register in the
+     initialization context, then we can't see it in the given
+     call frame data.  So have the initialization context tell us.  */
+  context->ra = __builtin_extract_return_addr (outer_ra);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+  asm ("");
+}
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+
+#define uw_install_context(CURRENT, TARGET)                              \
+  do                                                                     \
+    {                                                                    \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
+      handler = (void*)( ( (unsigned)handler ) >> 1 ) ;                  \
+      __builtin_eh_return (offset, handler);                             \
+    }                                                                    \
+  while (0)
+
+
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+	{
+	  _Unwind_Word w;
+	  _Unwind_Ptr p;
+	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	    {
+	      w = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &w, sizeof (_Unwind_Word));
+	    }
+	  else
+	    {
+	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      p = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &p, sizeof (_Unwind_Ptr));
+	    }
+	}
+      else if (t && c && t != c)
+	memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
+      if (STACK_GROWS_DOWNWARD)
+	return target_cfa - current->cfa + target->args_size;
+      else
+	return current->cfa - target_cfa - target->args_size;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (STACK_GROWS_DOWNWARD)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config/cr16/unwind-dw2.h mod/gcc/config/cr16/unwind-dw2.h
--- orig/gcc/config/cr16/unwind-dw2.h	1970-01-01 05:30:00.000000000 +0530
+++ mod/gcc/config/cr16/unwind-dw2.h	2010-12-21 18:56:46.000000000 +0530
@@ -0,0 +1,87 @@
+/* DWARF2 frame unwind data structure.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* A target can override (perhaps for backward compatibility) how
+   many dwarf2 columns are unwound.  */
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* The result of interpreting the frame unwind info for a frame.
+   This is all symbolic at this point, as none of the values can
+   be resolved until the target pc is located.  */
+typedef struct
+{
+  /* Each register save state can be described in terms of a CFA slot,
+     another register, or a location expression.  */
+  struct frame_state_reg_info
+  {
+    struct {
+      union {
+	_Unwind_Word reg;
+	_Unwind_Sword offset;
+	const unsigned char *exp;
+      } loc;
+      enum {
+	REG_UNSAVED,
+	REG_SAVED_OFFSET,
+	REG_SAVED_REG,
+	REG_SAVED_EXP,
+	REG_SAVED_VAL_OFFSET,
+	REG_SAVED_VAL_EXP,
+	REG_UNDEFINED
+      } how;
+    } reg[DWARF_FRAME_REGISTERS+1];
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct frame_state_reg_info *prev;
+
+    /* The CFA can be described in terms of a reg+offset or a
+       location expression.  */
+    _Unwind_Sword cfa_offset;
+    _Unwind_Word cfa_reg;
+    const unsigned char *cfa_exp;
+    enum {
+      CFA_UNSET,
+      CFA_REG_OFFSET,
+      CFA_EXP
+    } cfa_how;
+  } regs;
+
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Sword data_align;
+  _Unwind_Word code_align;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+} _Unwind_FrameState;
+
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/config.gcc mod/gcc/config.gcc
--- orig/gcc/config.gcc	2010-12-21 19:58:41.000000000 +0530
+++ mod/gcc/config.gcc	2010-12-21 18:56:46.000000000 +0530
@@ -926,6 +926,12 @@ bfin*-*)
 	use_collect2=no
 	use_gcc_stdint=wrap
 	;;
+cr16-*-elf)
+        tm_file="elfos.h ${tm_file}"
+        tmake_file="${tmake_file} cr16/t-cr16 "
+        extra_parts="crtbegin.o crtend.o"
+        use_collect2=no
+        ;;
 crisv32-*-elf | crisv32-*-none)
 	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
 	tmake_file="cris/t-cris"
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/extend.texi mod/gcc/doc/extend.texi
--- orig/gcc/doc/extend.texi	2010-12-21 19:58:53.000000000 +0530
+++ mod/gcc/doc/extend.texi	2010-12-21 18:56:46.000000000 +0530
@@ -2545,7 +2545,7 @@ This attribute is ignored for R8C target
 
 @item interrupt
 @cindex interrupt handler functions
-Use this attribute on the ARM, AVR, CRX, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, CR16, CRX, M32C, M32R/D, m68k, MeP, MIPS,
 RX and Xstormy16 ports to indicate that the specified function is an
 interrupt handler.  The compiler will generate function entry and exit
 sequences suitable for use in an interrupt handler when this attribute
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/install.texi mod/gcc/doc/install.texi
--- orig/gcc/doc/install.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/install.texi	2010-12-21 18:56:46.000000000 +0530
@@ -3185,6 +3185,33 @@ is available at @uref{http://blackfin.uc
 @html
 <hr />
 @end html
+@heading @anchor{cr16}CR16
+
+The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is 
+used in embedded applications.
+
+@ifnothtml
+@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
+Collection (GCC)},
+@end ifnothtml
+
+@ifhtml
+See ``CR16 Options'' in the main manual for a list of CR16-specific options.
+@end ifhtml
+
+Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
+GCC@ for building a CR16 elf cross-compiler.
+
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
+GCC@ for building a CR16 uclinux cross-compiler.
+
+@html
+<hr />
+@end html
+
+@html
+<hr />
+@end html
 @heading @anchor{cris}CRIS
 
 CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/invoke.texi mod/gcc/doc/invoke.texi
--- orig/gcc/doc/invoke.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/invoke.texi	2010-12-21 18:56:46.000000000 +0530
@@ -500,6 +500,12 @@ Objective-C and Objective-C++ Dialects}.
 -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
 -mmul-bug-workaround  -mno-mul-bug-workaround}
 
+@emph{CR16 Options}
+@gccoptlist{-mmac @gol
+-mcr16cplus -mcr16c @gol
+-msim -mint32
+-mdata-model=@var{model}}
+
 @emph{CRX Options}
 @gccoptlist{-mmac -mpush-args}
 
@@ -9885,6 +9891,7 @@ platform.
 * AVR Options::
 * Blackfin Options::
 * CRIS Options::
+* CR16 Options::
 * CRX Options::
 * Darwin Options::
 * DEC Alpha Options::
@@ -10713,6 +10720,43 @@ Like @option{-sim}, but pass linker opti
 0x40000000 and zero-initialized data at 0x80000000.
 @end table
 
+@node CR16 Options
+@subsection CR16 Options
+@cindex CR16 Options
+
+These options are defined specifically for the CR16 ports.
+
+@table @gcctabopt
+
+@item -mmac
+@opindex mmac
+Enable the use of multiply-accumulate instructions. Disabled by default.
+
+@item -mcr16cplus
+@itemx -mcr16c
+@opindex mcr16cplus
+@opindex mcr16c
+Generate code for CR16C or CR16C+ architecture. CR16C+ architecture 
+is default.
+
+@item -msim
+@opindex msim
+Links the library libsim.a which is in compatible with simulator. Applicable
+to elf compiler only.
+
+@item -mint32
+@opindex mint32
+Choose integer type as 32-bit wide.
+
+@item -mdata-model=@var{model}
+@opindex mdata-model
+Choose a data model. The choices for @var{model} are @samp{near}, 
+@samp{far} or @samp{medium}. @samp{medium} is default.
+However, @samp{far} is not valid when -mcr16c option is chosen as
+CR16C architecture does not support far data model.
+@end table
+
+
 @node CRX Options
 @subsection CRX Options
 @cindex CRX Options
diff -uprN -x'*.orig' -x'*.rej' orig/gcc/doc/md.texi mod/gcc/doc/md.texi
--- orig/gcc/doc/md.texi	2010-12-21 19:58:52.000000000 +0530
+++ mod/gcc/doc/md.texi	2010-12-21 18:56:46.000000000 +0530
@@ -1775,6 +1775,40 @@ Integer constant in the range @minus{}6 
 A memory address based on Y or Z pointer with displacement.
 @end table
 
+@item CR16 Architecture---@file{config/cr16/cr16.h}
+@table @code
+
+@item b
+Registers from r0 to r14 (registers without stack pointer)
+
+@item t
+Register from r0 to r11 (all 16-bit registers)
+
+@item p
+Register from r12 to r15 (all 32-bit registers)
+
+@item I
+Signed constant that fits in 4 bits
+
+@item J
+Signed constant that fits in 5 bits
+
+@item K
+Signed constant that fits in 6 bits
+
+@item L
+Unsigned constant that fits in 4 bits
+
+@item M
+Signed constant that fits in 32 bits
+
+@item N
+Check for 64 bits wide constants for add/sub instructions
+
+@item G
+Floating point constant that is legal for store immediate
+@end table
+
 @item CRX Architecture---@file{config/crx/crx.h}
 @table @code
 
diff -uprN -x'*.orig' -x'*.rej' orig/libgcc/config.host mod/libgcc/config.host
--- orig/libgcc/config.host	2010-12-21 19:58:26.000000000 +0530
+++ mod/libgcc/config.host	2010-12-21 18:56:46.000000000 +0530
@@ -250,6 +250,9 @@ cris-*-linux* | crisv32-*-linux*)
 	;;
 crx-*-elf)
 	;;
+cr16-*-elf)
+        tmake_file="${tmake_file} cr16/t-cr16"
+        ;;
 fido-*-elf)
 	;;
 fr30-*-elf)
diff -uprN -x'*.orig' -x'*.rej' orig/libstdc++-v3/configure mod/libstdc++-v3/configure
--- orig/libstdc++-v3/configure	2010-12-21 20:00:22.000000000 +0530
+++ mod/libstdc++-v3/configure	2010-12-21 18:56:46.000000000 +0530
@@ -26431,6 +26431,9 @@ case "${host}" in
   arm*-*-symbianelf*)
     # This is a freestanding configuration; there is nothing to do here.
     ;;
+  
+  cr16-*-*)
+    ;;
 
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
diff -uprN -x'*.orig' -x'*.rej' orig/libstdc++-v3/crossconfig.m4 mod/libstdc++-v3/crossconfig.m4
--- orig/libstdc++-v3/crossconfig.m4	2010-12-21 20:00:21.000000000 +0530
+++ mod/libstdc++-v3/crossconfig.m4	2010-12-22 12:51:06.000000000 +0530
@@ -8,7 +8,10 @@ case "${host}" in
   arm*-*-symbianelf*)
     # This is a freestanding configuration; there is nothing to do here.
     ;;
-
+  cr16-*-*)
+    # SiTel
+    #     ;;
+ 
   mips*-sde-elf*)
     # These definitions are for the SDE C library rather than newlib.
     SECTION_FLAGS='-ffunction-sections -fdata-sections'

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-07-15  6:09 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-08 13:26 CR16 Port addition Sumanth Gundapaneni
2011-04-08 14:56 ` Joseph S. Myers
2011-05-20 13:59   ` Sumanth Gundapaneni
2011-05-20 17:07     ` Joseph S. Myers
2011-05-30 15:44       ` Sumanth Gundapaneni
2011-06-09 10:15       ` Sumanth Gundapaneni
2011-06-28  8:32       ` Sumanth Gundapaneni
2011-07-15  7:54       ` Sumanth Gundapaneni
  -- strict thread matches above, loose matches on Subject: below --
2011-01-13  9:06 Sumanth Gundapaneni
2011-01-14 18:54 ` Richard Henderson
2010-12-22 11:58 Sumanth Gundapaneni
2010-12-22 13:25 ` Joseph S. Myers
2010-12-29 15:32   ` Sumanth Gundapaneni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).