This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


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

[patch] New target "cr16" support added



Hello All,


I have added CompactRISC processor - CR16 architecture support to
Binutils 2.17.50 sources. Attached the patch file (File name: binutils-2.17.50-cr16.patch).


Please review and approve the above patch.


Configuring and Installing --------------------------

Go to the Binutils sources (after patching the above patch file) and do:

   > configure --target=cr16-elf
   > make all
   > make install

Testing Binutils for CR16
-------------------------

- The test cases for the CR16 architecture has been integrated into the DEJAGNU
  test suite, which will be posted later for approval.

Please visit the below link for more information on CR16 architecture:
http://www.national.com/appinfo/compactrisc/core_arch.html


Thanks, Swami
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/archures.c binutils-2.17.50-cr16/bfd/archures.c
*** binutils-2.17.50/bfd/archures.c	2007-04-26 20:16:55.000000000 +0530
--- binutils-2.17.50-cr16/bfd/archures.c	2007-06-26 14:52:08.000000000 +0530
*************** DESCRIPTION
*** 347,352 ****
--- 347,354 ----
  .#define bfd_mach_avr6		6
  .  bfd_arch_bfin,        {* ADI Blackfin *}
  .#define bfd_mach_bfin          1
+ .  bfd_arch_cr16,       {* National Semiconductor CompactRISC (ie CR16). *}
+ .#define bfd_mach_cr16		1
  .  bfd_arch_cr16c,       {* National Semiconductor CompactRISC. *}
  .#define bfd_mach_cr16c		1
  .  bfd_arch_crx,       {*  National Semiconductor CRX.  *}
*************** extern const bfd_arch_info_type bfd_arc_
*** 436,441 ****
--- 438,444 ----
  extern const bfd_arch_info_type bfd_arm_arch;
  extern const bfd_arch_info_type bfd_avr_arch;
  extern const bfd_arch_info_type bfd_bfin_arch;
+ extern const bfd_arch_info_type bfd_cr16_arch;
  extern const bfd_arch_info_type bfd_cr16c_arch;
  extern const bfd_arch_info_type bfd_cris_arch;
  extern const bfd_arch_info_type bfd_crx_arch;
*************** static const bfd_arch_info_type * const 
*** 506,511 ****
--- 509,515 ----
      &bfd_arm_arch,
      &bfd_avr_arch,
      &bfd_bfin_arch,
+     &bfd_cr16_arch,
      &bfd_cr16c_arch,
      &bfd_cris_arch,
      &bfd_crx_arch,
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/bfd-in2.h binutils-2.17.50-cr16/bfd/bfd-in2.h
*** binutils-2.17.50/bfd/bfd-in2.h	2007-05-11 08:40:11.000000000 +0530
--- binutils-2.17.50-cr16/bfd/bfd-in2.h	2007-06-26 14:52:08.000000000 +0530
*************** enum bfd_architecture
*** 2011,2016 ****
--- 2011,2018 ----
  #define bfd_mach_avr6          6
    bfd_arch_bfin,        /* ADI Blackfin */
  #define bfd_mach_bfin          1
+   bfd_arch_cr16,       /* National Semiconductor CompactRISC (ie CR16). */
+ #define bfd_mach_cr16          1
    bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
  #define bfd_mach_cr16c         1
    bfd_arch_crx,       /*  National Semiconductor CRX.  */
*************** This is the 5 bits of a value.  */
*** 4103,4108 ****
--- 4105,4138 ----
    BFD_RELOC_16C_IMM32,
    BFD_RELOC_16C_IMM32_C,
  
+ /* NS CR16 Relocations.  */
+   BFD_RELOC_CR16_NUM8,
+   BFD_RELOC_CR16_NUM16,
+   BFD_RELOC_CR16_NUM32,
+   BFD_RELOC_CR16_NUM32a,
+   BFD_RELOC_CR16_REGREL0,
+   BFD_RELOC_CR16_REGREL4,
+   BFD_RELOC_CR16_REGREL4a,
+   BFD_RELOC_CR16_REGREL14,
+   BFD_RELOC_CR16_REGREL14a,
+   BFD_RELOC_CR16_REGREL16,
+   BFD_RELOC_CR16_REGREL20,
+   BFD_RELOC_CR16_REGREL20a,
+   BFD_RELOC_CR16_ABS20,
+   BFD_RELOC_CR16_ABS24,
+   BFD_RELOC_CR16_IMM4,
+   BFD_RELOC_CR16_IMM8,
+   BFD_RELOC_CR16_IMM16,
+   BFD_RELOC_CR16_IMM20,
+   BFD_RELOC_CR16_IMM24,
+   BFD_RELOC_CR16_IMM32,
+   BFD_RELOC_CR16_IMM32a,
+   BFD_RELOC_CR16_DISP4,
+   BFD_RELOC_CR16_DISP8,
+   BFD_RELOC_CR16_DISP16,
+   BFD_RELOC_CR16_DISP24,
+   BFD_RELOC_CR16_DISP24a,
+ 
  /* NS CRX Relocations.  */
    BFD_RELOC_CRX_REL4,
    BFD_RELOC_CRX_REL8,
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/ChangeLog binutils-2.17.50-cr16/bfd/ChangeLog
*** binutils-2.17.50/bfd/ChangeLog	2007-05-18 05:55:03.000000000 +0530
--- binutils-2.17.50-cr16/bfd/ChangeLog	2007-06-26 13:41:47.000000000 +0530
***************
*** 1,3 ****
--- 1,28 ----
+ 2007-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+ 	* Makefile.am: Add cr16 related entry
+ 	* Makefile.in: Regenerate
+ 	* archures.c: Add bfd_cr16_arch
+ 	* bfd-in2.h: Regenerate
+ 	* config.bfd: Add cr16-elf
+ 	* configure.in: Add bfd_elf32_cr16_vec
+ 	* configure: Regenerate.
+ 	* targets.c: Added cr16 related information
+ 	* cpu-cr16.c: New file.
+ 	* elf32-cr16.c: New file.
+ 	* doc/archures.texi: Added cr16 related information
+ 	* doc/reloc.texi: Added cr16 related information
+ 	  BFD_RELOC_CR16_NUM8, BFD_RELOC_CR16_NUM16, BFD_RELOC_CR16_NUM32, 
+ 	  BFD_RELOC_CR16_NUM32a, BFD_RELOC_CR16_REGREL0, BFD_RELOC_CR16_REGREL4,
+ 	  BFD_RELOC_CR16_REGREL4a, BFD_RELOC_CR16_REGREL14, 
+ 	  BFD_RELOC_CR16_REGREL14a, BFD_RELOC_CR16_REGREL16, 
+ 	  BFD_RELOC_CR16_REGREL20, BFD_RELOC_CR16_REGREL20a, 
+ 	  BFD_RELOC_CR16_ABS20, BFD_RELOC_CR16_ABS24, BFD_RELOC_CR16_IMM4, 
+ 	  BFD_RELOC_CR16_IMM8, BFD_RELOC_CR16_IMM16, BFD_RELOC_CR16_IMM20, 
+ 	  BFD_RELOC_CR16_IMM24, BFD_RELOC_CR16_IMM32, BFD_RELOC_CR16_IMM32a, 
+ 	  BFD_RELOC_CR16_DISP4, BFD_RELOC_CR16_DISP8, BFD_RELOC_CR16_DISP16, 
+ 	  BFD_RELOC_CR16_DISP20,BFD_RELOC_CR16_DISP24 and BFD_RELOC_CR16_DISP24a
+ 
  2007-05-18  Paul Brook  <paul@codesourcery.com>
  
  	* elf32-arm.c (ARM2THUMB_V5_STATIC_GLUE_SIZE): Define.
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/config.bfd binutils-2.17.50-cr16/bfd/config.bfd
*** binutils-2.17.50/bfd/config.bfd	2007-04-21 10:31:22.000000000 +0530
--- binutils-2.17.50-cr16/bfd/config.bfd	2007-06-26 14:52:08.000000000 +0530
*************** bfin*)		 targ_archs=bfd_bfin_arch ;;
*** 76,81 ****
--- 76,82 ----
  c30*)		 targ_archs=bfd_tic30_arch ;;
  c4x*)		 targ_archs=bfd_tic4x_arch ;;
  c54x*)		 targ_archs=bfd_tic54x_arch ;;
+ cr16*)		 targ_archs=bfd_cr16_arch ;;
  crisv32)	 targ_archs=bfd_cris_arch ;;
  crx*)		 targ_archs=bfd_crx_arch ;;
  dlx*)		 targ_archs=bfd_dlx_arch ;;
*************** case "${targ}" in
*** 353,358 ****
--- 354,364 ----
      targ_underscore=yes
      ;;
  
+   cr16-*-elf*)
+     targ_defvec=bfd_elf32_cr16_vec
+     targ_underscore=yes
+     ;;
+ 
    cr16c-*-elf*)
      targ_defvec=bfd_elf32_cr16c_vec
      targ_underscore=yes
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/configure binutils-2.17.50-cr16/bfd/configure
*** binutils-2.17.50/bfd/configure	2007-04-24 09:35:03.000000000 +0530
--- binutils-2.17.50-cr16/bfd/configure	2007-06-26 14:52:08.000000000 +0530
*************** do
*** 13725,13730 ****
--- 13725,13731 ----
      bfd_elf32_bigmips_vec) 	tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
      bfd_elf32_bigmips_vxworks_vec)
  			 	tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+     bfd_elf32_cr16_vec)		tb="$tb elf32-cr16.lo elf32.lo $elf" ;;
      bfd_elf32_cr16c_vec)	tb="$tb elf32-cr16c.lo elf32.lo $elf" ;;
      bfd_elf32_cris_vec)		tb="$tb elf32-cris.lo elf32.lo $elf" ;;
      bfd_elf32_crx_vec)          tb="$tb elf32-crx.lo elf32.lo $elf" ;;
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/configure.in binutils-2.17.50-cr16/bfd/configure.in
*** binutils-2.17.50/bfd/configure.in	2007-04-24 09:35:03.000000000 +0530
--- binutils-2.17.50-cr16/bfd/configure.in	2007-06-26 14:52:08.000000000 +0530
*************** do
*** 610,615 ****
--- 610,616 ----
      bfd_elf32_bigmips_vec) 	tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
      bfd_elf32_bigmips_vxworks_vec)
  			 	tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+     bfd_elf32_cr16_vec)		tb="$tb elf32-cr16.lo elf32.lo $elf" ;;
      bfd_elf32_cr16c_vec)	tb="$tb elf32-cr16c.lo elf32.lo $elf" ;;
      bfd_elf32_cris_vec)		tb="$tb elf32-cris.lo elf32.lo $elf" ;;
      bfd_elf32_crx_vec)          tb="$tb elf32-crx.lo elf32.lo $elf" ;;    
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/cpu-cr16.c binutils-2.17.50-cr16/bfd/cpu-cr16.c
*** binutils-2.17.50/bfd/cpu-cr16.c	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/bfd/cpu-cr16.c	2007-06-22 14:50:49.000000000 +0530
***************
*** 0 ****
--- 1,40 ----
+ /* BFD support for the CR16 processor.
+    Copyright 2007 Free Software Foundation, Inc.
+    Written by M R Swami Reddy
+ 
+    This file is part of BFD, the Binary File Descriptor library.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #include "sysdep.h"
+ #include "bfd.h"
+ #include "libbfd.h"
+ 
+ 
+ const bfd_arch_info_type bfd_cr16_arch =
+   {
+     16,               /* 16 bits in a word.  */
+     32,               /* 32 bits in an address.  */
+     8,                /*  8 bits in a byte.  */
+     bfd_arch_cr16,    /* enum bfd_architecture arch.  */
+     bfd_mach_cr16,
+     "cr16",           /* Arch name.  */
+     "cr16",           /* Printable name.  */
+     1,                /* Unsigned int section alignment power.  */
+     TRUE,             /* The one and only.  */
+     bfd_default_compatible, 
+     bfd_default_scan ,
+     0,
+   };
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/doc/archures.texi binutils-2.17.50-cr16/bfd/doc/archures.texi
*** binutils-2.17.50/bfd/doc/archures.texi	2007-05-22 11:15:05.000000000 +0530
--- binutils-2.17.50-cr16/bfd/doc/archures.texi	2007-06-26 14:52:08.000000000 +0530
*************** enum bfd_architecture
*** 313,318 ****
--- 313,320 ----
  #define bfd_mach_avr6          6
    bfd_arch_bfin,        /* ADI Blackfin */
  #define bfd_mach_bfin          1
+   bfd_arch_cr16,       /*  National Semiconductor CompactRISC CR16.  */
+ #define bfd_mach_cr16           1
    bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
  #define bfd_mach_cr16c         1
    bfd_arch_crx,       /*  National Semiconductor CRX.  */
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/doc/reloc.texi binutils-2.17.50-cr16/bfd/doc/reloc.texi
*** binutils-2.17.50/bfd/doc/reloc.texi	2007-05-22 11:15:05.000000000 +0530
--- binutils-2.17.50-cr16/bfd/doc/reloc.texi	2007-06-22 14:48:07.000000000 +0530
*************** This is the 5 bits of a value.
*** 2272,2277 ****
--- 2272,2305 ----
  @deffnx {} BFD_RELOC_16C_IMM32_C
  NS CR16C Relocations.
  @end deffn
+ @deffn {} BFD_RELOC_CR16_NUM8
+ @deffnx {} BFD_RELOC_CR16_NUM16
+ @deffnx {} BFD_RELOC_CR16_NUM32
+ @deffnx {} BFD_RELOC_CR16_REG04
+ @deffnx {} BFD_RELOC_CR16_REGREL0
+ @deffnx {} BFD_RELOC_CR16_REGREL4
+ @deffnx {} BFD_RELOC_CR16_REGREL4a
+ @deffnx {} BFD_RELOC_CR16_REGREL14
+ @deffnx {} BFD_RELOC_CR16_REGREL14a
+ @deffnx {} BFD_RELOC_CR16_REGREL16
+ @deffnx {} BFD_RELOC_CR16_REGREL20
+ @deffnx {} BFD_RELOC_CR16_REGREL20a
+ @deffnx {} BFD_RELOC_CR16_ABS20
+ @deffnx {} BFD_RELOC_CR16_ABS24
+ @deffnx {} BFD_RELOC_CR16_IMM4
+ @deffnx {} BFD_RELOC_CR16_IMM8
+ @deffnx {} BFD_RELOC_CR16_IMM16
+ @deffnx {} BFD_RELOC_CR16_IMM20
+ @deffnx {} BFD_RELOC_CR16_IMM24
+ @deffnx {} BFD_RELOC_CR16_IMM32
+ @deffnx {} BFD_RELOC_CR16_DISP4
+ @deffnx {} BFD_RELOC_CR16_DISP8
+ @deffnx {} BFD_RELOC_CR16_DISP16
+ @deffnx {} BFD_RELOC_CR16_DISP20
+ @deffnx {} BFD_RELOC_CR16_DISP24
+ @deffnx {} BFD_RELOC_CR16_DISP24a
+ NS CR16 Relocations.
+ @end deffn
  @deffn {} BFD_RELOC_CRX_REL4
  @deffnx {} BFD_RELOC_CRX_REL8
  @deffnx {} BFD_RELOC_CRX_REL8_CMP
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/elf32-cr16.c binutils-2.17.50-cr16/bfd/elf32-cr16.c
*** binutils-2.17.50/bfd/elf32-cr16.c	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/bfd/elf32-cr16.c	2007-06-26 13:53:14.000000000 +0530
***************
*** 0 ****
--- 1,1461 ----
+ /* BFD back-end for National Semiconductor's CR16 ELF
+    Copyright 2007 Free Software Foundation, Inc.
+    Written by M R Swami Reddy.
+ 
+    This file is part of BFD, the Binary File Descriptor library.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #include "sysdep.h"
+ #include "bfd.h"
+ #include "bfdlink.h"
+ #include "libbfd.h"
+ #include "elf-bfd.h"
+ #include "elf/cr16.h"
+ 
+ static reloc_howto_type *elf_cr16_reloc_type_lookup
+   (bfd *, bfd_reloc_code_real_type);
+ static reloc_howto_type *elf_cr16_reloc_name_lookup
+   (bfd *, const char *);
+ static void elf_cr16_info_to_howto
+   (bfd *, arelent *, Elf_Internal_Rela *);
+ static bfd_boolean elf32_cr16_relax_delete_bytes
+   (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
+ static bfd_reloc_status_type cr16_elf_final_link_relocate
+   (reloc_howto_type *, bfd *, bfd *, asection *,
+    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
+    struct bfd_link_info *, asection *, int);
+ static bfd_boolean elf32_cr16_relocate_section
+   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
+ static asection * elf32_cr16_gc_mark_hook
+   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+    struct elf_link_hash_entry *, Elf_Internal_Sym *);
+ static bfd_boolean elf32_cr16_gc_sweep_hook
+   (bfd *, struct bfd_link_info *, asection *,
+    const Elf_Internal_Rela *);
+ static bfd_boolean elf32_cr16_relax_section
+   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
+ static bfd_byte * elf32_cr16_get_relocated_section_contents
+   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+    bfd_byte *, bfd_boolean, asymbol **);
+ 
+ /* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
+ 
+ struct cr16_reloc_map
+ {
+   bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
+   unsigned short cr16_reloc_type;          /* CR16 relocation type.  */
+ };
+ 
+ static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
+ {
+   {BFD_RELOC_NONE,           R_CR16_NONE},
+   {BFD_RELOC_CR16_NUM8,      R_CR16_NUM8},
+   {BFD_RELOC_CR16_NUM16,     R_CR16_NUM16},
+   {BFD_RELOC_CR16_NUM32,     R_CR16_NUM32},
+   {BFD_RELOC_CR16_NUM32a,    R_CR16_NUM32a},
+   {BFD_RELOC_CR16_REGREL4,   R_CR16_REGREL4},
+   {BFD_RELOC_CR16_REGREL4a,  R_CR16_REGREL4a},
+   {BFD_RELOC_CR16_REGREL14,  R_CR16_REGREL14},
+   {BFD_RELOC_CR16_REGREL14a, R_CR16_REGREL14a},
+   {BFD_RELOC_CR16_REGREL16,  R_CR16_REGREL16},
+   {BFD_RELOC_CR16_REGREL20,  R_CR16_REGREL20},
+   {BFD_RELOC_CR16_REGREL20a, R_CR16_REGREL20a},
+   {BFD_RELOC_CR16_ABS20,     R_CR16_ABS20},
+   {BFD_RELOC_CR16_ABS24,     R_CR16_ABS24},
+   {BFD_RELOC_CR16_IMM4,      R_CR16_IMM4},
+   {BFD_RELOC_CR16_IMM8,      R_CR16_IMM8},
+   {BFD_RELOC_CR16_IMM16,     R_CR16_IMM16},
+   {BFD_RELOC_CR16_IMM20,     R_CR16_IMM20},
+   {BFD_RELOC_CR16_IMM24,     R_CR16_IMM24},
+   {BFD_RELOC_CR16_IMM32,     R_CR16_IMM32},
+   {BFD_RELOC_CR16_IMM32a,    R_CR16_IMM32a},
+   {BFD_RELOC_CR16_DISP4,     R_CR16_DISP4},
+   {BFD_RELOC_CR16_DISP8,     R_CR16_DISP8},
+   {BFD_RELOC_CR16_DISP16,    R_CR16_DISP16},
+   {BFD_RELOC_CR16_DISP24,    R_CR16_DISP24},
+   {BFD_RELOC_CR16_DISP24a,   R_CR16_DISP24a}
+ };
+ 
+ static reloc_howto_type cr16_elf_howto_table[] =
+ {
+   HOWTO (R_CR16_NONE,              /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          32,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_dont,   /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_NONE",            /* name */
+          FALSE,                    /* partial_inplace */
+          0,                        /* src_mask */
+          0,                        /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_NUM8,              /* type */
+          0,                        /* rightshift */
+          0,                        /* size */
+          8,                        /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_NUM8",            /* name */
+          FALSE,                    /* partial_inplace */
+          0xff,                     /* src_mask */
+          0xff,                     /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_NUM16,             /* type */
+          0,                        /* rightshift */
+          1,                        /* size */
+          16,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_NUM16",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffff,                   /* src_mask */
+          0xffff,                   /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_NUM32,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          32,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_NUM32",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffffff,               /* src_mask */
+          0xffffffff,               /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_NUM32a,            /* type */
+          1,                        /* rightshift */
+          2,                        /* size */
+          32,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_NUM32a",          /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffffff,               /* src_mask */
+          0xffffffff,               /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL4,           /* type */
+          0,                        /* rightshift */
+          0,                        /* size */
+          4,                        /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL4",         /* name */
+          FALSE,                    /* partial_inplace */
+          0xf,                      /* src_mask */
+          0xf,                      /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL4a,          /* type */
+          0,                        /* rightshift */
+          0,                        /* size */
+          4,                        /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL4a",        /* name */
+          FALSE,                    /* partial_inplace */
+          0xf,                      /* src_mask */
+          0xf,                      /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL14,          /* type */
+          0,                        /* rightshift */
+          1,                        /* size */
+          14,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL14",        /* name */
+          FALSE,                    /* partial_inplace */
+          0x3fff,                   /* src_mask */
+          0x3fff,                   /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL14a,         /* type */
+          0,                        /* rightshift */
+          1,                        /* size */
+          14,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL14a",       /* name */
+          FALSE,                    /* partial_inplace */
+          0x3fff,                   /* src_mask */
+          0x3fff,                   /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL16,          /* type */
+          0,                        /* rightshift */
+          1,                        /* size */
+          16,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL16",        /* name */
+          FALSE,                    /* partial_inplace */
+          0xffff,                   /* src_mask */
+          0xffff,                   /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL20,          /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          20,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL20",        /* name */
+          FALSE,                    /* partial_inplace */
+          0xfffff,                  /* src_mask */
+          0xfffff,                  /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_REGREL20a,         /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          20,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_REGREL20a",       /* name */
+          FALSE,                    /* partial_inplace */
+          0xfffff,                  /* src_mask */
+          0xfffff,                  /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_ABS20,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          20,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_ABS20",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xfffff,                  /* src_mask */
+          0xfffff,                  /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_ABS24,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          24,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_ABS24",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffff,                 /* src_mask */
+          0xffffff,                 /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM4,              /* type */
+          0,                        /* rightshift */
+          0,                        /* size */
+          4,                        /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM4",            /* name */
+          FALSE,                    /* partial_inplace */
+          0xf,                      /* src_mask */
+          0xf,                      /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM8,              /* type */
+          0,                        /* rightshift */
+          0,                        /* size */
+          8,                        /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM8",            /* name */
+          FALSE,                    /* partial_inplace */
+          0xff,                     /* src_mask */
+          0xff,                     /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM16,             /* type */
+          0,                        /* rightshift */
+          1,                        /* size */
+          16,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM16",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffff,                   /* src_mask */
+          0xffff,                   /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM20,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          20,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM20",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xfffff,                  /* src_mask */
+          0xfffff,                  /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM24,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          24,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM24",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffff,                 /* src_mask */
+          0xffffff,                 /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM32,             /* type */
+          0,                        /* rightshift */
+          2,                        /* size */
+          32,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM32",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffffff,               /* src_mask */
+          0xffffffff,               /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_IMM32a,            /* type */
+          1,                        /* rightshift */
+          2,                        /* size */
+          32,                       /* bitsize */
+          FALSE,                    /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_bitfield,/* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_IMM32a",          /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffffff,               /* src_mask */
+          0xffffffff,               /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_DISP4,             /* type */
+          1,                        /* rightshift */
+          0,                        /* size (0 = byte, 1 = short, 2 = long) */
+          4,                        /* bitsize */
+          TRUE,                     /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_unsigned, /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_DISP4",           /* name */
+          FALSE,                    /* partial_inplace */
+          0xf,                      /* src_mask */
+          0xf,                      /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_DISP8,             /* type */
+          1,                        /* rightshift */
+          0,                        /* size (0 = byte, 1 = short, 2 = long) */
+          8,                        /* bitsize */
+          TRUE,                     /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_unsigned, /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_DISP8",           /* name */
+          FALSE,                    /* partial_inplace */
+          0x1ff,                    /* src_mask */
+          0x1ff,                    /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_DISP16,            /* type */
+          0,                        /* rightshift REVIITS: To sync with WinIDEA*/
+          1,                        /* size (0 = byte, 1 = short, 2 = long) */
+          16,                       /* bitsize */
+          TRUE,                     /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_unsigned, /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_DISP16",          /* name */
+          FALSE,                    /* partial_inplace */
+          0x1ffff,                  /* src_mask */
+          0x1ffff,                  /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+   /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
+      but its not done, to sync with WinIDEA and CR16 4.1 tools */
+   HOWTO (R_CR16_DISP24,            /* type */
+          0,                        /* rightshift */
+          2,                        /* size (0 = byte, 1 = short, 2 = long) */
+          24,                       /* bitsize */
+          TRUE,                     /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_unsigned, /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_DISP24",          /* name */
+          FALSE,                    /* partial_inplace */
+          0x1ffffff,                /* src_mask */
+          0x1ffffff,                /* dst_mask */
+          FALSE),                   /* pcrel_offset */
+ 
+   HOWTO (R_CR16_DISP24a,           /* type */
+          0,                        /* rightshift */
+          2,                        /* size (0 = byte, 1 = short, 2 = long) */
+          24,                       /* bitsize */
+          TRUE,                     /* pc_relative */
+          0,                        /* bitpos */
+          complain_overflow_unsigned, /* complain_on_overflow */
+          bfd_elf_generic_reloc,    /* special_function */
+          "R_CR16_DISP24a",         /* name */
+          FALSE,                    /* partial_inplace */
+          0xffffff,                 /* src_mask */
+          0xffffff,                 /* dst_mask */
+          FALSE)                    /* pcrel_offset */
+ 
+ };
+ 
+ /* Retrieve a howto ptr using a BFD reloc_code.  */
+ 
+ static reloc_howto_type *
+ elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                             bfd_reloc_code_real_type code)
+ {
+   unsigned int i;
+ 
+   for (i = 0; i < R_CR16_MAX; i++)
+     if (code == cr16_reloc_map[i].bfd_reloc_enum)
+       return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
+ 
+   printf ("This relocation Type is not supported -0x%x\n", code);
+   return 0;
+ }
+ 
+ static reloc_howto_type *
+ elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                             const char *r_name)
+ {
+   unsigned int i;
+ 
+   for (i = 0;
+        i < sizeof (cr16_elf_howto_table) / sizeof (cr16_elf_howto_table[0]);
+        i++)
+     if (cr16_elf_howto_table[i].name != NULL
+         && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
+       return &cr16_elf_howto_table[i];
+ 
+   return NULL;
+ }
+ 
+ /* Retrieve a howto ptr using an internal relocation entry.  */
+ 
+ static void
+ elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+                         Elf_Internal_Rela *dst)
+ {
+   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
+   BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
+   cache_ptr->howto = &cr16_elf_howto_table[r_type];
+ }
+ 
+ /* Perform a relocation as part of a final link.  */
+ 
+ static bfd_reloc_status_type
+ cr16_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
+                               bfd *output_bfd ATTRIBUTE_UNUSED,
+                               asection *input_section, bfd_byte *contents,
+                               bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
+                               struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                               asection *sec ATTRIBUTE_UNUSED,
+                               int is_local ATTRIBUTE_UNUSED)
+ {
+   unsigned short r_type = howto->type;
+   bfd_byte *hit_data = contents + offset;
+   bfd_vma reloc_bits, check, Rvalue1;
+ 
+   switch (r_type)
+     {
+      case R_CR16_IMM4:
+      case R_CR16_IMM8:
+      case R_CR16_IMM16:
+      case R_CR16_IMM20:
+      case R_CR16_IMM32:
+      case R_CR16_IMM32a:
+      case R_CR16_REGREL4:
+      case R_CR16_REGREL4a:
+      case R_CR16_REGREL14:
+      case R_CR16_REGREL14a:
+      case R_CR16_REGREL16:
+      case R_CR16_REGREL20:
+      case R_CR16_ABS20:
+      case R_CR16_ABS24:
+      case R_CR16_DISP16:
+      case R_CR16_DISP24:
+        /* 'hit_data' is relative to the start of the instruction, not the
+            relocation offset. Advance it to account for the exact offset.  */
+        hit_data += 2;
+        break;
+ 
+      case R_CR16_NONE:
+        return bfd_reloc_ok;
+        break;
+ 
+      case R_CR16_DISP4:
+      case R_CR16_DISP8:
+      case R_CR16_DISP24a:
+        /* We only care about the addend, where the difference between
+           expressions is kept.  */
+        if (is_local) Rvalue -= -1;
+        
+      default:
+        break;
+     }
+ 
+   if (howto->pc_relative)
+     {
+       /* Subtract the address of the section containing the location.  */
+       Rvalue -= (input_section->output_section->vma
+                  + input_section->output_offset);
+       /* Subtract the position of the location within the section.  */
+       Rvalue -= offset;
+     }
+ 
+   /* Add in supplied addend.  */
+   Rvalue += addend;
+ 
+   /* Complain if the bitfield overflows, whether it is considered
+      as signed or unsigned.  */
+   check = Rvalue >> howto->rightshift;
+ 
+   /* Assumes two's complement.  This expression avoids
+      overflow if howto->bitsize is the number of bits in
+      bfd_vma.  */
+   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+ 
+   if (((bfd_vma) check & ~reloc_bits) != 0
+       && (((bfd_vma) check & ~reloc_bits)
+       != (-(bfd_vma) 1 & ~reloc_bits)))
+     {
+       /* The above right shift is incorrect for a signed
+          value.  See if turning on the upper bits fixes the
+          overflow.  */
+       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
+         {
+           check |= ((bfd_vma) - 1
+                     & ~((bfd_vma) - 1
+                      >> howto->rightshift));
+ 
+           if (((bfd_vma) check & ~reloc_bits)
+               != (-(bfd_vma) 1 & ~reloc_bits))
+              return bfd_reloc_overflow;
+         }
+       else
+         return bfd_reloc_overflow;
+     }
+ 
+   /* Drop unwanted bits from the value we are relocating to.  */
+   Rvalue >>= (bfd_vma) howto->rightshift;
+ 
+   /* Apply dst_mask to select only relocatable part of the insn.  */
+   Rvalue &= howto->dst_mask;
+ 
+   switch (howto->size)
+     {
+       case 0:
+         if ((r_type == R_CR16_IMM4) || (r_type == R_CR16_DISP4) ||
+             (r_type == R_CR16_DISP8))
+           {
+              Rvalue1 = bfd_get_16 (input_bfd, hit_data);
+              Rvalue = ((Rvalue1&0xf000) | ((Rvalue<<4)&0xf00) |
+                        (Rvalue1&0x00f0) | (Rvalue&0xf));
+              bfd_put_16 (input_bfd,  Rvalue, hit_data);
+           }
+         break;
+ 
+       case 1:
+         if (r_type == R_CR16_DISP16)
+           {
+             Rvalue |= (bfd_get_16 (input_bfd, hit_data));
+             Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
+ 
+             bfd_put_16 (input_bfd, Rvalue, hit_data);
+           }
+         break;
+ 
+       case 2:
+         if (r_type == R_CR16_ABS20)
+           {
+             Rvalue |= (((bfd_get_16 (input_bfd, hit_data)<<16) |
+                         (bfd_get_16 (input_bfd, hit_data+2))) & ~howto->dst_mask);
+             Rvalue |= (bfd_get_16 (input_bfd, hit_data+2) << 16);
+ 
+             /* Relocation on INSTRUCTIONS is different : Instructions are
+                word-addressable, that is, each word itself is arranged according
+                to little-endian convention, whereas the words are arranged with
+                respect to one another in BIG ENDIAN fashion.
+                When there is an immediate value that spans a word boundary, 
+                it is split in a big-endian way with respect to the words.  */
+             bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data);
+             bfd_put_16 (input_bfd, (Rvalue >> 16)& 0xffff, hit_data + 2);
+           }
+         else if (r_type == R_CR16_ABS24)
+           {
+             Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf)<<8)|
+                       (bfd_get_16 (input_bfd, hit_data))) | 
+                       ((Rvalue & 0xffff) << 16));
+ 
+             bfd_put_32 (input_bfd, Rvalue, hit_data);
+           }
+         else if (r_type == R_CR16_DISP24)
+           {
+             Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf)<<8)|
+                       (bfd_get_16 (input_bfd, hit_data))) | 
+                       (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16));
+ 
+             bfd_put_32 (input_bfd, Rvalue, hit_data);
+           }
+         else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
+           {
+             Rvalue = (((Rvalue >> 16)& 0xffff) |
+                       (bfd_get_16 (input_bfd, hit_data))) | 
+                       ((Rvalue & 0xffff) << 16);
+             bfd_put_32 (input_bfd, Rvalue, hit_data);
+           }
+         else if (r_type == R_CR16_DISP24a)
+           {
+             Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));  
+             Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16) | 
+                       (bfd_get_32 (input_bfd, hit_data));
+ 
+             bfd_put_32 (input_bfd, Rvalue, hit_data);
+           }
+         else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a))
+           {
+             bfd_put_32 (input_bfd, Rvalue, hit_data);
+           }
+       break;
+ 
+       default:
+         return bfd_reloc_notsupported;
+     }
+ 
+   return bfd_reloc_ok;
+ }
+ 
+ /* Delete some bytes from a section while relaxing.  */
+ 
+ static bfd_boolean
+ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd, 
+                                asection *sec, bfd_vma addr, int count)
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   unsigned int sec_shndx;
+   bfd_byte *contents;
+   Elf_Internal_Rela *irel, *irelend;
+   Elf_Internal_Rela *irelalign;
+   bfd_vma toaddr;
+   Elf_Internal_Sym *isym;
+   Elf_Internal_Sym *isymend;
+   struct elf_link_hash_entry **sym_hashes;
+   struct elf_link_hash_entry **end_hashes;
+   struct elf_link_hash_entry **start_hashes;
+   unsigned int symcount;
+ 
+   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+ 
+   contents = elf_section_data (sec)->this_hdr.contents;
+ 
+   /* The deletion must stop at the next ALIGN reloc for an aligment
+      power larger than the number of bytes we are deleting.  */
+ 
+   irelalign = NULL;
+   toaddr = sec->size;
+ 
+   irel = elf_section_data (sec)->relocs;
+   irelend = irel + sec->reloc_count;
+ 
+   /* Actually delete the bytes.  */
+   memmove (contents + addr, contents + addr + count,
+            (size_t) (toaddr - addr - count));
+   sec->size -= count;
+ 
+   /* Adjust all the relocs.  */
+   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
+     {
+       /* Get the new reloc address.  */
+       if ((irel->r_offset > addr && irel->r_offset < toaddr))
+          irel->r_offset -= count;
+     }
+ 
+   /* Adjust the local symbols defined in this section.  */
+   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
+     {
+       if (isym->st_shndx == sec_shndx
+           && isym->st_value > addr
+           && isym->st_value < toaddr)
+         {
+           /* Adjust the addend of SWITCH relocations in this section, 
+              which reference this local symbol.  */
+           for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
+             {
+               unsigned long r_symndx;
+               Elf_Internal_Sym *rsym;
+               bfd_vma addsym, subsym;
+         
+               r_symndx = ELF32_R_SYM (irel->r_info);
+               rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
+ 
+               /* Skip if not the local adjusted symbol.  */
+               if (rsym != isym)
+                 continue;
+ 
+               addsym = isym->st_value;
+               subsym = addsym - irel->r_addend;
+ 
+               /* Fix the addend only when -->> (addsym > addr >= subsym).  */
+               if (subsym <= addr)
+                 irel->r_addend -= count;
+               else
+                 continue;
+             }
+ 
+           isym->st_value -= count;
+         }
+     }
+ 
+   /* Now adjust the global symbols defined in this section.  */
+   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+                - symtab_hdr->sh_info);
+   sym_hashes = start_hashes = elf_sym_hashes (abfd);
+   end_hashes = sym_hashes + symcount;
+ 
+   for (; sym_hashes < end_hashes; sym_hashes++)
+     {
+       struct elf_link_hash_entry *sym_hash = *sym_hashes;
+ 
+       /* The '--wrap SYMBOL' option is causing a pain when the object file, 
+          containing the definition of __wrap_SYMBOL, includes a direct 
+          call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 
+          the same symbol (which is __wrap_SYMBOL), but still exist as two 
+          different symbols in 'sym_hashes', we don't want to adjust 
+          the global symbol __wrap_SYMBOL twice.  
+          This check is only relevant when symbols are being wrapped.  */
+       if (link_info->wrap_hash != NULL)
+         {
+           struct elf_link_hash_entry **cur_sym_hashes;
+ 
+           /* Loop only over the symbols whom been already checked.  */
+           for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
+                cur_sym_hashes++)
+             {
+               /* If the current symbol is identical to 'sym_hash', that means
+                  the symbol was already adjusted (or at least checked).  */
+               if (*cur_sym_hashes == sym_hash)
+                 break;
+             }
+           /* Don't adjust the symbol again.  */
+           if (cur_sym_hashes < sym_hashes)
+             continue;
+         }
+ 
+       if ((sym_hash->root.type == bfd_link_hash_defined
+           || sym_hash->root.type == bfd_link_hash_defweak)
+           && sym_hash->root.u.def.section == sec
+           && sym_hash->root.u.def.value > addr
+           && sym_hash->root.u.def.value < toaddr)
+         sym_hash->root.u.def.value -= count;
+     }
+ 
+   return TRUE;
+ }
+ 
+ /* This is a version of bfd_generic_get_relocated_section_contents
+    which uses elf32_cr16_relocate_section.  */
+ 
+ static bfd_byte *
+ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
+                                            struct bfd_link_info *link_info,
+                                            struct bfd_link_order *link_order,
+                                            bfd_byte *data,
+                                            bfd_boolean relocatable,
+                                            asymbol **symbols)
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   asection *input_section = link_order->u.indirect.section;
+   bfd *input_bfd = input_section->owner;
+   asection **sections = NULL;
+   Elf_Internal_Rela *internal_relocs = NULL;
+   Elf_Internal_Sym *isymbuf = NULL;
+ 
+   /* We only need to handle the case of relaxing, or of having a
+      particular set of section contents, specially.  */
+   if (relocatable
+       || elf_section_data (input_section)->this_hdr.contents == NULL)
+     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
+                                                        link_order, data,
+                                                        relocatable,
+                                                        symbols);
+ 
+   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ 
+   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
+           (size_t) input_section->size);
+ 
+   if ((input_section->flags & SEC_RELOC) != 0
+       && input_section->reloc_count > 0)
+     {
+       Elf_Internal_Sym *isym;
+       Elf_Internal_Sym *isymend;
+       asection **secpp;
+       bfd_size_type amt;
+ 
+       internal_relocs = (_bfd_elf_link_read_relocs
+       (input_bfd, input_section, (PTR) NULL,
+        (Elf_Internal_Rela *) NULL, FALSE));
+       if (internal_relocs == NULL)
+         goto error_return;
+ 
+       if (symtab_hdr->sh_info != 0)
+         {
+           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+           if (isymbuf == NULL)
+             isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+                                             symtab_hdr->sh_info, 0,
+                                             NULL, NULL, NULL);
+           if (isymbuf == NULL)
+             goto error_return;
+         }
+ 
+       amt = symtab_hdr->sh_info;
+       amt *= sizeof (asection *);
+       sections = bfd_malloc (amt);
+       if (sections == NULL && amt != 0)
+         goto error_return;
+ 
+       isymend = isymbuf + symtab_hdr->sh_info;
+       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
+         {
+           asection *isec;
+ 
+           if (isym->st_shndx == SHN_UNDEF)
+             isec = bfd_und_section_ptr;
+           else if (isym->st_shndx == SHN_ABS)
+             isec = bfd_abs_section_ptr;
+           else if (isym->st_shndx == SHN_COMMON)
+             isec = bfd_com_section_ptr;
+           else
+             isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
+ 
+           *secpp = isec;
+         }
+ 
+       if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
+                                      input_section, data, internal_relocs,
+                                      isymbuf, sections))
+         goto error_return;
+ 
+       if (sections != NULL)
+         free (sections);
+       if (isymbuf != NULL
+           && symtab_hdr->contents != (unsigned char *) isymbuf)
+         free (isymbuf);
+       if (elf_section_data (input_section)->relocs != internal_relocs)
+         free (internal_relocs);
+     }
+ 
+   return data;
+ 
+  error_return:
+   if (sections != NULL)
+     free (sections);
+   if (isymbuf != NULL
+       && symtab_hdr->contents != (unsigned char *) isymbuf)
+     free (isymbuf);
+   if (internal_relocs != NULL
+       && elf_section_data (input_section)->relocs != internal_relocs)
+     free (internal_relocs);
+   return NULL;
+ }
+ 
+ /* Relocate a CR16 ELF section.  */
+ 
+ static bfd_boolean
+ elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
+                             bfd *input_bfd, asection *input_section,
+                             bfd_byte *contents, Elf_Internal_Rela *relocs,
+                             Elf_Internal_Sym *local_syms,
+                             asection **local_sections)
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   struct elf_link_hash_entry **sym_hashes;
+   Elf_Internal_Rela *rel, *relend;
+ 
+   if (info->relocatable)
+     return TRUE;
+ 
+   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+   sym_hashes = elf_sym_hashes (input_bfd);
+ 
+   rel = relocs;
+   relend = relocs + input_section->reloc_count;
+   for (; rel < relend; rel++)
+     {
+       int r_type;
+       reloc_howto_type *howto;
+       unsigned long r_symndx;
+       Elf_Internal_Sym *sym;
+       asection *sec;
+       struct elf_link_hash_entry *h;
+       bfd_vma relocation;
+       bfd_reloc_status_type r;
+ 
+       r_symndx = ELF32_R_SYM (rel->r_info);
+       r_type = ELF32_R_TYPE (rel->r_info);
+       howto = cr16_elf_howto_table + (r_type);
+ 
+       h = NULL;
+       sym = NULL;
+       sec = NULL;
+       if (r_symndx < symtab_hdr->sh_info)
+         {
+           sym = local_syms + r_symndx;
+           sec = local_sections[r_symndx];
+           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+         }
+       else
+         {
+           bfd_boolean unresolved_reloc, warned;
+ 
+           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                    r_symndx, symtab_hdr, sym_hashes,
+                                    h, sec, relocation,
+                                    unresolved_reloc, warned);
+         }
+ 
+       r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
+                                         input_section,
+                                         contents, rel->r_offset,
+                                         relocation, rel->r_addend,
+                                         info, sec, h == NULL);
+ 
+       if (r != bfd_reloc_ok)
+         {
+           const char *name;
+           const char *msg = (const char *) 0;
+ 
+           if (h != NULL)
+             name = h->root.root.string;
+           else
+             {
+               name = (bfd_elf_string_from_elf_section
+                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
+               if (name == NULL || *name == '\0')
+                 name = bfd_section_name (input_bfd, sec);
+             }
+ 
+           switch (r)
+             {
+              case bfd_reloc_overflow:
+                if (!((*info->callbacks->reloc_overflow)
+                      (info, (h ? &h->root : NULL), name, howto->name,
+                       (bfd_vma) 0, input_bfd, input_section,
+                       rel->r_offset)))
+                  return FALSE;
+                break;
+ 
+              case bfd_reloc_undefined:
+                if (!((*info->callbacks->undefined_symbol)
+                      (info, name, input_bfd, input_section,
+                       rel->r_offset, TRUE)))
+                  return FALSE;
+                break;
+ 
+              case bfd_reloc_outofrange:
+                msg = _("internal error: out of range error");
+                goto common_error;
+ 
+              case bfd_reloc_notsupported:
+                msg = _("internal error: unsupported relocation error");
+                goto common_error;
+ 
+              case bfd_reloc_dangerous:
+                msg = _("internal error: dangerous error");
+                goto common_error;
+ 
+              default:
+                msg = _("internal error: unknown error");
+                /* Fall through.  */
+ 
+              common_error:
+                if (!((*info->callbacks->warning)
+                      (info, msg, name, input_bfd, input_section,
+                       rel->r_offset)))
+                  return FALSE;
+                break;
+             }
+         }
+     }
+ 
+   return TRUE;
+ }
+ 
+ /* This function handles relaxing for the CR16.
+ 
+    There's quite a few relaxing opportunites available on the CR16:
+ 
+         * bcond:24 -> bcond:16                                2 bytes
+         * bcond:16 -> bcond:8                                2 bytes
+         * arithmetic imm32 -> arithmetic imm16                2 bytes
+ 
+    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
+ 
+ static bfd_boolean
+ elf32_cr16_relax_section (bfd *abfd, asection *sec,
+                          struct bfd_link_info *link_info, bfd_boolean *again)
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   Elf_Internal_Rela *internal_relocs;
+   Elf_Internal_Rela *irel, *irelend;
+   bfd_byte *contents = NULL;
+   Elf_Internal_Sym *isymbuf = NULL;
+ 
+   /* Assume nothing changes.  */
+   *again = FALSE;
+ 
+   /* We don't have to do anything for a relocatable link, if
+      this section does not have relocs, or if this is not a
+      code section.  */
+   if (link_info->relocatable
+       || (sec->flags & SEC_RELOC) == 0
+       || sec->reloc_count == 0
+       || (sec->flags & SEC_CODE) == 0)
+     return TRUE;
+ 
+   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ 
+   /* Get a copy of the native relocations.  */
+   internal_relocs = (_bfd_elf_link_read_relocs
+                      (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                       link_info->keep_memory));
+   if (internal_relocs == NULL)
+     goto error_return;
+ 
+   /* Walk through them looking for relaxing opportunities.  */
+   irelend = internal_relocs + sec->reloc_count;
+   for (irel = internal_relocs; irel < irelend; irel++)
+     {
+       bfd_vma symval;
+ 
+       /* If this isn't something that can be relaxed, then ignore
+          this reloc.  */
+       if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
+           && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24)
+         continue;
+ 
+       /* Get the section contents if we haven't done so already.  */
+       if (contents == NULL)
+         {
+           /* Get cached copy if it exists.  */
+           if (elf_section_data (sec)->this_hdr.contents != NULL)
+             contents = elf_section_data (sec)->this_hdr.contents;
+           /* Go get them off disk.  */
+           else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+             goto error_return;
+         }
+ 
+       /* Read this BFD's local symbols if we haven't done so already.  */
+       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+         {
+           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+           if (isymbuf == NULL)
+             isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                             symtab_hdr->sh_info, 0,
+                                             NULL, NULL, NULL);
+           if (isymbuf == NULL)
+             goto error_return;
+         }
+ 
+       /* Get the value of the symbol referred to by the reloc.  */
+       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+         {
+           /* A local symbol.  */
+           Elf_Internal_Sym *isym;
+           asection *sym_sec;
+ 
+           isym = isymbuf + ELF32_R_SYM (irel->r_info);
+           if (isym->st_shndx == SHN_UNDEF)
+             sym_sec = bfd_und_section_ptr;
+           else if (isym->st_shndx == SHN_ABS)
+             sym_sec = bfd_abs_section_ptr;
+           else if (isym->st_shndx == SHN_COMMON)
+             sym_sec = bfd_com_section_ptr;
+           else
+             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+           symval = (isym->st_value
+                     + sym_sec->output_section->vma
+                     + sym_sec->output_offset);
+         }
+       else
+         {
+           unsigned long indx;
+           struct elf_link_hash_entry *h;
+ 
+           /* An external symbol.  */
+           indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+           h = elf_sym_hashes (abfd)[indx];
+           BFD_ASSERT (h != NULL);
+ 
+           if (h->root.type != bfd_link_hash_defined
+               && h->root.type != bfd_link_hash_defweak)
+             /* This appears to be a reference to an undefined
+                symbol.  Just ignore it--it will be caught by the
+                regular reloc processing.  */
+             continue;
+ 
+           symval = (h->root.u.def.value
+                     + h->root.u.def.section->output_section->vma
+                     + h->root.u.def.section->output_offset);
+         }
+ 
+       /* For simplicity of coding, we are going to modify the section
+          contents, the section relocs, and the BFD symbol table.  We
+          must tell the rest of the code not to free up this
+          information.  It would be possible to instead create a table
+          of changes which have to be made, as is done in coff-mips.c;
+          that would be more work, but would require less memory when
+          the linker is run.  */
+ 
+       /* Try to turn a 24  branch/call into a 16bit relative 
+        * branch/call.  */
+       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
+         {
+           bfd_vma value = symval;
+ 
+           /* Deal with pc-relative gunk.  */
+           value -= (sec->output_section->vma + sec->output_offset);
+           value -= irel->r_offset;
+           value += irel->r_addend;
+ 
+           /* See if the value will fit in 16 bits, note the high value is
+              0xfffe + 2 as the target will be two bytes closer if we are
+              able to relax.  */
+           if ((long) value < 0x10000 && (long) value > -0x10002)
+             {
+               unsigned int code;
+ 
+               /* Get the opcode.  */
+               code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
+ 
+               /* Verify it's a 'bcond' and fix the opcode.  */
+               if ((code  & 0xffff) == 0x0010)
+                 {
+                 bfd_put_16 (abfd, 0x1800 | ((0xf & (code >>20))<<4), contents + irel->r_offset);
+                 bfd_put_16 (abfd, value, contents + irel->r_offset+2);
+                 }
+               else
+                 continue;
+ 
+               /* Note that we've changed the relocs, section contents, etc.  */
+               elf_section_data (sec)->relocs = internal_relocs;
+               elf_section_data (sec)->this_hdr.contents = contents;
+               symtab_hdr->contents = (unsigned char *) isymbuf;
+ 
+               /* Fix the relocation's type.  */
+               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                            R_CR16_DISP16);
+ 
+               /* Delete two bytes of data.  */
+               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
+                                                    irel->r_offset + 2, 2))
+                 goto error_return;
+ 
+               /* That will change things, so, we should relax again.
+                  Note that this is not required, and it may be slow.  */
+               *again = TRUE;
+             }
+         }
+ 
+       /* Try to turn a 16bit pc-relative branch into an
+          8bit pc-relative branch.  */
+       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
+         {
+           bfd_vma value = symval;
+ 
+           /* Deal with pc-relative gunk.  */
+           value -= (sec->output_section->vma + sec->output_offset);
+           value -= irel->r_offset;
+           value += irel->r_addend;
+ 
+           /* See if the value will fit in 8 bits, note the high value is
+              0xfc + 2 as the target will be two bytes closer if we are
+              able to relax.  */
+           if ((long) value < 0xfe && (long) value > -0x100)
+             {
+               unsigned short code;
+ 
+               /* Get the opcode.  */
+               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
+ 
+               /* Verify it's a 'bcond' opcode.  */
+               if ((code & 0xff00) == 0x1800)
+                 {
+                  bfd_put_8 (abfd, 0x1 | ((0xf & (code>>4))<<4), contents + irel->r_offset);
+                  bfd_put_8 (abfd, value, contents + irel->r_offset+2);
+                 }
+               else
+                 continue;
+ 
+               /* Note that we've changed the relocs, section contents, etc.  */
+               elf_section_data (sec)->relocs = internal_relocs;
+               elf_section_data (sec)->this_hdr.contents = contents;
+               symtab_hdr->contents = (unsigned char *) isymbuf;
+ 
+               /* Fix the relocation's type.  */
+               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                            R_CR16_DISP8);
+ 
+               /* Delete two bytes of data.  */
+               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
+                                                    irel->r_offset + 2, 2))
+                 goto error_return;
+ 
+               /* That will change things, so, we should relax again.
+                  Note that this is not required, and it may be slow.  */
+               *again = TRUE;
+             }
+         }
+ 
+ #if 0 // REVISIT: To support IMM relaxation in CR16 target
+       /* Try to turn a 32bit immediate address into
+          a 20bit immediate address.  */
+       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
+         {
+           bfd_vma value = symval;
+ 
+           /* See if the value will fit in 20 bits.  */
+           if ((long) value < 0x7ffff && (long) value > -0x80000)
+             {
+               unsigned short code;
+ 
+               /* Get the opcode.  */
+               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
+ 
+               /* Verify it's a 'arithmetic double'.  */
+               if ((code & 0xfff0) != 0x0070)
+                 continue;
+ 
+               /* Note that we've changed the relocs, section contents, etc.  */
+               elf_section_data (sec)->relocs = internal_relocs;
+               elf_section_data (sec)->this_hdr.contents = contents;
+               symtab_hdr->contents = (unsigned char *) isymbuf;
+ 
+               /* Fix the opcode.  */
+               bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
+ 
+               /* Fix the relocation's type.  */
+               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                            R_CR16_IMM20);
+ 
+               /* Delete two bytes of data.  */
+               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
+                                                    irel->r_offset + 2, 2))
+                 goto error_return;
+ 
+               /* That will change things, so, we should relax again.
+                  Note that this is not required, and it may be slow.  */
+               *again = TRUE;
+             }
+         }
+       /* Try to turn a 20bit/16bit immediate address into
+          a 4bit immediate address.  */
+       if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20) || 
+           (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
+         {
+           bfd_vma value = symval;
+ 
+           /* See if the value will fit in 4 bits.  */
+           if ((long) value < 0x7 && (long) value > -0x8)
+             {
+               unsigned short code;
+ 
+               /* Get the opcode.  */
+               code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset);
+ 
+               /* Verify it's a 'arithmetic double'.  */
+               if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45))
+                 continue;
+ 
+               /* Note that we've changed the relocs, section contents, etc.  */
+               elf_section_data (sec)->relocs = internal_relocs;
+               elf_section_data (sec)->this_hdr.contents = contents;
+               symtab_hdr->contents = (unsigned char *) isymbuf;
+ 
+               /* Fix the opcode.  */
+               bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
+ 
+               /* Fix the relocation's type.  */
+               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                            R_CR16_IMM4);
+ 
+               /* Delete two bytes of data.  */
+               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
+                                                    irel->r_offset + 2, 2))
+                 goto error_return;
+ 
+               /* That will change things, so, we should relax again.
+                  Note that this is not required, and it may be slow.  */
+               *again = TRUE;
+             }
+         }
+ #endif
+     }
+ 
+   if (isymbuf != NULL
+       && symtab_hdr->contents != (unsigned char *) isymbuf)
+     {
+       if (! link_info->keep_memory)
+         free (isymbuf);
+       else
+         {
+           /* Cache the symbols for elf_link_input_bfd.  */
+           symtab_hdr->contents = (unsigned char *) isymbuf;
+         }
+     }
+ 
+   if (contents != NULL
+       && elf_section_data (sec)->this_hdr.contents != contents)
+     {
+       if (! link_info->keep_memory)
+         free (contents);
+       else
+         {
+           /* Cache the section contents for elf_link_input_bfd.  */
+           elf_section_data (sec)->this_hdr.contents = contents;
+         }
+     }
+ 
+   if (internal_relocs != NULL
+       && elf_section_data (sec)->relocs != internal_relocs)
+     free (internal_relocs);
+ 
+   return TRUE;
+ 
+  error_return:
+   if (isymbuf != NULL
+       && symtab_hdr->contents != (unsigned char *) isymbuf)
+     free (isymbuf);
+   if (contents != NULL
+       && elf_section_data (sec)->this_hdr.contents != contents)
+     free (contents);
+   if (internal_relocs != NULL
+       && elf_section_data (sec)->relocs != internal_relocs)
+     free (internal_relocs);
+ 
+   return FALSE;
+ }
+ 
+ static asection *
+ elf32_cr16_gc_mark_hook (asection *sec,
+                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                         Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+                         struct elf_link_hash_entry *h,
+                         Elf_Internal_Sym *sym)
+ {
+   if (h == NULL)
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+ 
+   switch (h->root.type)
+     {
+       case bfd_link_hash_defined:
+       case bfd_link_hash_defweak:
+         return h->root.u.def.section;
+ 
+       case bfd_link_hash_common:
+         return h->root.u.c.p->section;
+ 
+       default:
+         return NULL;
+     }
+ }
+ 
+ /* Update the got entry reference counts for the section being removed.  */
+ 
+ static bfd_boolean
+ elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          asection *sec ATTRIBUTE_UNUSED,
+                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
+ {
+   /* We don't support garbage collection of GOT and PLT relocs yet.  */
+   return TRUE;
+ }
+ 
+ /* Definitions for setting CR16 target vector.  */
+ #define TARGET_LITTLE_SYM                 bfd_elf32_cr16_vec
+ #define TARGET_LITTLE_NAME                "elf32-cr16"
+ #define ELF_ARCH                          bfd_arch_cr16
+ #define ELF_MACHINE_CODE                  EM_CR16
+ #define ELF_MAXPAGESIZE                   0x1
+ #define elf_symbol_leading_char           '_'
+ 
+ #define bfd_elf32_bfd_reloc_type_lookup   elf_cr16_reloc_type_lookup
+ #define bfd_elf32_bfd_reloc_name_lookup   \
+                                           elf_cr16_reloc_name_lookup
+ #define elf_info_to_howto                 elf_cr16_info_to_howto
+ #define elf_info_to_howto_rel             0
+ #define elf_backend_relocate_section      elf32_cr16_relocate_section
+ #define bfd_elf32_bfd_relax_section       elf32_cr16_relax_section
+ #define bfd_elf32_bfd_get_relocated_section_contents \
+                                 elf32_cr16_get_relocated_section_contents
+ #define elf_backend_gc_mark_hook          elf32_cr16_gc_mark_hook
+ #define elf_backend_gc_sweep_hook         elf32_cr16_gc_sweep_hook
+ #define elf_backend_can_gc_sections       1
+ #define elf_backend_rela_normal           1
+ 
+ #include "elf32-target.h"
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/Makefile.am binutils-2.17.50-cr16/bfd/Makefile.am
*** binutils-2.17.50/bfd/Makefile.am	2007-04-26 20:16:55.000000000 +0530
--- binutils-2.17.50-cr16/bfd/Makefile.am	2007-06-26 14:52:08.000000000 +0530
*************** ALL_MACHINES = \
*** 64,69 ****
--- 64,70 ----
  	cpu-arm.lo \
  	cpu-avr.lo \
  	cpu-bfin.lo \
+ 	cpu-cr16.lo \
  	cpu-cr16c.lo \
  	cpu-cris.lo \
  	cpu-crx.lo \
*************** ALL_MACHINES_CFILES = \
*** 129,134 ****
--- 130,136 ----
  	cpu-arm.c \
  	cpu-avr.c \
  	cpu-bfin.c \
+ 	cpu-cr16.c \
  	cpu-cris.c \
  	cpu-cr16c.c \
  	cpu-crx.c \
*************** BFD32_BACKENDS = \
*** 242,247 ****
--- 244,250 ----
  	elf32-arm.lo \
  	elf32-avr.lo \
  	elf32-bfin.lo \
+ 	elf32-cr16.lo \
  	elf32-cr16c.lo \
  	elf32-cris.lo \
  	elf32-crx.lo \
*************** BFD32_BACKENDS_CFILES = \
*** 419,424 ****
--- 422,428 ----
  	elf32-arm.c \
  	elf32-avr.c \
  	elf32-bfin.c \
+ 	elf32-cr16.c \
  	elf32-cr16c.c \
  	elf32-cris.c \
  	elf32-crx.c \
*************** cpu-arm.lo: cpu-arm.c $(INCDIR)/filename
*** 1051,1056 ****
--- 1055,1061 ----
    $(INCDIR)/libiberty.h
  cpu-avr.lo: cpu-avr.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-bfin.lo: cpu-bfin.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+ cpu-cr16.lo: cpu-cr16.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-cris.lo: cpu-cris.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-cr16c.lo: cpu-cr16c.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-crx.lo: cpu-crx.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
*************** elf32-bfin.lo: elf32-bfin.c $(INCDIR)/fi
*** 1313,1318 ****
--- 1318,1327 ----
    $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/bfin.h \
    $(INCDIR)/elf/reloc-macros.h $(INCDIR)/elf/dwarf2.h \
    elf32-target.h
+ elf32-cr16.lo: elf32-cr16.c $(INCDIR)/filenames.h \
+   $(INCDIR)/hashtab.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16.h \
+   $(INCDIR)/elf/reloc-macros.h elf-bfd.h $(INCDIR)/elf/common.h \
+   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elf32-target.h
  elf32-cr16c.lo: elf32-cr16c.c $(INCDIR)/filenames.h \
    $(INCDIR)/hashtab.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16c.h \
    $(INCDIR)/elf/reloc-macros.h elf-bfd.h $(INCDIR)/elf/common.h \
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/Makefile.in binutils-2.17.50-cr16/bfd/Makefile.in
*** binutils-2.17.50/bfd/Makefile.in	2007-04-26 20:16:55.000000000 +0530
--- binutils-2.17.50-cr16/bfd/Makefile.in	2007-06-26 14:52:08.000000000 +0530
*************** ALL_MACHINES = \
*** 300,305 ****
--- 300,306 ----
  	cpu-arm.lo \
  	cpu-avr.lo \
  	cpu-bfin.lo \
+ 	cpu-cr16.lo \
  	cpu-cr16c.lo \
  	cpu-cris.lo \
  	cpu-crx.lo \
*************** ALL_MACHINES_CFILES = \
*** 365,370 ****
--- 366,372 ----
  	cpu-arm.c \
  	cpu-avr.c \
  	cpu-bfin.c \
+ 	cpu-cr16.c \
  	cpu-cris.c \
  	cpu-cr16c.c \
  	cpu-crx.c \
*************** BFD32_BACKENDS = \
*** 479,484 ****
--- 481,487 ----
  	elf32-arm.lo \
  	elf32-avr.lo \
  	elf32-bfin.lo \
+ 	elf32-cr16.lo \
  	elf32-cr16c.lo \
  	elf32-cris.lo \
  	elf32-crx.lo \
*************** BFD32_BACKENDS_CFILES = \
*** 656,661 ****
--- 659,665 ----
  	elf32-arm.c \
  	elf32-avr.c \
  	elf32-bfin.c \
+ 	elf32-cr16.c \
  	elf32-cr16c.c \
  	elf32-cris.c \
  	elf32-crx.c \
*************** cpu-arm.lo: cpu-arm.c $(INCDIR)/filename
*** 1618,1623 ****
--- 1622,1628 ----
    $(INCDIR)/libiberty.h
  cpu-avr.lo: cpu-avr.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-bfin.lo: cpu-bfin.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+ cpu-cr16.lo: cpu-cr16.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-cris.lo: cpu-cris.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-cr16c.lo: cpu-cr16c.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
  cpu-crx.lo: cpu-crx.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
*************** elf32-bfin.lo: elf32-bfin.c $(INCDIR)/fi
*** 1880,1885 ****
--- 1885,1894 ----
    $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/bfin.h \
    $(INCDIR)/elf/reloc-macros.h $(INCDIR)/elf/dwarf2.h \
    elf32-target.h
+ elf32-cr16.lo: elf32-cr16.c $(INCDIR)/filenames.h \
+   $(INCDIR)/hashtab.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16.h \
+   $(INCDIR)/elf/reloc-macros.h elf-bfd.h $(INCDIR)/elf/common.h \
+   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elf32-target.h
  elf32-cr16c.lo: elf32-cr16c.c $(INCDIR)/filenames.h \
    $(INCDIR)/hashtab.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16c.h \
    $(INCDIR)/elf/reloc-macros.h elf-bfd.h $(INCDIR)/elf/common.h \
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/reloc.c binutils-2.17.50-cr16/bfd/reloc.c
*** binutils-2.17.50/bfd/reloc.c	2007-05-11 08:40:11.000000000 +0530
--- binutils-2.17.50-cr16/bfd/reloc.c	2007-06-22 14:48:07.000000000 +0530
*************** ENUMDOC
*** 4516,4521 ****
--- 4516,4578 ----
    NS CR16C Relocations.
  
  ENUM
+   BFD_RELOC_CR16_NUM8
+ ENUMX
+   BFD_RELOC_CR16_NUM16
+ ENUMX
+   BFD_RELOC_CR16_NUM32
+ ENUMX
+   BFD_RELOC_CR16_NUM32a
+ ENUMX
+   BFD_RELOC_CR16_REGREL0
+ ENUMX
+   BFD_RELOC_CR16_REGREL4
+ ENUMX
+   BFD_RELOC_CR16_REGREL4a
+ ENUMX
+   BFD_RELOC_CR16_REGREL14
+ ENUMX
+   BFD_RELOC_CR16_REGREL14a
+ ENUMX
+   BFD_RELOC_CR16_REGREL16
+ ENUMX
+   BFD_RELOC_CR16_REGREL20
+ ENUMX
+   BFD_RELOC_CR16_REGREL20a
+ ENUMX
+   BFD_RELOC_CR16_ABS20
+ ENUMX
+   BFD_RELOC_CR16_ABS24
+ ENUMX
+   BFD_RELOC_CR16_IMM4
+ ENUMX
+   BFD_RELOC_CR16_IMM8
+ ENUMX
+   BFD_RELOC_CR16_IMM16
+ ENUMX
+   BFD_RELOC_CR16_IMM20
+ ENUMX
+   BFD_RELOC_CR16_IMM24
+ ENUMX
+   BFD_RELOC_CR16_IMM32
+ ENUMX
+   BFD_RELOC_CR16_IMM32a
+ ENUMX
+   BFD_RELOC_CR16_DISP4
+ ENUMX
+   BFD_RELOC_CR16_DISP8
+ ENUMX
+   BFD_RELOC_CR16_DISP16
+ ENUMX
+   BFD_RELOC_CR16_DISP20
+ ENUMX
+   BFD_RELOC_CR16_DISP24
+ ENUMX
+   BFD_RELOC_CR16_DISP24a
+ ENUMDOC
+   NS CR16 Relocations.
+ 
+ ENUM
    BFD_RELOC_CRX_REL4
  ENUMX
    BFD_RELOC_CRX_REL8
diff -Napr --exclude=testsuite binutils-2.17.50/bfd/targets.c binutils-2.17.50-cr16/bfd/targets.c
*** binutils-2.17.50/bfd/targets.c	2007-04-26 20:16:58.000000000 +0530
--- binutils-2.17.50-cr16/bfd/targets.c	2007-06-26 14:52:08.000000000 +0530
*************** extern const bfd_target bfd_elf32_bigarm
*** 572,577 ****
--- 572,578 ----
  extern const bfd_target bfd_elf32_bigarm_vxworks_vec;
  extern const bfd_target bfd_elf32_bigmips_vec;
  extern const bfd_target bfd_elf32_bigmips_vxworks_vec;
+ extern const bfd_target bfd_elf32_cr16_vec;
  extern const bfd_target bfd_elf32_cr16c_vec;
  extern const bfd_target bfd_elf32_cris_vec;
  extern const bfd_target bfd_elf32_crx_vec;
*************** static const bfd_target * const _bfd_tar
*** 896,901 ****
--- 897,903 ----
  	&bfd_elf32_bigarm_vxworks_vec,
  	&bfd_elf32_bigmips_vec,
  	&bfd_elf32_bigmips_vxworks_vec,
+ 	&bfd_elf32_cr16_vec,
  	&bfd_elf32_cr16c_vec,
  	&bfd_elf32_cris_vec,
  	&bfd_elf32_crx_vec,
diff -Napr --exclude=testsuite binutils-2.17.50/config.sub binutils-2.17.50-cr16/config.sub
*** binutils-2.17.50/config.sub	2007-02-06 00:40:45.000000000 +0530
--- binutils-2.17.50-cr16/config.sub	2007-06-22 14:36:50.000000000 +0530
*************** case $basic_machine in
*** 490,495 ****
--- 490,499 ----
  	cris | cris-* | etrax*)
  		basic_machine=cris-axis
  		;;
+ 	cr16)
+ 		basic_machine=cr16-unknown
+ 		os=-elf
+ 		;;
  	crx)
  		basic_machine=crx-unknown
  		os=-elf
diff -Napr --exclude=testsuite binutils-2.17.50/gas/ChangeLog binutils-2.17.50-cr16/gas/ChangeLog
*** binutils-2.17.50/gas/ChangeLog	2007-05-19 00:33:52.000000000 +0530
--- binutils-2.17.50-cr16/gas/ChangeLog	2007-06-22 15:25:00.000000000 +0530
***************
*** 1,3 ****
--- 1,16 ----
+ 2007-06-18  M R Swami Reddy <MR.Swami.Redd@nsc.com>
+ 
+ 	* Makefile.am: Add CR16 related entry.
+ 	* Makefile.in: Regenerate.
+ 	* config/tc-cr16.h: New file
+ 	* config/tc-cr16.c: New file
+ 	* doc/c-cr16.texi: New file for cr16 
+ 	* doc/all.texi: Entry for cr16 
+ 	* doc/Makefile.am: Added c-cr16.texi
+ 	* doc/Makefile.in: Regenerate 
+ 	* doc/as.texinfo: Entry for CR16 target
+ 	* NEWS: Announce the support for the new target.
+ 
  2007-05-18  Joseph Myers  <joseph@codesourcery.com>
  
  	* config/tc-mips.c (s_mipsset): Use generic s_set for directives
diff -Napr --exclude=testsuite binutils-2.17.50/gas/config/tc-cr16.c binutils-2.17.50-cr16/gas/config/tc-cr16.c
*** binutils-2.17.50/gas/config/tc-cr16.c	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/gas/config/tc-cr16.c	2007-06-26 15:01:25.000000000 +0530
***************
*** 0 ****
--- 1,2518 ----
+ /* tc-cr16.c -- Assembler code for the CR16 CPU core.
+    Copyright 2007 Free Software Foundation, Inc.
+ 
+    Contributed by M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+    This file is part of GAS, the GNU Assembler.
+ 
+    GAS is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    GAS 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 GAS; see the file COPYING.  If not, write to the
+    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+    MA 02110-1301, USA.  */
+ 
+ #include "as.h"
+ #include "safe-ctype.h"
+ #include "dwarf2dbg.h"
+ #include "opcode/cr16.h"
+ #include "elf/cr16.h"
+ 
+ 
+ /* Word is considered here as a 16-bit unsigned short int.  */
+ #define WORD_SHIFT  16
+ 
+ /* Register is 2-byte size.  */
+ #define REG_SIZE   2
+ 
+ /* Maximum size of a single instruction (in words).  */
+ #define INSN_MAX_SIZE   3
+ 
+ /* Maximum bits which may be set in a `mask16' operand.  */
+ #define MAX_REGS_IN_MASK16  8
+ 
+ /* Assign a number NUM, shifted by SHIFT bytes, into a location
+    pointed by index BYTE of array 'output_opcode'.  */
+ #define CR16_PRINT(BYTE, NUM, SHIFT)   output_opcode[BYTE] |= (NUM << SHIFT)
+ 
+ /* Operand errors.  */
+ typedef enum
+   {
+     OP_LEGAL = 0,       /* Legal operand.  */
+     OP_OUT_OF_RANGE,    /* Operand not within permitted range.  */
+     OP_NOT_EVEN         /* Operand is Odd number, should be even.  */
+   }
+ op_err;
+ 
+ /* Opcode mnemonics hash table.  */
+ static struct hash_control *cr16_inst_hash;
+ /* CR16 registers hash table.  */
+ static struct hash_control *reg_hash;
+ /* CR16 register pair hash table.  */
+ static struct hash_control *regp_hash;
+ /* CR16 processor registers hash table.  */
+ static struct hash_control *preg_hash;
+ /* CR16 processor registers 32 bit hash table.  */
+ static struct hash_control *pregp_hash;
+ /* Current instruction we're assembling.  */
+ const inst *instruction;
+ 
+ 
+ static int code_label = 0;
+ static void l_cons(register int r);
+ 
+ /* Global variables.  */
+ 
+ /* Array to hold an instruction encoding.  */
+ long output_opcode[2];
+ 
+ /* Nonzero means a relocatable symbol.  */
+ int relocatable;
+ 
+ /* A copy of the original instruction (used in error messages).  */
+ char ins_parse[MAX_INST_LEN];
+ 
+ /* The current processed argument number.  */
+ int cur_arg_num;
+ 
+ /* Generic assembler global variables which must be defined by all targets.  */
+ 
+ /* Characters which always start a comment.  */
+ const char comment_chars[] = "#";
+ 
+ /* Characters which start a comment at the beginning of a line.  */
+ const char line_comment_chars[] = "#";
+ 
+ /* This array holds machine specific line separator characters.  */
+ const char line_separator_chars[] = ";";
+ 
+ /* Chars that can be used to separate mant from exp in floating point nums.  */
+ const char EXP_CHARS[] = "eE";
+ 
+ /* Chars that mean this number is a floating point constant as in 0f12.456  */
+ const char FLT_CHARS[] = "f'";
+ 
+ /* Target-specific multicharacter options, not const-declared at usage.  */
+ const char *md_shortopts = "";
+ struct option md_longopts[] =
+ {
+   {NULL, no_argument, NULL, 0}
+ };
+ size_t md_longopts_size = sizeof (md_longopts);
+ 
+ static void
+ l_cons (register int nbytes )
+ {
+   int c;
+   expressionS exp;
+ 
+ #ifdef md_flush_pending_output
+     md_flush_pending_output ();
+ #endif
+ 
+   if (is_it_end_of_statement ())
+     {
+       demand_empty_rest_of_line ();
+       return;
+     }
+ 
+ #ifdef TC_ADDRESS_BYTES
+   if (nbytes == 0)
+     nbytes = TC_ADDRESS_BYTES ();
+ #endif
+ 
+ #ifdef md_cons_align
+    md_cons_align (nbytes);
+ #endif
+ 
+    c = 0;
+    do
+      {
+        unsigned int bits_available = BITS_PER_CHAR * nbytes;
+        char *hold = input_line_pointer;
+ 
+        expression (&exp);
+ 
+        if (*input_line_pointer == ':')
+          {
+            /* Bitfields.  */
+            long value = 0;
+ 
+            for (;;)
+              {
+                unsigned long width;
+ 
+                if (*input_line_pointer != ':')
+                  {
+                    input_line_pointer = hold;
+                    break;
+                  }                   /* Next piece is not a bitfield.  */
+                if (exp.X_op == O_absent)
+                  {
+                    as_warn (_("using a bit field width of zero"));
+                    exp.X_add_number = 0;
+                    exp.X_op = O_constant;
+                  }                   /* Implied zero width bitfield.  */
+ 
+                if (exp.X_op != O_constant)
+                  {
+                    *input_line_pointer = '\0';
+                    as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
+                    *input_line_pointer = ':';
+                    demand_empty_rest_of_line ();
+                    return;
+                  }                   /* Too complex.  */
+ 
+                if ((width = exp.X_add_number) >
+                    (unsigned int)(BITS_PER_CHAR * nbytes))
+                  {
+                    as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), width, nbytes, (BITS_PER_CHAR * nbytes));
+                    width = BITS_PER_CHAR * nbytes;
+                  }                   /* Too big.  */
+ 
+ 
+                if (width > bits_available)
+                  {
+                    /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
+                    input_line_pointer = hold;
+                    exp.X_add_number = value;
+                    break;
+                  }                   /* Won't fit.  */
+ 
+                /* Skip ':'.  */
+                hold = ++input_line_pointer;
+ 
+                expression (&exp);
+                if (exp.X_op != O_constant)
+                  {
+                    char cache = *input_line_pointer;
+ 
+                    *input_line_pointer = '\0';
+                    as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
+                    *input_line_pointer = cache;
+                    demand_empty_rest_of_line ();
+                    return;
+                  }                   /* Too complex.  */
+ 
+                value |= ((~(-1 << width) & exp.X_add_number)
+                          << ((BITS_PER_CHAR * nbytes) - bits_available));
+ 
+                if ((bits_available -= width) == 0
+                     || is_it_end_of_statement ()
+                     || *input_line_pointer != ',')
+                  {
+                    break;
+                  }                 /* All the bitfields we're gonna get.  */
+ 
+                hold = ++input_line_pointer;
+                expression (&exp);
+              }
+ 
+            exp.X_add_number = value;
+            exp.X_op = O_constant;
+            exp.X_unsigned = 1;
+          }
+ 
+        if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
+          code_label = 1;
+        emit_expr (&exp, (unsigned int) nbytes);
+        ++c;
+        if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
+          {
+            input_line_pointer +=3;
+           break;
+          }
+      }
+    while ((*input_line_pointer++ == ','));
+ 
+    input_line_pointer--;         /* Put terminator back into stream.  */
+ 
+    demand_empty_rest_of_line ();
+ }
+ 
+ 
+ /* This table describes all the machine specific pseudo-ops
+    the assembler has to support.  The fields are:
+    *** Pseudo-op name without dot.
+    *** Function to call to execute this pseudo-op.
+    *** Integer arg to pass to the function.  */
+ 
+ const pseudo_typeS md_pseudo_table[] =
+ {
+   /* In CR16 machine, align is in bytes (not a ptwo boundary).  */
+   {"align", s_align_bytes, 0},
+   {"long", l_cons,  4 },
+   {0, 0, 0}
+ };
+ 
+ /* CR16 relaxation table.  */
+ const relax_typeS md_relax_table[] =
+ {
+   /* bCC  */
+   {0xfa, -0x100, 2, 1},                 /*  8 */
+   {0xfffe, -0x10000, 4, 2},             /* 16 */
+   {0xfffffe, -0x1000000, 6, 0},         /* 24 */
+ };
+ 
+ static void    reset_vars               (char *);
+ static reg     get_register             (char *);
+ static reg     get_register_pair        (char *);
+ static reg     get_index_register       (char *);
+ static reg     get_index_register_pair  (char *);
+ static preg    get_pregister            (char *);
+ static preg    get_pregisterp           (char *);
+ static int     get_cc                   (char *);
+ static argtype get_optype               (operand_type);
+ static int     get_opbits               (operand_type);
+ static int     get_opflags              (operand_type);
+ static int     get_number_of_operands   (void);
+ static void    parse_operand            (char *, ins *);
+ static int     gettrap                  (char *);
+ static char *  get_b_cc                 (char *);
+ static int     is_bcc_insn              (char *);
+ static int     check_cinv_options       (char *);
+ static long    getconstant              (long, int);
+ static op_err  check_range              (long *, int, unsigned int, int);
+ static int     getreg_image             (reg);
+ static int     getregp_image            (reg);
+ static int     getidxregp_image         (reg);
+ static int     getprocreg_image         (reg);
+ static int     getprocregp_image        (reg);
+ static void    parse_operands           (ins *, char *);
+ static void    parse_insn               (ins *, char *);
+ static void    print_operand            (int, int, argument *);
+ static void    print_constant           (int, int, argument *);
+ static void    process_label_constant   (char *, ins *);
+ static void    set_operand              (char *, ins *);
+ static int     assemble_insn            (char *, ins *);
+ static void    print_insn               (ins *);
+ static void    warn_if_needed           (ins *);
+ static int     adjust_if_needed         (ins *);
+ 
+ /* Return the bit size for a given operand.  */
+ 
+ static int
+ get_opbits (operand_type op)
+ {
+   if (op < MAX_OPRD)
+     return cr16_optab[op].bit_size;
+   else
+     return 0;
+ }
+ 
+ /* Return the argument type of a given operand.  */
+ 
+ static argtype
+ get_optype (operand_type op)
+ {
+   if (op < MAX_OPRD)
+     return cr16_optab[op].arg_type;
+   else
+     return nullargs;
+ }
+ 
+ /* Return the flags of a given operand.  */
+ 
+ static int
+ get_opflags (operand_type op)
+ {
+   if (op < MAX_OPRD)
+     return cr16_optab[op].flags;
+   else
+     return 0;
+ }
+ 
+ /* Get the cc code  */
+ 
+ static int
+ get_cc (char *cc_name)
+ {
+    unsigned int i;
+    for (i = 0; i < cr16_num_cc; i++)
+      {
+        if (strcmp (cc_name, cr16_b_cond_tab[i]) == 0) 
+          return i;
+      }
+    return -1;
+ }
+ 
+ /* Get the core processor register 'reg_name'.  */
+ 
+ static reg
+ get_register (char *reg_name)
+ {
+   const reg_entry *reg;
+ 
+   reg = (const reg_entry *) hash_find (reg_hash, reg_name);
+ 
+   if (reg != NULL)
+     return reg->value.reg_val;
+   else
+     return nullregister;
+ }
+ /* Get the core processor register-pair 'reg_name'.  */
+ 
+ static reg
+ get_register_pair (char *reg_name)
+ {
+   const reg_entry *reg;
+   char tmp_rp[16]="\0";
+ 
+   /* Add '(' and ')' to the reg pair, if its not present */
+   if (reg_name[0] != '(') 
+     {
+       tmp_rp[0] = '(';
+       strcat(tmp_rp,reg_name);
+       strcat(tmp_rp,")");
+       reg = (const reg_entry *) hash_find (regp_hash, tmp_rp);
+     }
+   else
+     reg = (const reg_entry *) hash_find (regp_hash, reg_name);
+ 
+   if (reg != NULL)
+     return reg->value.reg_val;
+   else
+     return nullregister;
+ } 
+ 
+ /* Get the index register 'reg_name'.  */
+ 
+ static reg
+ get_index_register (char *reg_name)
+ {
+   const reg_entry *reg;
+ 
+   reg = (const reg_entry *) hash_find (reg_hash, reg_name);
+ 
+   if ((reg != NULL) && 
+       ((reg->value.reg_val == 12) || (reg->value.reg_val == 13)))
+     return reg->value.reg_val;
+   else
+     return nullregister;
+ }
+ /* Get the core processor index register-pair 'reg_name'.  */
+ 
+ static reg
+ get_index_register_pair (char *reg_name)
+ {
+   const reg_entry *reg;
+ 
+   reg = (const reg_entry *) hash_find (regp_hash, reg_name);
+ 
+   if (reg != NULL)
+     {
+       if ((reg->value.reg_val != 1) || (reg->value.reg_val != 7) ||
+           (reg->value.reg_val != 9) || (reg->value.reg_val > 10) )
+          return reg->value.reg_val;
+       else
+         as_bad (_("Unknown register pair - index relative mode: `%d'"), reg->value.reg_val);
+       return nullregister;
+    }
+   else
+     return nullregister;
+ }
+ 
+ /* Get the processor register 'preg_name'.  */
+ 
+ static preg
+ get_pregister (char *preg_name)
+ {
+   const reg_entry *preg;
+ 
+   preg = (const reg_entry *) hash_find (preg_hash, preg_name);
+ 
+   if (preg != NULL)
+     return preg->value.preg_val;
+   else
+     return nullpregister;
+ }
+ 
+ /* Get the processor register 'preg_name 32 bit'.  */
+ 
+ static preg
+ get_pregisterp (char *preg_name)
+ {
+   const reg_entry *preg;
+ 
+   preg = (const reg_entry *) hash_find (pregp_hash, preg_name);
+ 
+   if (preg != NULL)
+     return preg->value.preg_val;
+   else
+     return nullpregister;
+ }
+ 
+ 
+ /* Round up a section size to the appropriate boundary.  */
+ 
+ valueT
+ md_section_align (segT seg, valueT val)
+ {
+   /* Round .text section to a multiple of 2.  */
+   if (seg == text_section)
+     return (val + 1) & ~1;
+   return val;
+ }
+ 
+ /* Parse an operand that is machine-specific (remove '*').  */
+ 
+ void
+ md_operand (expressionS * exp)
+ {
+   char c = *input_line_pointer;
+ 
+   switch (c)
+     {
+       case '*':
+         input_line_pointer++;
+         expression (exp);
+         break;
+       default:
+         break;
+     }
+ }
+ 
+ /* Reset global variables before parsing a new instruction.  */
+ 
+ static void
+ reset_vars (char *op)
+ {
+   cur_arg_num = relocatable = 0;
+   memset (& output_opcode, '\0', sizeof (output_opcode));
+ 
+   /* Save a copy of the original OP (used in error messages).  */
+   strncpy (ins_parse, op, sizeof ins_parse - 1);
+   ins_parse [sizeof ins_parse - 1] = 0;
+ }
+ 
+ /* This macro decides whether a particular reloc is an entry in a
+    switch table.  It is used when relaxing, because the linker needs
+    to know about all such entries so that it can adjust them if
+    necessary.  */
+ 
+ #define SWITCH_TABLE(fix)                                  \
+   (   (fix)->fx_addsy != NULL                              \
+    && (fix)->fx_subsy != NULL                              \
+    && S_GET_SEGMENT ((fix)->fx_addsy) ==                   \
+       S_GET_SEGMENT ((fix)->fx_subsy)                      \
+    && S_GET_SEGMENT (fix->fx_addsy) != undefined_section   \
+    && (   (fix)->fx_r_type == BFD_RELOC_CR16_NUM8          \
+        || (fix)->fx_r_type == BFD_RELOC_CR16_NUM16         \
+        || (fix)->fx_r_type == BFD_RELOC_CR16_NUM32         \
+        || (fix)->fx_r_type == BFD_RELOC_CR16_NUM32a))
+ 
+ /* See whether we need to force a relocation into the output file.
+    This is used to force out switch and PC relative relocations when
+    relaxing.  */
+ 
+ int
+ cr16_force_relocation (fixS *fix)
+ {
+   /* REVISIT: Check if the "SWITCH_TABLE (fix)" should be added 
+      if (generic_force_reloc (fix) || SWITCH_TABLE (fix))  */
+   if (generic_force_reloc (fix))
+     return 1;
+ 
+   return 0;
+ }
+ 
+ /* Record a fixup for a cons expression.  */
+ 
+ void
+ cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp)
+ {
+   int rtype;
+   switch (len)
+     {
+       case 1: rtype = BFD_RELOC_CR16_NUM8 ; break;
+       case 2: rtype = BFD_RELOC_CR16_NUM16; break;
+       case 4: 
+         {
+           if (code_label) 
+             {
+               rtype = BFD_RELOC_CR16_NUM32a;
+               code_label = 0;
+             }
+           else 
+             rtype = BFD_RELOC_CR16_NUM32;
+         }
+         break;
+       default: rtype = BFD_RELOC_NONE; break;
+     }
+   fix_new_exp(frag,offset,len,exp,0,rtype);
+ }
+ 
+ /* Generate a relocation entry for a fixup.  */
+ 
+ arelent *
+ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
+ {
+   arelent * reloc;
+ 
+   reloc = xmalloc (sizeof (arelent));
+   reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
+   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
+   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
+   reloc->addend = fixP->fx_offset;
+ 
+   if (fixP->fx_subsy != NULL)
+     {
+       if (SWITCH_TABLE (fixP))
+         {
+           /* Keep the current difference in the addend.  */
+           reloc->addend = (S_GET_VALUE (fixP->fx_addsy)
+                            - S_GET_VALUE (fixP->fx_subsy) + fixP->fx_offset);
+ 
+           switch (fixP->fx_r_type)
+             {
+               case BFD_RELOC_CR16_NUM8:
+                 fixP->fx_r_type = BFD_RELOC_CR16_NUM8;
+                 break;
+               case BFD_RELOC_CR16_NUM16:
+                 fixP->fx_r_type = BFD_RELOC_CR16_NUM16;
+                 break;
+               case BFD_RELOC_CR16_NUM32:
+                 fixP->fx_r_type = BFD_RELOC_CR16_NUM32;
+                 break;
+               case BFD_RELOC_CR16_NUM32a:
+                 fixP->fx_r_type = BFD_RELOC_CR16_NUM32a;
+                 break;
+               default:
+                 abort ();
+                 break;
+             }
+         }
+       else
+         {
+           /* We only resolve difference expressions in the same section.  */
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("can't resolve `%s' {%s section} - `%s' {%s section}"),
+                         fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
+                         segment_name (fixP->fx_addsy
+                                       ? S_GET_SEGMENT (fixP->fx_addsy)
+                                       : absolute_section),
+                         S_GET_NAME (fixP->fx_subsy),
+                         segment_name (S_GET_SEGMENT (fixP->fx_addsy)));
+         }
+     }
+ 
+   assert ((int) fixP->fx_r_type > 0);
+   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+ 
+   if (reloc->howto == (reloc_howto_type *) NULL)
+     {
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("internal error: reloc %d (`%s') not supported by object file format"),
+                     fixP->fx_r_type,
+                     bfd_get_reloc_code_name (fixP->fx_r_type));
+       return NULL;
+     }
+   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
+ 
+   return reloc;
+ }
+ 
+ /* Prepare machine-dependent frags for relaxation.  */
+ 
+ int
+ md_estimate_size_before_relax (fragS *fragp, asection *seg)
+ {
+   /* If symbol is undefined or located in a different section,
+      select the largest supported relocation.  */
+   relax_substateT subtype;
+   relax_substateT rlx_state[] = {0, 2};
+ 
+   for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
+     {
+       if (fragp->fr_subtype == rlx_state[subtype]
+           && (!S_IS_DEFINED (fragp->fr_symbol)
+               || seg != S_GET_SEGMENT (fragp->fr_symbol)))
+         {
+           fragp->fr_subtype = rlx_state[subtype + 1];
+           break;
+         }
+     }
+ 
+   if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
+     abort ();
+ 
+   return md_relax_table[fragp->fr_subtype].rlx_length;
+ }
+ 
+ void
+ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
+ {
+   /* 'opcode' points to the start of the instruction, whether
+      we need to change the instruction's fixed encoding.  */
+   bfd_reloc_code_real_type reloc = BFD_RELOC_NONE;
+ 
+   subseg_change (sec, 0);
+ 
+   fix_new (fragP, fragP->fr_fix,
+            bfd_get_reloc_size (bfd_reloc_type_lookup (stdoutput, reloc)),
+            fragP->fr_symbol, fragP->fr_offset, 1, reloc);
+   fragP->fr_var = 0;
+   fragP->fr_fix += md_relax_table[fragP->fr_subtype].rlx_length;
+ }
+ 
+ /* Process machine-dependent command line options.  Called once for
+    each option on the command line that the machine-independent part of
+    GAS does not understand.  */
+ 
+ int
+ md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
+ {
+   return 0;
+ }
+ 
+ /* Machine-dependent usage-output.  */
+ 
+ void
+ md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
+ {
+   return;
+ }
+ 
+ /* Turn a string in input_line_pointer into a floating point constant
+    of type TYPE, and store the appropriate bytes in *LITP.  The number
+    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
+    returned, or NULL on OK.  */
+ 
+ char *
+ md_atof (int type, char *litP, int *sizeP)
+ {
+   int prec,i;
+   LITTLENUM_TYPE words[4];
+   char *t;
+ 
+   switch (type)
+     {
+       case 'f':
+         prec = 2;
+         break;
+ 
+       case 'd':
+         prec = 4;
+         break;
+ 
+       default:
+         *sizeP = 0;
+         return _("bad call to md_atof");
+     }
+ 
+   t = atof_ieee (input_line_pointer, type, words);
+   if (t)
+     input_line_pointer = t;
+ 
+   *sizeP = prec * 2;
+ 
+   if (! target_big_endian)
+     {
+       for (i = prec - 1; i >= 0; i--)
+         {
+           md_number_to_chars (litP, (valueT) words[i], 2);
+           litP += 2;
+         }
+     }
+   else
+     {
+       for (i = 0; i < prec; i++)
+         {
+           md_number_to_chars (litP, (valueT) words[i], 2);
+           litP += 2;
+         }
+     }
+ 
+   return NULL;
+ }
+ 
+ /* Apply a fixS (fixup of an instruction or data that we didn't have
+    enough info to complete immediately) to the data in a frag.
+    Since linkrelax is nonzero and TC_LINKRELAX_FIXUP is defined to disable
+    relaxation of debug sections, this function is called only when
+    fixuping relocations of debug sections.  */
+ 
+ void
+ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
+ {
+   valueT val = * valP;
+   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+   fixP->fx_offset = 0;
+ 
+   switch (fixP->fx_r_type)
+     {
+       case BFD_RELOC_CR16_NUM8:
+         bfd_put_8 (stdoutput, (unsigned char) val, buf);
+         break;
+       case BFD_RELOC_CR16_NUM16:
+         bfd_put_16 (stdoutput, val, buf);
+         break;
+       case BFD_RELOC_CR16_NUM32:
+         bfd_put_32 (stdoutput, val, buf);
+         break;
+       case BFD_RELOC_CR16_NUM32a:
+         bfd_put_32 (stdoutput, val, buf);
+         break;
+       default:
+         /* We shouldn't ever get here because linkrelax is nonzero.  */
+         abort ();
+         break;
+     }
+ 
+   fixP->fx_done = 0;
+ 
+   if (fixP->fx_addsy == NULL
+       && fixP->fx_pcrel == 0)
+     fixP->fx_done = 1;
+ 
+   if (fixP->fx_pcrel == 1
+       && fixP->fx_addsy != NULL
+       && S_GET_SEGMENT (fixP->fx_addsy) == seg)
+     fixP->fx_done = 1;
+ }
+ 
+ /* The location from which a PC relative jump should be calculated,
+    given a PC relative reloc.  */
+ 
+ long
+ md_pcrel_from (fixS *fixp)
+ {
+   return fixp->fx_frag->fr_address + fixp->fx_where;
+ }
+ 
+ /* This function is called once, at assembler startup time.  This should
+    set up all the tables, etc that the MD part of the assembler needs.  */
+ 
+ void
+ md_begin (void)
+ {
+   const char *hashret = NULL;
+   int i = 0;
+ 
+   /* Set up a hash table for the instructions.  */
+   if ((cr16_inst_hash = hash_new ()) == NULL)
+     as_fatal (_("Virtual memory exhausted"));
+   
+   while (cr16_instruction[i].mnemonic != NULL)
+     {
+       const char *mnemonic = cr16_instruction[i].mnemonic;
+ 
+       hashret = hash_insert (cr16_inst_hash, mnemonic,
+         (PTR) &cr16_instruction[i]);
+ 
+       if (hashret != NULL && *hashret != '\0')
+         as_fatal (_("Can't hash `%s': %s\n"), cr16_instruction[i].mnemonic,
+                   *hashret == 0 ? _("(unknown reason)") : hashret);
+ 
+       /* Insert unique names into hash table.  The CR16 instruction set
+          has many identical opcode names that have different opcodes based
+          on the operands.  This hash table then provides a quick index to
+          the first opcode with a particular name in the opcode table.  */
+       do
+         {
+           ++i;
+         }
+       while (cr16_instruction[i].mnemonic != NULL
+              && streq (cr16_instruction[i].mnemonic, mnemonic));
+     }
+ 
+   /* Initialize reg_hash hash table.  */
+   if ((reg_hash = hash_new ()) == NULL)
+     as_fatal (_("Virtual memory exhausted"));
+   {
+     const reg_entry *regtab;
+ 
+     for (regtab = cr16_regtab;
+          regtab < (cr16_regtab + NUMREGS); regtab++)
+       {
+         hashret = hash_insert (reg_hash, regtab->name, (PTR) regtab);
+         if (hashret)
+           as_fatal (_("Internal Error:  Can't hash %s: %s"),
+                     regtab->name,
+                     hashret);
+       }
+   }
+ 
+   /* Initialize regp_hash hash table.  */
+   if ((regp_hash = hash_new ()) == NULL)
+     as_fatal (_("Virtual memory exhausted"));
+   {
+     const reg_entry *regptab;
+ 
+     for (regptab = cr16_regptab;
+          regptab < (cr16_regptab + NUMREGPS); regptab++)
+       {
+         hashret = hash_insert (regp_hash, regptab->name, (PTR) regptab);
+         if (hashret)
+           as_fatal (_("Internal Error:  Can't hash %s: %s"),
+                     regptab->name,
+                     hashret);
+       }
+   }
+ 
+   /* Initialize preg_hash hash table.  */
+   if ((preg_hash = hash_new ()) == NULL)
+     as_fatal (_("Virtual memory exhausted"));
+ 
+   {
+     const reg_entry *pregtab;
+ 
+     for (pregtab = cr16_pregtab; pregtab < (cr16_pregtab + NUMPREGS);
+          pregtab++)
+       {
+         hashret = hash_insert (preg_hash, pregtab->name, (PTR) pregtab);
+         if (hashret)
+           as_fatal (_("Internal Error:  Can't hash %s: %s"),
+                     pregtab->name,
+                     hashret);
+       }
+   }
+   /* Initialize pregp_hash hash table.  */
+   if ((pregp_hash = hash_new ()) == NULL)
+     as_fatal (_("Virtual memory exhausted"));
+ 
+   {
+     const reg_entry *pregptab;
+ 
+     for (pregptab = cr16_pregptab; pregptab < (cr16_pregptab + NUMPREGPS);
+          pregptab++)
+       {
+         hashret = hash_insert (pregp_hash, pregptab->name, (PTR) pregptab);
+         if (hashret)
+           as_fatal (_("Internal Error:  Can't hash %s: %s"),
+                     pregptab->name,
+                     hashret);
+       }
+   }
+   /*  Set linkrelax here to avoid fixups in most sections.  */
+   linkrelax = 1;
+ }
+ 
+ /* Process constants (immediate/absolute) 
+    and labels (jump targets/Memory locations).  */
+ 
+ static void
+ process_label_constant (char *str, ins * cr16_ins)
+ {
+   char *saved_input_line_pointer;
+   int symbol_with_at = 0,symbol_with_s = 0,symbol_with_m = 0,symbol_with_l = 0;
+   argument *cur_arg = &cr16_ins->arg[cur_arg_num];  /* Current argument.  */
+ 
+   saved_input_line_pointer = input_line_pointer;
+   input_line_pointer = str;
+ 
+   expression (&cr16_ins->exp);
+ 
+   switch (cr16_ins->exp.X_op)
+     {
+       case O_big:
+       case O_absent:
+         /* Missing or bad expr becomes absolute 0.  */
+         as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
+                   str);
+         cr16_ins->exp.X_op = O_constant;
+         cr16_ins->exp.X_add_number = 0;
+         cr16_ins->exp.X_add_symbol = (symbolS *) 0;
+         cr16_ins->exp.X_op_symbol = (symbolS *) 0;
+         /* Fall through.  */
+ 
+       case O_constant:
+         cur_arg->X_op = O_constant;
+         cur_arg->constant = cr16_ins->exp.X_add_number;
+         break;
+ 
+       case O_symbol:
+       case O_subtract:
+       case O_add:
+         cur_arg->X_op = O_symbol;
+         cr16_ins->rtype = BFD_RELOC_NONE;
+         relocatable = 1;
+ 
+       if (strneq (input_line_pointer, "@c", 2)) 
+          symbol_with_at = 1;
+ 
+       if (strneq (input_line_pointer, "@l", 2) ||
+           strneq (input_line_pointer, ":l", 2))
+          symbol_with_l = 1;
+ 
+       if (strneq (input_line_pointer, "@m", 2) ||
+           strneq (input_line_pointer, ":m", 2))
+          symbol_with_m = 1;
+ 
+       if (strneq (input_line_pointer, "@s", 2) ||
+           strneq (input_line_pointer, ":s", 2))
+          symbol_with_s = 1;
+ 
+       switch (cur_arg->type)
+         {
+           case arg_cr:
+             if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+               {
+                 if (cur_arg->size == 20) 
+                    cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+                 else 
+                   cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
+               }
+             break;
+ 
+           case arg_crp:
+             if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+               switch (instruction->size)
+                 {
+                   case 1: 
+                     switch(cur_arg->size)
+                       {
+                         case 0: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0;break;
+                         case 4: 
+                           if (IS_INSN_MNEMONIC("loadb")||IS_INSN_MNEMONIC("storb"))
+                             cr16_ins->rtype = BFD_RELOC_CR16_REGREL4;
+                           else  
+                             cr16_ins->rtype = BFD_RELOC_CR16_REGREL4a;
+                           break;
+                         default: break;
+                       }
+                     break;
+                   case 2: cr16_ins->rtype = BFD_RELOC_CR16_REGREL16; break;
+                   case 3:
+                     {
+                       if (cur_arg->size == 20)
+                         cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+                       else
+                          cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
+                     }
+                     break;
+                   default: break;
+                 }
+               break;
+ 
+           case arg_idxr:
+             if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+               cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+             break;
+ 
+           case arg_idxrp:
+             if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+               switch(instruction->size)
+                 {
+                   case 1: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0; break;
+                   case 2: cr16_ins->rtype = BFD_RELOC_CR16_REGREL14; break;
+                   case 3: cr16_ins->rtype = BFD_RELOC_CR16_REGREL20; break;
+                   default: break;
+                 }
+             break;
+ 
+           case arg_c:
+             if (IS_INSN_MNEMONIC ("bal"))
+               cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
+             else if (IS_INSN_TYPE (BRANCH_INS))
+               {
+                 if (symbol_with_s)
+                   cr16_ins->rtype = BFD_RELOC_CR16_DISP8;
+                 else if (symbol_with_m)
+                   cr16_ins->rtype = BFD_RELOC_CR16_DISP16;
+                 else 
+                   cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
+               }
+             else if (IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (LD_STOR_INS)
+                      || IS_INSN_TYPE (CSTBIT_INS))
+                    {
+                      if (symbol_with_s)
+                        as_bad (_("operand %d: illegal use expression: `%s`"), cur_arg_num+1,str);
+                      if (symbol_with_m)
+                        cr16_ins->rtype = BFD_RELOC_CR16_ABS20;
+                      else /* Default to (symbol_with_l) */
+                        cr16_ins->rtype = BFD_RELOC_CR16_ABS24;
+                    }
+             else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
+                    cr16_ins->rtype = BFD_RELOC_CR16_DISP4;
+           break;
+ 
+         case arg_ic:
+           if (IS_INSN_TYPE (ARITH_INS))
+             {
+               if (symbol_with_s)
+                 cr16_ins->rtype = BFD_RELOC_CR16_IMM4; 
+               else if (symbol_with_m)
+                 cr16_ins->rtype = BFD_RELOC_CR16_IMM20; 
+               else if (symbol_with_at)
+                 cr16_ins->rtype = BFD_RELOC_CR16_IMM32a; 
+               else /* Default to (symbol_with_l) */
+                 cr16_ins->rtype = BFD_RELOC_CR16_IMM32; 
+             }
+           else if (IS_INSN_TYPE (ARITH_BYTE_INS))
+                  {
+                    cr16_ins->rtype = BFD_RELOC_CR16_IMM16;
+                  }
+           break;
+         default:
+           break;
+       }
+       break;
+ 
+       default:
+         cur_arg->X_op = cr16_ins->exp.X_op;
+         break;
+     }
+ 
+   input_line_pointer = saved_input_line_pointer;
+   return;
+ }
+ 
+ /* Parsing different types of operands
+    -> constants             Immediate/Absolute/Relative numbers
+    -> Labels                Relocatable symbols
+    -> (reg pair base)       Register pair base
+    -> (rbase)               Register base
+    -> disp(rbase)           Register relative
+    -> [rinx]disp(reg pair)  Register index with reg pair mode 
+    -> disp(rbase,ridx,scl)  Register index mode  */
+ 
+ static void
+ set_operand (char *operand, ins * cr16_ins)
+ {
+   char *operandS; /* Pointer to start of sub-opearand.  */
+   char *operandE; /* Pointer to end of sub-opearand.  */
+ 
+   argument *cur_arg = &cr16_ins->arg[cur_arg_num]; /* Current argument.  */
+ 
+   /* Initialize pointers.  */
+   operandS = operandE = operand;
+ 
+   switch (cur_arg->type)
+     {
+     case arg_ic:    /* Case $0x18.  */
+       operandS++;
+     case arg_c:     /* Case 0x18.  */
+       /* Set constant.  */
+       process_label_constant (operandS, cr16_ins);
+       
+       if (cur_arg->type != arg_ic)
+         cur_arg->type = arg_c;
+       break;
+ 
+     case arg_icr:   /* Case $0x18(r1).  */
+       operandS++;
+     case arg_cr:    /* Case 0x18(r1).   */
+       /* Set displacement constant.  */
+       while (*operandE != '(')
+         operandE++;
+       *operandE = '\0';
+       process_label_constant (operandS, cr16_ins);
+       operandS = operandE;    
+     case arg_rbase: /* Case (r1) or (r1,r0).  */
+       operandS++;
+       /* Set register base.  */
+       while (*operandE != ')')
+         operandE++;
+       *operandE = '\0';
+       if ((cur_arg->r = get_register (operandS)) == nullregister)
+          as_bad (_("Illegal register `%s' in Instruction `%s'"),
+               operandS, ins_parse);
+ 
+       /* set the arg->rp, if reg is "r12" or "r13" or "14" or "15" */
+       if ((cur_arg->type != arg_rbase) && 
+           ((getreg_image(cur_arg->r) == 12)||(getreg_image(cur_arg->r) == 13)||
+            (getreg_image(cur_arg->r) == 14)||(getreg_image(cur_arg->r) == 15)))
+          {
+            cur_arg->type = arg_crp;
+            cur_arg->rp = cur_arg->r;
+          }
+       break;
+ 
+     case arg_crp:    /* Case 0x18(r1,r0).   */
+       /* Set displacement constant.  */
+       while (*operandE != '(')
+         operandE++;
+       *operandE = '\0';
+       process_label_constant (operandS, cr16_ins);
+       operandS = operandE;    
+       operandS++;
+       /* Set register pair base.  */
+       while (*operandE != ')')
+         operandE++;
+       *operandE = '\0';
+       if ((cur_arg->rp = get_register_pair (operandS)) == nullregister)
+          as_bad (_("Illegal register pair `%s' in Instruction `%s'"),
+               operandS, ins_parse);
+       break;
+ 
+     case arg_idxr:
+       /* Set register pair base.  */
+       if ((strchr(operandS,'(') != NULL))
+         {
+          while ((*operandE != '(') && (! ISSPACE (*operandE)))
+            operandE++;
+          if ((cur_arg->rp = get_index_register_pair (operandE)) == nullregister)
+               as_bad (_("Illegal register pair `%s' in Instruction `%s'"),
+                             operandS, ins_parse);
+          *operandE++ = '\0';
+          cur_arg->type = arg_idxrp;
+         }
+         else 
+           cur_arg->rp = -1;
+ 
+        operandE = operandS;
+       /* Set displacement constant.  */
+       while (*operandE != ']')
+         operandE++;
+       process_label_constant (++operandE, cr16_ins);
+       *operandE++ = '\0';
+       operandE = operandS;
+ 
+       /* Set index register .  */
+       operandS = strchr(operandE,'[');
+       if (operandS != NULL )
+         { /* Eliminate '[', detach from rest of operand.  */
+           *operandS++ = '\0';
+ 
+           operandE = strchr (operandS, ']');
+ 
+           if (operandE == NULL)
+             as_bad (_("unmatched '['"));
+           else
+             { /* Eliminate ']' and make sure it was the last thing
+                  in the string.  */
+               *operandE = '\0';
+               if (*(operandE + 1) != '\0')
+                 as_bad (_("garbage after index spec ignored"));
+             }
+         }
+ 
+       if ((cur_arg->i_r = get_index_register (operandS)) == nullregister)
+         as_bad (_("Illegal register `%s' in Instruction `%s'"),
+                 operandS, ins_parse);
+       *operandE = '\0';
+       *operandS = '\0';
+       break;
+ 
+     default:
+       break;
+     }
+ }
+ 
+ /* Parse a single operand.
+    operand - Current operand to parse.
+    cr16_ins - Current assembled instruction.  */
+ 
+ static void
+ parse_operand (char *operand, ins * cr16_ins)
+ {
+   int ret_val;
+ 
+   argument *cur_arg = &cr16_ins->arg[cur_arg_num]; /* Current argument.  */
+ 
+   /* Initialize the type to NULL before parsing.  */
+   cur_arg->type = nullargs;
+ 
+   /* Check whether this is a condition code .  */
+   if ((IS_INSN_MNEMONIC("b")) && ((ret_val = get_cc (operand)) != -1))
+     {
+       cur_arg->type = arg_cc;
+       cur_arg->cc = ret_val;
+       cur_arg->X_op = O_register;
+       return;
+     }
+ 
+ 
+   /* Check whether this is a general processor register.  */
+   if ((ret_val = get_register (operand)) != nullregister)
+     {
+       cur_arg->type = arg_r;
+       cur_arg->r = ret_val;
+       cur_arg->X_op = 0;
+       return;
+     }
+ 
+   /* Check whether this is a general processor register pair.  */
+   if ((operand[0] == '(') && 
+       ((ret_val = get_register_pair (operand)) != nullregister))
+     {
+       cur_arg->type = arg_rp;
+       cur_arg->rp = ret_val;
+       cur_arg->X_op = O_register;
+       return;
+     }
+ 
+   /* Check whether the operand is a processor register.
+      For "lprd" and "sprd" instruction, only 32 bit
+      processor registers used */
+   if (!(IS_INSN_MNEMONIC("lprd") || (IS_INSN_MNEMONIC("sprd"))) &&
+       ((ret_val = get_pregister (operand)) != nullpregister))
+     {
+       cur_arg->type = arg_pr;
+       cur_arg->pr = ret_val;
+       cur_arg->X_op = O_register;
+       return;
+     }
+ 
+   /* Check whether this is a processor register - 32 bit.  */
+   if ((ret_val = get_pregisterp (operand)) != nullpregister)
+     {
+       cur_arg->type = arg_prp;
+       cur_arg->prp = ret_val;
+       cur_arg->X_op = O_register;
+       return;
+     }
+ 
+ 
+   /* Deal with special characters.  */
+   switch (operand[0])
+     {
+       case '$':
+         if (strchr (operand, '(') != NULL)
+           cur_arg->type = arg_icr;
+         else
+           cur_arg->type = arg_ic;
+         goto set_params;
+         break;
+ 
+       case '(':
+         cur_arg->type = arg_rbase;
+         goto set_params;
+         break;
+ 
+       case '[':
+         cur_arg->type = arg_idxr;
+         goto set_params;
+         break;
+ 
+       default:
+         break;
+     }
+       
+   if (strchr (operand, '(') != NULL)
+     {
+       if (strchr (operand, ',') != NULL
+           && (strchr (operand, ',') > strchr (operand, '(')))
+         cur_arg->type = arg_crp;
+       else
+         cur_arg->type = arg_cr;
+     }
+   else
+     cur_arg->type = arg_c;
+   goto set_params;
+ 
+ /* Parse an operand according to its type.  */
+ set_params:
+   cur_arg->constant = 0;
+   set_operand (operand, cr16_ins);
+ }
+ 
+ /* Parse the various operands. Each operand is then analyzed to fillup 
+    the fields in the cr16_ins data structure.  */
+ 
+ static void
+ parse_operands (ins * cr16_ins, char *operands)
+ {
+   char *operandS;            /* Operands string.  */
+   char *operandH, *operandT; /* Single operand head/tail pointers.  */
+   int allocated = 0;         /* Indicates a new operands string was allocated.*/
+   char *operand[MAX_OPERANDS];/* Separating the operands.  */
+   int op_num = 0;             /* Current operand number we are parsing.  */
+   int bracket_flag = 0;       /* Indicates a bracket '(' was found.  */
+   int sq_bracket_flag = 0;    /* Indicates a square bracket '[' was found.  */
+ 
+   /* Preprocess the list of registers, if necessary.  */
+   operandS = operandH = operandT = operands;
+ 
+   while (*operandT != '\0')
+     {
+       if (*operandT == ',' && bracket_flag != 1 && sq_bracket_flag != 1)
+         {
+           *operandT++ = '\0';
+           operand[op_num++] = strdup (operandH);
+           operandH = operandT;
+           continue;
+         }
+ 
+       if (*operandT == ' ')
+         as_bad (_("Illegal operands (whitespace): `%s'"), ins_parse);
+ 
+       if (*operandT == '(')
+         bracket_flag = 1;
+       else if (*operandT == '[')
+         sq_bracket_flag = 1;
+ 
+       if (*operandT == ')')
+         {
+           if (bracket_flag)
+             bracket_flag = 0;
+           else
+             as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
+         }
+       else if (*operandT == ']')
+         {
+           if (sq_bracket_flag)
+             sq_bracket_flag = 0;
+           else
+             as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
+         }
+ 
+       if (bracket_flag == 1 && *operandT == ')')
+         bracket_flag = 0;
+       else if (sq_bracket_flag == 1 && *operandT == ']')
+         sq_bracket_flag = 0;
+ 
+       operandT++;
+     }
+ 
+   /* Adding the last operand.  */
+   operand[op_num++] = strdup (operandH);
+   cr16_ins->nargs = op_num;
+ 
+   /* Verifying correct syntax of operands (all brackets should be closed).  */
+   if (bracket_flag || sq_bracket_flag)
+     as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
+ 
+   /* Now we parse each operand separately.  */
+   for (op_num = 0; op_num < cr16_ins->nargs; op_num++)
+     {
+       cur_arg_num = op_num;
+       parse_operand (operand[op_num], cr16_ins);
+       free (operand[op_num]);
+     }
+ 
+   if (allocated)
+     free (operandS);
+ }
+ 
+ /* Get the trap index in dispatch table, given its name.
+    This routine is used by assembling the 'excp' instruction.  */
+ 
+ static int
+ gettrap (char *s)
+ {
+   const trap_entry *trap;
+ 
+   for (trap = cr16_traps; trap < (cr16_traps + NUMTRAPS); trap++)
+     if (strcasecmp (trap->name, s) == 0)
+       return trap->entry;
+ 
+   /* To make compatable with CR16 4.1 tools, the below 3-lines of 
+    * code added. Refer: Development Tracker item #123 */
+   for (trap = cr16_traps; trap < (cr16_traps + NUMTRAPS); trap++)
+     if (trap->entry  == (unsigned int)atoi(s)) 
+       return trap->entry;
+ 
+   as_bad (_("Unknown exception: `%s'"), s);
+   return 0;
+ }
+ 
+ /* Top level module where instruction parsing starts.
+    cr16_ins - data structure holds some information.
+    operands - holds the operands part of the whole instruction.  */
+ 
+ static void
+ parse_insn (ins *insn, char *operands)
+ {
+   int i;
+ 
+   /* Handle instructions with no operands.  */
+   for (i = 0; no_op_insn[i] != NULL; i++)
+   {
+     if (streq (no_op_insn[i], instruction->mnemonic))
+     {
+       insn->nargs = 0;
+       return;
+     }
+   }
+ 
+   /* Handle 'excp' instructions.  */
+   if (IS_INSN_MNEMONIC ("excp"))
+     {
+       insn->nargs = 1;
+       insn->arg[0].type = arg_ic;
+       insn->arg[0].constant = gettrap (operands);
+       insn->arg[0].X_op = O_constant;
+       return;
+     }
+ 
+   if (operands != NULL)
+     parse_operands (insn, operands);
+ }
+ 
+ /* bCC instruction requires special handling.  */
+ static char *
+ get_b_cc (char * op)
+ {
+   unsigned int i;
+   char op1[5];
+   for (i = 1; i < strlen (op); i++)
+      op1[i-1] = op[i];
+ 
+   op1[i-1] = '\0';
+ 
+   for (i = 0; i < cr16_num_cc ; i++)
+     {
+       if (streq (op1, cr16_b_cond_tab[i]))
+         return (char *)cr16_b_cond_tab[i];
+     }
+ 
+    return NULL;
+ }
+ 
+ /* bCC instruction requires special handling.  */
+ static int
+ is_bcc_insn (char * op)
+ {
+   if (!(streq(op,"bal") || streq(op,"beq0b") || streq(op,"bnq0b") ||
+         streq(op,"beq0w") || streq(op,"bnq0w")))
+     if ((op[0] == 'b') && (get_b_cc(op) != NULL))
+       return 1;
+   return 0;
+ }
+ 
+ /* Cinv instruction requires special handling.  */
+ 
+ static int
+ check_cinv_options (char * operand)
+ {
+   char *p = operand;
+   int i_used = 0, u_used = 0, d_used = 0;
+ 
+   while (*++p != ']')
+     {
+       if (*p == ',' || *p == ' ')
+         continue;
+ 
+       else if (*p == 'i')
+         i_used = 1;
+       else if (*p == 'u')
+         u_used = 1;
+       else if (*p == 'd')
+         d_used = 1;
+       else
+         as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
+     }
+ 
+   return (0);
+ }
+ 
+ /* Retrieve the opcode image of a given register.
+    If the register is illegal for the current instruction,
+    issue an error.  */
+ 
+ static int
+ getreg_image (reg r)
+ {
+   const reg_entry *reg;
+   char *reg_name;
+   int is_procreg = 0; /* Nonzero means argument should be processor reg.  */
+ 
+   /* Check whether the register is in registers table.  */
+   if (r < MAX_REG)
+     reg = &cr16_regtab[r];
+   else /* Register not found.  */
+     {
+       as_bad (_("Unknown register: `%d'"), r);
+       return 0;
+     }
+ 
+   reg_name = reg->name;
+ 
+ /* Issue a error message when register is illegal.  */
+ #define IMAGE_ERR \
+   as_bad (_("Illegal register (`%s') in Instruction: `%s'"), \
+             reg_name, ins_parse);                            \
+   break;
+ 
+   switch (reg->type)
+     {
+       case CR16_R_REGTYPE:
+         if (! is_procreg)
+           return reg->image;
+         else
+           IMAGE_ERR;
+ 
+       case CR16_P_REGTYPE:
+         return reg->image;
+         break;
+ 
+       default:
+         IMAGE_ERR;
+     }
+ 
+   return 0;
+ }
+ 
+ /* Retrieve the opcode image of a given register pair.
+    If the register is illegal for the current instruction,
+    issue an error.  */
+ 
+ static int
+ getregp_image (reg r)
+ {
+   const reg_entry *reg;
+   char *reg_name;
+ 
+   /* Check whether the register is in registers table.  */
+   if (r < MAX_REG)
+     reg = &cr16_regptab[r];
+   /* Register not found.  */
+   else
+     {
+       as_bad (_("Unknown register pair: `%d'"), r);
+       return 0;
+     }
+ 
+   reg_name = reg->name;
+ 
+ /* Issue a error message when register  pair is illegal.  */
+ #define RPAIR_IMAGE_ERR \
+   as_bad (_("Illegal register pair (`%s') in Instruction: `%s'"), \
+             reg_name, ins_parse);                                 \
+   break;
+ 
+   switch (reg->type)
+     {
+       case CR16_RP_REGTYPE:
+         return reg->image;
+       default:
+         RPAIR_IMAGE_ERR;
+     }
+ 
+   return 0;
+ }
+ 
+ /* Retrieve the opcode image of a given index register pair.
+    If the register is illegal for the current instruction,
+    issue an error.  */
+ 
+ static int
+ getidxregp_image (reg r)
+ {
+   const reg_entry *reg;
+   char *reg_name;
+ 
+   /* Check whether the register is in registers table.  */
+   if (r < MAX_REG)
+     reg = &cr16_regptab[r];
+   /* Register not found.  */
+   else
+     {
+       as_bad (_("Unknown register pair: `%d'"), r);
+       return 0;
+     }
+ 
+   reg_name = reg->name;
+ 
+ /* Issue a error message when register  pair is illegal.  */
+ #define IDX_RPAIR_IMAGE_ERR \
+   as_bad (_("Illegal index register pair (`%s') in Instruction: `%s'"), \
+             reg_name, ins_parse);                                       \
+ 
+   if (reg->type == CR16_RP_REGTYPE)
+     {
+      switch (reg->image)
+        {
+          case 0:  return 0; break;
+          case 2:  return 1; break;
+          case 4:  return 2; break;
+          case 6:  return 3; break;
+          case 8:  return 4; break;
+          case 10: return 5; break;
+          case 3:  return 6; break;
+          case 5:  return 7; break;
+          default:
+            break;
+        }
+     }
+ 
+   IDX_RPAIR_IMAGE_ERR;
+   return 0;
+ }
+ 
+ /* Retrieve the opcode image of a given processort register.
+    If the register is illegal for the current instruction,
+    issue an error.  */
+ static int
+ getprocreg_image (reg r)
+ {
+   const reg_entry *reg;
+   char *reg_name;
+ 
+   /* Check whether the register is in registers table.  */
+   if (r < MAX_PREG)
+     reg = &cr16_pregtab[r - MAX_REG];
+   /* Register not found.  */
+   else
+     {
+       as_bad (_("Unknown processor register : `%d'"), r);
+       return 0;
+     }
+ 
+   reg_name = reg->name;
+ 
+ /* Issue a error message when register  pair is illegal.  */
+ #define PROCREG_IMAGE_ERR \
+   as_bad (_("Illegal processor register (`%s') in Instruction: `%s'"), \
+             reg_name, ins_parse);                                      \
+   break;
+ 
+   switch (reg->type)
+     {
+       case CR16_P_REGTYPE:
+         return reg->image;
+       default:
+         PROCREG_IMAGE_ERR;
+     }
+ 
+   return 0;
+ }
+ 
+ /* Retrieve the opcode image of a given processort register.
+    If the register is illegal for the current instruction,
+    issue an error.  */
+ static int
+ getprocregp_image (reg r)
+ {
+   const reg_entry *reg;
+   char *reg_name;
+   int pregptab_disp = 0;
+ 
+   /* Check whether the register is in registers table.  */
+   if (r < MAX_PREG)
+     {
+       r = r - MAX_REG;
+       switch (r)
+         {
+           case 4: pregptab_disp = 1;  break;
+           case 6: pregptab_disp = 2;  break;
+           case 8:
+           case 9:
+           case 10:
+             pregptab_disp = 3;  break;
+           case 12: 
+             pregptab_disp = 4;  break;
+           case 14: 
+             pregptab_disp = 5;  break;
+           default: break;
+         }
+       reg = &cr16_pregptab[r - pregptab_disp];
+     }
+   /* Register not found.  */
+   else
+     {
+       as_bad (_("Unknown processor register (32 bit) : `%d'"), r);
+       return 0;
+     }
+ 
+   reg_name = reg->name;
+ 
+ /* Issue a error message when register  pair is illegal.  */
+ #define PROCREGP_IMAGE_ERR \
+   as_bad (_("Illegal 32 bit - processor register (`%s') in Instruction: `%s'"),\
+             reg_name, ins_parse);                                              \
+   break;
+ 
+   switch (reg->type)
+     {
+       case CR16_P_REGTYPE:
+         return reg->image;
+       default:
+         PROCREGP_IMAGE_ERR;
+     }
+ 
+   return 0;
+ }
+ 
+ /* Routine used to represent integer X using NBITS bits.  */
+ 
+ static long
+ getconstant (long x, int nbits)
+ {
+   /* The following expression avoids overflow if
+      'nbits' is the number of bits in 'bfd_vma'.  */
+   return (x & ((((1 << (nbits - 1)) - 1) << 1) | 1));
+ }
+ 
+ /* Print a constant value to 'output_opcode':
+    ARG holds the operand's type and value.
+    SHIFT represents the location of the operand to be print into.
+    NBITS determines the size (in bits) of the constant.  */
+ 
+ static void
+ print_constant (int nbits, int shift, argument *arg)
+ {
+   unsigned long mask = 0;
+ 
+   long constant = getconstant (arg->constant, nbits);
+ 
+   switch (nbits)
+     {
+       case 32:
+       case 28:
+         /* mask the upper part of the constant, that is, the bits
+            going to the lowest byte of output_opcode[0].
+            The upper part of output_opcode[1] is always filled,
+            therefore it is always masked with 0xFFFF.  */
+         mask = (1 << (nbits - 16)) - 1;
+         /* Divide the constant between two consecutive words :
+                  0        1         2         3
+             +---------+---------+---------+---------+
+             |         | X X X X | x X x X |         |
+             +---------+---------+---------+---------+
+               output_opcode[0]    output_opcode[1]     */
+ 
+         CR16_PRINT (0, (constant >> WORD_SHIFT) & mask, 0);
+         CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
+         break;
+ 
+       case 21:
+         if ((nbits == 21) && (IS_INSN_TYPE(LD_STOR_INS))) nbits = 20;
+       case 24:
+       case 22:
+       case 20:
+         /* mask the upper part of the constant, that is, the bits
+            going to the lowest byte of output_opcode[0].
+            The upper part of output_opcode[1] is always filled,
+            therefore it is always masked with 0xFFFF.  */
+         mask = (1 << (nbits - 16)) - 1;
+         /* Divide the constant between two consecutive words :
+                  0        1         2          3
+             +---------+---------+---------+---------+
+             |         | X X X X | - X - X |         |
+             +---------+---------+---------+---------+
+               output_opcode[0]    output_opcode[1]     */
+ 
+         if ((instruction->size > 2) && (shift == WORD_SHIFT))
+           {
+             if (arg->type == arg_idxrp)
+               {
+                 CR16_PRINT (0, ((constant >> WORD_SHIFT) & mask) << 8, 0);
+                 CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
+               }   
+             else 
+               {
+                 CR16_PRINT (0, (((((constant >> WORD_SHIFT) & mask) << 8) & 0x0f00) | ((((constant >> WORD_SHIFT) & mask) >> 4) & 0xf)),0);
+                 CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
+               }
+           }
+         else
+           {
+             CR16_PRINT (0, constant, shift);
+           }
+ 
+         break;
+ 
+       case 14:
+         if (arg->type == arg_idxrp)
+           {
+             if (instruction->size == 2)
+               {
+                 CR16_PRINT (0, ((constant)&0xf), shift);         // 0-3 bits
+                 CR16_PRINT (0, ((constant>>4)&0x3), (shift+20)); // 4-5 bits
+                 CR16_PRINT (0, ((constant>>6)&0x3), (shift+14)); // 6-7 bits
+                 CR16_PRINT (0, ((constant>>8)&0x3f), (shift+8)); // 8-13 bits
+               }
+             else
+               CR16_PRINT (0, constant, shift);
+           }
+         break;
+ 
+       case 16:
+       case 12:
+         /* When instruction size is 3 and 'shift' is 16, a 16-bit constant is 
+            always filling the upper part of output_opcode[1]. If we mistakenly 
+            write it to output_opcode[0], the constant prefix (that is, 'match')
+            will be overriden.
+                  0        1         2         3
+             +---------+---------+---------+---------+
+             | 'match' |         | X X X X |         |
+             +---------+---------+---------+---------+
+               output_opcode[0]    output_opcode[1]     */
+ 
+         if ((instruction->size > 2) && (shift == WORD_SHIFT))
+           CR16_PRINT (1, constant, WORD_SHIFT);
+         else
+           CR16_PRINT (0, constant, shift);
+         break;
+ 
+       case 8:
+         CR16_PRINT (0, ((constant/2)&0xf), shift);
+         CR16_PRINT (0, ((constant/2)>>4),  (shift+8));
+         break;
+ 
+       default:
+         CR16_PRINT (0, constant,  shift);
+         break;
+     }
+ }
+ 
+ /* Print an operand to 'output_opcode', which later on will be
+    printed to the object file:
+    ARG holds the operand's type, size and value.
+    SHIFT represents the printing location of operand.
+    NBITS determines the size (in bits) of a constant operand.  */
+ 
+ static void
+ print_operand (int nbits, int shift, argument *arg)
+ {
+   switch (arg->type)
+     {
+       case arg_cc:
+         CR16_PRINT (0, arg->cc, shift);
+         break;
+ 
+       case arg_r:
+         CR16_PRINT (0, getreg_image (arg->r), shift);
+         break;
+ 
+       case arg_rp:
+         CR16_PRINT (0, getregp_image (arg->rp), shift);
+         break;
+ 
+       case arg_pr:
+         CR16_PRINT (0, getprocreg_image (arg->pr), shift);
+         break;
+ 
+       case arg_prp:
+         CR16_PRINT (0, getprocregp_image (arg->prp), shift);
+         break;
+ 
+       case arg_idxrp:
+         /*    16      12      8    6      0
+             +-----------------------------+
+             | r_index | disp  | rp_base   |
+             +-----------------------------+          */
+    
+         if (instruction->size == 3)
+           {
+             CR16_PRINT (0, getidxregp_image (arg->rp), 0);
+             if (getreg_image (arg->i_r) == 12)
+               CR16_PRINT (0, 0, 3);
+             else
+               CR16_PRINT (0, 1, 3);
+           }
+         else
+           {
+             CR16_PRINT (0, getidxregp_image (arg->rp), 16);
+             if (getreg_image (arg->i_r) == 12)
+               CR16_PRINT (0, 0, 19);
+             else
+               CR16_PRINT (0, 1, 19);
+           }
+         print_constant (nbits, shift, arg);
+       break;
+ 
+       case arg_idxr:
+         if (getreg_image (arg->i_r) == 12)
+           if (IS_INSN_MNEMONIC("cbitb") || IS_INSN_MNEMONIC("sbitb") ||
+               IS_INSN_MNEMONIC("tbitb")) 
+             CR16_PRINT (0, 0, 23);
+           else CR16_PRINT (0, 0, 24);
+         else
+           if (IS_INSN_MNEMONIC("cbitb") || IS_INSN_MNEMONIC("sbitb") ||
+               IS_INSN_MNEMONIC("tbitb")) 
+             CR16_PRINT (0, 1, 23);
+           else CR16_PRINT (0, 1, 24);
+ 
+         print_constant (nbits, shift, arg);
+         break;
+ 
+      case arg_ic:
+      case arg_c:
+        print_constant (nbits, shift, arg);
+        break;
+ 
+      case arg_rbase:
+        CR16_PRINT (0, getreg_image (arg->r), shift);
+        break;
+ 
+      case arg_cr:
+        print_constant (nbits, shift , arg);
+       /* Add the register argument to the output_opcode.  */
+       CR16_PRINT (0, getreg_image (arg->r), (shift+16));
+       break;
+ 
+      case arg_crp:
+        print_constant (nbits, shift , arg);
+        if (instruction->size > 1)
+          CR16_PRINT (0, getregp_image (arg->rp), (shift+16));
+        else if (IS_INSN_TYPE(LD_STOR_INS) || (IS_INSN_TYPE(CSTBIT_INS)))
+               {
+                 if (instruction->size == 2)
+                   CR16_PRINT (0, getregp_image (arg->rp), (shift-8));
+                 else if (instruction->size == 1)
+                        CR16_PRINT (0, getregp_image (arg->rp), 16);
+               }
+         else  
+           CR16_PRINT (0, getregp_image (arg->rp), shift);
+        break;
+ 
+      default:
+        break;
+     }
+ }
+ 
+ /* Retrieve the number of operands for the current assembled instruction.  */
+ 
+ static int
+ get_number_of_operands (void)
+ {
+   int i;
+ 
+   for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
+     ;
+   return i;
+ }
+ 
+ /* Verify that the number NUM can be represented in BITS bits (that is,
+    within its permitted range), based on the instruction's FLAGS.
+    If UPDATE is nonzero, update the value of NUM if necessary.
+    Return OP_LEGAL upon success, actual error type upon failure.  */
+ 
+ static op_err
+ check_range (long *num, int bits, int unsigned flags, int update)
+ {
+   long min, max;
+   int retval = OP_LEGAL;
+   long value = *num;
+ 
+   if (bits == 0 && value > 0) return OP_OUT_OF_RANGE;
+ 
+   /* For hosts witah longs bigger than 32-bits make sure that the top 
+      bits of a 32-bit negative value read in by the parser are set,
+      so that the correct comparisons are made.  */
+   if (value & 0x80000000)
+     value |= (-1L << 31);
+ 
+ 
+   /* Verify operand value is even.  */
+   if (flags & OP_EVEN)
+     {
+       if (value % 2)
+         return OP_NOT_EVEN;
+     }
+ 
+   if (flags & OP_DEC)
+     {
+       value -= 1;
+       if (update)
+         *num = value;
+     }
+ 
+   if (flags & OP_SHIFT)
+     {
+       value >>= 1;
+       if (update)
+         *num = value;
+     }
+   else if (flags & OP_SHIFT_DEC)
+     {
+       value = (value >> 1) - 1;
+       if (update)
+         *num = value;
+     }
+ 
+   if (flags & OP_ABS20)
+     {
+       if (value > 0xEFFFF)
+         return OP_OUT_OF_RANGE;
+     }
+ 
+   if (flags & OP_ESC)
+     {
+       if (value == 0xB || value == 0x9)
+         return OP_OUT_OF_RANGE;
+       else if (value == -1)   
+              {
+                if (update) 
+                  *num = 9;
+                return retval;
+              }
+     }
+ 
+   if (flags & OP_ESC1)
+     {
+       if (value > 13)
+         return OP_OUT_OF_RANGE;
+     }
+ 
+ 
+    if (flags & OP_SIGNED)
+      {
+        max = (1 << (bits - 1)) - 1;
+        min = - (1 << (bits - 1));
+        if ((value > max) || (value < min))
+          retval = OP_OUT_OF_RANGE;
+      } 
+    else if (flags & OP_UNSIGNED)
+      {
+        max = ((((1 << (bits - 1)) - 1) << 1) | 1);
+        min = 0;
+        if (((unsigned long) value > (unsigned long) max) 
+             || ((unsigned long) value < (unsigned long) min))
+          retval = OP_OUT_OF_RANGE;
+      }
+    else if (flags & OP_NEG)
+      {
+        max = - 1;
+        min = - ((1 << (bits - 1))-1);
+        if ((value > max) || (value < min))
+          retval = OP_OUT_OF_RANGE;
+      }
+    return retval;
+ }
+ 
+ /* Assemble a single instruction:
+    INSN is already parsed (that is, all operand values and types are set).
+    For instruction to be assembled, we need to find an appropriate template in
+    the instruction table, meeting the following conditions:
+     1: Has the same number of operands.
+     2: Has the same operand types.
+     3: Each operand size is sufficient to represent the instruction's values.
+    Returns 1 upon success, 0 upon failure.  */
+ 
+ static int
+ assemble_insn (char *mnemonic, ins *insn)
+ {
+   /* Type of each operand in the current template.  */
+   argtype cur_type[MAX_OPERANDS];
+   /* Size (in bits) of each operand in the current template.  */
+   unsigned int cur_size[MAX_OPERANDS];
+   /* Flags of each operand in the current template.  */
+   unsigned int cur_flags[MAX_OPERANDS];
+   /* Instruction type to match.  */
+   unsigned int ins_type;
+   /* Boolean flag to mark whether a match was found.  */
+   int match = 0;
+   int i;
+   /* Nonzero if an instruction with same number of operands was found.  */
+   int found_same_number_of_operands = 0;
+   /* Nonzero if an instruction with same argument types was found.  */
+   int found_same_argument_types = 0;
+   /* Nonzero if a constant was found within the required range.  */
+   int found_const_within_range  = 0;
+   /* Argument number of an operand with invalid type.  */
+   int invalid_optype = -1;
+   /* Argument number of an operand with invalid constant value.  */
+   int invalid_const  = -1;
+   /* Operand error (used for issuing various constant error messages).  */
+   op_err op_error, const_err = OP_LEGAL;
+ 
+ /* Retrieve data (based on FUNC) for each operand of a given instruction.  */
+ #define GET_CURRENT_DATA(FUNC, ARRAY)                           \
+   for (i = 0; i < insn->nargs; i++)                             \
+     ARRAY[i] = FUNC (instruction->operands[i].op_type)
+ 
+ #define GET_CURRENT_TYPE    GET_CURRENT_DATA(get_optype, cur_type)
+ #define GET_CURRENT_SIZE    GET_CURRENT_DATA(get_opbits, cur_size)
+ #define GET_CURRENT_FLAGS   GET_CURRENT_DATA(get_opflags, cur_flags)
+ 
+   /* Instruction has no operands -> only copy the constant opcode.   */
+   if (insn->nargs == 0)
+     {
+       output_opcode[0] = BIN (instruction->match, instruction->match_bits);
+       return 1;
+     }
+ 
+   /* In some case, same mnemonic can appear with different instruction types.
+      For example, 'storb' is supported with 3 different types :
+      LD_STOR_INS, LD_STOR_INS_INC, STOR_IMM_INS.
+      We assume that when reaching this point, the instruction type was 
+      pre-determined. We need to make sure that the type stays the same
+      during a search for matching instruction.  */
+   ins_type = CR16_INS_TYPE(instruction->flags);
+ 
+   while (/* Check that match is still not found.  */
+          match != 1
+          /* Check we didn't get to end of table.  */
+          && instruction->mnemonic != NULL
+          /* Check that the actual mnemonic is still available.  */
+          && IS_INSN_MNEMONIC (mnemonic)
+          /* Check that the instruction type wasn't changed.  */
+          && IS_INSN_TYPE(ins_type))
+     {
+       /* Check whether number of arguments is legal.  */
+       if (get_number_of_operands () != insn->nargs)
+         goto next_insn;
+       found_same_number_of_operands = 1;
+ 
+       /* Initialize arrays with data of each operand in current template.  */
+       GET_CURRENT_TYPE;
+       GET_CURRENT_SIZE;
+       GET_CURRENT_FLAGS;
+ 
+       /* Check for type compatibility.  */
+       for (i = 0; i < insn->nargs; i++)
+         {
+           if (cur_type[i] != insn->arg[i].type)
+             {
+               if (invalid_optype == -1)
+                 invalid_optype = i + 1;
+               goto next_insn;
+             }
+         }
+       found_same_argument_types = 1;
+ 
+       for (i = 0; i < insn->nargs; i++)
+         {
+           /* if 'bal' instruction size is '2' and reg operand is not 'ra'
+              then goto next instruction */
+           if (IS_INSN_MNEMONIC("bal") && (i == 0) &&
+              (instruction->size == 2) && (insn->arg[i].rp != 14))
+             goto next_insn;
+ 
+           /* If 'storb' instruction with 'sp' reg and 16-bit disp of 
+            * reg-pair, leads to undifined trap, so this should use 
+            * 20-bit disp of reg-pair. */ 
+           if (IS_INSN_MNEMONIC("storb") && (instruction->size == 2) && 
+              (insn->arg[i].r == 15) && (insn->arg[i+1].type == arg_crp))
+             goto next_insn;
+ 
+           /* Only check range - don't update the constant's value, since the
+              current instruction may not be the last we try to match. 
+              The constant's value will be updated later, right before printing
+              it to the object file.  */
+           if ((insn->arg[i].X_op == O_constant) 
+               && (op_error = check_range (&insn->arg[i].constant, cur_size[i],
+                                           cur_flags[i], 0)))
+             {
+               if (invalid_const == -1)
+                 {
+                   invalid_const = i + 1;
+                   const_err = op_error;
+                 }
+               goto next_insn;
+             }
+           /* For symbols, we make sure the relocation size (which was already 
+              determined) is sufficient.  */
+           else if ((insn->arg[i].X_op == O_symbol)
+                    && ((bfd_reloc_type_lookup (stdoutput,insn->rtype))->bitsize 
+                          > cur_size[i]))
+                   goto next_insn;
+         }
+       found_const_within_range = 1;
+ 
+       /* If we got till here -> Full match is found.  */
+       match = 1;
+       break;
+ 
+ /* Try again with next instruction.  */
+ next_insn:
+       instruction++;
+     }
+ 
+   if (!match)
+     {
+       /* We haven't found a match - instruction can't be assembled.  */
+       if (!found_same_number_of_operands)
+         as_bad (_("Incorrect number of operands"));
+       else if (!found_same_argument_types)
+         as_bad (_("Illegal type of operand (arg %d)"), invalid_optype);
+       else if (!found_const_within_range)
+         {
+           switch (const_err)
+             {
+               case OP_OUT_OF_RANGE:
+                 as_bad (_("Operand out of range (arg %d)"), invalid_const);
+                 break;
+               case OP_NOT_EVEN:
+                 as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
+                 break;
+               default:
+                 as_bad (_("Illegal operand (arg %d)"), invalid_const);
+                 break;
+             }
+         }
+       
+        return 0;
+     }
+   else
+     /* Full match - print the encoding to output file.  */
+     {
+       /* Make further checkings (such that couldn't be made earlier).
+          Warn the user if necessary.  */
+       warn_if_needed (insn);
+       
+       /* Check whether we need to adjust the instruction pointer.  */
+       if (adjust_if_needed (insn))
+         /* If instruction pointer was adjusted, we need to update 
+            the size of the current template operands.  */
+         GET_CURRENT_SIZE;
+ 
+       for (i = 0; i < insn->nargs; i++)
+         {
+           int j = instruction->flags & REVERSE_MATCH ?
+                   i == 0 ? 1 :
+                   i == 1 ? 0 : i :
+                   i;
+ 
+           /* This time, update constant value before printing it.  */
+             if ((insn->arg[j].X_op == O_constant) 
+                && (check_range (&insn->arg[j].constant, cur_size[j],
+                                 cur_flags[j], 1) != OP_LEGAL))
+               as_fatal (_("Illegal operand (arg %d)"), j+1);
+         }
+ 
+       /* First, copy the instruction's opcode.  */
+       output_opcode[0] = BIN (instruction->match, instruction->match_bits);
+ 
+       for (i = 0; i < insn->nargs; i++)
+         {
+          /* For BAL (ra),disp17 instuction only. And also set the
+           * DISP24a relocation type */
+          if (IS_INSN_MNEMONIC ("bal") && (instruction->size == 2) && i == 0) 
+            {
+              insn->rtype = BFD_RELOC_CR16_DISP24a;
+              continue;
+            }
+           cur_arg_num = i;
+           print_operand (cur_size[i], instruction->operands[i].shift,
+                          &insn->arg[i]);
+         }
+     }
+ 
+   return 1;
+ }
+ 
+ /* Bunch of error checkings.
+    The checks are made after a matching instruction was found.  */
+ 
+ void
+ warn_if_needed (ins *insn)
+ {
+   /* If the post-increment address mode is used and the load/store 
+      source register is the same as rbase, the result of the 
+      instruction is undefined.  */
+   if (IS_INSN_TYPE (LD_STOR_INS_INC))
+     {
+       /* Enough to verify that one of the arguments is a simple reg.  */
+       if ((insn->arg[0].type == arg_r) || (insn->arg[1].type == arg_r))
+         if (insn->arg[0].r == insn->arg[1].r)
+           as_bad (_("Same src/dest register is used (`r%d'), result is undefined"), insn->arg[0].r);
+     }
+ 
+ 
+   if (IS_INSN_MNEMONIC("pop") || IS_INSN_MNEMONIC("push") ||
+       IS_INSN_MNEMONIC("popret")) 
+     {
+       unsigned int count = insn->arg[0].constant, reg_val;
+      /* Check if count operand caused to save/retrive the RA twice
+         to generate warning message */
+      if (insn->nargs > 2)
+        {
+          reg_val = getreg_image (insn->arg[1].r);
+ 
+          if (((reg_val == 9) &&  (count > 7)) ||
+              ((reg_val == 10) && (count > 6)) ||
+              ((reg_val == 11) && (count > 5)) ||
+              ((reg_val == 12) && (count > 4)) ||
+              ((reg_val == 13) && (count > 2)) ||
+              ((reg_val == 14) && (count > 0)))
+            as_warn (_("RA register is saved twice."));
+ 
+          /* Check if the third operand is "RA" or "ra" */
+          if (!(((insn->arg[2].r) == ra) || ((insn->arg[2].r) == RA)))
+            as_bad (_("`%s' Illegal use of registers."), ins_parse);
+        }
+ 
+       if (insn->nargs > 1)
+        { 
+          reg_val = getreg_image (insn->arg[1].r);
+ 
+          /* If register is a register pair ie r12/r13/r14 in operand1, then
+             the count constant should be validated  */
+          if (((reg_val == 11) && (count > 7)) ||
+              ((reg_val == 12) && (count > 6)) ||
+              ((reg_val == 13) && (count > 4)) ||
+              ((reg_val == 14) && (count > 2)) ||
+              ((reg_val == 15) && (count > 0)))
+            as_bad (_("`%s' Illegal count-register combination."), ins_parse);
+        }
+      else
+        {
+          /* Check if the operand is "RA" or "ra" */
+          if (!(((insn->arg[0].r) == ra) || ((insn->arg[0].r) == RA)))
+            as_bad (_("`%s' Illegal use of register."), ins_parse);
+        }
+     }
+ 
+   /* Some instruction assume the stack pointer as rptr operand.
+      Issue an error when the register to be loaded is also SP.  */
+   if (instruction->flags & NO_SP)
+     {
+       if (getreg_image (insn->arg[1].r) == getreg_image (sp))
+         as_bad (_("`%s' has undefined result"), ins_parse);
+     }
+ 
+   /* If the rptr register is specified as one of the registers to be loaded,
+      the final contents of rptr are undefined. Thus, we issue an error.  */
+   if (instruction->flags & NO_RPTR)
+     {
+       if ((1 << getreg_image (insn->arg[0].r)) & insn->arg[1].constant)
+         as_bad (_("Same src/dest register is used (`r%d'),result is undefined"),
+                   getreg_image (insn->arg[0].r));
+     }
+ }
+ 
+ /* In some cases, we need to adjust the instruction pointer although a
+    match was already found. Here, we gather all these cases.
+    Returns 1 if instruction pointer was adjusted, otherwise 0.  */
+ 
+ int
+ adjust_if_needed (ins *insn ATTRIBUTE_UNUSED)
+ {
+   int ret_value = 0;
+ 
+   if ((IS_INSN_TYPE (CSTBIT_INS)) || (IS_INSN_TYPE (LD_STOR_INS)))
+     {
+       if ((instruction->operands[0].op_type == abs24)
+            && ((insn->arg[0].constant) > 0xF00000))
+         {
+           insn->arg[0].constant &= 0xFFFFF;
+           instruction--;
+           ret_value = 1;
+         }
+     }
+ 
+   return ret_value;
+ }
+ 
+ /* Print the instruction.
+    Handle also cases where the instruction is relaxable/relocatable.  */
+ 
+ void
+ print_insn (ins *insn)
+ {
+   unsigned int i, j, insn_size;
+   char *this_frag;
+   unsigned short words[4];
+   int addr_mod;
+ 
+   /* Arrange the insn encodings in a WORD size array.  */
+   for (i = 0, j = 0; i < 2; i++)
+     {
+       words[j++] = (output_opcode[i] >> 16) & 0xFFFF;
+       words[j++] = output_opcode[i] & 0xFFFF;
+     }
+ 
+     insn_size = instruction->size;
+     this_frag = frag_more (insn_size * 2);
+ 
+     /* Handle relocation.  */
+     if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
+       {
+          reloc_howto_type *reloc_howto;
+          int size;
+ 
+          reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
+ 
+          if (!reloc_howto)
+            abort ();
+ 
+          size = bfd_get_reloc_size (reloc_howto);
+ 
+          if (size < 1 || size > 4)
+            abort ();
+ 
+          fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
+                       size, &insn->exp, reloc_howto->pc_relative,
+                       insn->rtype);
+       }
+ 
+   /* Verify a 2-byte code alignment.  */
+   addr_mod = frag_now_fix () & 1;
+   if (frag_now->has_code && frag_now->insn_addr != addr_mod)
+     as_bad (_("instruction address is not a multiple of 2"));
+   frag_now->insn_addr = addr_mod;
+   frag_now->has_code = 1;
+ 
+   /* Write the instruction encoding to frag.  */
+   for (i = 0; i < insn_size; i++)
+     {
+       md_number_to_chars (this_frag, (valueT) words[i], 2);
+       this_frag += 2;
+     }
+ }
+ 
+ /* This is the guts of the machine-dependent assembler.  OP points to a
+    machine dependent instruction.  This function is supposed to emit
+    the frags/bytes it assembles to.  */
+ 
+ void
+ md_assemble (char *op)
+ {
+   ins cr16_ins;
+   char *param, param1[32];
+   char c;
+ 
+   /* Reset global variables for a new instruction.  */
+   reset_vars (op);
+ 
+   /* Strip the mnemonic.  */
+   for (param = op; *param != 0 && !ISSPACE (*param); param++)
+     ;
+   c = *param;
+   *param++ = '\0';
+ 
+   /* bCC instuctions and adjust the mnemonic by adding extra white spaces */
+   if (is_bcc_insn(op))
+     {
+       strcpy(param1, get_b_cc(op));
+       op = "b";
+       strcat(param1,",");
+       strcat(param1,param);
+       param = (char*)&param1;
+     }
+ 
+   /* Checking the cinv options and adjust the mnemonic by removing the 
+      extra white spaces */
+   if (streq("cinv", op))
+     {
+      /* validate the cinv options */
+       check_cinv_options(param);
+       strcat(op,param);
+     }
+ 
+   /* MAPPING - SHIFT INSN, if imm4/imm16 positive values
+      lsh[b/w] imm4/imm6, reg ==> ashu[b/w] imm4/imm16, reg
+      as CR16 core doesn't support lsh[b/w] right shift operaions*/
+   if ((streq("lshb", op) || streq("lshw",op) || streq("lshd", op)) &&
+       (param [0] == '$')) 
+     {
+       strcpy(param1, param);
+       /* Find the instruction.  */
+       instruction = (const inst *) hash_find (cr16_inst_hash, op);
+        parse_operands (&cr16_ins, param1);
+       if (((&cr16_ins)->arg[0].type == arg_ic) &&
+           ((&cr16_ins)->arg[0].constant >= 0))
+         {
+            if (streq ("lshb",op))    op = "ashub";
+            else 
+              if (streq ("lshd",op))  op = "ashud";
+              else                    op = "ashuw";
+         }
+     }
+ 
+ 
+   /* Find the instruction.  */
+   instruction = (const inst *) hash_find (cr16_inst_hash, op);
+   if (instruction == NULL)
+     {
+       as_bad (_("Unknown opcode: `%s'"), op);
+       return;
+     }
+ 
+   /* Tie dwarf2 debug info to the address at the start of the insn.  */
+   dwarf2_emit_insn (0);
+ 
+   /* Parse the instruction's operands.  */
+   parse_insn (&cr16_ins, param);
+ 
+   /* Assemble the instruction - return upon failure.  */
+   if (assemble_insn (op, &cr16_ins) == 0)
+     return;
+ 
+   /* Print the instruction.  */
+   print_insn (&cr16_ins);
+ }
diff -Napr --exclude=testsuite binutils-2.17.50/gas/config/tc-cr16.h binutils-2.17.50-cr16/gas/config/tc-cr16.h
*** binutils-2.17.50/gas/config/tc-cr16.h	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/gas/config/tc-cr16.h	2007-06-22 15:25:00.000000000 +0530
***************
*** 0 ****
--- 1,73 ----
+ /* tc-cr16.h -- Header file for tc-cr16.c, the CR16 GAS port.
+    Copyright 2007 Free Software Foundation, Inc.
+ 
+    Contributed by M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+    This file is part of GAS, the GNU Assembler.
+ 
+    GAS is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    GAS 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 GAS; see the file COPYING.  If not, write to the
+    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+    MA 02110-1301, USA.  */
+ 
+ #ifndef TC_CR16_H
+ #define TC_CR16_H
+ 
+ #define TC_CR16 1
+ 
+ #define TARGET_BYTES_BIG_ENDIAN 0
+ 
+ #define TARGET_FORMAT "elf32-cr16"
+ #define TARGET_ARCH   bfd_arch_cr16
+ 
+ #define WORKING_DOT_WORD
+ #define LOCAL_LABEL_PREFIX '.'
+ 
+ #define md_undefined_symbol(s)  0
+ #define md_number_to_chars      number_to_chars_littleendian
+ 
+ /* We do relaxing in the assembler as well as the linker.  */
+ extern const struct relax_type md_relax_table[];
+ #define TC_GENERIC_RELAX_TABLE md_relax_table
+ 
+ /* We do not want to adjust any relocations to make implementation of
+    linker relaxations easier.  */
+ #define tc_fix_adjustable(fixP)  0
+ 
+ /* We need to force out some relocations when relaxing.  */
+ #define TC_FORCE_RELOCATION(FIXP) cr16_force_relocation (FIXP)
+ extern int cr16_force_relocation (struct fix *);
+ 
+ /* Fixup debug sections since we will never relax them.  */
+ #define TC_LINKRELAX_FIXUP(seg) (seg->flags & SEC_ALLOC)
+ 
+ /* CR16 instructions, with operands included, are a multiple
+    of two bytes long.  */
+ #define DWARF2_LINE_MIN_INSN_LENGTH 2
+ 
+ extern void cr16_cons_fix_new (struct frag *, int, int, struct expressionS *);
+ /* This is called by emit_expr when creating a reloc for a cons.
+    We could use the definition there, except that we want to handle 
+    the CR16 reloc type specially, rather than the BFD_RELOC type.  */
+ #define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \
+  cr16_cons_fix_new(FRAG, OFF, LEN, EXP) 
+ 
+ /* Give an error if a frag containing code is not aligned to a 2-byte 
+    boundary.  */
+ #define md_frag_check(FRAGP) \
+   if ((FRAGP)->has_code                                                \
+       && (((FRAGP)->fr_address + (FRAGP)->insn_addr) & 1) != 0)        \
+      as_bad_where ((FRAGP)->fr_file, (FRAGP)->fr_line,                 \
+                   _("instruction address is not a multiple of 2"));
+ 
+ #endif /* TC_CR16_H */
diff -Napr --exclude=testsuite binutils-2.17.50/gas/configure.tgt binutils-2.17.50-cr16/gas/configure.tgt
*** binutils-2.17.50/gas/configure.tgt	2007-04-04 23:32:39.000000000 +0530
--- binutils-2.17.50-cr16/gas/configure.tgt	2007-06-26 15:01:25.000000000 +0530
*************** case ${cpu} in
*** 35,40 ****
--- 35,41 ----
    arm*)			cpu_type=arm endian=little ;;
    bfin*)		cpu_type=bfin endian=little ;;
    c4x*)			cpu_type=tic4x ;;
+   cr16*)		cpu_type=cr16 endian=little ;;
    crisv32)		cpu_type=cris arch=crisv32 ;;
    crx*)			cpu_type=crx endian=little ;;
    fido)			cpu_type=m68k ;;
*************** case ${generic_target} in
*** 126,131 ****
--- 127,133 ----
    avr-*-*)				fmt=elf bfd_gas=yes ;;
    bfin-*-*)				fmt=elf bfd_gas=yes ;;
    bfin-*elf)				fmt=elf ;;
+   cr16-*-elf*)	    			fmt=elf ;;
  
    cris-*-linux-* | crisv32-*-linux-*)
  					fmt=multi em=linux ;;
diff -Napr --exclude=testsuite binutils-2.17.50/gas/doc/all.texi binutils-2.17.50-cr16/gas/doc/all.texi
*** binutils-2.17.50/gas/doc/all.texi	2006-07-24 19:19:49.000000000 +0530
--- binutils-2.17.50-cr16/gas/doc/all.texi	2007-06-22 15:25:00.000000000 +0530
***************
*** 31,36 ****
--- 31,37 ----
  @set ARM
  @set AVR
  @set BFIN
+ @set CR16
  @set CRIS
  @set D10V
  @set D30V
diff -Napr --exclude=testsuite binutils-2.17.50/gas/doc/as.texinfo binutils-2.17.50-cr16/gas/doc/as.texinfo
*** binutils-2.17.50/gas/doc/as.texinfo	2007-05-17 22:57:26.000000000 +0530
--- binutils-2.17.50-cr16/gas/doc/as.texinfo	2007-06-26 15:01:25.000000000 +0530
*************** subject, see the hardware manufacturer's
*** 6359,6364 ****
--- 6359,6367 ----
  @ifset BFIN
  * BFIN-Dependent::		BFIN Dependent Features
  @end ifset
+ @ifset CR16
+ * CR16-Dependent::              CR16 Dependent Features
+ @end ifset
  @ifset CRIS
  * CRIS-Dependent::              CRIS Dependent Features
  @end ifset
*************** subject, see the hardware manufacturer's
*** 6480,6485 ****
--- 6483,6492 ----
  @include c-bfin.texi
  @end ifset
  
+ @ifset CR16
+ @include c-cr16.texi
+ @end ifset
+ 
  @ifset CRIS
  @include c-cris.texi
  @end ifset
diff -Napr --exclude=testsuite binutils-2.17.50/gas/doc/c-cr16.texi binutils-2.17.50-cr16/gas/doc/c-cr16.texi
*** binutils-2.17.50/gas/doc/c-cr16.texi	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/gas/doc/c-cr16.texi	2007-06-22 15:25:00.000000000 +0530
***************
*** 0 ****
--- 1,80 ----
+ @c Copyright 2007 Free Software Foundation, Inc.
+ @c This is part of the GAS manual.
+ @c For copying conditions, see the file as.texinfo.
+ 
+ @ifset GENERIC
+ @page
+ @node CR16-Dependent
+ @chapter CR16 Dependent Features
+ @end ifset
+ @ifclear GENERIC
+ @node Machine Dependencies
+ @chapter CR16 Dependent Features
+ @end ifclear
+ 
+ @cindex CR16 support
+ @menu
+ * CR16 Operand Qualifiers::     CR16 Machine Operand Qualifiers
+ @end menu
+ 
+ @node CR16 Operand Qualifiers
+ @section CR16 Operand Qualifiers
+ @cindex CR16 Operand Qualifiers
+ 
+ The National Semiconductor CR16 target of @code{@value{AS}} has a few machine dependent operand qualifiers.  
+ 
+ Operand expression type qualifier is an optional field in the instruction operand, to determines the type of the expression field of an operand. The @code{@@} is required. CR16 architecture uses one of the following expression qualifiers:
+ 
+ @table @code
+ @item  s 
+ - @code{Specifies expression operand type as small}
+ @item  m 
+ - @code{Specifies expression operand type as medium}
+ @item  l 
+ - @code{Specifies expression operand type as large}
+ @item  c 
+ - @code{Specifies the CR16 Assembler generates a relocation entry for the operand, where pc has implied bit, the expression is adjusted accordingly. The linker uses the relocation entry to update the operand address at link time.}
+ @end table
+ 
+ CR16 target operand qualifiers and its size (in bits):
+ 
+ @table @samp
+ @item Immediate Operand
+ - s ---- 4 bits
+ @item 
+ - m ---- 16 bits, for movb and movw instructions.
+ @item 
+ - m ---- 20 bits, movd instructions.
+ @item 
+ - l ---- 32 bits
+ 
+ @item Absolute Operand
+ - s ---- Illegal specifier for this operand.
+ @item  
+ - m ---- 20 bits, movd instructions.
+ 
+ @item Displacement Operand
+ - s ---- 8 bits
+ @item
+ - m ---- 16 bits
+ @item 
+ - l ---- 24 bits
+ @end table
+ 
+ For example:
+ @example
+ 1   @code{movw $_myfun@@c,r1}
+ 
+     This loads the address of _myfun, shifted right by 1, into r1.
+ 
+ 2   @code{movd $_myfun@@c,(r2,r1)}
+ 
+     This loads the address of _myfun, shifted right by 1, into register-pair r2-r1.
+                 
+ 3   @code{_myfun_ptr:}
+     @code{.long _myfun@@c}
+     @code{loadd _myfun_ptr, (r1,r0)}
+     @code{jal (r1,r0)}
+ 
+     This .long directive, the address of _myfunc, shifted right by 1 at link time.
+ @end example
diff -Napr --exclude=testsuite binutils-2.17.50/gas/doc/Makefile.am binutils-2.17.50-cr16/gas/doc/Makefile.am
*** binutils-2.17.50/gas/doc/Makefile.am	2007-03-15 19:47:18.000000000 +0530
--- binutils-2.17.50-cr16/gas/doc/Makefile.am	2007-06-22 15:25:00.000000000 +0530
*************** CPU_DOCS = \
*** 34,39 ****
--- 34,40 ----
  	c-arm.texi \
  	c-avr.texi \
  	c-bfin.texi \
+ 	c-cr16.texi \
  	c-d10v.texi \
  	c-cris.texi \
  	c-h8300.texi \
diff -Napr --exclude=testsuite binutils-2.17.50/gas/doc/Makefile.in binutils-2.17.50-cr16/gas/doc/Makefile.in
*** binutils-2.17.50/gas/doc/Makefile.in	2007-04-19 16:17:50.000000000 +0530
--- binutils-2.17.50-cr16/gas/doc/Makefile.in	2007-06-22 15:25:00.000000000 +0530
*************** CPU_DOCS = \
*** 223,228 ****
--- 223,229 ----
  	c-arm.texi \
  	c-avr.texi \
  	c-bfin.texi \
+ 	c-cr16.texi \
  	c-d10v.texi \
  	c-cris.texi \
  	c-h8300.texi \
diff -Napr --exclude=testsuite binutils-2.17.50/gas/Makefile.am binutils-2.17.50-cr16/gas/Makefile.am
*** binutils-2.17.50/gas/Makefile.am	2007-04-24 09:36:14.000000000 +0530
--- binutils-2.17.50-cr16/gas/Makefile.am	2007-06-22 15:25:00.000000000 +0530
*************** CPU_TYPES = \
*** 48,53 ****
--- 48,54 ----
  	arm \
  	avr \
  	bfin \
+ 	cr16 \
  	cris \
  	crx \
  	d10v \
*************** TARGET_CPU_CFILES = \
*** 240,245 ****
--- 241,247 ----
  	config/tc-arm.c \
  	config/tc-avr.c \
  	config/tc-bfin.c \
+ 	config/tc-cr16.c \
  	config/tc-cris.c \
  	config/tc-crx.c \
  	config/tc-d10v.c \
*************** TARGET_CPU_HFILES = \
*** 294,299 ****
--- 296,302 ----
  	config/tc-arm.h \
  	config/tc-avr.h \
  	config/tc-bfin.h \
+ 	config/tc-cr16.h \
  	config/tc-cris.h \
  	config/tc-crx.h \
  	config/tc-d10v.h \
*************** DEPTC_bfin_elf = $(srcdir)/config/obj-el
*** 1053,1058 ****
--- 1056,1066 ----
    $(INCDIR)/hashtab.h $(INCDIR)/elf/common.h $(INCDIR)/elf/bfin.h \
    $(INCDIR)/elf/reloc-macros.h $(srcdir)/config/bfin-aux.h \
    $(srcdir)/config/bfin-defs.h $(INCDIR)/opcode/bfin.h
+ DEPTC_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(INCDIR)/safe-ctype.h dwarf2dbg.h $(INCDIR)/opcode/cr16.h \
+   $(INCDIR)/elf/cr16.h $(INCDIR)/elf/reloc-macros.h
  DEPTC_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h \
    subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/cris.h \
*************** DEPOBJ_bfin_elf = $(srcdir)/config/obj-e
*** 1482,1487 ****
--- 1490,1500 ----
    $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h dwarf2dbg.h \
    $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
    $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
+ DEPOBJ_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+   $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
  DEPOBJ_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
    $(INCDIR)/obstack.h
*************** DEP_bfin_elf = $(srcdir)/config/obj-elf.
*** 1838,1843 ****
--- 1851,1861 ----
    $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h dwarf2dbg.h \
    $(srcdir)/config/obj-coff.h $(INCDIR)/coff/internal.h \
    $(BFDDIR)/libcoff.h
+ DEP_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(srcdir)/config/obj-coff.h $(INCDIR)/coff/internal.h \
+   $(BFDDIR)/libcoff.h
  DEP_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
  DEP_cris_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
diff -Napr --exclude=testsuite binutils-2.17.50/gas/Makefile.in binutils-2.17.50-cr16/gas/Makefile.in
*** binutils-2.17.50/gas/Makefile.in	2007-04-24 09:36:14.000000000 +0530
--- binutils-2.17.50-cr16/gas/Makefile.in	2007-06-22 15:25:00.000000000 +0530
*************** CPU_TYPES = \
*** 279,284 ****
--- 279,285 ----
  	arm \
  	avr \
  	bfin \
+ 	cr16 \
  	cris \
  	crx \
  	d10v \
*************** TARGET_CPU_CFILES = \
*** 469,474 ****
--- 470,476 ----
  	config/tc-arm.c \
  	config/tc-avr.c \
  	config/tc-bfin.c \
+ 	config/tc-cr16.c \
  	config/tc-cris.c \
  	config/tc-crx.c \
  	config/tc-d10v.c \
*************** TARGET_CPU_HFILES = \
*** 523,528 ****
--- 525,531 ----
  	config/tc-arm.h \
  	config/tc-avr.h \
  	config/tc-bfin.h \
+ 	config/tc-cr16.h \
  	config/tc-cris.h \
  	config/tc-crx.h \
  	config/tc-d10v.h \
*************** DEPTC_bfin_elf = $(srcdir)/config/obj-el
*** 810,815 ****
--- 813,824 ----
    $(INCDIR)/elf/reloc-macros.h $(srcdir)/config/bfin-aux.h \
    $(srcdir)/config/bfin-defs.h $(INCDIR)/opcode/bfin.h
  
+ DEPTC_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(INCDIR)/safe-ctype.h dwarf2dbg.h $(INCDIR)/opcode/cr16.h \
+   $(INCDIR)/elf/cr16.h $(INCDIR)/elf/reloc-macros.h
+ 
  DEPTC_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h \
    subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/cris.h \
*************** DEPOBJ_bfin_elf = $(srcdir)/config/obj-e
*** 1318,1323 ****
--- 1327,1338 ----
    $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
    $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
  
+ DEPOBJ_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+   $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
+ 
  DEPOBJ_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
    $(INCDIR)/obstack.h
*************** DEP_bfin_elf = $(srcdir)/config/obj-elf.
*** 1753,1758 ****
--- 1768,1779 ----
    $(srcdir)/config/obj-coff.h $(INCDIR)/coff/internal.h \
    $(BFDDIR)/libcoff.h
  
+ DEP_cr16_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+   $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+   $(INCDIR)/bfdlink.h $(srcdir)/config/tc-cr16.h dwarf2dbg.h \
+   $(srcdir)/config/obj-coff.h $(INCDIR)/coff/internal.h \
+   $(BFDDIR)/libcoff.h
+ 
  DEP_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
    $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
  
diff -Napr --exclude=testsuite binutils-2.17.50/gas/NEWS binutils-2.17.50-cr16/gas/NEWS
*** binutils-2.17.50/gas/NEWS	2007-03-27 14:03:47.000000000 +0530
--- binutils-2.17.50-cr16/gas/NEWS	2007-06-22 15:25:00.000000000 +0530
***************
*** 1,4 ****
--- 1,6 ----
  -*- text -*-
+ * Support for the National Semiconductor CR16 target has been added.
+ 
  * Added gas .reloc pseudo.  This is a low-level interface for creating
    relocations.
  
diff -Napr --exclude=testsuite binutils-2.17.50/include/ChangeLog binutils-2.17.50-cr16/include/ChangeLog
*** binutils-2.17.50/include/ChangeLog	2007-05-08 06:59:28.000000000 +0530
--- binutils-2.17.50-cr16/include/ChangeLog	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,3 ****
--- 1,7 ----
+ 2007-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+         * dis-asm.h (print_insn_cr16): New prototype.
+ 
  2007-05-07  Nathan Froyd  <froydnj@codesourcery.com>
  
  	* libiberty.h (writeargv): Declare.
diff -Napr --exclude=testsuite binutils-2.17.50/include/dis-asm.h binutils-2.17.50-cr16/include/dis-asm.h
*** binutils-2.17.50/include/dis-asm.h	2007-02-06 00:47:10.000000000 +0530
--- binutils-2.17.50-cr16/include/dis-asm.h	2007-06-22 15:41:13.000000000 +0530
*************** extern int print_insn_big_mips		(bfd_vma
*** 217,222 ****
--- 217,223 ----
  extern int print_insn_big_or32		(bfd_vma, disassemble_info *);
  extern int print_insn_big_powerpc	(bfd_vma, disassemble_info *);
  extern int print_insn_big_score         (bfd_vma, disassemble_info *);
+ extern int print_insn_cr16              (bfd_vma, disassemble_info *);
  extern int print_insn_crx               (bfd_vma, disassemble_info *);
  extern int print_insn_d10v		(bfd_vma, disassemble_info *);
  extern int print_insn_d30v		(bfd_vma, disassemble_info *);
diff -Napr --exclude=testsuite binutils-2.17.50/include/elf/ChangeLog binutils-2.17.50-cr16/include/elf/ChangeLog
*** binutils-2.17.50/include/elf/ChangeLog	2007-05-21 22:05:11.000000000 +0530
--- binutils-2.17.50-cr16/include/elf/ChangeLog	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,3 ****
--- 1,8 ----
+ 2007-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+ 	* common.h (EM_CR16): New entry for CR16 cpu.
+ 	* cr16.h: New file.
+ 
  2007-05-18  Caroline Tice  <ctice@apple.com>
  
  	* dwarf2.h: (enum dwarf_location_atom): Add new DW_OP, 
diff -Napr --exclude=testsuite binutils-2.17.50/include/elf/common.h binutils-2.17.50-cr16/include/elf/common.h
*** binutils-2.17.50/include/elf/common.h	2007-04-26 12:29:55.000000000 +0530
--- binutils-2.17.50-cr16/include/elf/common.h	2007-06-22 15:41:13.000000000 +0530
***************
*** 186,191 ****
--- 186,192 ----
  #define EM_BLACKFIN	106	/* ADI Blackfin */
  #define EM_ALTERA_NIOS2	113	/* Altera Nios II soft-core processor */
  #define EM_CRX		114	/* National Semiconductor CRX */
+ #define EM_CR16		115	/* National Semiconductor CompactRISC - CR16 */
  #define EM_SCORE        135     /* Sunplus Score */ 
  
  /* If it is necessary to assign new unofficial EM_* values, please pick large
diff -Napr --exclude=testsuite binutils-2.17.50/include/elf/cr16.h binutils-2.17.50-cr16/include/elf/cr16.h
*** binutils-2.17.50/include/elf/cr16.h	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/include/elf/cr16.h	2007-06-22 15:41:13.000000000 +0530
***************
*** 0 ****
--- 1,56 ----
+ /* CR16 ELF support for BFD.
+    Copyright 2007 Free Software Foundation, Inc.
+    Contributed by M R Swami Reddy.
+ 
+    This file is part of BFD, the Binary File Descriptor library.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #ifndef _ELF_CR16_H
+ #define _ELF_CR16_H
+ 
+ #include "elf/reloc-macros.h"
+ 
+ /* Creating indices for reloc_map_index array.  */
+ START_RELOC_NUMBERS(elf_cr16_reloc_type)
+   RELOC_NUMBER (R_CR16_NONE,           0)
+   RELOC_NUMBER (R_CR16_NUM8,           1)
+   RELOC_NUMBER (R_CR16_NUM16,          2)
+   RELOC_NUMBER (R_CR16_NUM32,          3)
+   RELOC_NUMBER (R_CR16_NUM32a,         4)
+   RELOC_NUMBER (R_CR16_REGREL4,        5)
+   RELOC_NUMBER (R_CR16_REGREL4a,       6)
+   RELOC_NUMBER (R_CR16_REGREL14,       7)
+   RELOC_NUMBER (R_CR16_REGREL14a,      8)
+   RELOC_NUMBER (R_CR16_REGREL16,       9)
+   RELOC_NUMBER (R_CR16_REGREL20,       10)
+   RELOC_NUMBER (R_CR16_REGREL20a,      11)
+   RELOC_NUMBER (R_CR16_ABS20,          12)
+   RELOC_NUMBER (R_CR16_ABS24,          13)
+   RELOC_NUMBER (R_CR16_IMM4,           14)
+   RELOC_NUMBER (R_CR16_IMM8,           15)
+   RELOC_NUMBER (R_CR16_IMM16,          16)
+   RELOC_NUMBER (R_CR16_IMM20,          17)
+   RELOC_NUMBER (R_CR16_IMM24,          18)
+   RELOC_NUMBER (R_CR16_IMM32,          19)
+   RELOC_NUMBER (R_CR16_IMM32a,         20)
+   RELOC_NUMBER (R_CR16_DISP4,          21)
+   RELOC_NUMBER (R_CR16_DISP8,          22)
+   RELOC_NUMBER (R_CR16_DISP16,         23)
+   RELOC_NUMBER (R_CR16_DISP24,         24)
+   RELOC_NUMBER (R_CR16_DISP24a,        25)
+ END_RELOC_NUMBERS(R_CR16_MAX)
+         
+ #endif /* _ELF_CR16_H */
diff -Napr --exclude=testsuite binutils-2.17.50/include/opcode/ChangeLog binutils-2.17.50-cr16/include/opcode/ChangeLog
*** binutils-2.17.50/include/opcode/ChangeLog	2007-05-02 16:54:17.000000000 +0530
--- binutils-2.17.50-cr16/include/opcode/ChangeLog	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,3 ****
--- 1,7 ----
+ 2006-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+ 	* cr16.h: New file for CR16 target.
+ 
  2007-05-02  Alan Modra  <amodra@bigpond.net.au>
  
  	* ppc.h (PPC_OPERAND_PLUS1): Update comment.
diff -Napr --exclude=testsuite binutils-2.17.50/include/opcode/cr16.h binutils-2.17.50-cr16/include/opcode/cr16.h
*** binutils-2.17.50/include/opcode/cr16.h	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/include/opcode/cr16.h	2007-06-26 15:11:59.000000000 +0530
***************
*** 0 ****
--- 1,437 ----
+ /* cr16.h -- Header file for CR16 opcode and register tables.
+    Copyright 2007 Free Software Foundation, Inc.
+    Contributed by M R Swami Reddy
+ 
+    This file is part of GAS, GDB and the GNU binutils.
+ 
+    GAS, GDB, and GNU binutils is free software; you can redistribute it
+    and/or modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at your
+    option) any later version.
+ 
+    GAS, GDB, and GNU binutils are distributed in the hope that they 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #ifndef _CR16_H_
+ #define _CR16_H_
+ 
+ /* CR16 core Registers :
+    The enums are used as indices to CR16 registers table (cr16_regtab).
+    Therefore, order MUST be preserved.  */
+ 
+ typedef enum
+   {
+     /* 16-bit general purpose registers.  */
+     r0, r1, r2, r3, 
+     r4, r5, r6, r7, 
+     r8, r9, r10, r11, 
+     r12_L = 12, r13_L = 13, ra = 14, sp_L = 15,
+ 
+     /* 32-bit general purpose registers.  */
+     r12 = 12, r13 = 13, r14 = 14, r15 = 15, 
+     era = 14, sp = 15, RA,
+ 
+     /* Not a register.  */
+     nullregister,
+     MAX_REG
+   }
+ reg;
+ 
+ /* CR16 processor registers and special registers :
+    The enums are used as indices to CR16 processor registers table
+    (cr16_pregtab). Therefore, order MUST be preserved.  */
+ 
+ typedef enum
+   {
+     /* processor registers.  */
+     dbs = MAX_REG, 
+     dsr, dcrl, dcrh, 
+     car0l, car0h, car1l, car1h, 
+     cfg, psr, intbasel, intbaseh, 
+     ispl, isph, uspl, usph,
+     dcr =  dcrl, 
+     car0 = car0l, 
+     car1 = car1l, 
+     intbase = intbasel, 
+     isp =  ispl, 
+     usp =  uspl,
+     /* Not a processor register.  */
+     nullpregister = usph + 1,
+     MAX_PREG
+   }
+ preg;
+ 
+ /* CR16 Register types. */
+ 
+ typedef enum
+   {
+     CR16_R_REGTYPE,    /* r<N>      */
+     CR16_RP_REGTYPE,   /* reg pair  */
+     CR16_P_REGTYPE     /* Processor register  */
+   }
+ reg_type;
+ 
+ /* CR16 argument types :
+    The argument types correspond to instructions operands
+ 
+    Argument types :
+    r - register
+    rp - register pair
+    c - constant
+    i - immediate
+    idxr - index with register
+    idxrp - index with register pair
+    rbase - register base
+    rpbase - register pair base
+    pr - processor register */
+ 
+ typedef enum
+   {
+     arg_r,
+     arg_c,
+     arg_cr,
+     arg_crp,
+     arg_ic,
+     arg_icr,
+     arg_idxr,
+     arg_idxrp,
+     arg_rbase,
+     arg_rpbase,
+     arg_rp,
+     arg_pr,
+     arg_prp,
+     arg_cc,
+     arg_ra,
+     /* Not an argument.  */
+     nullargs
+   }
+ argtype;
+ 
+ /* CR16 operand types:The operand types correspond to instructions operands.*/
+ 
+ typedef enum
+   {
+     dummy,
+     /* N-bit signed immediate.  */
+     imm3, imm4, imm5, imm6, imm16, imm20, imm32,
+     /* N-bit unsigned immediate.  */
+     uimm3, uimm3_1, uimm4, uimm4_1, uimm5, uimm16, uimm20, uimm32,
+     /* N-bit signed displacement.  */
+     disps5, disps17, disps25,
+     /* N-bit unsigned displacement.  */
+     dispe9,
+     /* N-bit absolute address.  */
+     abs20, abs24,
+     /* Register relative.  */
+     rra, rbase, rbase_disps20, rbase_dispe20,
+     /* Register pair relative.  */
+     rpbase_disps0, rpbase_dispe4, rpbase_disps4, rpbase_disps16,
+     rpbase_disps20, rpbase_dispe20,
+     /* Register index.  */
+     rindex7_abs20, rindex8_abs20,
+     /* Register pair index.  */
+     rpindex_disps0, rpindex_disps14, rpindex_disps20,
+     /* register.  */
+     regr, 
+     /* register pair.  */
+     regp, 
+     /* processor register.  */
+     pregr, 
+     /* processor register 32 bit.  */
+     pregrp, 
+     /* condition code - 4 bit.  */
+     cc, 
+     /* Not an operand.  */
+     nulloperand,
+     /* Maximum supported operand.  */
+     MAX_OPRD
+   }
+ operand_type;
+ 
+ /* CR16 instruction types.  */
+ 
+ #define NO_TYPE_INS       0
+ #define ARITH_INS         1
+ #define LD_STOR_INS       2
+ #define BRANCH_INS        3
+ #define ARITH_BYTE_INS    4
+ #define SHIFT_INS         5
+ #define BRANCH_NEQ_INS    6
+ #define LD_STOR_INS_INC   7
+ #define STOR_IMM_INS      8
+ #define CSTBIT_INS        9
+ 
+ /* Maximum value supported for instruction types.  */
+ #define CR16_INS_MAX        (1 << 4)
+ /* Mask to record an instruction type.  */
+ #define CR16_INS_MASK       (CR16_INS_MAX - 1)
+ /* Return instruction type, given instruction's attributes.  */
+ #define CR16_INS_TYPE(attr) ((attr) & CR16_INS_MASK)
+ 
+ /* Indicates whether this instruction has a register list as parameter.  */
+ #define REG_LIST        CR16_INS_MAX
+ 
+ /* The operands in binary and assembly are placed in reverse order.
+    load - (REVERSE_MATCH)/store - (! REVERSE_MATCH).  */
+ #define REVERSE_MATCH  (1 << 5)
+ 
+ /* Printing formats, where the instruction prefix isn't consecutive.  */
+ #define FMT_1          (1 << 9)    /* 0xF0F00000 */
+ #define FMT_2          (1 << 10)   /* 0xFFF0FF00 */
+ #define FMT_3          (1 << 11)   /* 0xFFF00F00 */
+ #define FMT_4          (1 << 12)   /* 0xFFF0F000 */
+ #define FMT_5          (1 << 13)   /* 0xFFF0FFF0 */
+ #define FMT_CR16       (FMT_1 | FMT_2 | FMT_3 | FMT_4 | FMT_5)
+ 
+ /* Indicates whether this instruction can be relaxed.  */
+ #define RELAXABLE      (1 << 14)
+ 
+ /* Indicates that instruction uses user registers (and not 
+    general-purpose registers) as operands.  */
+ #define USER_REG       (1 << 15)
+ 
+ 
+ /* Instruction shouldn't allow 'sp' usage.  */
+ #define NO_SP          (1 << 17)
+ 
+ /* Instruction shouldn't allow to push a register which is used as a rptr.  */
+ #define NO_RPTR        (1 << 18)
+ 
+ /* Maximum operands per instruction.  */
+ #define MAX_OPERANDS     5
+ /* Maximum register name length. */
+ #define MAX_REGNAME_LEN  10
+ /* Maximum instruction length. */
+ #define MAX_INST_LEN     256
+ 
+ 
+ /* Values defined for the flags field of a struct operand_entry.  */
+ 
+ /* Operand must be an unsigned number.  */
+ #define OP_UNSIGNED   (1 << 0)
+ /* Operand must be a signed number.  */
+ #define OP_SIGNED     (1 << 1)
+ /* Operand must be a negative number.  */
+ #define OP_NEG        (1 << 2)
+ /* A special load/stor 4-bit unsigned displacement operand.  */
+ #define OP_DEC        (1 << 3)
+ /* Operand must be an even number.  */
+ #define OP_EVEN       (1 << 4)
+ /* Operand is shifted right.  */
+ #define OP_SHIFT      (1 << 5)
+ /* Operand is shifted right and decremented.  */
+ #define OP_SHIFT_DEC  (1 << 6)
+ /* Operand has reserved escape sequences.  */
+ #define OP_ESC        (1 << 7)
+ /* Operand must be a ABS20 number.  */
+ #define OP_ABS20      (1 << 8)
+ /* Operand must be a ABS24 number.  */
+ #define OP_ABS24      (1 << 9)
+ /* Operand has reserved escape sequences type 1.  */
+ #define OP_ESC1       (1 << 10)
+ 
+ /* Single operand description.  */
+ 
+ typedef struct
+   {
+     /* Operand type.  */
+     operand_type op_type;
+     /* Operand location within the opcode.  */
+     unsigned int shift;
+   }
+ operand_desc;
+ 
+ /* Instruction data structure used in instruction table.  */
+ 
+ typedef struct
+   {
+     /* Name.  */
+     const char *mnemonic;
+     /* Size (in words).  */
+     unsigned int size;
+     /* Constant prefix (matched by the disassembler).  */
+     unsigned long match;  /* ie opcode */
+     /* Match size (in bits).  */
+     /* MASK: if( (i & match_bits) == match ) then match */
+     int match_bits;
+     /* Attributes.  */
+     unsigned int flags;
+     /* Operands (always last, so unreferenced operands are initialized).  */
+     operand_desc operands[MAX_OPERANDS];
+   }
+ inst;
+ 
+ /* Data structure for a single instruction's arguments (Operands).  */
+ 
+ typedef struct
+   {
+     /* Register or base register.  */
+     reg r;
+     /* Register pair register.  */
+     reg rp;
+     /* Index register.  */
+     reg i_r;
+     /* Processor register.  */
+     preg pr;
+     /* Processor register. 32 bit  */
+     preg prp;
+     /* Constant/immediate/absolute value.  */
+     long constant;
+     /* CC code.  */
+     unsigned int cc;
+     /* Scaled index mode.  */
+     unsigned int scale;
+     /* Argument type.  */
+     argtype type;
+     /* Size of the argument (in bits) required to represent.  */
+     int size;
+   /* The type of the expression.  */
+     unsigned char X_op;
+   }
+ argument;
+ 
+ /* Internal structure to hold the various entities
+    corresponding to the current assembling instruction.  */
+ 
+ typedef struct
+   {
+     /* Number of arguments.  */
+     int nargs;
+     /* The argument data structure for storing args (operands).  */
+     argument arg[MAX_OPERANDS];
+ /* The following fields are required only by CR16-assembler.  */
+ #ifdef TC_CR16
+     /* Expression used for setting the fixups (if any).  */
+     expressionS exp;
+     bfd_reloc_code_real_type rtype;
+ #endif /* TC_CR16 */
+     /* Instruction size (in bytes).  */
+     int size;
+   }
+ ins;
+ 
+ /* Structure to hold information about predefined operands.  */
+ 
+ typedef struct
+   {
+     /* Size (in bits).  */
+     unsigned int bit_size;
+     /* Argument type.  */
+     argtype arg_type;
+     /* One bit syntax flags.  */
+     int flags;
+   }
+ operand_entry;
+ 
+ /* Structure to hold trap handler information.  */
+ 
+ typedef struct
+   {
+     /* Trap name.  */
+     char *name;
+     /* Index in dispatch table.  */
+     unsigned int entry;
+   }
+ trap_entry;
+ 
+ /* Structure to hold information about predefined registers.  */
+ 
+ typedef struct
+   {
+     /* Name (string representation).  */
+     char *name;
+     /* Value (enum representation).  */
+     union
+     {
+       /* Register.  */
+       reg reg_val;
+       /* processor register.  */
+       preg preg_val;
+     } value;
+     /* Register image.  */
+     int image;
+     /* Register type.  */
+     reg_type type;
+   }
+ reg_entry;
+ 
+ /* CR16 opcode table.  */
+ extern const inst cr16_instruction[];
+ extern const unsigned int cr16_num_opcodes;
+ #define NUMOPCODES cr16_num_opcodes
+ 
+ /* CR16 operands table.  */
+ extern const operand_entry cr16_optab[];
+ 
+ /* CR16 registers table.  */
+ extern const reg_entry cr16_regtab[];
+ extern const unsigned int cr16_num_regs;
+ #define NUMREGS cr16_num_regs
+ 
+ /* CR16 register pair table.  */
+ extern const reg_entry cr16_regptab[];
+ extern const unsigned int cr16_num_regps;
+ #define NUMREGPS cr16_num_regps
+ 
+ /* CR16 processor registers table.  */
+ extern const reg_entry cr16_pregtab[];
+ extern const unsigned int cr16_num_pregs;
+ #define NUMPREGS cr16_num_pregs
+ 
+ /* CR16 processor registers - 32 bit table.  */
+ extern const reg_entry cr16_pregptab[];
+ extern const unsigned int cr16_num_pregps;
+ #define NUMPREGPS cr16_num_pregps
+ 
+ /* CR16 trap/interrupt table.  */
+ extern const trap_entry cr16_traps[];
+ extern const unsigned int cr16_num_traps;
+ #define NUMTRAPS cr16_num_traps
+ 
+ /* CR16 CC - codes bit table.  */
+ extern const char * cr16_b_cond_tab[];
+ extern const unsigned int cr16_num_cc;
+ #define NUMCC cr16_num_cc;
+ 
+ 
+ /* Table of instructions with no operands.  */
+ extern const char* no_op_insn[];
+ 
+ /* Current instruction we're assembling.  */
+ extern const inst *instruction;
+ 
+ /* A macro for representing the instruction "constant" opcode, that is,
+    the FIXED part of the instruction. The "constant" opcode is represented
+    as a 32-bit unsigned long, where OPC is expanded (by a left SHIFT)
+    over that range.  */
+ #define BIN(OPC,SHIFT)        (OPC << SHIFT)
+ 
+ /* Is the current instruction type is TYPE ?  */
+ #define IS_INSN_TYPE(TYPE)              \
+   (CR16_INS_TYPE(instruction->flags) == TYPE)
+ 
+ /* Is the current instruction mnemonic is MNEMONIC ?  */
+ #define IS_INSN_MNEMONIC(MNEMONIC)    \
+   (strcmp(instruction->mnemonic,MNEMONIC) == 0)
+ 
+ /* Does the current instruction has register list ?  */
+ #define INST_HAS_REG_LIST              \
+   (instruction->flags & REG_LIST)
+ 
+ 
+ /* Utility macros for string comparison.  */
+ #define streq(a, b)           (strcmp (a, b) == 0)
+ #define strneq(a, b, c)       (strncmp (a, b, c) == 0)
+ 
+ /* Long long type handling.  */
+ /* Replace all appearances of 'long long int' with LONGLONG.  */
+ typedef long long int LONGLONG;
+ typedef unsigned long long ULONGLONG;
+ 
+ #endif /* _CR16_H_ */
diff -Napr --exclude=testsuite binutils-2.17.50/ld/ChangeLog binutils-2.17.50-cr16/ld/ChangeLog
*** binutils-2.17.50/ld/ChangeLog	2007-05-18 14:48:18.000000000 +0530
--- binutils-2.17.50-cr16/ld/ChangeLog	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,3 ****
--- 1,15 ----
+ 2006-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+ 	* scripttemp/elf32cr16.sc: Default linker script.
+ 	* emulparams/elf32cr16.sh: Emulation script.
+ 	* emultempl/cr16elf.em: Emulation script.
+ 	* Makefile.am: Add entry to make cr16 target.
+ 	* Makefile.in: Regenerate.
+ 	* configure.tgt: Specify default and other emulation parameters
+ 	for cr16.
+ 	* ChangeLog: Added CR16 target entry.
+ 	* NEWS: Announce the support for the CR16 new target.
+ 
  2007-05-18  Richard Sandiford  <richard@codesourcery.com>
  
  	* emulparams/elf32ebmipvxworks.sh (OTHER_READONLY_SECTIONS)
diff -Napr --exclude=testsuite binutils-2.17.50/ld/configure.tgt binutils-2.17.50-cr16/ld/configure.tgt
*** binutils-2.17.50/ld/configure.tgt	2007-04-04 23:32:39.000000000 +0530
--- binutils-2.17.50-cr16/ld/configure.tgt	2007-06-26 15:11:11.000000000 +0530
*************** bfin-*-linux-uclibc*)	targ_emul=elf32bfi
*** 121,126 ****
--- 121,127 ----
  			targ_extra_emuls="elf32bfinfd"
  			targ_extra_libpath=$targ_extra_emuls
  			;;
+ cr16-*-elf*)            targ_emul=elf32cr16 ;;
  cr16c-*-elf*)           targ_emul=elf32cr16c
  			;;
  cris-*-*aout*)		targ_emul=crisaout
diff -Napr --exclude=testsuite binutils-2.17.50/ld/emulparams/elf32cr16.sh binutils-2.17.50-cr16/ld/emulparams/elf32cr16.sh
*** binutils-2.17.50/ld/emulparams/elf32cr16.sh	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/ld/emulparams/elf32cr16.sh	2007-06-22 15:41:13.000000000 +0530
***************
*** 0 ****
--- 1,6 ----
+ SCRIPT_NAME=elf32cr16
+ TEMPLATE_NAME=elf32
+ OUTPUT_FORMAT="elf32-cr16"
+ ARCH=cr16
+ ENTRY=_start
+ EXTRA_EM_FILE=cr16elf
diff -Napr --exclude=testsuite binutils-2.17.50/ld/emultempl/cr16elf.em binutils-2.17.50-cr16/ld/emultempl/cr16elf.em
*** binutils-2.17.50/ld/emultempl/cr16elf.em	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/ld/emultempl/cr16elf.em	2007-06-26 13:27:47.000000000 +0530
***************
*** 0 ****
--- 1,94 ----
+ # This shell script emits a C file. -*- C -*-
+ # Copyright 2007 Free Software Foundation, Inc.
+ # Contributed by M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ #
+ # This file is part of GLD, the Gnu Linker.
+ #
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ #
+ # This program 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 this program; if not, write to the Free Software
+ # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ #
+ 
+ # This file is sourced from elf32.em, and defines extra cr16-elf
+ # specific routines.
+ #
+ cat >>e${EMULATION_NAME}.c <<EOF
+ 
+ #include "ldctor.h"
+ 
+ /* Flag for the emulation-specific "--no-relax" option.  */
+ static bfd_boolean disable_relaxation = FALSE;
+ 
+ static void cr16elf_after_parse (void);
+ 
+ static void
+ cr16elf_after_parse (void)
+ {
+   /* Always behave as if called with --sort-common command line
+      option.
+      This is to emulate the CRTools' method of keeping variables
+      of different alignment in separate sections.  */
+   config.sort_common = TRUE;
+ 
+   /* Don't create a demand-paged executable, since this feature isn't
+      meaninful in CR16 embedded systems. Moreover, when magic_demand_paged
+      is true the link sometimes fails.  */
+   config.magic_demand_paged = FALSE;
+ }
+ 
+ /* This is called after the sections have been attached to output
+    sections, but before any sizes or addresses have been set.  */
+ 
+ static void
+ cr16elf_before_allocation (void)
+ {
+   /* Call the default first.  */
+   gld${EMULATION_NAME}_before_allocation ();
+ 
+   /* Enable relaxation by default if the "--no-relax" option was not
+      specified.  This is done here instead of in the before_parse hook
+      because there is a check in main() to prohibit use of --relax and
+      -r together.  */
+ 
+   if (!disable_relaxation)
+     command_line.relax = TRUE;
+ }
+ 
+ EOF
+ 
+ # Define some shell vars to insert bits of code into the standard elf
+ # parse_args and list_options functions.
+ #
+ PARSE_AND_LIST_PROLOGUE='
+ #define OPTION_NO_RELAX			301
+ '
+ 
+ PARSE_AND_LIST_LONGOPTS='
+   { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
+ '
+ 
+ PARSE_AND_LIST_OPTIONS='
+   fprintf (file, _("  --no-relax                  Do not relax branches\n"));
+ '
+ 
+ PARSE_AND_LIST_ARGS_CASES='
+     case OPTION_NO_RELAX:
+       disable_relaxation = TRUE;
+       break;
+ '
+ 
+ # Put these extra cr16-elf routines in ld_${EMULATION_NAME}_emulation
+ #
+ LDEMUL_AFTER_PARSE=cr16elf_after_parse
+ LDEMUL_BEFORE_ALLOCATION=cr16elf_before_allocation
+ 
diff -Napr --exclude=testsuite binutils-2.17.50/ld/Makefile.am binutils-2.17.50-cr16/ld/Makefile.am
*** binutils-2.17.50/ld/Makefile.am	2007-04-26 20:16:59.000000000 +0530
--- binutils-2.17.50-cr16/ld/Makefile.am	2007-06-26 15:11:11.000000000 +0530
*************** ALL_EMULATIONS = \
*** 157,162 ****
--- 157,163 ----
  	eelf32b4300.o \
  	eelf32bfin.o \
  	eelf32bfinfd.o \
+ 	eelf32cr16.o \
  	eelf32cr16c.o \
  	eelf32bmip.o \
  	eelf32bmipn32.o \
*************** eelf32b4300.c: $(srcdir)/emulparams/elf3
*** 742,747 ****
--- 743,752 ----
    $(srcdir)/emulparams/elf32bmip.sh $(ELF_DEPS) \
    $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32b4300 "$(tdir_elf32b4300)"
+ eelf32cr16.c: $(srcdir)/emulparams/elf32cr16.sh \
+   $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/cr16elf.em \
+   $(srcdir)/scripttempl/elf32cr16.sc ${GEN_DEPENDS} 
+ 	${GENSCRIPTS} elf32cr16 "$(tdir_elf32crx)"
  eelf32cr16c.c: $(srcdir)/emulparams/elf32cr16c.sh \
    $(ELF_DEPS) \
    $(srcdir)/scripttempl/elf32cr16c.sc ${GEN_DEPENDS}
diff -Napr --exclude=testsuite binutils-2.17.50/ld/Makefile.in binutils-2.17.50-cr16/ld/Makefile.in
*** binutils-2.17.50/ld/Makefile.in	2007-04-26 20:16:59.000000000 +0530
--- binutils-2.17.50-cr16/ld/Makefile.in	2007-06-22 15:41:13.000000000 +0530
*************** ALL_EMULATIONS = \
*** 393,398 ****
--- 393,399 ----
  	eelf32b4300.o \
  	eelf32bfin.o \
  	eelf32bfinfd.o \
+ 	eelf32cr16.o \
  	eelf32cr16c.o \
  	eelf32bmip.o \
  	eelf32bmipn32.o \
*************** eelf32b4300.c: $(srcdir)/emulparams/elf3
*** 1557,1562 ****
--- 1558,1567 ----
    $(srcdir)/emulparams/elf32bmip.sh $(ELF_DEPS) \
    $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32b4300 "$(tdir_elf32b4300)"
+ eelf32cr16.c: $(srcdir)/emulparams/elf32cr16.sh \
+   $(srcdir)/emultempl/elf32.em  $(srcdir)/emultempl/cr16elf.em \
+   $(srcdir)/scripttempl/elf32cr16.sc ${GEN_DEPENDS}
+ 	${GENSCRIPTS} elf32cr16 "$(tdir_elf32cr16)"
  eelf32cr16c.c: $(srcdir)/emulparams/elf32cr16c.sh \
    $(ELF_DEPS) \
    $(srcdir)/scripttempl/elf32cr16c.sc ${GEN_DEPENDS}
diff -Napr --exclude=testsuite binutils-2.17.50/ld/NEWS binutils-2.17.50-cr16/ld/NEWS
*** binutils-2.17.50/ld/NEWS	2007-03-29 22:46:05.000000000 +0530
--- binutils-2.17.50-cr16/ld/NEWS	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,4 ****
--- 1,6 ----
  -*- text -*-
+ * Added support for National Semicondutor CompactRISC (ie CR16) target.
+ *
  * -l:foo now searches the library path for a filename called foo,
    without converting it to libfoo.a or libfoo.so.
  
diff -Napr --exclude=testsuite binutils-2.17.50/ld/scripttempl/elf32cr16.sc binutils-2.17.50-cr16/ld/scripttempl/elf32cr16.sc
*** binutils-2.17.50/ld/scripttempl/elf32cr16.sc	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/ld/scripttempl/elf32cr16.sc	2007-06-22 15:41:13.000000000 +0530
***************
*** 0 ****
--- 1,175 ----
+ # Linker Script for National Semiconductor's CR16-ELF32.
+ 
+ # The next line should be uncommented if it is desired to link
+ # without libstart.o and directly enter main.
+ 
+ # ENTRY=_main
+ 
+ test -z "$ENTRY" && ENTRY=_start
+ cat <<EOF
+ 
+ /* Example Linker Script for linking NS CR16 elf32 files. */
+ 
+ /* The next line forces the entry point (${ENTRY} in this script)
+    to be entered in the output file as an undefined symbol.
+    It is needed in case the entry point is not called explicitly
+    (which is the usual case) AND is in an archive.  */
+ 
+ OUTPUT_FORMAT("${OUTPUT_FORMAT}")
+ OUTPUT_ARCH(${ARCH})
+ EXTERN(${ENTRY})
+ ENTRY(${ENTRY})
+ 
+ /* Define memory regions.  */
+ MEMORY
+ {
+         rom         : ORIGIN = 0x2,         LENGTH = 3M
+         ram         : ORIGIN = 4M,          LENGTH = 10M
+ }
+ 
+ /*  Many sections come in three flavours.  There is the 'real' section,
+     like ".data".  Then there are the per-procedure or per-variable
+     sections, generated by -ffunction-sections and -fdata-sections in GCC,
+     and useful for --gc-sections, which for a variable "foo" might be
+     ".data.foo".  Then there are the linkonce sections, for which the linker
+     eliminates duplicates, which are named like ".gnu.linkonce.d.foo".
+     The exact correspondences are:
+ 
+     Section	Linkonce section
+     .text	.gnu.linkonce.t.foo
+     .rdata	.gnu.linkonce.r.foo
+     .data	.gnu.linkonce.d.foo
+     .bss	.gnu.linkonce.b.foo
+     .debug_info	.gnu.linkonce.wi.foo  */
+ 
+ SECTIONS
+ {
+   .init :
+   { 
+     __INIT_START = .; 
+     KEEP (*(.init))
+     __INIT_END = .; 
+   } > rom
+ 
+   .fini :
+   { 
+     __FINI_START = .; 
+     KEEP (*(.fini))
+     __FINI_END = .; 
+   } > rom
+ 
+   .jcr :
+   { 
+     KEEP (*(.jcr))
+   } > rom
+ 
+   .text : 
+   {
+     __TEXT_START = .;
+     *(.text) *(.text.*) *(.gnu.linkonce.t.*)
+     __TEXT_END = .;
+   } > rom
+ 
+   .rdata :
+   {
+     __RDATA_START = .;
+     *(.rdata_4) *(.rdata_2) *(.rdata_1) *(.rdata.*) *(.gnu.linkonce.r.*) *(.rodata*)
+     __RDATA_END = .;
+   } > rom
+ 
+   .ctor ALIGN(4) : 
+   { 
+     __CTOR_START = .; 
+     /* The compiler uses crtbegin.o to find the start
+        of the constructors, so we make sure it is
+        first.  Because this is a wildcard, it
+        doesn't matter if the user does not
+        actually link against crtbegin.o; the
+        linker won't look for a file to match a
+        wildcard.  The wildcard also means that it
+        doesn't matter which directory crtbegin.o
+        is in.  */
+ 
+     KEEP (*crtbegin*.o(.ctors))
+ 
+     /* We don't want to include the .ctor section from
+        the crtend.o file until after the sorted ctors.
+        The .ctor section from the crtend file contains the
+        end of ctors marker and it must be last */
+ 
+     KEEP (*(EXCLUDE_FILE (*crtend*.o) .ctors))
+     KEEP (*(SORT(.ctors.*)))
+     KEEP (*(.ctors))
+     __CTOR_END = .; 
+   } > rom
+ 
+   .dtor ALIGN(4) : 
+   { 
+     __DTOR_START = .; 
+     KEEP (*crtbegin*.o(.dtors))
+     KEEP (*(EXCLUDE_FILE (*crtend*.o) .dtors))
+     KEEP (*(SORT(.dtors.*)))
+     KEEP (*(.dtors))
+     __DTOR_END = .; 
+   } > rom
+ 
+   .data :
+   {
+     __DATA_START = .;
+     *(.data_4) *(.data_2) *(.data_1) *(.data) *(.data.*) *(.gnu.linkonce.d.*)
+     __DATA_END = .;
+   } > ram AT > rom
+ 
+   .bss (NOLOAD) :
+   {
+     __BSS_START = .;
+     *(.bss_4) *(.bss_2) *(.bss_1) *(.bss) *(COMMON) *(.bss.*) *(.gnu.linkonce.b.*)
+     __BSS_END = .;
+   } > ram
+ 
+ /* You may change the sizes of the following sections to fit the actual
+    size your program requires.
+ 
+    The heap and stack are aligned to the bus width, as a speed optimization
+    for accessing data located there.  */
+ 
+   .heap :
+   {
+     . = ALIGN(4);
+     __HEAP_START = .;
+     . += 0x2000; __HEAP_MAX = .;
+   } > ram
+ 
+   .stack :
+   {
+     . = ALIGN(4);
+     . += 0x6000;
+     __STACK_START = .;
+   } > ram
+ 
+   .istack :
+   {
+     . = ALIGN(4);
+     . += 0x100;
+     __ISTACK_START = .;
+   } > ram
+ 
+   .comment        0 : { *(.comment) }
+ 
+   /* DWARF debug sections.
+      Symbols in the DWARF debugging sections are relative to the beginning
+      of the section so we begin them at 0.  */
+ 
+   .debug_aranges  0 : { *(.debug_aranges) }
+   .debug_pubnames 0 : { *(.debug_pubnames) }
+   .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+   .debug_abbrev   0 : { *(.debug_abbrev) }
+   .debug_line     0 : { *(.debug_line) }
+   .debug_frame    0 : { *(.debug_frame) }
+   .debug_str      0 : { *(.debug_str) }
+   .debug_loc      0 : { *(.debug_loc) }
+   .debug_macinfo  0 : { *(.debug_macinfo) }
+ }
+ 
+ __DATA_IMAGE_START = LOADADDR(.data);
+ EOF
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/ChangeLog binutils-2.17.50-cr16/opcodes/ChangeLog
*** binutils-2.17.50/opcodes/ChangeLog	2007-05-18 07:02:56.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/ChangeLog	2007-06-22 15:41:13.000000000 +0530
***************
*** 1,3 ****
--- 1,13 ----
+ 2007-06-18  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+ 
+ 	* cr16-opc.c: New file.
+ 	* cr16-dis.c: New file.
+ 	* Makefile.am: Entries for cr16.
+ 	* Makefile.in: Regenerate.
+ 	* cofigure.in: Add cr16 target information.
+ 	* configure  : Regenerate.
+ 	* disassemble.c: Add cr16 target information.
+ 
  2007-05-18  Alan Modra  <amodra@bigpond.net.au>
  
  	* ppc-dis.c (print_insn_powerpc): Don't skip all operands
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/configure binutils-2.17.50-cr16/opcodes/configure
*** binutils-2.17.50/opcodes/configure	2007-03-15 20:01:24.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/configure	2007-06-26 15:07:16.000000000 +0530
*************** if test x${all_targets} = xfalse ; then
*** 6530,6535 ****
--- 6530,6536 ----
  	bfd_arm_arch)		ta="$ta arm-dis.lo" ;;
  	bfd_avr_arch)		ta="$ta avr-dis.lo" ;;
  	bfd_bfin_arch)		ta="$ta bfin-dis.lo" ;;
+ 	bfd_cr16_arch)    	ta="$ta cr16-dis.lo cr16-opc.lo" ;;
  	bfd_cris_arch)		ta="$ta cris-dis.lo cris-opc.lo cgen-bitset.lo" ;;
  	bfd_crx_arch)    	ta="$ta crx-dis.lo crx-opc.lo" ;;
  	bfd_d10v_arch)		ta="$ta d10v-dis.lo d10v-opc.lo" ;;
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/configure.in binutils-2.17.50-cr16/opcodes/configure.in
*** binutils-2.17.50/opcodes/configure.in	2007-03-15 20:01:24.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/configure.in	2007-06-26 15:07:16.000000000 +0530
*************** if test x${all_targets} = xfalse ; then
*** 159,164 ****
--- 159,165 ----
  	bfd_arm_arch)		ta="$ta arm-dis.lo" ;;
  	bfd_avr_arch)		ta="$ta avr-dis.lo" ;;
  	bfd_bfin_arch)		ta="$ta bfin-dis.lo" ;;
+ 	bfd_cr16_arch)    	ta="$ta cr16-dis.lo cr16-opc.lo" ;;
  	bfd_cris_arch)		ta="$ta cris-dis.lo cris-opc.lo cgen-bitset.lo" ;;
  	bfd_crx_arch)    	ta="$ta crx-dis.lo crx-opc.lo" ;;
  	bfd_d10v_arch)		ta="$ta d10v-dis.lo d10v-opc.lo" ;;
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/cr16-dis.c binutils-2.17.50-cr16/opcodes/cr16-dis.c
*** binutils-2.17.50/opcodes/cr16-dis.c	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/cr16-dis.c	2007-06-22 15:41:13.000000000 +0530
***************
*** 0 ****
--- 1,822 ----
+ /* Disassembler code for CR16.
+    Copyright 2007 Free Software Foundation, Inc.
+    Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
+ 
+    This file is part of GAS, GDB and the GNU binutils.
+ 
+    This program is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #include "dis-asm.h"
+ #include "sysdep.h"
+ #include "opcode/cr16.h"
+ 
+ /* String to print when opcode was not matched.  */
+ #define ILLEGAL  "illegal"
+   /* Escape to 16-bit immediate.  */
+ #define ESCAPE_16_BIT  0xB
+ 
+ /* Extract 'n_bits' from 'a' starting from offset 'offs'.  */
+ #define EXTRACT(a, offs, n_bits)                    \
+   (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL)   \
+   : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
+ 
+ /* Set Bit Mask - a mask to set all bits starting from offset 'offs'.  */
+ #define SBM(offs)  ((((1 << (32 - offs)) -1) << (offs)))
+ 
+ typedef unsigned long dwordU;
+ typedef unsigned short wordU;
+ 
+ typedef struct
+ {
+   dwordU val;
+   int nbits;
+ } parameter;
+ 
+ /* Structure to map valid 'cinv' instruction options.  */
+ 
+ typedef struct
+   {
+     /* Cinv printed string.  */
+     char *istr;
+     /* Value corresponding to the string.  */
+     char *ostr;
+   }
+ cinv_entry;
+ 
+ /* CR16 'cinv' options mapping.  */
+ const cinv_entry cr16_cinvs[] =
+ {
+   {"cinv[i]",     "cinv    [i]"},
+   {"cinv[i,u]",   "cinv    [i,u]"},
+   {"cinv[d]",     "cinv    [d]"},
+   {"cinv[d,u]",   "cinv    [d,u]"},
+   {"cinv[d,i]",   "cinv    [d,i]"},
+   {"cinv[d,i,u]", "cinv    [d,i,u]"}
+ };
+ 
+ /* Number of valid 'cinv' instruction options.  */
+ int NUMCINVS = ((sizeof cr16_cinvs)/(sizeof cr16_cinvs[0]));
+ 
+ /* Enum to distinguish different registers argument types.  */
+ typedef enum REG_ARG_TYPE
+   {
+     /* General purpose register (r<N>).  */
+     REG_ARG = 0,
+     /*Processor register   */
+     P_ARG,
+   }
+ REG_ARG_TYPE;
+ 
+ /* Current opcode table entry we're disassembling.  */
+ const inst *instruction;
+ /* Current instruction we're disassembling.  */
+ ins currInsn;
+ /* The current instruction is read into 3 consecutive words.  */
+ wordU words[3];
+ /* Contains all words in appropriate order.  */
+ ULONGLONG allWords;
+ /* Holds the current processed argument number.  */
+ int processing_argument_number;
+ /* Nonzero means a IMM4 instruction.  */
+ int imm4flag;
+ /* Nonzero means the instruction's original size is
+    incremented (escape sequence is used).  */
+ int size_changed;
+ 
+ static int get_number_of_operands (void);
+ static argtype getargtype     (operand_type);
+ static int getbits            (operand_type);
+ static char *getregname       (reg);
+ static char *getregpname      (reg);
+ static char *getidxregpname   (reg);
+ static char * getprocregname  (int);
+ static char * getprocpregname (int);
+ static char *gettrapstring    (unsigned);
+ static char *getcinvstring    (char *);
+ static char *getccstring      (unsigned);
+ static wordU get_word_at_PC   (bfd_vma, struct disassemble_info *);
+ static void get_words_at_PC   (bfd_vma, struct disassemble_info *);
+ static unsigned long build_mask (void);
+ static int match_opcode         (void);
+ static void make_instruction    (void);
+ static void print_arguments   (ins *, bfd_vma, struct disassemble_info *);
+ static void print_arg         (argument *, bfd_vma, struct disassemble_info *);
+ static char *print_exp_len    (int);
+ 
+ 
+ /* print the constant expression length */
+ 
+ static char *  
+ print_exp_len(int size)
+ {
+   switch (size)  
+     {
+       case 4  : case 5  : case 6  : case 8  : case 14: case 16:
+            return (":s");
+       case 20 :  case 24 : case 32 : return (":m");
+       case 48 : return (":l");
+       default:
+            return ("");
+     }
+ }
+ 
+ 
+ /* Retrieve the number of operands for the current assembled instruction.  */
+ 
+ static int
+ get_number_of_operands (void)
+ {
+   int i;
+ 
+   for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
+     ;
+ 
+   return i;
+ }
+ 
+ /* Return the bit size for a given operand.  */
+ 
+ static int
+ getbits (operand_type op)
+ {
+   if (op < MAX_OPRD)
+     return cr16_optab[op].bit_size;
+   else
+     return 0;
+ }
+ 
+ /* Return the argument type of a given operand.  */
+ 
+ static argtype
+ getargtype (operand_type op)
+ {
+   if (op < MAX_OPRD)
+     return cr16_optab[op].arg_type;
+   else
+     return nullargs;
+ }
+ 
+ /* Given a 'CC' instruction constant operand, return its corresponding
+    string. This routine is used when disassembling the 'CC' instruction. */
+ 
+ static char *
+ getccstring (unsigned cc)
+ {
+      return (char *)cr16_b_cond_tab[cc];
+ }
+ 
+ 
+ /* Given a 'cinv' instruction constant operand, return its corresponding
+    string. This routine is used when disassembling the 'cinv' instruction. */
+ 
+ static char *
+ getcinvstring (char *str)
+ {
+   const cinv_entry *cinv;
+ 
+   for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
+     if (strcmp(cinv->istr, str) == 0)
+       return cinv->ostr;
+ 
+   return ILLEGAL;
+ }
+ 
+ /* Given the trap index in dispatch table, return its name.
+    This routine is used when disassembling the 'excp' instruction.  */
+ 
+ static char *
+ gettrapstring (unsigned int index)
+ {
+   const trap_entry *trap;
+ 
+   for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
+     if (trap->entry == index)
+       return trap->name;
+ 
+   return ILLEGAL;
+ }
+ 
+ /* Given a register enum value, retrieve its name.  */
+ 
+ char *
+ getregname (reg r)
+ {
+   const reg_entry *reg = &cr16_regtab[r];
+ 
+   if (reg->type != CR16_R_REGTYPE)
+     return ILLEGAL;
+   else
+     return reg->name;
+ }
+ 
+ /* Given a register pair enum value, retrieve its name.  */
+ 
+ char *
+ getregpname (reg r)
+ {
+   const reg_entry *reg = &cr16_regptab[r];
+ 
+   if (reg->type != CR16_RP_REGTYPE)
+     return ILLEGAL;
+   else
+     return reg->name;
+ }
+ 
+ /* Given a index register pair enum value, retrieve its name.  */
+ 
+ char *
+ getidxregpname (reg r)
+ {
+   const reg_entry *reg;
+   switch (r) 
+    {
+      case 0: r = 0; break;
+      case 1: r = 2; break;
+      case 2: r = 4; break;
+      case 3: r = 6; break;
+      case 4: r = 8; break;
+      case 5: r = 10; break;
+      case 6: r = 3; break;
+      case 7: r = 5; break;
+      default:
+        break;
+    }
+   reg = &cr16_regptab[r];
+ 
+   if (reg->type != CR16_RP_REGTYPE)
+     return ILLEGAL;
+   else
+     return reg->name;
+ }
+ 
+ /* Getting a processor register name.  */
+ 
+ static char *
+ getprocregname (int index)
+ {
+   const reg_entry *r;
+ 
+   for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
+     if (r->image == index)
+       return r->name;
+ 
+   return "ILLEGAL REGISTER";
+ }
+ 
+ /* Getting a processor register name - 32 bit size.  */
+ 
+ static char *
+ getprocpregname (int index)
+ {
+   const reg_entry *r;
+ 
+   for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
+     if (r->image == index)
+       return r->name;
+ 
+   return "ILLEGAL REGISTER";
+ }
+ 
+ /* START and END are relating 'allWords' struct, which is 48 bits size.
+ 
+                           START|--------|END
+              +---------+---------+---------+---------+
+              |         |   V    |     A    |   L     |
+              +---------+---------+---------+---------+
+                        0         16        32        48
+     words                  [0]       [1]       [2]      */
+ 
+ static parameter
+ makelongparameter (ULONGLONG val, int start, int end)
+ {
+   parameter p;
+ 
+   p.val = (dwordU) EXTRACT(val, 48 - end, end - start);
+   p.nbits = end - start;
+   return p;
+ }
+ 
+ /* Build a mask of the instruction's 'constant' opcode,
+    based on the instruction's printing flags.  */
+ 
+ static unsigned long
+ build_mask (void)
+ {
+   unsigned long mask = SBM(instruction->match_bits);
+   return mask;
+ }
+ 
+ /* Search for a matching opcode. Return 1 for success, 0 for failure.  */
+ 
+ static int
+ match_opcode (void)
+ {
+   unsigned long mask;
+ 
+   /* The instruction 'constant' opcode doewsn't exceed 32 bits.  */
+   unsigned long doubleWord = words[1] + (words[0] << 16);
+ 
+   /* Start searching from end of instruction table.  */
+   instruction = &cr16_instruction[NUMOPCODES - 2];
+ 
+   /* Loop over instruction table until a full match is found.  */
+   while (instruction >= cr16_instruction)
+     {
+       mask = build_mask ();
+       if ((doubleWord & mask) == BIN(instruction->match, 
+                                      instruction->match_bits))
+         return 1;
+       else
+         instruction--;
+     }
+   return 0;
+ }
+ 
+ /* Set the proper parameter value for different type of arguments.  */
+ 
+ static void
+ make_argument (argument * a, int start_bits)
+ {
+   int inst_bit_size;
+   parameter p;
+ 
+   if ((instruction->size == 3) && a->size >= 16)
+     inst_bit_size = 48;
+   else
+     inst_bit_size = 32;
+ 
+   switch (a->type)
+     {
+       case arg_r:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+       a->r = p.val;
+       break;
+ 
+       case arg_rp:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+       a->rp = p.val;
+       break;
+ 
+       case arg_pr:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+       a->pr = p.val;
+       break;
+ 
+       case arg_prp:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+       a->prp = p.val;
+       break;
+ 
+       case arg_ic:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+       a->constant = p.val;
+       break;
+ 
+       case arg_cc:
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
+                              inst_bit_size - start_bits);
+ 
+       a->cc = p.val;
+       break;
+ 
+       case arg_idxr:
+       if ((IS_INSN_MNEMONIC("cbitb")) || (IS_INSN_MNEMONIC("sbitb")) || 
+           (IS_INSN_MNEMONIC("tbitb")))
+          p = makelongparameter (allWords, 8, 9);
+       else
+          p = makelongparameter (allWords, 9, 10);
+       a->i_r = p.val;
+       p = makelongparameter (allWords, inst_bit_size - a->size, inst_bit_size);
+       a->constant = p.val;
+       break;
+ 
+       case arg_idxrp:
+       p = makelongparameter (allWords, start_bits + 12, start_bits + 13);
+       a->i_r = p.val;
+       p = makelongparameter (allWords, start_bits + 13, start_bits + 16);
+       a->rp = p.val;
+       if (inst_bit_size > 32)
+        {
+          p = makelongparameter (allWords, inst_bit_size - start_bits - 12, 
+                                 inst_bit_size);
+          a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
+        }
+       else if (instruction->size == 2)
+             {
+               p = makelongparameter (allWords, inst_bit_size - 22, inst_bit_size);
+               a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)| 
+                             ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
+             }
+            else if (instruction->size == 1 && a->size == 0)
+                  a->constant = 0;
+ 
+       break;
+ 
+       case arg_rbase:
+       p = makelongparameter (allWords, inst_bit_size, inst_bit_size);
+       a->constant = p.val;
+       p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
+                              inst_bit_size - start_bits);
+       a->r = p.val;
+       break;
+ 
+       case arg_cr:
+       p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
+       a->r = p.val;
+       p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
+       a->constant = p.val;
+       break;
+ 
+       case arg_crp:
+         if (instruction->size == 1)
+           p = makelongparameter (allWords, 12, 16);
+         else
+           p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
+         a->rp = p.val;
+ 
+         if (inst_bit_size > 32)
+           {
+             p = makelongparameter (allWords, inst_bit_size - start_bits - 12, 
+                                    inst_bit_size);
+             a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
+           }
+         else if (instruction->size == 2)
+           {
+             p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
+             a->constant = p.val;
+           }
+         else if (instruction->size == 1 && a->size !=0) 
+           {
+             p = makelongparameter (allWords, 4, 8);
+             if (IS_INSN_MNEMONIC("loadw") || IS_INSN_MNEMONIC("loadd") ||
+                 IS_INSN_MNEMONIC("storw") || IS_INSN_MNEMONIC("stord"))
+               a->constant = (p.val*2);
+             else
+               a->constant = p.val;
+           }
+         else /* below case for 0x0(reg pair) */
+           a->constant = 0;
+ 
+         break;
+ 
+       case arg_c:
+   
+         if ((IS_INSN_TYPE(BRANCH_INS)) || (IS_INSN_MNEMONIC("bal")) ||
+            (IS_INSN_TYPE(CSTBIT_INS)) || (IS_INSN_TYPE(LD_STOR_INS)))
+           {
+             switch (a->size)
+               {
+                 case 8 :
+                   p = makelongparameter (allWords, 0, start_bits);
+                   a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
+                   break;
+ 
+                 case 24:
+                   if (instruction->size == 3)
+                     {
+                       p = makelongparameter (allWords, 16, inst_bit_size);
+                       a->constant = ((((p.val>>16)&0xf) << 20)|
+                                      (((p.val>>24)&0xf) << 16)| 
+                                      (p.val & 0xffff));
+                     }
+                   else if (instruction->size == 2)
+                     {
+                       p = makelongparameter (allWords, 8, inst_bit_size);
+                       a->constant = p.val;
+                     }
+                   break;
+ 
+                 default:
+                   p = makelongparameter (allWords, inst_bit_size - (start_bits +
+                                          a->size), inst_bit_size - start_bits);
+                   a->constant = p.val;
+                   break;
+               }
+           }
+         else
+           {
+             p = makelongparameter (allWords, inst_bit_size -
+                                    (start_bits + a->size),
+                                    inst_bit_size - start_bits);
+             a->constant = p.val;
+           }
+         break;
+ 
+       default:
+         break;
+     }
+ }
+ 
+ /*  Print a single argument.  */
+ 
+ static void
+ print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
+ {
+   LONGLONG longdisp, mask;
+   int sign_flag = 0;
+   int relative = 0;
+   bfd_vma number;
+   PTR stream = info->stream;
+   fprintf_ftype func = info->fprintf_func;
+ 
+   switch (a->type)
+     {
+       case arg_r:
+         func (stream, "%s", getregname (a->r));
+         break;
+ 
+       case arg_rp:
+         func (stream, "%s", getregpname (a->rp));
+         break;
+ 
+       case arg_pr:
+         func (stream, "%s", getprocregname (a->pr));
+         break;
+ 
+       case arg_prp:
+         func (stream, "%s", getprocpregname (a->prp));
+         break;
+ 
+       case arg_cc:
+         func (stream, "%s", getccstring (a->cc));
+         func (stream, "%s", "\t");
+         break;
+ 
+       case arg_ic:
+         if (IS_INSN_MNEMONIC ("excp"))
+           {
+             func (stream, "%s", gettrapstring (a->constant));
+             break;
+           }
+         else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS)) &&
+                  ((instruction->size == 1) && (a->constant == 9)))
+                func (stream, "$%d", -1);
+         else if (INST_HAS_REG_LIST)
+                func (stream, "$0x%lx", a->constant +1);
+         else if (IS_INSN_TYPE(SHIFT_INS))
+                {
+                  longdisp = a->constant;
+                  mask = ((LONGLONG)1 << a->size) - 1;
+                  if (longdisp & ((LONGLONG)1 << (a->size -1)))
+                    {
+                      sign_flag = 1;
+                      longdisp = ~(longdisp) + 1;
+                    }
+                  a->constant = (unsigned long int) (longdisp & mask);
+                  func (stream, "$%d", ((int)(sign_flag ? -a->constant :
+                                              a->constant)));
+                }
+              else
+                func (stream, "$0x%lx", a->constant);
+         switch (a->size)  
+           {
+              case 4  : case 5  : case 6  : case 8  :
+                func (stream, "%s", ":s"); break;
+              case 16 : case 20 : func (stream, "%s", ":m"); break;
+              case 24 : case 32 : func (stream, "%s", ":l"); break;
+                default: break;
+           }
+         break;
+ 
+       case arg_idxr:
+         if (a->i_r == 0) func (stream, "[r12]");
+         if (a->i_r == 1) func (stream, "[r13]");
+         func (stream, "0x%lx", a->constant);
+         func (stream, "%s", print_exp_len(instruction->size*16));
+         break;
+ 
+       case arg_idxrp:
+         if (a->i_r == 0) func (stream, "[r12]");
+         if (a->i_r == 1) func (stream, "[r13]");
+         func (stream, "0x%lx", a->constant);
+         func (stream, "%s", print_exp_len(instruction->size*16));
+         func (stream, "%s", getidxregpname (a->rp));
+         break;
+ 
+       case arg_rbase:
+         func (stream, "(%s)", getregname (a->r));
+         break;
+ 
+       case arg_cr:
+         func (stream, "0x%lx", a->constant);
+         func (stream, "%s", print_exp_len(instruction->size * 16));
+         func (stream, "(%s)", getregname (a->r));
+         break;
+ 
+       case arg_crp:
+         func (stream, "0x%lx", a->constant);
+         func (stream, "%s", print_exp_len(instruction->size * 16));
+         func (stream, "%s", getregpname (a->rp));
+         break;
+ 
+       case arg_c:
+         /*Removed the *2 part as because implicit zeros are no more required.
+           Have to fix this as this needs a bit of extension in terms of branch
+           instructions. */
+         if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
+           {
+             relative = 1;
+             longdisp = a->constant;
+             /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
+                line commented */
+             /* longdisp <<= 1; */
+             mask = ((LONGLONG)1 << a->size) - 1;
+             switch (a->size)
+               {
+                 case 8  :
+                   {
+                     longdisp <<= 1;
+                     if (longdisp & ((LONGLONG)1 << a->size))
+                       {
+                         sign_flag = 1;
+                         longdisp = ~(longdisp) + 1;
+                       }
+                     break;
+                    }
+                  case 16 :
+                  case 24 :
+                    {
+                      if (longdisp & 1)
+                        {
+                           sign_flag = 1;
+                           longdisp = ~(longdisp) + 1;
+                        }
+                      break;
+                    }
+                  default:
+                    func (stream, "Wrong offset used in branch/bal instruction");
+                    break;
+               }
+             a->constant = (unsigned long int) (longdisp & mask);
+           }
+         /* For branch Neq instruction it is 2*offset + 2.  */
+         else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
+                a->constant = 2 * a->constant + 2;
+ 
+         if ((!IS_INSN_TYPE(CSTBIT_INS)) && (!IS_INSN_TYPE(LD_STOR_INS)))
+             (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
+ 
+         func (stream, "%s", "0x");
+         number = ((relative ? memaddr : 0) +
+                   (sign_flag ? ((-a->constant)&(0xffffffe)) : a->constant));
+ 
+         (*info->print_address_func) ((number & ((1<<(24))-1)), info);
+ 
+         func (stream, "%s", print_exp_len(instruction->size * 16));
+         break;
+ 
+       default:
+         break;
+     }
+ }
+ 
+ /* Print all the arguments of CURRINSN instruction.  */
+ 
+ static void
+ print_arguments (ins *currInsn, bfd_vma memaddr, struct disassemble_info *info)
+ {
+   int i;
+ 
+   /* For "pop/push/popret RA instruction only */
+   if ((IS_INSN_MNEMONIC ("pop") || (IS_INSN_MNEMONIC ("popret") ||
+       (IS_INSN_MNEMONIC ("push")))) && currInsn->nargs == 1) 
+     {
+       info->fprintf_func (info->stream, "RA");
+       return;
+     }
+ 
+   for (i = 0; i < currInsn->nargs; i++)
+     {
+       processing_argument_number = i;
+ 
+       /* For "bal (ra), disp17" instruction only */
+       if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
+         {
+           info->fprintf_func (info->stream, "(ra),");
+           continue;
+         }
+ 
+       if ((INST_HAS_REG_LIST) && (i == 2))
+         info->fprintf_func (info->stream, "RA");
+       else
+         print_arg (&currInsn->arg[i], memaddr, info);
+ 
+       if ((i != currInsn->nargs - 1) && (!IS_INSN_MNEMONIC("b")))
+         info->fprintf_func (info->stream, ",");
+     }
+ }
+ 
+ /* Build the instruction's arguments.  */
+ 
+ static void
+ make_instruction (void)
+ {
+   int i;
+   unsigned int shift;
+ 
+   for (i = 0; i < currInsn.nargs; i++)
+     {
+       argument a;
+ 
+       memset (&a, 0, sizeof (a));
+       a.type = getargtype (instruction->operands[i].op_type);
+       a.size = getbits (instruction->operands[i].op_type);
+       shift = instruction->operands[i].shift;
+ 
+       make_argument (&a, shift);
+       currInsn.arg[i] = a;
+     }
+ 
+   /* Calculate instruction size (in bytes).  */
+   currInsn.size = instruction->size + (size_changed ? 1 : 0);
+   /* Now in bits.  */
+   currInsn.size *= 2;
+ }
+ 
+ /* Retrieve a single word from a given memory address.  */
+ 
+ static wordU
+ get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
+ {
+   bfd_byte buffer[4];
+   int status;
+   wordU insn = 0;
+ 
+   status = info->read_memory_func (memaddr, buffer, 2, info);
+ 
+   if (status == 0)
+     insn = (wordU) bfd_getl16 (buffer);
+ 
+   return insn;
+ }
+ 
+ /* Retrieve multiple words (3) from a given memory address.  */
+ 
+ static void
+ get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
+ {
+   int i;
+   bfd_vma mem;
+ 
+   for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
+     words[i] = get_word_at_PC (mem, info);
+ 
+   allWords =
+     ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2];
+ }
+ 
+ /* Prints the instruction by calling print_arguments after proper matching.  */
+ 
+ int
+ print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
+ {
+   int is_decoded;     /* Nonzero means instruction has a match.  */
+ 
+   /* Initialize global variables.  */
+   imm4flag = 0;
+   size_changed = 0;
+ 
+   /* Retrieve the encoding from current memory location.  */
+   get_words_at_PC (memaddr, info);
+   /* Find a matching opcode in table.  */
+   is_decoded = match_opcode ();
+   /* If found, print the instruction's mnemonic and arguments.  */
+   if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0)
+     {
+       if (strneq(instruction->mnemonic, "cinv", 4))
+         info->fprintf_func (info->stream,"%s",getcinvstring((char *)instruction->mnemonic));
+       else
+         info->fprintf_func (info->stream, "%s", instruction->mnemonic);
+ 
+       if (((currInsn.nargs = get_number_of_operands ()) != 0) && 
+            !(IS_INSN_MNEMONIC("b")))
+         info->fprintf_func (info->stream, "\t");
+       make_instruction ();
+       /* for push/pop/pushrtn with RA instructions */
+       if ((INST_HAS_REG_LIST) && ((words[0] >> 7) & 0x1))
+         currInsn.nargs +=1;
+       print_arguments (&currInsn, memaddr, info);
+       return currInsn.size;
+     }
+ 
+   /* No match found.  */
+   info->fprintf_func (info->stream,"%s ",ILLEGAL);
+   return 2;
+ }
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/cr16-opc.c binutils-2.17.50-cr16/opcodes/cr16-opc.c
*** binutils-2.17.50/opcodes/cr16-opc.c	1970-01-01 05:30:00.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/cr16-opc.c	2007-06-26 13:22:07.000000000 +0530
***************
*** 0 ****
--- 1,611 ----
+ /* cr16-opc.c -- Table of opcodes for the CR16 processor.
+    Copyright 2007 Free Software Foundation, Inc.
+    Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com)
+ 
+    This file is part of GAS, GDB and the GNU binutils.
+ 
+    GAS, GDB, and GNU binutils is free software; you can redistribute it
+    and/or modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at your
+    option) any later version.
+ 
+    GAS, GDB, and GNU binutils are distributed in the hope that they 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 this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+ #include <stdio.h>
+ #include "libiberty.h"
+ #include "symcat.h"
+ #include "opcode/cr16.h"
+ 
+ const inst cr16_instruction[] =
+ {
+ /* Create an arithmetic instruction - INST[bw].  */
+ #define  ARITH_BYTE_INST(NAME, OPC, OP1)                             \
+   /* opc8 imm4 r */                                                  \
+   {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{uimm4_1,20}, {regr,16}}},     \
+   /* opc8 imm16 r */                                                 \
+   {NAME, 2, (OPC<<4)+0xB, 20, ARITH_BYTE_INS, {{OP1,0}, {regr,16}}}, \
+   /* opc8 r r */                                                     \
+   {NAME, 1, OPC+0x1, 24, ARITH_BYTE_INS, {{regr,20}, {regr,16}}}
+ 
+ /* for Logincal operations, allow unsinged imm16 also */
+ #define  ARITH1_BYTE_INST(NAME, OPC, OP1)                            \
+   /* opc8 imm16 r */                                                 \
+   {NAME, 2, (OPC<<4)+0xB, 20, ARITH_BYTE_INS, {{OP1,0}, {regr,16}}}
+ 
+ 
+   ARITH_BYTE_INST ("andb", 0x20, uimm16),
+   ARITH1_BYTE_INST ("andb", 0x20, imm16),
+   ARITH_BYTE_INST ("andw", 0x22, uimm16),
+   ARITH1_BYTE_INST ("andw", 0x22, imm16),
+ 
+   ARITH_BYTE_INST ("orb",  0x24, uimm16),
+   ARITH1_BYTE_INST ("orb",  0x24, imm16),
+   ARITH_BYTE_INST ("orw",  0x26, uimm16),
+   ARITH1_BYTE_INST ("orw",  0x26, imm16),
+ 
+   ARITH_BYTE_INST ("xorb", 0x28, uimm16),
+   ARITH1_BYTE_INST ("xorb", 0x28, imm16),
+   ARITH_BYTE_INST ("xorw", 0x2A, uimm16),
+   ARITH1_BYTE_INST ("xorw", 0x2A, imm16),
+ 
+   ARITH_BYTE_INST ("addub", 0x2C, imm16),
+   ARITH_BYTE_INST ("adduw", 0x2E, imm16),
+   ARITH_BYTE_INST ("addb",  0x30, imm16),
+   ARITH_BYTE_INST ("addw",  0x32, imm16),
+   ARITH_BYTE_INST ("addcb", 0x34, imm16),
+   ARITH_BYTE_INST ("addcw", 0x36, imm16),
+ 
+   ARITH_BYTE_INST ("subb",  0x38, imm16),
+   ARITH_BYTE_INST ("subw",  0x3A, imm16),
+   ARITH_BYTE_INST ("subcb", 0x3C, imm16),
+   ARITH_BYTE_INST ("subcw", 0x3E, imm16),
+ 
+   ARITH_BYTE_INST ("cmpb",  0x50, imm16),
+   ARITH_BYTE_INST ("cmpw",  0x52, imm16),
+ 
+   ARITH_BYTE_INST ("movb",  0x58, imm16),
+   ARITH_BYTE_INST ("movw",  0x5A, imm16),
+ 
+   ARITH_BYTE_INST ("mulb",  0x64, imm16),
+   ARITH_BYTE_INST ("mulw",  0x66, imm16),
+ 
+ #define  ARITH_BYTE_INST1(NAME, OPC)                       \
+   /* opc8 r r */                                           \
+   {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{regr,20}, {regr,16}}}
+ 
+   ARITH_BYTE_INST1 ("movxb",  0x5C),
+   ARITH_BYTE_INST1 ("movzb",  0x5D),
+   ARITH_BYTE_INST1 ("mulsb",  0x0B),
+ 
+ #define  ARITH_BYTE_INST2(NAME, OPC)                       \
+   /* opc8 r rp */                                          \
+   {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{regr,20}, {regp,16}}}
+ 
+   ARITH_BYTE_INST2 ("movxw",  0x5E),
+   ARITH_BYTE_INST2 ("movzw",  0x5F),
+   ARITH_BYTE_INST2 ("mulsw",  0x62),
+   ARITH_BYTE_INST2 ("muluw",  0x63),
+ 
+ /* Create an arithmetic instruction - INST[d]- with 3 types.  */
+ #define  ARITH_INST_D(NAME, OPC)                                     \
+   /* opc8 imm4 rp */                                                 \
+   {NAME, 1, OPC, 24, ARITH_INS, {{uimm4_1,20}, {regp,16}}},          \
+   /* opc8 imm16 rp */                                                \
+   {NAME, 2, (OPC<<4)+0xB, 20, ARITH_INS, {{imm16,0}, {regp,16}}},    \
+   /* opc8 rp rp */                                                   \
+   {NAME, 1, OPC+1, 24, ARITH_INS, {{regp,20}, {regp,16}}}
+ 
+ /* Create an arithmetic instruction - INST[d]-20 bit types.  */
+ #define  ARITH_INST20(NAME, OPC)                        \
+   /* opc8 uimm20 rp */                                  \
+   {NAME, 2, OPC, 24, ARITH_INS, {{uimm20,0},  {regp,20}}}
+ 
+ /* Create an arithmetic instruction - INST[d]-32 bit types.  */
+ #define  ARITH_INST32(NAME, OPC, OP1)                \
+   /* opc12 imm32 rp */                               \
+   {NAME, 3, OPC, 20, ARITH_INS, {{OP1,0},  {regp,16}}}
+ 
+ /* Create an arithmetic instruction - INST[d]-32bit types(reg pairs).*/
+ #define  ARITH_INST32RP(NAME, OPC)                   \
+   /* opc24 rp rp */                                  \
+   {NAME, 2, OPC, 12, ARITH_INS, {{regp,4},  {regp,0}}}
+ 
+   ARITH_INST_D   ("movd", 0x54),
+   ARITH_INST20   ("movd", 0x05),
+   ARITH_INST32   ("movd", 0x007, imm32),
+   ARITH_INST_D   ("addd", 0x60),
+   ARITH_INST20   ("addd", 0x04),
+   ARITH_INST32   ("addd", 0x002, imm32),
+   ARITH_INST32   ("subd", 0x003, imm32),
+   ARITH_INST32RP ("subd", 0x0014C),
+   ARITH_INST_D   ("cmpd", 0x56),
+   ARITH_INST32   ("cmpd", 0x009, imm32),
+   ARITH_INST32   ("andd", 0x004, uimm32),
+   ARITH_INST32RP ("andd", 0x0014B),
+   ARITH_INST32   ("ord",  0x005, uimm32),
+   ARITH_INST32RP ("ord",  0x00149),
+   ARITH_INST32   ("xord", 0x006, uimm32),
+   ARITH_INST32RP ("xord", 0x0014A),
+ 
+ /* Create a shift instruction.  */
+ #define  SHIFT_INST_A(NAME, OPC1, OPC2, SHIFT, OP1, OP2)    \
+   /* opc imm r */                                           \
+   {NAME, 1, OPC1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}},  \
+   /* opc imm r */                                           \
+   {NAME, 1, OPC1+1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}},\
+   /* opc r r */                                             \
+   {NAME, 1, OPC2, 24, SHIFT_INS, {{regr,20}, {OP2,16}}}
+ 
+   SHIFT_INST_A("ashub", 0x80, 0x41, 23, imm4, regr),
+   SHIFT_INST_A("ashud", 0x26, 0x48, 25, imm6, regp),
+   SHIFT_INST_A("ashuw", 0x42, 0x45, 24, imm5, regr),
+ 
+ #define  SHIFT_INST_L(NAME, OPC1, OPC2, SHIFT, OP1, OP2)    \
+   /* opc imm r */                                           \
+   {NAME, 1, OPC1, SHIFT, SHIFT_INS, {{OP1,20}, {OP2,16}}},  \
+   /* opc r r */                                             \
+   {NAME, 1, OPC2, 24, SHIFT_INS, {{regr,20}, {OP2,16}}}
+ 
+   SHIFT_INST_L("lshb", 0x13, 0x44, 23, imm4, regr),
+   SHIFT_INST_L("lshd", 0x25, 0x47, 25, imm6, regp),
+   SHIFT_INST_L("lshw", 0x49, 0x46, 24, imm5, regr),
+ 
+ /* Create a conditional branch instruction.  */
+ #define  BRANCH_INST(NAME, OPC)                                       \
+   /* opc4 c4 dispe9 */                                                \
+   {NAME,  1, OPC, 28, BRANCH_INS, {{cc,20}, {dispe9,16}}},            \
+   /* opc4 c4 disps17 */                                               \
+   {NAME,  2, ((OPC<<4)+0x8), 24, BRANCH_INS, {{cc,20}, {disps17,0}}}, \
+   /* opc4 c4 disps25 */                                               \
+   {NAME,  3, (OPC<<4), 16 , BRANCH_INS, {{cc,4}, {disps25,16}}}
+ 
+   BRANCH_INST ("b", 0x1),
+ 
+ /* Create a 'Branch if Equal to 0' instruction.  */
+ #define  BRANCH_NEQ_INST(NAME, OPC)                           \
+   /* opc8 disps5 r */                                         \
+   {NAME,  1, OPC, 24, BRANCH_NEQ_INS, {{regr,16}, {disps5,20}}}
+ 
+   BRANCH_NEQ_INST ("beq0b",  0x0C),
+   BRANCH_NEQ_INST ("bne0b",  0x0D),
+   BRANCH_NEQ_INST ("beq0w",  0x0E),
+   BRANCH_NEQ_INST ("bne0w",  0x0F),
+ 
+ 
+ /* Create an instruction using a single register operand.  */
+ #define  REG1_INST(NAME, OPC)                  \
+   /* opc8 c4 r */                              \
+   {NAME,  1, OPC, 20, NO_TYPE_INS, {{regr,16}}}
+ 
+ #define  REGP1_INST(NAME, OPC)                \
+   /* opc8 c4 r */                             \
+   {NAME,  1, OPC, 20, NO_TYPE_INS, {{regp,16}}}
+ 
+ /* Same as REG1_INST, with additional FLAGS.  */
+ #define  REG1_FLAG_INST(NAME, OPC, FLAGS)             \
+   /* opc8 c4 r */                                     \
+   {NAME,  1, OPC, 20, NO_TYPE_INS | FLAGS, {{regp,16}}}
+ 
+   /* JCond instructions */
+   REGP1_INST ("jeq",  0x0A0),
+   REGP1_INST ("jne",  0x0A1),
+   REGP1_INST ("jcs",  0x0A2),
+   REGP1_INST ("jcc",  0x0A3),
+   REGP1_INST ("jhi",  0x0A4),
+   REGP1_INST ("jls",  0x0A5),
+   REGP1_INST ("jgt",  0x0A6),
+   REGP1_INST ("jle",  0x0A7),
+   REGP1_INST ("jfs",  0x0A8),
+   REGP1_INST ("jfc",  0x0A9),
+   REGP1_INST ("jlo",  0x0AA),
+   REGP1_INST ("jhs",  0x0AB),
+   REGP1_INST ("jlt",  0x0AC),
+   REGP1_INST ("jge",  0x0AD),
+   REGP1_INST ("jump", 0x0AE),
+   REGP1_INST ("jusr", 0x0AF),
+ 
+   /* SCond instructions */
+   REG1_INST ("seq",  0x080),
+   REG1_INST ("sne",  0x081),
+   REG1_INST ("scs",  0x082),
+   REG1_INST ("scc",  0x083),
+   REG1_INST ("shi",  0x084),
+   REG1_INST ("sls",  0x085),
+   REG1_INST ("sgt",  0x086),
+   REG1_INST ("sle",  0x087),
+   REG1_INST ("sfs",  0x088),
+   REG1_INST ("sfc",  0x089),
+   REG1_INST ("slo",  0x08A),
+   REG1_INST ("shs",  0x08B),
+   REG1_INST ("slt",  0x08C),
+   REG1_INST ("sge",  0x08D),
+ 
+ 
+ /* Create an instruction using two register operands.  */
+ #define  REG3_INST(NAME, OPC)                                    \
+   /* opc24 r r rp  */                                            \
+   {NAME,  2, OPC,  12, NO_TYPE_INS, {{regr,4}, {regr,0}, {regp,8}}}
+ 
+   /* MULTIPLY INSTRUCTIONS */
+   REG3_INST ("macqw",  0x0014d),
+   REG3_INST ("macuw",  0x0014e),
+   REG3_INST ("macsw",  0x0014f),
+ 
+ /* Create a branch instruction.  */
+ #define  BR_INST(NAME, OPC)                               \
+   /* opc12 ra disps25 */                                  \
+   {NAME,  2, OPC,  24, NO_TYPE_INS, {{rra,0}, {disps25,0}}}
+ 
+ #define  BR_INST_RP(NAME, OPC)                              \
+   /* opc8 rp disps25 */                                     \
+   {NAME,  3, OPC,  12, NO_TYPE_INS, {{regp,4}, {disps25,16}}}
+ 
+   BR_INST    ("bal", 0xC0),
+   BR_INST_RP ("bal", 0x00102),
+ 
+ #define  REGPP2_INST(NAME, OPC)                         \
+   /* opc16 rp rp  */                                    \
+   {NAME,  2, OPC,  12, NO_TYPE_INS, {{regp,0}, {regp,4}}}
+  /* Jump and link instructions.  */
+   REGP1_INST  ("jal",0x00D),
+   REGPP2_INST ("jal",0x00148),
+ 
+ 
+ /* Instructions including a register list (opcode is represented as a mask). */
+ #define  REGLIST_INST(NAME, OPC, TYPE)                               \
+   /* opc7 r count3 RA */                                             \
+   {NAME,1, (OPC<<1)+1, 23, TYPE, {{uimm3_1,20},{regr,16},{regr,0}}}, \
+   /* opc8 r count3 */                                                \
+   {NAME,  1, OPC, 24, TYPE, {{uimm3_1,20}, {regr,16}}},              \
+   /* opc12 RA  */                                                    \
+   {NAME,  1, (OPC<<8)+0x1E, 16, TYPE, {{regr,0}}}
+ 
+    REGLIST_INST   ("push",   0x01, (NO_TYPE_INS | REG_LIST)),
+    REGLIST_INST   ("pop",    0x02, (NO_TYPE_INS | REG_LIST)),
+    REGLIST_INST   ("popret", 0x03, (NO_TYPE_INS | REG_LIST)),
+ 
+   {"loadm",  1, 0x14, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}},
+   {"loadmp", 1, 0x15, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}},
+   {"storm",  1, 0x16, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}},
+   {"stormp", 1, 0x17, 19, NO_TYPE_INS | REG_LIST, {{uimm3_1,16}}},
+ 
+  /* Processor Regsiter Manipulation instructions  */
+   /* opc16 reg, preg */
+   {"lpr",  2, 0x00140, 12, NO_TYPE_INS, {{regr,0}, {pregr,4}}},
+   /* opc16 regp, pregp */
+   {"lprd", 2, 0x00141, 12, NO_TYPE_INS, {{regp,0}, {pregrp,4}}},
+   /* opc16 preg, reg */
+   {"spr",  2, 0x00142, 12, NO_TYPE_INS, {{pregr,4}, {regr,0}}},
+   /* opc16 pregp, regp */
+   {"sprd", 2, 0x00143, 12, NO_TYPE_INS, {{pregrp,4}, {regp,0}}},
+ 
+  /* Miscellaneous.  */
+   /* opc12 ui4 */
+   {"excp", 1, 0x00C, 20, NO_TYPE_INS, {{uimm4,16}}},
+ 
+ /* Create a bit-b instruction.  */
+ #define  CSTBIT_INST_B(NAME, OP, OPC1, OPC2, OPC3, OPC4)               \
+   /* opcNN iN abs20 */                                                 \
+   {NAME,  2, (OPC3+1), 23, CSTBIT_INS, {{OP,20},{abs20,0}}},           \
+   /* opcNN iN abs24 */                                                 \
+   {NAME,  3, (OPC2+3), 12, CSTBIT_INS, {{OP,4},{abs24,16}}},           \
+   /* opcNN iN (Rindex)abs20 */                                         \
+   {NAME,  2, OPC1, 24, CSTBIT_INS, {{OP,20}, {rindex7_abs20,0}}},      \
+   /* opcNN iN (prp) disps14(RPbase) */                                 \
+   {NAME,  2, OPC4, 22, CSTBIT_INS, {{OP,4},{rpindex_disps14,0}}},      \
+   /* opcNN iN disps20(Rbase) */                                        \
+   {NAME,  3, OPC2, 12, CSTBIT_INS, {{OP,4}, {rbase_disps20,16}}},      \
+   /* opcNN iN (rp) disps0(RPbase) */                                   \
+   {NAME,  1, OPC3-2, 23, CSTBIT_INS, {{OP,20}, {rpbase_disps0,16}}},   \
+   /* opcNN iN (rp) disps16(RPBase) */                                  \
+   {NAME,  2, OPC3,  23, CSTBIT_INS, {{OP,20}, {rpbase_disps16,0}}},    \
+   /* opcNN iN (rp) disps20(RPBase) */                                  \
+   {NAME,  3, (OPC2+1), 12, CSTBIT_INS, {{OP,4}, {rpbase_disps20,16}}}, \
+   /* opcNN iN rrp (Rindex)disps20(RPbase) */                           \
+   {NAME,  3, (OPC2+2), 12, CSTBIT_INS, {{OP,4}, {rpindex_disps20,16}}}
+ 
+   CSTBIT_INST_B ("cbitb", uimm3, 0x68, 0x00104, 0xD6, 0x1AA),
+   CSTBIT_INST_B ("sbitb", uimm3, 0x70, 0x00108, 0xE6, 0x1CA),
+   CSTBIT_INST_B ("tbitb", uimm3, 0x78, 0x0010C, 0xF6, 0x1EA),
+ 
+ /* Create a bit-w instruction.  */
+ #define  CSTBIT_INST_W(NAME, OP, OPC1, OPC2, OPC3, OPC4)               \
+   /* opcNN iN abs20 */                                                 \
+   {NAME,  2, OPC1+6, 24, CSTBIT_INS, {{OP,20},{abs20,0}}},             \
+   /* opcNN iN abs24 */                                                 \
+   {NAME,  3, OPC2+3, 12, CSTBIT_INS, {{OP,4},{abs24,16}}},             \
+   /* opcNN iN (Rindex)abs20 */                                         \
+   {NAME,  2, OPC3, 25, CSTBIT_INS, {{OP,20}, {rindex8_abs20,0}}},      \
+   /* opcNN iN (prp) disps14(RPbase) */                                 \
+   {NAME,  2, OPC4, 22, CSTBIT_INS, {{OP,4},{rpindex_disps14,0}}},      \
+   /* opcNN iN disps20(Rbase) */                                        \
+   {NAME,  3, OPC2, 12, CSTBIT_INS, {{OP,4}, {rbase_disps20,16}}},      \
+   /* opcNN iN (rp) disps0(RPbase) */                                   \
+   {NAME,  1, OPC1+5, 24, CSTBIT_INS, {{OP,20}, {rpbase_disps0,16}}},   \
+   /* opcNN iN (rp) disps16(RPBase) */                                  \
+   {NAME,  2, OPC1,  24, CSTBIT_INS, {{OP,20}, {rpbase_disps16,0}}},    \
+   /* opcNN iN (rp) disps20(RPBase) */                                  \
+   {NAME,  3, OPC2+1, 12, CSTBIT_INS, {{OP,4}, {rpbase_disps20,16}}},   \
+   /* opcNN iN rrp (Rindex)disps20(RPbase) */                           \
+   {NAME,  3, OPC2+2, 12, CSTBIT_INS, {{OP,4}, {rpindex_disps20,16}}}
+ 
+   CSTBIT_INST_W ("cbitw", uimm4, 0x69, 0x00114, 0x36, 0x1AB),
+   CSTBIT_INST_W ("sbitw", uimm4, 0x71, 0x00118, 0x3A, 0x1CB),
+   CSTBIT_INST_W ("tbitw", uimm4, 0x79, 0x0011C, 0x3E, 0x1EB),
+ 
+   /* tbit cnt */
+   {"tbit", 1, 0x06, 24, CSTBIT_INS, {{uimm4,20}, {regr,16}}},
+   /* tbit reg reg */
+   {"tbit", 1, 0x07, 24, CSTBIT_INS, {{regr,20},  {regr,16}}},
+ 
+ 
+ /* Load instructions (from memory to register).  */
+ #define  LD_REG_INST(NAME, OPC1, OPC2, OPC3, OPC4, OPC5, OP_S, OP_D)     \
+  /* opc8 reg abs20 */                                                    \
+  {NAME, 2, OPC3,  24, LD_STOR_INS, {{abs20,0}, {OP_D,20}}},              \
+  /* opc20 reg abs24 */                                                   \
+  {NAME, 3, OPC1+3, 12, LD_STOR_INS, {{abs24,16}, {OP_D,4}}},             \
+  /* opc7 reg rindex8_abs20 */                                            \
+  {NAME, 2, OPC5, 25, LD_STOR_INS, {{rindex8_abs20,0}, {OP_D,20}}},       \
+   /* opc4 reg  disps4(RPbase) */                                         \
+  {NAME, 1, (OPC2>>4), 28, LD_STOR_INS, {{OP_S,24}, {OP_D,20}}},          \
+  /* opcNN reg  disps0(RPbase) */                                         \
+  {NAME, 1, OPC2, 24, LD_STOR_INS, {{rpindex_disps0,0}, {OP_D,20}}},      \
+  /* opc reg  disps14(RPbase) */                                          \
+  {NAME, 2, OPC4, 22, LD_STOR_INS, {{rpindex_disps14,0}, {OP_D,20}}},     \
+  /* opc reg -disps20(Rbase) */                                           \
+  {NAME, 3, OPC1+0x60, 12, LD_STOR_INS, {{rbase_dispe20,16}, {OP_D,4}}},  \
+  /* opc reg disps20(Rbase) */                                            \
+  {NAME, 3, OPC1, 12, LD_STOR_INS, {{rbase_disps20,16}, {OP_D,4}}},       \
+   /* opc reg (rp) disps16(RPbase) */                                     \
+  {NAME, 2, OPC2+1, 24, LD_STOR_INS, {{rpbase_disps16,0}, {OP_D,20}}},    \
+   /* opc16 reg (rp) disps20(RPbase) */                                   \
+  {NAME, 3, OPC1+1, 12, LD_STOR_INS, {{rpbase_disps20,16}, {OP_D,4}}},    \
+   /* op reg (rp) -disps20(RPbase) */                                     \
+  {NAME, 3, OPC1+0x61, 12, LD_STOR_INS, {{rpbase_dispe20,16}, {OP_D,4}}}, \
+  /* opc reg rrp (Rindex)disps20(RPbase) */                               \
+  {NAME, 3, (OPC1+2), 12, LD_STOR_INS, {{rpindex_disps20,16}, {OP_D,4}}}
+ 
+   LD_REG_INST ("loadb", 0x00124, 0xBE, 0x88, 0x219, 0x45, rpbase_disps4, regr),
+   LD_REG_INST ("loadd", 0x00128, 0xAE, 0x87, 0x21A, 0x46, rpbase_dispe4, regp),
+   LD_REG_INST ("loadw", 0x0012C, 0x9E, 0x89, 0x21B, 0x47, rpbase_dispe4, regr),
+ 
+ /* Store instructions (from reg to memory).  */
+ #define  ST_REG_INST(NAME, OPC1, OPC2, OPC3, OPC4, OPC5, OP_D, OP_S)     \
+  /* opc8 reg abs20 */                                                    \
+  {NAME, 2, OPC3,  24, LD_STOR_INS, {{OP_S,20}, {abs20,0}}},              \
+  /* opc20 reg abs24 */                                                   \
+  {NAME, 3, OPC1+3, 12, LD_STOR_INS, {{OP_S,4}, {abs24,16}}},             \
+  /* opc7 reg rindex8_abs20 */                                            \
+  {NAME, 2, OPC5, 25, LD_STOR_INS, {{OP_S,20}, {rindex8_abs20,0}}},       \
+   /* opc4 reg disps4(RPbase) */                                          \
+  {NAME, 1, (OPC2>>4), 28, LD_STOR_INS, {{OP_S,20}, {OP_D,24}}},          \
+  /* opcNN reg  disps0(RPbase) */                                         \
+  {NAME, 1, OPC2, 24, LD_STOR_INS, {{OP_S,20}, {rpindex_disps0,0}}},      \
+  /* opc reg  disps14(RPbase) */                                          \
+  {NAME, 2, OPC4, 22, LD_STOR_INS, {{OP_S,20}, {rpindex_disps14,0}}},     \
+  /* opc reg -disps20(Rbase) */                                           \
+  {NAME, 3, OPC1+0x60, 12, LD_STOR_INS, {{OP_S,4}, {rbase_dispe20,16}}},  \
+  /* opc reg disps20(Rbase) */                                            \
+  {NAME, 3, OPC1, 12, LD_STOR_INS, {{OP_S,4}, {rbase_disps20,16}}},       \
+   /* opc reg  disps16(RPbase) */                                         \
+  {NAME, 2, OPC2+1, 24, LD_STOR_INS, {{OP_S,20}, {rpbase_disps16,0}}},    \
+   /* opc16 reg disps20(RPbase) */                                        \
+  {NAME, 3, OPC1+1, 12, LD_STOR_INS, {{OP_S,4}, {rpbase_disps20,16}}},    \
+   /* op reg (rp) -disps20(RPbase) */                                     \
+  {NAME, 3, OPC1+0x61, 12, LD_STOR_INS, {{OP_S,4}, {rpbase_dispe20,16}}}, \
+  /* opc reg rrp (Rindex)disps20(RPbase) */                               \
+  {NAME, 3, OPC1+2, 12, LD_STOR_INS, {{OP_S,4}, {rpindex_disps20,16}}}
+ 
+ 
+ /* Store instructions (from imm to memory).  */
+ #define  ST_IMM_INST(NAME, OPC1, OPC2, OPC3, OPC4)                       \
+   /* opcNN iN abs20 */                                                   \
+   {NAME,  2, OPC1, 24, LD_STOR_INS, {{uimm4,20},{abs20,0}}},             \
+   /* opcNN iN abs24 */                                                   \
+   {NAME,  3, OPC2+3, 12, LD_STOR_INS, {{uimm4,4},{abs24,16}}},           \
+   /* opcNN iN (Rindex)abs20 */                                           \
+   {NAME,  2, OPC3, 25, LD_STOR_INS, {{uimm4,20}, {rindex8_abs20,0}}},    \
+   /* opcNN iN (prp) disps14(RPbase) */                                   \
+   {NAME,  2, OPC4, 22, LD_STOR_INS, {{uimm4,4},{rpindex_disps14,0}}},    \
+   /* opcNN iN (rp) disps0(RPbase) */                                     \
+   {NAME,  1, OPC1+1, 24, LD_STOR_INS, {{uimm4,20}, {rpbase_disps0,16}}}, \
+   /* opcNN iN disps20(Rbase) */                                          \
+   {NAME,  3, OPC2, 12, LD_STOR_INS, {{uimm4,4}, {rbase_disps20,16}}},    \
+   /* opcNN iN (rp) disps16(RPBase) */                                    \
+   {NAME,  2, OPC1+2, 24, LD_STOR_INS, {{uimm4,20}, {rpbase_disps16,0}}}, \
+   /* opcNN iN (rp) disps20(RPBase) */                                    \
+   {NAME,  3, OPC2+1, 12, LD_STOR_INS, {{uimm4,4}, {rpbase_disps20,16}}}, \
+   /* opcNN iN rrp (Rindex)disps20(RPbase) */                             \
+   {NAME,  3, OPC2+2, 12, LD_STOR_INS, {{uimm4,4}, {rpindex_disps20,16}}}
+ 
+   ST_REG_INST ("storb", 0x00134, 0xFE, 0xC8, 0x319, 0x65, rpbase_disps4, regr),
+   ST_IMM_INST ("storb", 0x81, 0x00120, 0x42, 0x218),
+   ST_REG_INST ("stord", 0x00138, 0xEE, 0xC7, 0x31A, 0x66, rpbase_dispe4, regp),
+   ST_REG_INST ("storw", 0x0013C, 0xDE, 0xC9, 0x31B, 0x67, rpbase_dispe4, regr),
+   ST_IMM_INST ("storw", 0xC1, 0x00130, 0x62, 0x318),
+ 
+ /* Create instruction with no operands.  */
+ #define  NO_OP_INST(NAME, OPC)   \
+   /* opc16 */                    \
+   {NAME,  1, OPC, 16, 0, {{0, 0}}}
+ 
+   NO_OP_INST ("cinv[i]",     0x000A),
+   NO_OP_INST ("cinv[i,u]",   0x000B),
+   NO_OP_INST ("cinv[d]",     0x000C),
+   NO_OP_INST ("cinv[d,u]",   0x000D),
+   NO_OP_INST ("cinv[d,i]",   0x000E),
+   NO_OP_INST ("cinv[d,i,u]", 0x000F),
+   NO_OP_INST ("nop",         0x2C00),
+   NO_OP_INST ("retx",        0x0003),
+   NO_OP_INST ("di",          0x0004),
+   NO_OP_INST ("ei",          0x0005),
+   NO_OP_INST ("wait",        0x0006),
+   NO_OP_INST ("eiwait",      0x0007),
+ 
+   {NULL,      0, 0, 0,    0, {{0, 0}}}
+ };
+ 
+ const unsigned int cr16_num_opcodes = ARRAY_SIZE (cr16_instruction);
+ 
+ /* Macro to build a reg_entry, which have an opcode image :
+    For example :
+       REG(u4, 0x84, CR16_U_REGTYPE)
+    is interpreted as :
+       {"u4",  u4, 0x84, CR16_U_REGTYPE}  */
+ #define REG(NAME, N, TYPE)    {STRINGX(NAME), {NAME}, N, TYPE}
+ 
+ #define REGP(NAME, BNAME, N, TYPE)    {STRINGX(NAME), {BNAME}, N, TYPE}
+ 
+ const reg_entry cr16_regtab[] =
+ { /* Build a general purpose register r<N>.  */
+ #define REG_R(N)    REG(CONCAT2(r,N), N, CR16_R_REGTYPE)
+ 
+   REG_R(0), REG_R(1), REG_R(2), REG_R(3),
+   REG_R(4), REG_R(5), REG_R(6), REG_R(7),
+   REG_R(8), REG_R(9), REG_R(10), REG_R(11),
+   REG_R(12), REG_R(13), REG_R(14), REG_R(15),
+   REG(r12_L, 12,  CR16_R_REGTYPE),
+   REG(r13_L, 13,  CR16_R_REGTYPE),
+   REG(ra,    0xe, CR16_R_REGTYPE),
+   REG(sp,    0xf, CR16_R_REGTYPE),
+   REG(sp_L,  0xf, CR16_R_REGTYPE),
+   REG(RA,    0xe, CR16_R_REGTYPE),
+ };
+ 
+ const reg_entry cr16_regptab[] =
+ { /* Build a general purpose register r<N>.  */
+ 
+ #define REG_RP(M,N) REGP((CONCAT2(r,M),CONCAT2(r,N)), CONCAT2(r,N), N, CR16_RP_REGTYPE)
+ 
+   REG_RP(1,0), REG_RP(2,1), REG_RP(3,2), REG_RP(4,3),
+   REG_RP(5,4), REG_RP(6,5), REG_RP(7,6), REG_RP(8,7),
+   REG_RP(9,8), REG_RP(10,9), REG_RP(11,10), REG_RP(12,11),
+   REG((r12), 0xc, CR16_RP_REGTYPE),
+   REG((r13), 0xd, CR16_RP_REGTYPE),
+   //REG((r14), 0xe, CR16_RP_REGTYPE),
+   REG((ra), 0xe, CR16_RP_REGTYPE),
+   REG((sp), 0xf, CR16_RP_REGTYPE),
+ };
+ 
+ 
+ const unsigned int cr16_num_regs = ARRAY_SIZE (cr16_regtab) ;
+ const unsigned int cr16_num_regps = ARRAY_SIZE (cr16_regptab) ;
+ 
+ const reg_entry cr16_pregtab[] =
+ {
+ /* Build a processor register.  */
+   REG(dbs,   0x0, CR16_P_REGTYPE),
+   REG(dsr,   0x1, CR16_P_REGTYPE),
+   REG(dcrl,  0x2, CR16_P_REGTYPE),
+   REG(dcrh,  0x3, CR16_P_REGTYPE),
+   REG(car0l, 0x4, CR16_P_REGTYPE),
+   REG(car0h, 0x5, CR16_P_REGTYPE),
+   REG(car1l, 0x6, CR16_P_REGTYPE),
+   REG(car1h, 0x7, CR16_P_REGTYPE),
+   REG(cfg,   0x8, CR16_P_REGTYPE),
+   REG(psr,   0x9, CR16_P_REGTYPE),
+   REG(intbasel, 0xa, CR16_P_REGTYPE),
+   REG(intbaseh, 0xb, CR16_P_REGTYPE),
+   REG(ispl,  0xc, CR16_P_REGTYPE),
+   REG(isph,  0xd, CR16_P_REGTYPE),
+   REG(uspl,  0xe, CR16_P_REGTYPE),
+   REG(usph,  0xf, CR16_P_REGTYPE),
+ };
+ 
+ const reg_entry cr16_pregptab[] =
+ {
+   REG(dbs,   0, CR16_P_REGTYPE),
+   REG(dsr,   1, CR16_P_REGTYPE),
+   REG(dcr,   2, CR16_P_REGTYPE),
+   REG(car0,  4, CR16_P_REGTYPE),
+   REG(car1,  6, CR16_P_REGTYPE),
+   REG(cfg,   8, CR16_P_REGTYPE),
+   REG(psr,   9, CR16_P_REGTYPE),
+   REG(intbase, 10, CR16_P_REGTYPE),
+   REG(isp,   12, CR16_P_REGTYPE),
+   REG(usp,   14, CR16_P_REGTYPE),
+ };
+ 
+ const unsigned int cr16_num_pregs =  ARRAY_SIZE (cr16_pregtab);
+ const unsigned int cr16_num_pregps =  ARRAY_SIZE (cr16_pregptab);
+ 
+ const char *cr16_b_cond_tab[]=
+ {
+   "eq","ne","cs","cc","hi","ls","gt","le","fs","fc",
+   "lo","hs","lt","ge","r", "???"
+ };
+ 
+ const unsigned int cr16_num_cc =  ARRAY_SIZE (cr16_b_cond_tab);
+ 
+ /* CR16 operands table.  */
+ const operand_entry cr16_optab[] =
+ {
+   /* Index 0 is dummy, so we can count the instruction's operands.  */
+   {0,    nullargs,     0},                        /* dummy */
+   {3,    arg_ic,       OP_SIGNED},                /* imm3 */
+   {4,    arg_ic,       OP_SIGNED},                /* imm4 */
+   {5,    arg_ic,       OP_SIGNED},                /* imm5 */
+   {6,    arg_ic,       OP_SIGNED},                /* imm6 */
+   {16,   arg_ic,       OP_SIGNED},                /* imm16 */
+   {20,   arg_ic,       OP_SIGNED},                /* imm20 */
+   {32,   arg_ic,       OP_SIGNED},                /* imm32 */
+   {3,    arg_ic,       OP_UNSIGNED},              /* uimm3 */
+   {3,    arg_ic,       OP_UNSIGNED|OP_DEC},       /* uimm3_1 */
+   {4,    arg_ic,       OP_UNSIGNED},              /* uimm4 */
+   {4,    arg_ic,       OP_UNSIGNED|OP_ESC},       /* uimm4_1 */
+   {5,    arg_ic,       OP_UNSIGNED},              /* uimm5 */
+   {16,   arg_ic,       OP_UNSIGNED},              /* uimm16 */
+   {20,   arg_ic,       OP_UNSIGNED},              /* uimm20 */
+   {32,   arg_ic,       OP_UNSIGNED},              /* uimm32 */
+   {5,    arg_c,        OP_EVEN|OP_SHIFT_DEC|OP_SIGNED},      /* disps5 */
+   {16,   arg_c,        OP_EVEN|OP_UNSIGNED},      /* disps17 */
+   {24,   arg_c,        OP_EVEN|OP_UNSIGNED},      /* disps25 */
+   {8,    arg_c,        OP_EVEN|OP_UNSIGNED},      /* dispe9 */
+   {20,   arg_c,        OP_UNSIGNED|OP_ABS20},     /* abs20 */
+   {24,   arg_c,        OP_UNSIGNED|OP_ABS24},     /* abs24 */
+   {4,    arg_rp,       0},                        /* rra */
+   {4,    arg_rbase,    0},                        /* rbase */
+   {20,   arg_cr,       OP_UNSIGNED},              /* rbase_disps20 */
+   {21,   arg_cr,       OP_NEG},                   /* rbase_dispe20 */
+   {0,    arg_crp,      0},                        /* rpbase_disps0 */
+   {4,    arg_crp,      OP_EVEN|OP_SHIFT|OP_UNSIGNED|OP_ESC1},/* rpbase_dispe4 */
+   {4,    arg_crp,      OP_UNSIGNED|OP_ESC1},      /* rpbase_disps4 */
+   {16,   arg_crp,      OP_UNSIGNED},              /* rpbase_disps16 */
+   {20,   arg_crp,      OP_UNSIGNED},              /* rpbase_disps20 */
+   {21,   arg_crp,      OP_NEG},                   /* rpbase_dispe20 */
+   {20,   arg_idxr,     OP_UNSIGNED},              /* rindex7_abs20  */
+   {20,   arg_idxr,     OP_UNSIGNED},              /* rindex8_abs20  */
+   {0,    arg_idxrp,    OP_UNSIGNED},              /* rpindex_disps0 */
+   {14,   arg_idxrp,    OP_UNSIGNED},              /* rpindex_disps14 */
+   {20,   arg_idxrp,    OP_UNSIGNED},              /* rpindex_disps20 */
+   {4,    arg_r,        0},                        /* regr */
+   {4,    arg_rp,       0},                        /* reg pair */
+   {4,    arg_pr,       0},                        /* proc reg */
+   {4,    arg_prp,      0},                        /* 32 bit proc reg  */
+   {4,    arg_cc,       OP_UNSIGNED}               /* cc - code */
+ };
+ 
+ 
+ /* CR16 traps/interrupts.  */
+ const trap_entry cr16_traps[] =
+ {
+   {"svc", 5}, {"dvz",  6}, {"flg", 7}, {"bpt", 8}, {"trc", 9},
+   {"und", 10}, {"iad", 12}, {"dbg",14}, {"ise",15}
+ };
+ 
+ const unsigned int cr16_num_traps = ARRAY_SIZE (cr16_traps);
+ 
+ /* CR16 instructions that don't have arguments.  */
+ const char* no_op_insn[] = 
+ {
+   "cinv[i]", "cinv[i,u]", "cinv[d]", "cinv[d,u]", "cinv[d,i]", "cinv[d,i,u]",
+   "di", "ei", "eiwait", "nop", "retx", "wait", NULL
+ };
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/disassemble.c binutils-2.17.50-cr16/opcodes/disassemble.c
*** binutils-2.17.50/opcodes/disassemble.c	2007-02-06 01:34:22.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/disassemble.c	2007-06-26 15:07:16.000000000 +0530
***************
*** 25,30 ****
--- 25,31 ----
  #define ARCH_arm
  #define ARCH_avr
  #define ARCH_bfin
+ #define ARCH_cr16
  #define ARCH_cris
  #define ARCH_crx
  #define ARCH_d10v
*************** disassembler (abfd)
*** 129,134 ****
--- 130,140 ----
        disassemble = print_insn_bfin;
        break;
  #endif
+ #ifdef ARCH_cr16
+     case bfd_arch_cr16:
+       disassemble = print_insn_cr16;
+       break;
+ #endif
  #ifdef ARCH_cris
      case bfd_arch_cris:
        disassemble = cris_get_disassembler (abfd);
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/Makefile.am binutils-2.17.50-cr16/opcodes/Makefile.am
*** binutils-2.17.50/opcodes/Makefile.am	2007-04-26 20:16:59.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/Makefile.am	2007-06-26 15:07:16.000000000 +0530
*************** CFILES = \
*** 66,71 ****
--- 66,73 ----
  	cgen-bitset.c \
  	cgen-dis.c \
  	cgen-opc.c \
+ 	cr16-dis.c \
+ 	cr16-opc.c \
  	cris-dis.c \
  	cris-opc.c \
  	crx-dis.c \
*************** ALL_MACHINES = \
*** 217,222 ****
--- 219,226 ----
  	cgen-bitset.lo \
  	cgen-dis.lo \
  	cgen-opc.lo \
+ 	cr16-dis.lo \
+ 	cr16-opc.lo \
  	cris-dis.lo \
  	cris-opc.lo \
  	crx-dis.lo \
*************** cgen-opc.lo: cgen-opc.c sysdep.h config.
*** 675,680 ****
--- 679,689 ----
    $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h \
    $(BFD_H) $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/symcat.h \
    $(INCDIR)/opcode/cgen.h $(INCDIR)/symcat.h $(INCDIR)/opcode/cgen-bitset.h
+ cr16-dis.lo: cr16-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+   $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h sysdep.h config.h \
+   $(INCDIR)/opcode/cr16.h
+ cr16-opc.lo: cr16-opc.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
+   $(INCDIR)/symcat.h $(INCDIR)/opcode/cr16.h
  cris-dis.lo: cris-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
    $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h sysdep.h config.h \
    $(INCDIR)/ansidecl.h $(INCDIR)/opcode/cris.h $(INCDIR)/libiberty.h \
diff -Napr --exclude=testsuite binutils-2.17.50/opcodes/Makefile.in binutils-2.17.50-cr16/opcodes/Makefile.in
*** binutils-2.17.50/opcodes/Makefile.in	2007-04-26 20:17:00.000000000 +0530
--- binutils-2.17.50-cr16/opcodes/Makefile.in	2007-06-26 15:07:16.000000000 +0530
*************** CFILES = \
*** 281,286 ****
--- 281,288 ----
  	cgen-bitset.c \
  	cgen-dis.c \
  	cgen-opc.c \
+ 	cr16-dis.c \
+ 	cr16-opc.c \
  	cris-dis.c \
  	cris-opc.c \
  	crx-dis.c \
*************** ALL_MACHINES = \
*** 432,437 ****
--- 434,441 ----
  	cgen-bitset.lo \
  	cgen-dis.lo \
  	cgen-opc.lo \
+ 	cr16-dis.lo \
+ 	cr16-opc.lo \
  	cris-dis.lo \
  	cris-opc.lo \
  	crx-dis.lo \
*************** cgen-opc.lo: cgen-opc.c sysdep.h config.
*** 1213,1218 ****
--- 1217,1227 ----
    $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h \
    $(BFD_H) $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/symcat.h \
    $(INCDIR)/opcode/cgen.h $(INCDIR)/symcat.h $(INCDIR)/opcode/cgen-bitset.h
+ cr16-dis.lo: cr16-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+   $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h sysdep.h config.h \
+   $(INCDIR)/opcode/cr16.h
+ cr16-opc.lo: cr16-opc.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
+   $(INCDIR)/symcat.h $(INCDIR)/opcode/cr16.h
  cris-dis.lo: cris-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
    $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h sysdep.h config.h \
    $(INCDIR)/ansidecl.h $(INCDIR)/opcode/cris.h $(INCDIR)/libiberty.h \

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