public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* MCS51 patch - part 1 of 2 - new files (for binutils 2.11.2)
@ 2001-12-30 14:38 Radek Benedikt
  2002-01-02  9:41 ` Nick Clifton
  0 siblings, 1 reply; 2+ messages in thread
From: Radek Benedikt @ 2001-12-30 14:38 UTC (permalink / raw)
  To: binutils

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

Patch for Intel/Atmel/... MCS-51 cpu family (8051, 8052, 8031, 8032, ...)

[-- Attachment #2: i51.patch.112n --]
[-- Type: application/octet-stream, Size: 149360 bytes --]

diff -crN binutils.null/bfd/cpu-i51.c binutils-2.11.2.i51.new/bfd/cpu-i51.c
*** binutils.null/bfd/cpu-i51.c	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/bfd/cpu-i51.c	Wed Dec 26 16:20:51 2001
***************
*** 0 ****
--- 1,39 ----
+ /* BFD library support routines for the MCS-51 architecture.
+    Copyright (C) 2001 Free Software Foundation, Inc.
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #include "bfd.h"
+ #include "sysdep.h"
+ #include "libbfd.h"
+ 
+ const bfd_arch_info_type bfd_i51_arch =
+   {
+     8,	/* 8 bits in a word */
+     8,	/* 8 bits in an address */
+     8,	/* 8 bits in a byte */
+     bfd_arch_i51,
+     0,	/* only 1 machine */
+     "i51",
+     "i51",
+     0,    /* section align power */
+     true, /* the one and only */
+     bfd_default_compatible,
+     bfd_default_scan,
+     NULL,
+   };
diff -crN binutils.null/bfd/elf32-i51.c binutils-2.11.2.i51.new/bfd/elf32-i51.c
*** binutils.null/bfd/elf32-i51.c	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/bfd/elf32-i51.c	Sun Dec 30 10:47:56 2001
***************
*** 0 ****
--- 1,1030 ----
+ /* MCS-51 specific support for 32-bit ELF
+    Copyright (C) 2001 Free Software Foundation, Inc.
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #include "bfd.h"
+ #include "sysdep.h"
+ #include "libbfd.h"
+ #include "elf-bfd.h"
+ #include "elf/i51.h"
+ 
+ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
+   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+ static void i51_info_to_howto_rela
+   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+ static asection *elf32_i51_gc_mark_hook
+   PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
+ static boolean elf32_i51_gc_sweep_hook
+   PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ 	   const Elf_Internal_Rela *));
+ static boolean elf32_i51_check_relocs
+   PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ 	   const Elf_Internal_Rela *));
+ static bfd_reloc_status_type i51_final_link_relocate
+   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
+ 	   Elf_Internal_Rela *, bfd_vma));
+ static boolean elf32_i51_relocate_section
+   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ 	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+ static void bfd_elf_i51_final_write_processing 
+   PARAMS ((bfd *, boolean));
+ static boolean elf32_i51_object_p
+   PARAMS ((bfd *));
+ void elf32_i51_symbol_processing
+   PARAMS ((bfd *, asymbol *));
+ boolean elf32_i51_section_from_bfd_section
+   PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *));
+ static boolean elf32_i51_add_symbol_hook
+   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ 	   const char **, flagword *, asection **, bfd_vma *));
+ 
+ /* Use RELA instead of REL */
+ #undef USE_REL
+ 
+ static reloc_howto_type elf_i51_howto_table[] =
+ {
+   HOWTO (R_I51_NONE,		/* type */
+ 	 0,			/* rightshift */
+ 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 32,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_bitfield, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_NONE",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0,			/* src_mask */
+ 	 0,			/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 1 bit indirect register relocation. */
+   HOWTO (R_I51_R1,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_bitfield, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_R1",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0,			/* src_mask */
+ 	 0,			/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 3 bit register relocation. */
+   HOWTO (R_I51_R3,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_bitfield, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_R3",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0,			/* src_mask */
+ 	 0,			/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 7 bit PC relative relocation. */
+   HOWTO (R_I51_7_PCREL,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 true,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_bitfield, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc, /* special_function */
+ 	 "R_I51_7_PCREL",	/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x0000,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 11 bit absolute inpage relocation. */
+   HOWTO (R_I51_11,		/* type */
+ 	 0,			/* rightshift */
+ 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 16,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc, /* special_function */
+ 	 "R_I51_11",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0xffff,		/* src_mask */
+ 	 0xffff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 8 bit bit register relocation. */
+   HOWTO (R_I51_8_BIT,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_8_BIT",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x00ff,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 8 bit absolute relocation. */
+   HOWTO (R_I51_8,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_8",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x00ff,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 8 bit absolute LOW(word) relocation. */
+   HOWTO (R_I51_L,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_L",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x00ff,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 8 bit absolute HIGH(word) relocation. */
+   HOWTO (R_I51_H,		/* type */
+ 	 8,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_H",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x00ff,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 16 bit absolute relocation.  */
+   HOWTO (R_I51_16,		/* type */
+ 	 0,			/* rightshift */
+ 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 16,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_16",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0xffff,		/* src_mask */
+ 	 0xffff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 8 bit Byte2Bit relocation. */
+   HOWTO (R_I51_8_B2B,		/* type */
+ 	 0,			/* rightshift */
+ 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 8,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_I51_8_B2B",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0x00ff,		/* src_mask */
+ 	 0x00ff,		/* dst_mask */
+ 	 false),		/* pcrel_offset */
+ 
+   /* A 13 bit absolute pcode relocation. */
+   HOWTO (R_I51_13_PCODE,	/* type */
+ 	 0,			/* rightshift */
+ 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 16,			/* bitsize */
+ 	 false,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_dont, /* complain_on_overflow */
+ 	 bfd_elf_generic_reloc, /* special_function */
+ 	 "R_I51_13_PCODE",		/* name */
+ 	 false,			/* partial_inplace */
+ 	 0xffff,		/* src_mask */
+ 	 0xffff,		/* dst_mask */
+ 	 false)		        /* pcrel_offset */
+ };
+ 
+ /* Map BFD reloc types to I51 ELF reloc types.  */
+ 
+ struct i51_reloc_map
+ {
+   bfd_reloc_code_real_type bfd_reloc_val;
+   unsigned int elf_reloc_val;
+ };
+ 
+  static const struct i51_reloc_map i51_reloc_map[] =
+ {
+   { BFD_RELOC_NONE,                 R_I51_NONE },
+   { BFD_RELOC_I51_R1,               R_I51_R1 },
+   { BFD_RELOC_I51_R3,               R_I51_R3 },
+   { BFD_RELOC_I51_7_PCREL,          R_I51_7_PCREL },
+   { BFD_RELOC_I51_11,		    R_I51_11 },
+   { BFD_RELOC_I51_8_BIT,	    R_I51_8_BIT },
+   { BFD_RELOC_8,                    R_I51_8 },
+   { BFD_RELOC_I51_8_LOW,            R_I51_L },
+   { BFD_RELOC_I51_8_HIGH,           R_I51_H },
+   { BFD_RELOC_16,                   R_I51_16 },
+   { BFD_RELOC_I51_8_B2B,	    R_I51_8_B2B },
+   { BFD_RELOC_I51_13_PCODE,	    R_I51_13_PCODE }
+ };
+ 
+ static reloc_howto_type *
+ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      bfd_reloc_code_real_type code;
+ {
+   unsigned int i;
+ 
+   for (i = 0;
+        i < sizeof (i51_reloc_map) / sizeof (struct i51_reloc_map);
+        i++)
+     {
+       if (i51_reloc_map[i].bfd_reloc_val == code)
+ 	return &elf_i51_howto_table[i51_reloc_map[i].elf_reloc_val];
+     }
+   return NULL;
+ }
+ 
+ /* Set the howto pointer for an I51 ELF reloc.  */
+ 
+ static void
+ i51_info_to_howto_rela (abfd, cache_ptr, dst)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      arelent *cache_ptr;
+      Elf32_Internal_Rela *dst;
+ {
+   unsigned int r_type;
+ 
+   r_type = ELF32_R_TYPE (dst->r_info);
+   BFD_ASSERT (r_type < (unsigned int) R_I51_max);
+   cache_ptr->howto = &elf_i51_howto_table[r_type];
+ }
+ 
+ static asection *
+ elf32_i51_gc_mark_hook (abfd, info, rel, h, sym)
+      bfd *abfd;
+      struct bfd_link_info *info ATTRIBUTE_UNUSED;
+      Elf_Internal_Rela *rel;
+      struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *sym;
+ {
+   if (h != NULL)
+     {
+       switch (ELF32_R_TYPE (rel->r_info))
+ 	{
+ 	default:
+ 	  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:
+ 	      break;
+ 	    }
+ 	}
+     }
+   else
+     {
+       if (!(elf_bad_symtab (abfd)
+ 	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+ 	  && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+ 	       && sym->st_shndx != SHN_COMMON))
+ 	{
+ 	  return bfd_section_from_elf_index (abfd, sym->st_shndx);
+ 	}
+     }
+   return NULL;
+ }
+ 
+ static boolean
+ elf32_i51_gc_sweep_hook (abfd, info, sec, relocs)
+      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 use got and plt entries for i51.  */
+   return true;
+ }
+ 
+ /* Look through the relocs for a section during the first phase.
+    Since we don't do .gots or .plts, we just need to consider the
+    virtual table relocs for gc.  */
+ 
+ static boolean
+ elf32_i51_check_relocs (abfd, info, sec, relocs)
+      bfd *abfd;
+      struct bfd_link_info *info;
+      asection *sec;
+      const Elf_Internal_Rela *relocs;
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+   const Elf_Internal_Rela *rel;
+   const Elf_Internal_Rela *rel_end;
+ 
+   if (info->relocateable)
+     return true;
+ 
+   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+   sym_hashes = elf_sym_hashes (abfd);
+   sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
+   if (!elf_bad_symtab (abfd))
+     sym_hashes_end -= symtab_hdr->sh_info;
+ 
+   rel_end = relocs + sec->reloc_count;
+   for (rel = relocs; rel < rel_end; rel++)
+     {
+       struct elf_link_hash_entry *h;
+       unsigned long r_symndx;
+ 
+       r_symndx = ELF32_R_SYM (rel->r_info);
+       if (r_symndx < symtab_hdr->sh_info)
+         h = NULL;
+       else
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+     }
+ 
+   return true;
+ }
+ 
+ /* Perform a single relocation.  By default we use the standard BFD
+    routines, but a few relocs, we have to do them ourselves.  */
+ 
+ static bfd_reloc_status_type
+ i51_final_link_relocate (howto, input_bfd, input_section,
+ 			 contents, rel, relocation)
+      reloc_howto_type *  howto;
+      bfd *               input_bfd;
+      asection *          input_section;
+      bfd_byte *          contents;
+      Elf_Internal_Rela * rel;
+      bfd_vma             relocation;
+ {
+   bfd_reloc_status_type r = bfd_reloc_ok;
+   bfd_vma               x;
+   bfd_signed_vma	srel;
+ 
+   switch (howto->type)
+     {
+     case R_I51_7_PCREL:
+       contents += rel->r_offset;
+       srel = (bfd_signed_vma) relocation;
+       srel += rel->r_addend;
+       srel -= rel->r_offset;
+       srel -= (input_section->output_section->vma +
+ 	       input_section->output_offset);
+       /*
+       fprintf (stderr, "7PCREL contents: %lx rel->r_offset: %lx relocation: %lx\n",
+ 	       contents, rel->r_offset, (bfd_signed_vma)relocation);
+       fprintf (stderr, "7PCREL rel->r_addend: %lx srel: %lx\n",
+ 	       rel->r_addend, srel);
+       fprintf (stderr, "7PCREL input_section->output_section->vma: %lx input_section->output_offset: %lx\n",
+ 	       input_section->output_section->vma, input_section->output_offset);
+       */
+       /* Check for overflow.  */
+       if (srel > ((1 << 7) - 1) || (srel < - (1 << 7)))
+ 	return bfd_reloc_overflow;
+ 
+       //      x = bfd_get_8 (input_bfd, contents);
+       bfd_put_8 (input_bfd, srel, contents);
+       break;
+ 
+     case R_I51_11:
+       contents   += rel->r_offset;
+       srel = (bfd_signed_vma) relocation;
+       srel += rel->r_addend;
+       /*
+       fprintf (stderr, "R11 contents: %lx rel->r_offset: %lx relocation: %lx\n",
+ 	       contents, rel->r_offset, (bfd_signed_vma)relocation);
+       fprintf (stderr, "R11 rel->r_addend: %lx srel: %lx\n",
+ 	       rel->r_addend, srel);
+       fprintf (stderr, "R11 input_section->output_section->vma: %lx input_section->output_offset: %lx\n",
+ 	       input_section->output_section->vma, input_section->output_offset);
+       */
+       /* Check for overflow.  */
+       if (((srel ^ (rel->r_offset + input_section->output_section->vma + input_section->output_offset)) & 0x0000F800l) !=0)
+ 	{
+ 	  /*
+ 	  fprintf ("Err: %lx %lx %lx\n", srel,
+ 		   (rel->r_offset + input_section->output_section->vma + input_section->output_offset),
+ 		   ((srel ^ (rel->r_offset + input_section->output_section->vma + input_section->output_offset)) & 0x0000F800l));
+ 	  */
+ 	  return bfd_reloc_overflow;
+ 	}
+ 
+       srel = (((srel & 0x0700) << 5) | (srel & 0x00FF));
+       x = bfd_get_16 (input_bfd, contents);
+       x = (x & 0x1F00) | srel;
+       bfd_put_16 (input_bfd, x, contents);
+       break;
+ 
+     case R_I51_8_B2B:
+       contents += rel->r_offset;
+       srel = (bfd_signed_vma) relocation;
+       srel += rel->r_addend;
+       x = bfd_get_8 (input_bfd, contents);
+       /* Check for overflow.  */
+       if (srel < 0x20) return bfd_reloc_outofrange;
+       if ((srel < 0x30) && (((srel - 0x20) * 8 + x) > 0x80)) return bfd_reloc_overflow;
+       if ((srel >= 0x30) && (srel < 0x80)) return bfd_reloc_outofrange;
+       if ((srel + x) > 0x100) return bfd_reloc_overflow;
+       if (srel < 0x30)
+ 	bfd_put_8 (input_bfd, ((srel - 0x20) * 8 + x), contents);
+       else
+ 	bfd_put_8 (input_bfd, (srel + x), contents);
+       break;
+ 
+     case R_I51_13_PCODE:
+       contents   += rel->r_offset;
+       srel = (bfd_signed_vma) relocation;
+       srel += rel->r_addend;
+       /* Check for overflow.  */
+       if (srel < 0x0100) return bfd_reloc_outofrange;
+       if (srel > 0x1FFF) return bfd_reloc_overflow;
+ 
+       x = bfd_get_16 (input_bfd, contents);
+       x = (x & 0xE000) | srel;
+       bfd_put_16 (input_bfd, x, contents);
+       break;
+ 
+     default:
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ 				    contents, rel->r_offset,
+ 				    relocation, rel->r_addend);
+     }
+ 
+   return r;
+ }
+ 
+ /* Relocate an I51 ELF section.  */
+ static boolean
+ elf32_i51_relocate_section (output_bfd, info, input_bfd, input_section,
+ 			    contents, relocs, local_syms, local_sections)
+      bfd *output_bfd ATTRIBUTE_UNUSED;
+      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;
+   Elf_Internal_Rela *           relend;
+ 
+   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+   sym_hashes = elf_sym_hashes (input_bfd);
+   relend     = relocs + input_section->reloc_count;
+ 
+   for (rel = relocs; rel < relend; rel ++)
+     {
+       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;
+       const char *                 name = NULL;
+       int                          r_type;
+ 
+       r_type = ELF32_R_TYPE (rel->r_info);
+       r_symndx = ELF32_R_SYM (rel->r_info);
+ 
+       if (info->relocateable)
+ 	{
+ 	  /* This is a relocateable link.  We don't have to change
+              anything, unless the reloc is against a section symbol,
+              in which case we have to adjust according to where the
+              section symbol winds up in the output section.  */
+ 	  if (r_symndx < symtab_hdr->sh_info)
+ 	    {
+ 	      sym = local_syms + r_symndx;
+ 
+ 	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ 		{
+ 		  sec = local_sections [r_symndx];
+ 		  rel->r_addend += sec->output_offset + sym->st_value;
+ 		}
+ 	    }
+ 
+ 	  continue;
+ 	}
+ 
+       /* This is a final link.  */
+       howto  = elf_i51_howto_table + ELF32_R_TYPE (rel->r_info);
+       h      = NULL;
+       sym    = NULL;
+       sec    = NULL;
+ 
+       if (r_symndx < symtab_hdr->sh_info)
+ 	{
+ 	  sym = local_syms + r_symndx;
+ 	  sec = local_sections [r_symndx];
+ 	  relocation = (sec->output_section->vma
+ 			+ sec->output_offset
+ 			+ sym->st_value);
+ 
+ 	  name = bfd_elf_string_from_elf_section
+ 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
+ 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
+ 	}
+       else
+ 	{
+ 	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+ 
+ 	  while (h->root.type == bfd_link_hash_indirect
+ 		 || h->root.type == bfd_link_hash_warning)
+ 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ 
+ 	  name = h->root.root.string;
+ 
+ 	  if (h->root.type == bfd_link_hash_defined
+ 	      || h->root.type == bfd_link_hash_defweak)
+ 	    {
+ 	      sec = h->root.u.def.section;
+ 	      relocation = (h->root.u.def.value
+ 			    + sec->output_section->vma
+ 			    + sec->output_offset);
+ 	    }
+ 	  else if (h->root.type == bfd_link_hash_undefweak)
+ 	    {
+ 	      relocation = 0;
+ 	    }
+ 	  else
+ 	    {
+ 	      if (! ((*info->callbacks->undefined_symbol)
+ 		     (info, h->root.root.string, input_bfd,
+ 		      input_section, rel->r_offset, true)))
+ 		return false;
+ 	      relocation = 0;
+ 	    }
+ 	}
+ 
+       r = i51_final_link_relocate (howto, input_bfd, input_section,
+ 				   contents, rel, relocation);
+ 
+       if (r != bfd_reloc_ok)
+ 	{
+ 	  const char * msg = (const char *) NULL;
+ 
+ 	  switch (r)
+ 	    {
+ 	    case bfd_reloc_overflow:
+ 	      r = info->callbacks->reloc_overflow
+ 		(info, name, howto->name, (bfd_vma) 0,
+ 		 input_bfd, input_section, rel->r_offset);
+ 	      break;
+ 
+ 	    case bfd_reloc_undefined:
+ 	      r = info->callbacks->undefined_symbol
+ 		(info, name, input_bfd, input_section, rel->r_offset, true);
+ 	      break;
+ 
+ 	    case bfd_reloc_outofrange:
+ 	      msg = _("internal error: out of range error");
+ 	      break;
+ 
+ 	    case bfd_reloc_notsupported:
+ 	      msg = _("internal error: unsupported relocation error");
+ 	      break;
+ 
+ 	    case bfd_reloc_dangerous:
+ 	      msg = _("internal error: dangerous relocation");
+ 	      break;
+ 
+ 	    default:
+ 	      msg = _("internal error: unknown error");
+ 	      break;
+ 	    }
+ 
+ 	  if (msg)
+ 	    r = info->callbacks->warning
+ 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
+ 
+ 	  if (! r)
+ 	    return false;
+ 	}
+     }
+ 
+   return true;
+ }
+ 
+ /* The final processing done just before writing out a I51 ELF object
+    file.  This gets the I51 architecture right based on the machine
+    number.  */
+ 
+ static void
+ bfd_elf_i51_final_write_processing (abfd, linker)
+      bfd *abfd;
+      boolean linker ATTRIBUTE_UNUSED;
+ {
+   unsigned long val;
+ 
+   elf_elfheader (abfd)->e_machine = EM_I51;
+ }
+ 
+ /* Set the right machine number.  */
+ 
+ static boolean
+ elf32_i51_object_p (abfd)
+      bfd *abfd;
+ {
+   return true;
+ }
+ 
+ static boolean
+ i51_elf_section_from_shdr (abfd, hdr, name)
+      bfd *abfd;
+      Elf32_Internal_Shdr *hdr;
+      char *name;
+ {
+   asection *newsect;
+   flagword flags;
+ 
+   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+     return false;
+ 
+   newsect = hdr->bfd_section;
+   flags = bfd_get_section_flags (abfd, newsect);
+ 
+   if (hdr->sh_flags & SHF_CDATA) flags |= SEC_IS_COMMON;
+ 
+   bfd_set_section_flags (abfd, newsect, flags);
+ 
+   return true;
+ }
+ 
+ static boolean
+ i51_elf_fake_sections (abfd, shdr, asect)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      Elf32_Internal_Shdr *shdr;
+      asection *asect;
+ {
+   register const char * name;
+ 
+   name = bfd_get_section_name (abfd, asect);
+ 
+   if (strcmp (name, ".rbbs") == 0)
+     {
+       shdr->sh_flags |= SHF_RDATA;
+     }
+   else if (strcmp (name, ".bbbs") == 0)
+     {
+       shdr->sh_flags |= SHF_BDATA;
+     }
+   else if (strcmp (name, ".ibbs") == 0)
+     {
+       shdr->sh_flags |= SHF_IDATA;
+     }
+   else if (strcmp (name, ".xbbs") == 0)
+     {
+       shdr->sh_flags |= SHF_XDATA;
+     }
+   else if (strcmp (name, ".ebbs") == 0)
+     {
+       shdr->sh_flags |= SHF_EDATA;
+     }
+ 
+   return true;
+ }
+ 
+ 
+ /* Given a BFD section, try to locate the corresponding ELF section
+    index.  */
+ 
+ boolean
+ elf32_i51_section_from_bfd_section (abfd, hdr, sec, retval)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      Elf32_Internal_Shdr *hdr ATTRIBUTE_UNUSED;
+      asection *sec;
+      int *retval;
+ {
+   if (strcmp (bfd_get_section_name (abfd, sec), ".regbank") == 0)
+     {
+       *retval = SHN_I51_REGBANK;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".rbss") == 0)
+     {
+       *retval = SHN_I51_RDATA_C;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".bbss") == 0)
+     {
+       *retval = SHN_I51_BDATA_C;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".ibss") == 0)
+     {
+       *retval = SHN_I51_IDATA_C;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".xbss") == 0)
+     {
+       *retval = SHN_I51_XDATA_C;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".ebss") == 0)
+     {
+       *retval = SHN_I51_EDATA_C;
+       return true;
+     }
+   else if (strcmp (bfd_get_section_name (abfd, sec), ".bitbss") == 0)
+     {
+       *retval = SHN_I51_BITDATA_C;
+       return true;
+     }
+   return false;
+ }
+ 
+ 
+ static asection i51_elf_scom_section;
+ static asymbol i51_elf_scom_symbol;
+ static asymbol *i51_elf_scom_symbol_ptr;
+ 
+ static asection i51_elf_rcom_section;
+ static asymbol i51_elf_rcom_symbol;
+ static asymbol *i51_elf_rcom_symbol_ptr;
+ 
+ static asection i51_elf_bcom_section;
+ static asymbol i51_elf_bcom_symbol;
+ static asymbol *i51_elf_bcom_symbol_ptr;
+ 
+ static asection i51_elf_icom_section;
+ static asymbol i51_elf_icom_symbol;
+ static asymbol *i51_elf_icom_symbol_ptr;
+ 
+ static asection i51_elf_xcom_section;
+ static asymbol i51_elf_xcom_symbol;
+ static asymbol *i51_elf_xcom_symbol_ptr;
+ 
+ static asection i51_elf_ecom_section;
+ static asymbol i51_elf_ecom_symbol;
+ static asymbol *i51_elf_ecom_symbol_ptr;
+ 
+ static asection i51_elf_bitcom_section;
+ static asymbol i51_elf_bitcom_symbol;
+ static asymbol *i51_elf_bitcom_symbol_ptr;
+ 
+ /* Handle the special I51 section numbers that a symbol may use.  */
+ 
+ void
+ elf32_i51_symbol_processing (abfd, asym)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      asymbol *asym;
+ {
+   elf_symbol_type *elfsym;
+ 
+   elfsym = (elf_symbol_type *) asym;
+ 
+   switch (elfsym->internal_elf_sym.st_shndx)
+     {
+     case SHN_I51_REGBANK:
+       if (i51_elf_scom_section.name == NULL)
+ 	{
+ 	  /* Initialize the register common section.  */
+ 	  i51_elf_scom_section.name = ".regbank";
+ 	  i51_elf_scom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_scom_section.output_section = &i51_elf_scom_section;
+ 	  i51_elf_scom_section.alignment_power = 0;
+ 	  i51_elf_scom_section.symbol = &i51_elf_scom_symbol;
+ 	  i51_elf_scom_section.symbol_ptr_ptr = &i51_elf_scom_symbol_ptr;
+ 	  i51_elf_scom_symbol.name = ".regbank";
+ 	  i51_elf_scom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_scom_symbol.section = &i51_elf_scom_section;
+ 	  i51_elf_scom_symbol_ptr = &i51_elf_scom_symbol;
+ 	}
+       asym->section = &i51_elf_scom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_RDATA_C:
+       if (i51_elf_rcom_section.name == NULL)
+ 	{
+ 	  /* Initialize the rdata common section.  */
+ 	  i51_elf_rcom_section.name = ".rbss";
+ 	  i51_elf_rcom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_rcom_section.output_section = &i51_elf_rcom_section;
+ 	  i51_elf_rcom_section.alignment_power = 0;
+ 	  i51_elf_rcom_section.symbol = &i51_elf_rcom_symbol;
+ 	  i51_elf_rcom_section.symbol_ptr_ptr = &i51_elf_rcom_symbol_ptr;
+ 	  i51_elf_rcom_symbol.name = ".rbss";
+ 	  i51_elf_rcom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_rcom_symbol.section = &i51_elf_rcom_section;
+ 	  i51_elf_rcom_symbol_ptr = &i51_elf_rcom_symbol;
+ 	}
+       asym->section = &i51_elf_rcom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_BDATA_C:
+       if (i51_elf_bcom_section.name == NULL)
+ 	{
+ 	  /* Initialize the bdata common section.  */
+ 	  i51_elf_bcom_section.name = ".bbss";
+ 	  i51_elf_bcom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_bcom_section.output_section = &i51_elf_bcom_section;
+ 	  i51_elf_bcom_section.alignment_power = 0;
+ 	  i51_elf_bcom_section.symbol = &i51_elf_bcom_symbol;
+ 	  i51_elf_bcom_section.symbol_ptr_ptr = &i51_elf_bcom_symbol_ptr;
+ 	  i51_elf_bcom_symbol.name = ".bbss";
+ 	  i51_elf_bcom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_bcom_symbol.section = &i51_elf_bcom_section;
+ 	  i51_elf_bcom_symbol_ptr = &i51_elf_bcom_symbol;
+ 	}
+       asym->section = &i51_elf_bcom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_IDATA_C:
+       if (i51_elf_icom_section.name == NULL)
+ 	{
+ 	  /* Initialize the idata common section.  */
+ 	  i51_elf_icom_section.name = ".ibss";
+ 	  i51_elf_icom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_icom_section.output_section = &i51_elf_icom_section;
+ 	  i51_elf_icom_section.alignment_power = 0;
+ 	  i51_elf_icom_section.symbol = &i51_elf_icom_symbol;
+ 	  i51_elf_icom_section.symbol_ptr_ptr = &i51_elf_icom_symbol_ptr;
+ 	  i51_elf_icom_symbol.name = ".ibss";
+ 	  i51_elf_icom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_icom_symbol.section = &i51_elf_icom_section;
+ 	  i51_elf_icom_symbol_ptr = &i51_elf_icom_symbol;
+ 	}
+       asym->section = &i51_elf_icom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_XDATA_C:
+       if (i51_elf_xcom_section.name == NULL)
+ 	{
+ 	  /* Initialize the xdata common section.  */
+ 	  i51_elf_xcom_section.name = ".xbss";
+ 	  i51_elf_xcom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_xcom_section.output_section = &i51_elf_xcom_section;
+ 	  i51_elf_xcom_section.alignment_power = 0;
+ 	  i51_elf_xcom_section.symbol = &i51_elf_xcom_symbol;
+ 	  i51_elf_xcom_section.symbol_ptr_ptr = &i51_elf_xcom_symbol_ptr;
+ 	  i51_elf_xcom_symbol.name = ".xbss";
+ 	  i51_elf_xcom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_xcom_symbol.section = &i51_elf_xcom_section;
+ 	  i51_elf_xcom_symbol_ptr = &i51_elf_xcom_symbol;
+ 	}
+       asym->section = &i51_elf_xcom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_EDATA_C:
+       if (i51_elf_ecom_section.name == NULL)
+ 	{
+ 	  /* Initialize the edata common section.  */
+ 	  i51_elf_ecom_section.name = ".ebss";
+ 	  i51_elf_ecom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_ecom_section.output_section = &i51_elf_ecom_section;
+ 	  i51_elf_ecom_section.alignment_power = 0;
+ 	  i51_elf_ecom_section.symbol = &i51_elf_ecom_symbol;
+ 	  i51_elf_ecom_section.symbol_ptr_ptr = &i51_elf_ecom_symbol_ptr;
+ 	  i51_elf_ecom_symbol.name = ".ebss";
+ 	  i51_elf_ecom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_ecom_symbol.section = &i51_elf_ecom_section;
+ 	  i51_elf_ecom_symbol_ptr = &i51_elf_ecom_symbol;
+ 	}
+       asym->section = &i51_elf_ecom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     case SHN_I51_BITDATA_C:
+       if (i51_elf_bitcom_section.name == NULL)
+ 	{
+ 	  /* Initialize the bdata common section.  */
+ 	  i51_elf_bitcom_section.name = ".bitbss";
+ 	  i51_elf_bitcom_section.flags = SEC_IS_COMMON;
+ 	  i51_elf_bitcom_section.output_section = &i51_elf_bitcom_section;
+ 	  i51_elf_bitcom_section.alignment_power = 0;
+ 	  i51_elf_bitcom_section.symbol = &i51_elf_bitcom_symbol;
+ 	  i51_elf_bitcom_section.symbol_ptr_ptr = &i51_elf_bitcom_symbol_ptr;
+ 	  i51_elf_bitcom_symbol.name = ".bitbss";
+ 	  i51_elf_bitcom_symbol.flags = BSF_SECTION_SYM;
+ 	  i51_elf_bitcom_symbol.section = &i51_elf_bitcom_section;
+ 	  i51_elf_bitcom_symbol_ptr = &i51_elf_bitcom_symbol;
+ 	}
+       asym->section = &i51_elf_bitcom_section;
+       asym->value = elfsym->internal_elf_sym.st_size;
+       break;
+     }
+ }
+ 
+ static boolean
+ elf32_i51_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+      bfd *abfd;
+      struct bfd_link_info *info;
+      const Elf_Internal_Sym *sym;
+      const char **namep;
+      flagword *flagsp ATTRIBUTE_UNUSED;
+      asection **secp;
+      bfd_vma *valp;
+ 
+ {
+   switch (sym->st_shndx)
+     {
+     case SHN_I51_REGBANK:
+       *secp = bfd_make_section_old_way (abfd, ".regbank");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_RDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".rbss");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_BDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".bbss");
+       (*secp)->flags |= (SEC_IS_COMMON);
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_IDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".ibss");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_XDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".xbss");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_EDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".ebss");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     case SHN_I51_BITDATA_C:
+       *secp = bfd_make_section_old_way (abfd, ".bitbss");
+       (*secp)->flags |= SEC_IS_COMMON;
+       *valp = sym->st_size;
+       break;
+     }
+   return true;
+ }
+ 
+ #define ELF_ARCH		bfd_arch_i51
+ #define ELF_MACHINE_CODE	EM_I51
+ #define ELF_MAXPAGESIZE		1
+ 
+ #define TARGET_BIG_SYM       bfd_elf32_i51_vec
+ #define TARGET_BIG_NAME	"elf32-i51"
+ 
+ #define elf_info_to_howto	             i51_info_to_howto_rela
+ #define elf_info_to_howto_rel	             NULL
+ #define elf_backend_relocate_section         elf32_i51_relocate_section
+ #define elf_backend_gc_mark_hook             elf32_i51_gc_mark_hook
+ #define elf_backend_gc_sweep_hook            elf32_i51_gc_sweep_hook
+ #define elf_backend_check_relocs             elf32_i51_check_relocs
+ #define elf_backend_can_gc_sections          1
+ #define elf_backend_final_write_processing \
+ 					bfd_elf_i51_final_write_processing
+ #define elf_backend_object_p		elf32_i51_object_p
+ 
+ #define elf_backend_fake_sections		i51_elf_fake_sections
+ #define elf_backend_section_from_shdr		i51_elf_section_from_shdr
+ #define elf_backend_symbol_processing		elf32_i51_symbol_processing
+ #define elf_backend_section_from_bfd_section	elf32_i51_section_from_bfd_section
+ #define elf_backend_add_symbol_hook		elf32_i51_add_symbol_hook
+ #include "elf32-target.h"
diff -crN binutils.null/gas/config/tc-i51.c binutils-2.11.2.i51.new/gas/config/tc-i51.c
*** binutils.null/gas/config/tc-i51.c	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/gas/config/tc-i51.c	Sun Dec 30 10:49:19 2001
***************
*** 0 ****
--- 1,2609 ----
+ /* tc-i51.c -- Assembler code for the MCS-51
+ 
+    Copyright (C) 2001 Free Software Foundation, Inc.
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+    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, 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include <stdio.h>
+ #include <ctype.h>
+ #include "as.h"
+ #include "subsegs.h"
+ #include "elf/i51.h"
+ 
+ //#define ASMDBG 1
+ 
+ /* forward declaration */
+ static int  check_range PARAMS ((long, int));
+ static void fixup8      PARAMS ((expressionS *, int, int));
+ static void fixup11     PARAMS ((expressionS *, unsigned int, int, int));
+ static void fixup16     PARAMS ((expressionS *, int, int));
+ static void i51_using   PARAMS ((int));
+ static void i51_bss     PARAMS ((int));
+ static void i51_rbss    PARAMS ((int));
+ static void i51_bbss    PARAMS ((int));
+ static void i51_ibss    PARAMS ((int));
+ static void i51_xbss    PARAMS ((int));
+ static void i51_ebss    PARAMS ((int));
+ static void i51_bitbss  PARAMS ((int));
+ static void i51_rdata   PARAMS ((int));
+ static void i51_bdata   PARAMS ((int));
+ static void i51_idata   PARAMS ((int));
+ static void i51_xdata   PARAMS ((int));
+ static void i51_edata   PARAMS ((int));
+ static void i51_bitdata PARAMS ((int));
+ static void i51_eeprom  PARAMS ((int));
+ static void i51_pcode   PARAMS ((int));
+ static void i51_bit     PARAMS ((int));
+ void i51_common (int);
+ 
+ #ifndef TC_PARSE_CONS_EXPRESSION
+ #ifdef BITFIELD_CONS_EXPRESSIONS
+ #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
+ static void
+ parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+ #endif
+ #ifdef REPEAT_CONS_EXPRESSIONS
+ #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
+ static void
+ parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+ #endif
+ 
+ /* If we haven't gotten one yet, just call expression.  */
+ #ifndef TC_PARSE_CONS_EXPRESSION
+ #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
+ #endif
+ #endif
+ 
+ const char comment_chars[] = ";";
+ const char line_comment_chars[] = "#";
+ const char line_separator_chars[] = "$";
+ const char EXP_CHARS[] = "eE";
+ const char FLT_CHARS[] = "dD";
+ 
+ const char *md_shortopts = "";
+ struct option md_longopts[] =
+ {
+   { NULL, no_argument, NULL, 0 }
+ };
+ 
+ /* The target specific pseudo-ops which we support.  */
+ const pseudo_typeS md_pseudo_table[] =
+ {
+   { "bit",      i51_bit,	0 },
+   { "using",    i51_using,      0 },
+   { "rcomm",    i51_common,  0x01 },
+   { "rcommon",  i51_common,  0x01 },
+   { "bitcomm",  i51_common,  0x02 },
+   { "bitcommon",i51_common,  0x02 },
+   { "comm",     i51_common,  0x00 },
+   { "common",   i51_common,  0x00 },
+   { "icomm",    i51_common,  0x03 },
+   { "icommon",  i51_common,  0x03 },
+   { "xcomm",    i51_common,  0x04 },
+   { "xcommon",  i51_common,  0x04 },
+   { "ecomm",    i51_common,  0x05 },
+   { "ecommon",  i51_common,  0x05 },
+   { "bcomm",    i51_common,  0x06 },
+   { "bcommon",  i51_common,  0x06 },
+   { "bss",      i51_bss,        0 },
+   { "rbss",     i51_rbss,       0 },
+   { "bbss",     i51_bbss,       0 },
+   { "ibss",     i51_ibss,       0 },
+   { "xbss",     i51_xbss,       0 },
+   { "ebss",     i51_ebss,       0 },
+   { "bitbss",   i51_bitbss,     0 },
+   { "rdata",    i51_rdata,      0 },
+   { "bdata",    i51_bdata,      0 },
+   { "idata",    i51_idata,      0 },
+   { "xdata",    i51_xdata,      0 },
+   { "edata",    i51_edata,      0 },
+   { "bitdata",  i51_bitdata,    0 },
+   { "eeprom",   i51_eeprom,     0 },
+   { "pcode",    i51_pcode,      0 },
+   { NULL,	NULL,		0 }
+ };
+ 
+ 
+ size_t md_longopts_size = sizeof (md_longopts);
+ 
+ #define I51_OP_IMM8        0x0001
+ #define I51_OP_JUMP_REL    0x0002
+ #define I51_OP_JUMP_INPAGE 0x0003
+ #define I51_OP_IMM16       0x0004
+ #define I51_OP_BIT         0x0005
+ #define I51_OP_HIGH_ADDR   0x0100
+ #define I51_OP_LOW_ADDR    0x0200
+ #define I51_OP_B2B         0x0400
+ 
+ struct i51_opcodes_s
+ {
+   char *name;
+   char *args;
+   int insn_size;		/* In bytes  */
+   unsigned char mreloc;         /* modify & reloc mode */
+   unsigned char bin_opcode;
+ };
+ 
+ struct i51_directop_s
+ {
+   char *op;
+   char ref;
+   unsigned char value;
+ };
+ 
+ #define I51_INS(NAME, ARGS, SIZE, OPCODE, MRELOC, BIN, MASK) \
+ {NAME, ARGS, SIZE, MRELOC, BIN},
+ 
+ struct i51_opcodes_s i51_opcodes[] =
+ {
+ #include "opcode/i51.h"
+   {NULL, NULL, 0, 0, 0}
+ };
+ 
+ struct i51_directop_s i51_directop[] =
+ {
+   {"A",      'A', 0},
+   {"AB",     'C', 0},
+   {"R0",     'R', 0},
+   {"R1",     'R', 1},
+   {"R2",     'R', 2},
+   {"R3",     'R', 3},
+   {"R4",     'R', 4},
+   {"R5",     'R', 5},
+   {"R6",     'R', 6},
+   {"R7",     'R', 7},
+   {"C",      'r', 0},
+   {"DPTR",   'P', 0},
+   {"@A+DPTR",'@', 0},
+   {"@A+PC",  'X', 0},
+   {"@R0"  ,  'I', 0},
+   {"@R1",    'I', 1},
+   {"/C",     '/', 0},
+   {"@DPTR",  'T', 0},
+ // BYTE register bank addressable registers
+   {"AR0",    'U', 0},
+   {"AR1",    'U', 1},
+   {"AR2",    'U', 2},
+   {"AR3",    'U', 3},
+   {"AR4",    'U', 4},
+   {"AR5",    'U', 5},
+   {"AR6",    'U', 6},
+   {"AR7",    'U', 7},
+ // BYTE addressable registers
+   {"P0",     'D',0x80},
+   {"SP",     'D',0x81},
+   {"DPL",    'D',0x82},
+   {"DP0L",   'D',0x82},  // as called by Atmel
+   {"DPH",    'D',0x83},
+   {"DP0H",   'D',0x83},  // as called by Atmel
+   {"DP1L",   'D',0x84},  // at89S8252 specific register
+   {"DP1H",   'D',0x85},  // at89S8252 specific register
+   {"SPDR",   'D',0x86},  // at89S8252 specific register
+   {"PCON",   'D',0x87},
+   {"TCON",   'D',0x88},
+   {"TMOD",   'D',0x89},
+   {"TL0",    'D',0x8A},
+   {"TL1",    'D',0x8B},
+   {"TH0",    'D',0x8C},
+   {"TH1",    'D',0x8D},
+   {"P1",     'D',0x90},
+   {"WMCON",  'D',0x96},  // at89S8252 specific register
+   {"SCON",   'D',0x98},
+   {"SBUF",   'D',0x99},
+   {"P2",     'D',0xA0},
+   {"IE",     'D',0xA8},
+   {"SPSR",   'D',0xAA},  // at89S8252 specific register
+   {"P3",     'D',0xB0},
+   {"IP",     'D',0xB8},
+   {"T2CON",  'D',0xC8},
+   {"T2MOD",  'D',0xC9},
+   {"RCAP2L", 'D',0xCA},
+   {"RCAP2H", 'D',0xCB},
+   {"TL2",    'D',0xCC},
+   {"TH2",    'D',0xCD},
+   {"PSW",    'D',0xD0},
+   {"SPCR",   'D',0xD5},  // at89S8252 specific register
+   {"ACC",    'D',0xE0},
+   {"B",      'D',0xF0},
+ // BIT addressable registers
+ // P0
+   {"P0.0",   'B',0x80},
+   {"P0.1",   'B',0x81},
+   {"P0.2",   'B',0x82},
+   {"P0.3",   'B',0x83},
+   {"P0.4",   'B',0x84},
+   {"P0.5",   'B',0x85},
+   {"P0.6",   'B',0x86},
+   {"P0.7",   'B',0x87},
+ // TCON
+   {"IT0",    'B',0x88},
+   {"IE0",    'B',0x89},
+   {"IT1",    'B',0x8A},
+   {"IE1",    'B',0x8B},
+   {"TR0",    'B',0x8C},
+   {"TF0",    'B',0x8D},
+   {"TR1",    'B',0x8E},
+   {"TF1",    'B',0x8F},
+ // P1
+   {"P1.0",   'B',0x90},
+   {"P1.1",   'B',0x91},
+   {"P1.2",   'B',0x92},
+   {"P1.3",   'B',0x93},
+   {"P1.4",   'B',0x94},
+   {"P1.5",   'B',0x95},
+   {"P1.6",   'B',0x96},
+   {"P1.7",   'B',0x97},
+   {"T2",     'B',0x90},
+   {"T2EX",   'B',0x91},
+ // SCON
+   {"RI",     'B',0x98},
+   {"TI",     'B',0x99},
+   {"RB8",    'B',0x9A},
+   {"TB8",    'B',0x9B},
+   {"REN",    'B',0x9C},
+   {"SM2",    'B',0x9D},
+   {"SM1",    'B',0x9E},
+   {"SM0",    'B',0x9F},
+ // P2
+   {"P2.0",   'B',0xA0},
+   {"P2.1",   'B',0xA1},
+   {"P2.2",   'B',0xA2},
+   {"P2.3",   'B',0xA3},
+   {"P2.4",   'B',0xA4},
+   {"P2.5",   'B',0xA5},
+   {"P2.6",   'B',0xA6},
+   {"P2.7",   'B',0xA7},
+ // IE
+   {"EX0",    'B',0xA8},
+   {"ET0",    'B',0xA9},
+   {"EX1",    'B',0xAA},
+   {"ET1",    'B',0xAB},
+   {"ES",     'B',0xAC},
+   {"ET2",    'B',0xAD},
+   {"EA",     'B',0xAF},
+ // P3
+   {"P3.0",   'B',0xB0},
+   {"P3.1",   'B',0xB1},
+   {"P3.2",   'B',0xB2},
+   {"P3.3",   'B',0xB3},
+   {"P3.4",   'B',0xB4},
+   {"P3.5",   'B',0xB5},
+   {"P3.6",   'B',0xB6},
+   {"P3.7",   'B',0xB7},
+   {"RXD",    'B',0xB0},
+   {"TXD",    'B',0xB1},
+   {"INT0",   'B',0xB2},
+   {"INT1",   'B',0xB3},
+   {"T0",     'B',0xB4},
+   {"T1",     'B',0xB5},
+   {"WR",     'B',0xB6},
+   {"RD",     'B',0xB7},
+ // IP
+   {"PX0",    'B',0xB8},
+   {"PT0",    'B',0xB9},
+   {"PX1",    'B',0xBA},
+   {"PT1",    'B',0xBB},
+   {"PS",     'B',0xBC},
+   {"PT2",    'B',0xBD},
+ // T2CON
+   {"T2CON.0",'B',0xC8},
+   {"T2CON.1",'B',0xC9},
+   {"T2CON.2",'B',0xCA},
+   {"T2CON.3",'B',0xCB},
+   {"T2CON.4",'B',0xCC},
+   {"T2CON.5",'B',0xCD},
+   {"T2CON.6",'B',0xCE},
+   {"T2CON.7",'B',0xCF},
+   {"CP_RL2", 'B',0xC8},
+   {"C_T2",   'B',0xC9},
+   {"TR2",    'B',0xCA},
+   {"EXEN2",  'B',0xCB},
+   {"TCLK",   'B',0xCC},
+   {"RCLK",   'B',0xCD},
+   {"EXF2",   'B',0xCE},
+   {"TF2",    'B',0xCF},
+ // PSW
+   {"P",      'B',0xD0},
+   {"FL",     'B',0xD1},
+   {"OV",     'B',0xD2},
+   {"RS0",    'B',0xD3},
+   {"RS1",    'B',0xD4},
+   {"F0",     'B',0xD5},
+   {"AC",     'B',0xD6},
+   {"CY",     'B',0xD7},
+ // ACC
+   {"ACC.0",  'B',0xE0},
+   {"ACC.1",  'B',0xE1},
+   {"ACC.2",  'B',0xE2},
+   {"ACC.3",  'B',0xE3},
+   {"ACC.4",  'B',0xE4},
+   {"ACC.5",  'B',0xE5},
+   {"ACC.6",  'B',0xE6},
+   {"ACC.7",  'B',0xE7},
+ // B
+   {"B.0",    'B',0xF0},
+   {"B.1",    'B',0xF1},
+   {"B.2",    'B',0xF2},
+   {"B.3",    'B',0xF3},
+   {"B.4",    'B',0xF4},
+   {"B.5",    'B',0xF5},
+   {"B.6",    'B',0xF6},
+   {"B.7",    'B',0xF7},
+ //
+   {NULL,     '\0',0}
+ };
+ 
+ /* Opcode hash table.  */
+ static struct hash_control *i51_hash;
+ /* Operand hash table.  */
+ static struct hash_control *i51_operand;
+ 
+ /* local variables */
+ unsigned char regbank = 0xFF;
+ unsigned char regused = 0x00;
+ /* md_assemble */
+ struct i51_opcodes_s *opcode;
+ struct i51_directop_s *oper;
+ char op[11];
+ expressionS op_expr1;
+ expressionS op_expr2;
+ expressionS op_expr3;
+ expressionS op_expr4;
+ char *line;
+ unsigned char regno;
+ unsigned char op1mode;
+ unsigned char op2mode;
+ int op1hlmode;
+ int op2hlmode;
+ int b2b_offset;
+ enum  PADRMODE {
+   DIRECTWORD,
+   DIRECTBYTE,
+   DIRECTSWAP,
+   DIRECTSHL8,
+   INDIRECTWORD,
+   INDIRECTBYTE,
+   INDIRECTSWAP
+ } p1mode, p2mode, p3mode, p4mode;
+ 
+ /* Stuff for .regbank symbols.  */
+ static asection scom_section;
+ static asymbol  scom_symbol;
+ /* Stuff for .rbbs symbols.  */
+ static segT     rbss_section = NULL;
+ static asection rcom_section;
+ static asymbol  rcom_symbol;
+ /* Stuff for .bbbs symbols.  */
+ static segT     bbss_section = NULL;
+ static asection bcom_section;
+ static asymbol  bcom_symbol;
+ /* Stuff for .ibbs symbols.  */
+ static segT     ibss_section = NULL;
+ static asection icom_section;
+ static asymbol  icom_symbol;
+ /* Stuff for .xbbs symbols.  */
+ static segT     xbss_section = NULL;
+ static asection xcom_section;
+ static asymbol  xcom_symbol;
+ /* Stuff for .ebbs symbols.  */
+ static segT     ebss_section = NULL;
+ static asection ecom_section;
+ static asymbol  ecom_symbol;
+ /* Stuff for .bitbbs symbols.  */
+ static segT     bitbss_section = NULL;
+ static asection bitcom_section;
+ static asymbol  bitcom_symbol;
+ /* Stuff for .?data */
+ static segT     rdata_section = NULL;
+ static segT     bdata_section = NULL;
+ static segT     idata_section = NULL;
+ static segT     xdata_section = NULL;
+ static segT     edata_section = NULL;
+ static segT     eeprom_section = NULL;
+ static segT     bitdata_section = NULL;
+ 
+ /* local function */
+ void i51_build_ins (struct i51_opcodes_s *, unsigned char, expressionS *, expressionS *);
+ void i51_parse_operand1 (void);
+ void i51_parse_operand2 (void);
+ static inline char * skip_space (char *);
+ long md_pcrel_from_section (fixS *, segT);
+ void pcodeOperand (expressionS *, enum PADRMODE *, int);
+ void writePcodeOperand (expressionS *, enum PADRMODE *, int swapable ATTRIBUTE_UNUSED);
+ unsigned short decodePcodeOperand (expressionS *, enum PADRMODE *, int);
+ 
+ static inline char *
+ skip_space (s)
+      char *s;
+ {
+   while (*s == ' ' || *s == '\t')
+     ++s;
+   return s;
+ }
+ 
+ /* Extract one word from FROM and copy it to TO.  */
+ 
+ static char *
+ extract_word (char *from, char *to, int limit)
+ {
+   char *op_start;
+   char *op_end;
+   int size = 0;
+ 
+   /* Drop leading whitespace.  */
+   from = skip_space (from);
+   *to = 0;
+ 
+   /* Find the op code end.  */
+   for (op_start = op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
+     {
+       to[size++] = *op_end++;
+       if (size + 1 >= limit)
+ 	break;
+     }
+ 
+   to[size] = 0;
+   return op_end;
+ }
+ 
+ /* Extract one word from FROM and copy it to TO.  */
+ 
+ static char *
+ extract_op (char *from, char *to, int limit)
+ {
+   char *op_start;
+   char *op_end;
+   int size = 0;
+ 
+   /* Drop leading whitespace.  */
+   from = skip_space (from);
+   *to = 0;
+ 
+   /* Find the op code end.  */
+   for (op_start = op_end = from; *op_end != 0 && *op_end != ',' && *op_end != ' ';)
+     {
+       to[size++] = toupper(*op_end++);
+       if (size + 1 >= limit)
+ 	break;
+     }
+ 
+   to[size] = 0;
+   return op_end;
+ }
+ 
+ int
+ md_estimate_size_before_relax (fragp, seg)
+      fragS *fragp ATTRIBUTE_UNUSED;
+      asection *seg ATTRIBUTE_UNUSED;
+ {
+   abort ();
+   return 0;
+ }
+ 
+ void
+ md_show_usage (stream)
+      FILE *stream;
+ {
+   fprintf (stream,
+       _("A51 options:\n"
+ 	"                   NONE\n"));
+ }
+ 
+ 
+ int
+ md_parse_option (c, arg)
+      int c;
+      char *arg;
+ {
+   return 0;
+ }
+ 
+ 
+ void
+ md_begin ()
+ {
+   struct i51_opcodes_s *opcode;
+   struct i51_directop_s *oper;
+   i51_hash = hash_new ();
+   i51_operand = hash_new ();
+ 
+   /* Insert unique names into hash table.  This hash table then provides a
+      quick index to the first opcode with a particular name in the opcode
+      table.  */
+   for (opcode = i51_opcodes; opcode->name; opcode++)
+     hash_insert (i51_hash, opcode->name, (char *) opcode);
+   /* Insert unique names into hash table.  This hash table then provides a
+      quick index to the operand table.  */
+   for (oper = i51_directop; oper->op; oper++)
+     hash_insert (i51_operand, oper->op, (char *) oper);
+ 
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .regbank.  */
+   scom_section                = bfd_com_section;
+   scom_section.name           = ".regbank";
+   scom_section.output_section = &scom_section;
+   scom_section.symbol         = &scom_symbol;
+   scom_section.symbol_ptr_ptr = &scom_section.symbol;
+   scom_symbol                 = *bfd_com_section.symbol;
+   scom_symbol.name            = ".regbank";
+   scom_symbol.section         = &scom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .rbss.  */
+   rcom_section                = bfd_com_section;
+   rcom_section.name           = ".rbss";
+   rcom_section.output_section = &rcom_section;
+   rcom_section.symbol         = &rcom_symbol;
+   rcom_section.symbol_ptr_ptr = &rcom_section.symbol;
+   rcom_symbol                 = *bfd_com_section.symbol;
+   rcom_symbol.name            = ".rbss";
+   rcom_symbol.section         = &rcom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .bbss.  */
+   bcom_section                = bfd_com_section;
+   bcom_section.name           = ".bbss";
+   bcom_section.output_section = &bcom_section;
+   bcom_section.symbol         = &bcom_symbol;
+   bcom_section.symbol_ptr_ptr = &bcom_section.symbol;
+   bcom_symbol                 = *bfd_com_section.symbol;
+   bcom_symbol.name            = ".bbss";
+   bcom_symbol.section         = &bcom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .ibss.  */
+   icom_section                = bfd_com_section;
+   icom_section.name           = ".ibss";
+   icom_section.output_section = &icom_section;
+   icom_section.symbol         = &icom_symbol;
+   icom_section.symbol_ptr_ptr = &icom_section.symbol;
+   icom_symbol                 = *bfd_com_section.symbol;
+   icom_symbol.name            = ".ibss";
+   icom_symbol.section         = &icom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .xbss.  */
+   xcom_section                = bfd_com_section;
+   xcom_section.name           = ".xbss";
+   xcom_section.output_section = &xcom_section;
+   xcom_section.symbol         = &xcom_symbol;
+   xcom_section.symbol_ptr_ptr = &xcom_section.symbol;
+   xcom_symbol                 = *bfd_com_section.symbol;
+   xcom_symbol.name            = ".xbss";
+   xcom_symbol.section         = &xcom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .ebss.  */
+   ecom_section                = bfd_com_section;
+   ecom_section.name           = ".ebss";
+   ecom_section.output_section = &ecom_section;
+   ecom_section.symbol         = &ecom_symbol;
+   ecom_section.symbol_ptr_ptr = &ecom_section.symbol;
+   ecom_symbol                 = *bfd_com_section.symbol;
+   ecom_symbol.name            = ".ebss";
+   ecom_symbol.section         = &ecom_section;
+   /* We must construct a fake section similar to bfd_com_section
+      but with the name .bitbss.  */
+   bitcom_section                = bfd_com_section;
+   bitcom_section.name           = ".bitbss";
+   bitcom_section.output_section = &bitcom_section;
+   bitcom_section.symbol         = &bitcom_symbol;
+   bitcom_section.symbol_ptr_ptr = &bitcom_section.symbol;
+   bitcom_symbol                 = *bfd_com_section.symbol;
+   bitcom_symbol.name            = ".bitbss";
+   bitcom_symbol.section         = &bitcom_section;
+ }
+ 
+ void
+ md_assemble (str)
+      char *str;
+ {
+ #ifdef ASMDBG
+   fprintf(stderr, "%s\n",str);
+ #endif
+   op_expr1.X_op = O_max;
+   op_expr2.X_op = O_max;
+ 
+   str = skip_space (extract_word (str, op, sizeof (op)));
+ 
+   if (!op[0])
+     {
+       as_bad (_("can't find opcode "));
+       return;
+     }
+ 
+   regno = 0;
+ 
+   opcode = (struct i51_opcodes_s *) hash_find (i51_hash, op);
+ 
+   if (opcode == NULL)
+     {
+       as_bad (_("unknown opcode `%s'"), op);
+       return;
+     }
+   else 
+     {
+       op1mode = 'N';
+       op2mode = 'N';
+       line = skip_space (str);
+       if (*line != 0)
+ 	{
+ 	  if (opcode->args[0] == 'N')
+ 	    {
+ 	      as_bad (_("garbage at end of line"));
+ 	      return;
+ 	    }
+ 	  i51_parse_operand1 ();
+ 	  line = skip_space (line);
+           if ((*line) && (opcode->args[1] == 'N'))
+ 	    {
+ 	      as_bad (_("garbage at end of line"));
+ 	      return;
+ 	    }
+ 	  if (*line == ',')
+ 	    {
+ 	      line++;
+ 	      i51_parse_operand2 ();
+ 	      line = skip_space (line);
+ 	      if ((*line) && (opcode->args[2] == 'N'))
+ 		{
+ 		  as_bad (_("garbage at end of line"));
+ 		  return;
+ 		}
+ 	      if (opcode->args[2] == 'J')
+ 		{
+ 		  if (*line == ',')
+ 		    {
+ 		      input_line_pointer = line+1;
+ 		      //PARSE EXPRESION 2
+ 		      expression (&op_expr2);
+ 		      line = input_line_pointer;
+ 		      if (op_expr1.X_op == O_absent)
+ 			{
+ 			  as_bad (_("missing operand 3"));
+ 			  return;
+ 			}
+ 		    }
+ 		  else
+ 		    {
+ 		      as_bad (_("missing operand 3"));
+ 		      return;
+ 		    }
+ 		}
+ 	    }
+ 	  else if (opcode->args[1] != 'N')
+ 	    {
+ 	      as_bad (_("missing operand 2"));
+ 	      return;
+ 	    }
+ #ifdef ASMDBG
+ 	  fprintf(stderr, "args: %s reg: %i\n\n", opcode->args, regno);
+ #endif
+             input_line_pointer = line;
+ 	}
+       else
+ 	{
+ 	  if (opcode->args[0] != 'N')
+ 	    {
+ 	      as_bad (_("missing operand 1"));
+ 	      return;
+ 	    }
+ 	}
+       if ((op1mode == opcode->args[0]) && (op2mode == opcode->args[1]))
+ 	{
+ 	  i51_build_ins (opcode, regno, &op_expr1, &op_expr2);
+ 	}
+       else
+ 	{
+ #ifdef ASMDBG
+ 	  fprintf(stderr,"invalid instruction operands %c/%c %c/%c", op1mode, opcode->args[0], op2mode, opcode->args[1]);
+ #endif
+ 	  as_bad (_("invalid instruction operands"));
+ 	  return;
+ 	}
+     }
+ }
+ 
+ /* GAS will call this function for each section at the end of the assembly,
+    to permit the CPU backend to adjust the alignment of a section.  */
+ 
+ valueT
+ md_section_align (seg, addr)
+      asection *seg;
+      valueT addr;
+ {
+   int align = bfd_get_section_alignment (stdoutput, seg);
+   return ((addr + (1 << align) - 1) & (-1 << align));
+ }
+ 
+ /* If you define this macro, it should return the offset between the
+    address of a PC relative fixup and the position from which the PC
+    relative adjustment should be made.  On many processors, the base
+    of a PC relative instruction is the next instruction, so this
+    macro would return the length of an instruction.  */
+ 
+ long
+ md_pcrel_from_section (fixp, sec)
+      fixS *fixp;
+      segT sec;
+ {
+   if (fixp->fx_addsy != (symbolS *) NULL
+       && (!S_IS_DEFINED (fixp->fx_addsy)
+ 	  || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
+     return 0;
+   return fixp->fx_frag->fr_address + fixp->fx_where + 1;
+ }
+ 
+ /* GAS will call this for each fixup.  It should store the correct
+    value in the object file.  */
+ 
+ int
+ md_apply_fix3 (fixp, valuep, seg)
+      fixS *fixp;
+      valueT *valuep;
+      segT seg;
+ {
+   unsigned char *where;
+   unsigned long insn;
+   long value;
+ 
+   if (fixp->fx_addsy == (symbolS *) NULL)
+     {
+       value = *valuep;
+       fixp->fx_done = 1;
+     }
+   else if (fixp->fx_pcrel)
+     {
+       segT s = S_GET_SEGMENT (fixp->fx_addsy);
+ 
+       if (fixp->fx_addsy && (s == seg || s == absolute_section))
+ 	{
+ 	  value = S_GET_VALUE (fixp->fx_addsy) + *valuep;
+ 	  fixp->fx_done = 1;
+ 	}
+       else
+ 	value = *valuep;
+     }
+   else
+     {
+       value = fixp->fx_offset;
+ 
+       if (fixp->fx_subsy != (symbolS *) NULL)
+ 	{
+ 	  if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ 	    {
+ 	      value -= S_GET_VALUE (fixp->fx_subsy);
+ 	      fixp->fx_done = 1;
+ 	    }
+ 	  else
+ 	    {
+ 	      /* We don't actually support subtracting a symbol.  */
+ 	      as_bad_where (fixp->fx_file, fixp->fx_line,
+ 			    _("expression too complex"));
+ 	    }
+ 	}
+     }
+ 
+   switch (fixp->fx_r_type)
+     {
+     default:
+       fixp->fx_no_overflow = 1;
+       break;
+     }
+ 
+   if (fixp->fx_done)
+     {
+       /* Fetch the instruction, insert the fully resolved operand
+ 	 value, and stuff the instruction back again.  */
+       where = fixp->fx_frag->fr_literal + fixp->fx_where;
+       insn = bfd_getb16 (where);
+ 
+       switch (fixp->fx_r_type)
+ 	{
+ 	case BFD_RELOC_I51_8_LOW:
+ 	  // bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
+ 	  ((bfd_byte *) where)[0] = (bfd_byte) (value & 0xFF);
+ 	  break;
+ 
+ 	case BFD_RELOC_I51_8_HIGH:
+ 	  if (value < -65536 || value > 65535)
+ 	    as_bad_where (fixp->fx_file, fixp->fx_line,
+ 			  _("operand out of range: %ld"), value);
+ 	  value >>= 8;
+ 	  /* Fall through.  */
+ 
+ 	case BFD_RELOC_8:
+ 	case BFD_RELOC_I51_8_BIT:
+ 	  if (value < -256 || value > 255)
+ 	    as_bad_where (fixp->fx_file, fixp->fx_line,
+ 			  _("operand out of range: %ld"), value);
+ 	  // bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
+ 	  ((bfd_byte *) where)[0] = (bfd_byte) (value & 0xFF);
+ 	  break;
+ 
+ 	case BFD_RELOC_I51_7_PCREL:
+ 	  if (value < -128 || value > 127)
+ 	    as_bad_where (fixp->fx_file, fixp->fx_line,
+ 			  _("operand out of range: %ld"), value);
+ 	  // bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
+ 	  ((bfd_byte *) where)[0] = (bfd_byte) value;
+ #ifdef ASMDBG
+ 	  fprintf(stderr, "fbdreloc7: %lx\n", value);
+ #endif
+ 	  break;
+ 
+ 	case BFD_RELOC_16:
+ 	  bfd_putb16 ((bfd_vma) value, where);
+ 	  break;
+ 
+ 	case BFD_RELOC_I51_11:
+ 	  value = (((value & 0x0700) << 5) | (value & 0x00FF));
+ 	  value |= insn;
+ 	  bfd_putb16 ((bfd_vma) value, where);
+ 	  break;
+ 
+ 	default:
+ 	  as_fatal (_("line %d: unknown relocation type: 0x%x"),
+ 		    fixp->fx_line, fixp->fx_r_type);
+ 	  break;
+ 	}
+     }
+   else
+     {
+       switch (fixp->fx_r_type)
+ 	{
+ 	default:
+ 	  break;
+ 	}
+       fixp->fx_addnumber = value;
+     }
+   return 0;
+ }
+ 
+ /* 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 (type, litp, sizep)
+      int type;
+      char *litp;
+      int *sizep;
+ {
+   int prec;
+   LITTLENUM_TYPE words[4];
+   char *t;
+   int i;
+ 
+   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 = 0; i < prec; i++)
+ 	{
+ 	  md_number_to_chars (litp, (valueT) words[i], 2);
+ 	  litp += 2;
+ 	}
+     }
+   else
+     {
+       for (i = prec - 1; i >= 0; i--)
+ 	{
+ 	  md_number_to_chars (litp, (valueT) words[i], 2);
+ 	  litp += 2;
+ 	}
+     }
+ 
+   return NULL;
+ }
+ 
+ static void
+ i51_bit (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   expressionS exp;
+ 
+   if (is_it_end_of_statement ())
+     {
+       demand_empty_rest_of_line ();
+       return;
+     }
+ 
+   do
+     {
+       TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) 1);
+       if (exp.X_op == O_constant)
+ 	{
+ 	  if ((exp.X_add_number > 1) || (exp.X_add_number < 0))
+ 	    {
+ 	      as_bad (_("bit value is not in range 0..1 %ld"), exp.X_add_number);
+ 	      return;
+ 	    }
+ 	}
+       emit_expr (&exp, (unsigned int) 1);
+     }
+   while (*input_line_pointer++ == ',');
+ 
+   input_line_pointer--;		/* Put terminator back into stream.  */
+ 
+   demand_empty_rest_of_line ();
+ }
+ 
+ symbolS *
+ md_undefined_symbol (name)
+      char *name;
+ {
+   extract_op (name, op, sizeof (op));
+   oper = (struct i51_directop_s *) hash_find (i51_operand, op);
+   if (oper == NULL) return 0;
+   if ((oper->ref == 'D') || (oper->ref == 'B'))
+     {
+       return (symbol_new (name, absolute_section, oper->value, &zero_address_frag));
+     }
+   else if (oper->ref == 'U')
+     {
+       if (regbank == 0xFF)
+ 	{
+ 	  as_bad (_("missing .using"));
+ 	  return 0;
+ 	}
+       return (symbol_new (name, absolute_section, regbank + oper->value, &zero_address_frag));
+     }
+   else return 0;
+ }
+ 
+ void
+ md_convert_frag (abfd, sec, fragP)
+      bfd *abfd ATTRIBUTE_UNUSED;
+      asection *sec ATTRIBUTE_UNUSED;
+      fragS *fragP ATTRIBUTE_UNUSED;
+ {
+   abort ();
+ }
+ 
+ /* A `BFD_ASSEMBLER' GAS will call this to generate a reloc.  GAS
+    will pass the resulting reloc to `bfd_install_relocation'.  This
+    currently works poorly, as `bfd_install_relocation' often does the
+    wrong thing, and instances of `tc_gen_reloc' have been written to
+    work around the problems, which in turns makes it difficult to fix
+    `bfd_install_relocation'.  */
+ 
+ /* If while processing a fixup, a reloc really needs to be created
+    then it is done here.  */
+ 
+ arelent *
+ tc_gen_reloc (seg, fixp)
+      asection *seg ATTRIBUTE_UNUSED;
+      fixS *fixp;
+ {
+   arelent *reloc;
+ 
+   reloc = (arelent *) xmalloc (sizeof (arelent));
+ 
+   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ 
+   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+   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,
+ 		    _("reloc %d not supported by object file format"),
+ 		    (int) fixp->fx_r_type);
+       return NULL;
+     }
+ 
+   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+      reloc->address = fixp->fx_offset;
+ 
+   reloc->addend = fixp->fx_offset;
+ 
+   if (fixp->fx_pcrel)
+     reloc->addend -= 1;
+ 
+   return reloc;
+ }
+ 
+ void
+ i51_parse_operand1 (void)
+ {
+   int temp;
+ 
+   input_line_pointer = line;
+   line = extract_op (line, op, sizeof (op));
+   oper = (struct i51_directop_s *) hash_find (i51_operand, op);
+   op1hlmode = 0;
+   if (oper == NULL)
+     {
+       if (op[0] == '@')
+ 	{
+ 	  as_bad (_("indirect prefix not allowed 1: `%s'"), op);
+ 	  return;
+ 	}
+       else if (op[0] == '#')
+ 	{
+ 	  input_line_pointer++;
+ 	  op1mode = '#';                     /* # - #data */
+ 
+ 	  //scan hi/low prefix
+ 	  if      (strncmp (input_line_pointer, "HIGH(", 5) == 0) { input_line_pointer += 4; op1hlmode = I51_OP_HIGH_ADDR;}
+ 	  else if (strncmp (input_line_pointer, "LOW(",  4) == 0) { input_line_pointer += 3; op1hlmode = I51_OP_LOW_ADDR;}
+ 
+ 	  while (((opcode->insn_size & 0x80) == 0) && ( opcode->args[0] != op1mode)) opcode++;
+ 	  if (opcode->args[0] != op1mode)
+ 	    {
+ 	      as_bad (_("direct prefix not allowed 1: `%s'"), op);
+ 	      return;
+ 	    }
+ 	} 
+       else
+ 	{
+ 	  op1mode = ' ';
+ 
+ 	  //scan hi/low prefix
+ 	  if      (strncmp (input_line_pointer, "HIGH(", 5) == 0) { input_line_pointer += 4; op1hlmode = I51_OP_HIGH_ADDR;}
+ 	  else if (strncmp (input_line_pointer, "LOW(",  4) == 0) { input_line_pointer += 3; op1hlmode = I51_OP_LOW_ADDR;}
+ 	  else if (strncmp (input_line_pointer, "B2B(",  4) == 0) { input_line_pointer += 4; op1hlmode = I51_OP_B2B;}
+ 
+ 	  while (((opcode->insn_size & 0x80) == 0) && 
+ 		 ( opcode->args[0] != 'B') && /* B - bit */
+ 		 ( opcode->args[0] != 'D') && /* D - data */
+ 		 ( opcode->args[0] != 'J') && /* J - jump rel */
+ 		 ( opcode->args[0] != '1') && /* 1 - jump addr 11 */
+ 		 ( opcode->args[0] != '6')    /* 6 - jump addr 16 */
+ 		 ) opcode++;
+ 	}
+       if ((opcode->insn_size & 0x80) != 0)
+ 	{
+ 	  op1mode = opcode->args[0];
+ 	}
+       else if (( opcode->args[0] != 'B') && ( opcode->args[0] != 'D'))
+ 	{
+ 	  op1mode = opcode->args[0];
+ 	}
+       //PARSE EXPRESION 1
+       expression (&op_expr1);
+       if (op_expr1.X_op == O_absent)
+ 	{
+ 	  as_bad (_("missing operand 1"));
+ 	  return;
+ 	}
+ 
+       if (op1hlmode == I51_OP_B2B)
+ 	{
+ 	  SKIP_WHITESPACE ();
+ 	  if (*input_line_pointer != ',')
+ 	    {
+ 	      as_bad (_("Expected comma after symbol-name"));
+ 	      ignore_rest_of_line ();
+ 	      return;
+ 	    }
+ 	  input_line_pointer++;		/* skip ',' */
+ 	  if ((temp = get_absolute_expression ()) < 0)
+ 	    {
+ 	      as_bad (_("BYTE2BIT offset (%d.) <0! Ignored."), temp);
+ 	      ignore_rest_of_line ();
+ 	      return;
+ 	    }
+ 	  SKIP_WHITESPACE ();
+ 	  if (*input_line_pointer != ')')
+ 	    {
+ 	      as_bad (_("Expected ) after offset"));
+ 	      ignore_rest_of_line ();
+ 	      return;
+ 	    }
+ 	  input_line_pointer++;		/* skip ')' */
+ 	  b2b_offset = temp;
+ 	}
+ 
+       line = input_line_pointer;
+ 
+ #ifdef ASMDBG
+       fprintf(stderr, "op1: %c %s\n", op1mode, op);
+       //fprintf(stderr, "op1: %c %s %s\n", op1mode, op, S_GET_NAME(op_expr1.X_add_symbol));
+ #endif
+     }
+   else
+     {
+       op1mode = oper->ref;
+       if(op1mode == 'U') op1mode = 'D';
+       while (((opcode->insn_size & 0x80) == 0) && ( opcode->args[0] != op1mode)) opcode++;
+       if (opcode->args[0] != op1mode)
+ 	{
+ 	  as_bad (_("unknown instruction operand 1: `%s'"), op);
+ 	  return;
+ 	}
+       if ((op1mode == 'R') || (op1mode == 'I'))
+ 	{
+ 	  regno = oper->value;
+ 	}
+       else if (oper->ref == 'U')
+ 	{
+ 	  if (regbank == 0xFF)
+ 	    {
+ 	      as_bad (_("missing .using"));
+ 	      return;
+ 	    }
+ 	  op_expr1.X_op = O_constant;
+ 	  op_expr1.X_add_number = regbank + oper->value;
+ 	}
+       else if ((op1mode == 'D') || (op1mode == 'B'))
+ 	{
+ 	  op_expr1.X_op = O_constant;
+ 	  op_expr1.X_add_number = oper->value;
+ 	}
+ #ifdef ASMDBG
+       fprintf(stderr, "op1: %c %s\n", op1mode, op);
+ #endif
+     }
+ }
+ 
+ void
+ i51_parse_operand2 (void)
+ {
+   int temp;
+ 
+   input_line_pointer = line;
+   line = extract_op (line, op, sizeof (op));
+   oper = (struct i51_directop_s *) hash_find (i51_operand, op);
+   op2hlmode = 0;
+   if (oper == NULL)
+     {
+       if (op[0] == '@')
+ 	{
+ 	  as_bad (_("indirect prefix not allowed 2: `%s'"), op);
+ 	  return;
+ 	}
+       else if (op[0] == '#')
+ 	{
+ 	  input_line_pointer++;
+ 	  op2mode = op[0];   /* # - #data */
+ 
+ 	  //scan hi/low prefix
+ 	  if      (strncmp (input_line_pointer, "HIGH(", 5) == 0) { input_line_pointer += 4; op2hlmode = I51_OP_HIGH_ADDR;}
+ 	  else if (strncmp (input_line_pointer, "LOW(",  4) == 0) { input_line_pointer += 3; op2hlmode = I51_OP_LOW_ADDR;}
+ 
+ 	  while (((opcode->insn_size & 0x80) == 0) && ( opcode->args[1] != op2mode)) opcode++;
+ 	  if (opcode->args[1] != op2mode)
+ 	    {
+ 	      as_bad (_("direct prefix not allowed 2: `%s'"), op);
+ 	      return;
+ 	    }
+ 	  if (op1mode == ' ') op1mode = 'D';
+ 	} 
+       else if (op[0] == '/')
+ 	{
+ 	  op2mode = op[0];   /* - - /bit  */
+ 	  while (((opcode->insn_size & 0x80) == 0) && ( opcode->args[1] != op2mode)) opcode++;
+ 	  if (opcode->args[1] != op2mode)
+ 	    {
+ 	      as_bad (_("negation prefix not allowed 2: `%s'"), op);
+ 	      return;
+ 	    }
+ 	  if (op1mode == ' ') op1mode = 'B';
+ 	  input_line_pointer++;
+ 	} 
+       else
+ 	{
+ 	  //op2mode = ' ';
+ 
+ 	  //scan hi/low prefix
+ 	  if      (strncmp (input_line_pointer, "HIGH(", 5) == 0)
+ 	    {
+ 	      input_line_pointer += 4;
+ 	      op2hlmode = I51_OP_HIGH_ADDR;
+ 	    }
+ 	  else if (strncmp (input_line_pointer, "LOW(",  4) == 0)
+ 	    {
+ 	      input_line_pointer += 3;
+ 	      op2hlmode = I51_OP_LOW_ADDR;
+ 	    }
+ 	  else if ((op_expr1.X_op == O_max) && (strncmp (input_line_pointer, "B2B(",  4) == 0))
+ 	    {
+ 	      input_line_pointer += 4;
+ 	      op2hlmode = I51_OP_B2B;
+ 	    }
+ 
+ 	  while (((opcode->insn_size & 0x80) == 0) && 
+ 		 ( opcode->args[1] != 'B') && /* B - bit */
+ 		 ( opcode->args[1] != 'D') && /* D - data */
+ 		 ( opcode->args[1] != 'J') && /* J - jump rel */
+ 		 ( opcode->args[1] != 'd')    /* d - data16 */
+ 		 ) opcode++;
+ 	}
+       op2mode = opcode->args[1];
+       
+       if (op1mode == ' ') op1mode = opcode->args[0];
+ 
+       //PARSE EXPRESION 1 / 2
+       if (op_expr1.X_op == O_max)
+ 	{
+ 	  op1hlmode = op2hlmode;
+ 	  expression (&op_expr1);
+ 	  if (op_expr1.X_op == O_absent)
+ 	    {
+ 	      as_bad (_("missing operand 2"));
+ 	      return;
+ 	    }
+ 	  if (op2hlmode == I51_OP_B2B)
+ 	    {
+ 	      SKIP_WHITESPACE ();
+ 	      if (*input_line_pointer != ',')
+ 		{
+ 		  as_bad (_("Expected comma after symbol-name"));
+ 		  ignore_rest_of_line ();
+ 		  return;
+ 		}
+ 	      input_line_pointer++;		/* skip ',' */
+ 	      if ((temp = get_absolute_expression ()) < 0)
+ 		{
+ 		  as_bad (_("BYTE2BIT offset (%d.) <0! Ignored."), temp);
+ 		  ignore_rest_of_line ();
+ 		  return;
+ 		}
+ 	      SKIP_WHITESPACE ();
+ 	      if (*input_line_pointer != ')')
+ 		{
+ 		  as_bad (_("Expected ) after offset"));
+ 		  ignore_rest_of_line ();
+ 		  return;
+ 		}
+ 	      input_line_pointer++;		/* skip ')' */
+ 	      b2b_offset = temp;
+ 	    }
+ 	}
+       else
+ 	{
+ 	  expression (&op_expr2);
+ 	  if (op_expr2.X_op == O_absent)
+ 	    {
+ 	      as_bad (_("missing operand 2"));
+ 	      return;
+ 	    }
+ 	}
+ 
+       line = input_line_pointer;
+ 
+ #ifdef ASMDBG
+       fprintf(stderr, "op2: %c %s\n", op2mode, op);
+ #endif
+     }
+   else
+     {
+       op2mode = oper->ref;
+       if(op2mode == 'U') op2mode = 'D';
+       while (((opcode->insn_size & 0x80) == 0) && ( opcode->args[1] != op2mode)) opcode++;
+       if (opcode->args[1] != op2mode)
+ 	{
+ 	  as_bad (_("unknown instruction operand 2: `%s'"), op);
+ 	  return;
+ 	}
+       if ((opcode->args[0] != op1mode) &&
+ 	  ((op1mode != ' ') || ((opcode->args[0] != 'B') && (opcode->args[0] != 'D'))) )
+ 	{
+ 	  as_bad (_("unknown instruction operand 2: `%s'"), op);
+ 	  return;
+ 	}
+       if (op1mode == ' ') op1mode = opcode->args[0];
+       if ((op2mode == 'R') || (op2mode == 'I'))
+ 	{
+ 	  regno = oper->value;
+ 	}
+       else if (oper->ref == 'U')
+ 	{
+ 	  if (regbank == 0xFF)
+ 	    {
+ 	      as_bad (_("missing .using"));
+ 	      return;
+ 	    }
+ 	  if (op_expr1.X_op == O_max)
+ 	    {
+ 	      op_expr1.X_op = O_constant;
+ 	      op_expr1.X_add_number = regbank + oper->value;
+ 	    }
+ 	  else
+ 	    {
+ 	      op_expr2.X_op = O_constant;
+ 	      op_expr2.X_add_number = regbank + oper->value;
+ 	    }
+ 	}
+       else if ((op2mode == 'D') || (op2mode == 'B'))
+ 	{
+ 	  if (op_expr1.X_op == O_max)
+ 	    {
+ 	      op_expr1.X_op = O_constant;
+ 	      op_expr1.X_add_number = oper->value;
+ 	    }
+ 	  else
+ 	    {
+ 	      op_expr2.X_op = O_constant;
+ 	      op_expr2.X_add_number = oper->value;
+ 	    }
+ 	}
+ #ifdef ASMDBG
+       fprintf(stderr, "op2: %c %s\n", op2mode, op);
+ #endif
+     }
+ }
+ 
+ void
+ i51_build_ins (opcode, regnumber, op_expr1, op_expr2)
+   struct i51_opcodes_s *opcode;
+   unsigned char regnumber;
+   expressionS *op_expr1;
+   expressionS *op_expr2;
+ {
+   unsigned char bin_opcode;
+   char *frag;
+ 
+   bin_opcode = opcode->bin_opcode;
+   /* place register operand to instruction code */
+   switch (opcode->mreloc) {
+   case 'I':			// register indirect            - IIIIIIIr
+   case 'i':			// reg. indirect, data          - IIIIIIIr dddddddd
+   case 'X':			// reg. indirect, r. jump 8 bit - IIIIIIIr dddddddd aaaaaaaa
+     regnumber &= 0x01;
+     bin_opcode |= regnumber;
+     break;
+   case 'R':			// register                     - IIIIIrrr
+   case 'r':			// register,data                - IIIIIrrr dddddddd
+   case 'Y':			// register, rel. jump 8 bit    - IIIIIrrr dddddddd aaaaaaaa
+   case 'W':			// register, rel. jump 8 bit    - IIIIIrrr aaaaaaaa
+     regnumber &= 0x07;
+     bin_opcode |= regnumber;
+     break;
+   default:
+     break;
+   }
+ 
+   switch (opcode->mreloc) {
+   case '7':			//relative jump 8 bit          - IIIIIIII aaaaaaaa
+   case 'W':			//register, rel. jump 8 bit    - IIIIIrrr aaaaaaaa
+   case '1':			//jump 11 bit                  - aaaIIIII aaaaaaaa
+   case '6':			//data/jump 16 bit             - IIIIIIII aaaaaaaa aaaaaaaa
+     if (op1hlmode)
+       {
+ 	as_bad (_("HI/LOW/B2B prefix not allowed"));
+ 	return;
+       }
+   default:
+     break;
+   }
+ 
+   switch (opcode->mreloc) {
+   case 'N':			//none                - IIIIIIII
+   case 'I':			//register indirect   - IIIIIIIr
+   case 'R':			//register            - IIIIIrrr
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     break;
+ 
+   case 'D':			//data 8 bit                   - IIIIIIII dddddddd
+   case 'i':			//reg. indirect, data          - IIIIIIIr dddddddd
+   case 'r':			//register,data                - IIIIIrrr dddddddd
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_IMM8, op1hlmode);
+     break;
+ 
+   case '7':			//relative jump 8 bit          - IIIIIIII aaaaaaaa
+   case 'W':			//register, rel. jump 8 bit    - IIIIIrrr aaaaaaaa
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_JUMP_REL, 0);
+     break;
+ 
+   case '1':			//jump 11 bit                  - aaaIIIII aaaaaaaa
+     fixup11(op_expr1, bin_opcode, I51_OP_JUMP_INPAGE, 0);
+     break;
+ 
+   case 'B':			//bitdata 8 bit                - IIIIIIII bbbbbbbb
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_BIT, op1hlmode);
+     break;
+ 
+   case 'd':			//data,data 8 bit              - IIIIIIII dddddddd dddddddd
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr2, I51_OP_IMM8, op2hlmode);
+     fixup8 (op_expr1, I51_OP_IMM8, op1hlmode);
+     break;
+ 
+   case 'a':			//adr,data 8 bit               - IIIIIIII aaaaaaaa dddddddd
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_IMM8, op1hlmode);
+     fixup8 (op_expr2, I51_OP_IMM8, op2hlmode);
+     break;
+ 
+   case 'J':			//bit, r. jump 8 bit           - IIIIIIII bbbbbbbb aaaaaaaa
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_BIT, op1hlmode);
+     fixup8 (op_expr2, I51_OP_JUMP_REL, 0);
+     break;
+ 
+   case 'X':			//reg. indirect, r. jump 8 bit - IIIIIIIr dddddddd aaaaaaaa
+   case 'Y':			//register, rel. jump 8 bit    - IIIIIrrr dddddddd aaaaaaaa
+   case 'Z':			//data 8 bit, r. jump 8 bit    - IIIIIIII dddddddd aaaaaaaa
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup8 (op_expr1, I51_OP_IMM8, op1hlmode);
+     fixup8 (op_expr2, I51_OP_JUMP_REL, 0);
+     break;
+ 
+   case '6':			//data/jump 16 bit             - IIIIIIII aaaaaaaa aaaaaaaa
+     frag = frag_more (1);
+     number_to_chars_bigendian (frag, bin_opcode, 1);
+     fixup16 (op_expr1, I51_OP_IMM16, 0);
+     break;
+   }
+ }
+ 
+ /* Checks that the number 'num' fits for a given mode.  */
+ static int
+ check_range (num, mode)
+      long num;
+      int mode;
+ {
+   switch (mode)
+     {
+     case I51_OP_IMM8:
+     case I51_OP_BIT:
+       return (((num & 0xFFFFFF00) == 0) || ((num & 0xFFFFFF00) == 0xFFFFFF00)) ? 1 : 0;
+ 
+     case I51_OP_JUMP_REL:
+       return (num >= -128 && num <= 127) ? 1 : 0;
+ 
+     case I51_OP_JUMP_INPAGE:
+       return ((num & 0xFFFFF800) == 0);
+ 
+     case I51_OP_IMM16:
+     case I51_OP_HIGH_ADDR:
+       return (((num & 0xFFFF0000) == 0) || ((num & 0xFFFF0000) == 0xFFFF0000)) ? 1 : 0;
+ 
+     case I51_OP_LOW_ADDR:
+       return 1;
+ 
+     default:
+       return 0;
+     }
+ }
+ 
+ /* Gas fixup generation.  */
+ 
+ /* Put a 1 byte expression described by 'oper'.  If this expression contains
+    unresolved symbols, generate an 8-bit fixup.  */
+ static void
+ fixup8 (oper, mode, opmode)
+      expressionS *oper;
+      int mode;
+      int opmode;
+ {
+   char *f;
+ 
+   f = frag_more (1);
+ 
+   if (oper->X_op == O_constant)
+     {
+       switch (opmode) {
+       case I51_OP_HIGH_ADDR:
+ 	if (!check_range (oper->X_add_number, opmode))
+ 	  {
+ 	    as_bad (_("HIGH Operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	number_to_chars_bigendian (f, ((oper->X_add_number >> 8)) & 0xFF, 1);
+ 	break;
+       case I51_OP_LOW_ADDR:
+ 	if (!check_range (oper->X_add_number, opmode))
+ 	  {
+ 	    as_bad (_("LOW Operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	number_to_chars_bigendian (f, (oper->X_add_number & 0xFF), 1);
+ 	break;
+       case I51_OP_B2B:
+ 	if ((oper->X_add_number < 0x20) ||
+ 	    ((oper->X_add_number < 0x30) && (((oper->X_add_number - 0x20) * 8 + b2b_offset) > 0x80)) ||
+ 	    ((oper->X_add_number >= 0x30) && (oper->X_add_number < 0x80)) ||
+ 	    ((oper->X_add_number + b2b_offset) > 0x100) )
+ 	  {
+ 	    as_bad (_("Operand out of bit range: B2B(%ld,%d)."),
+ 		    oper->X_add_number, b2b_offset);
+ 	  }
+ 	if (oper->X_add_number < 0x30)
+ 	  {
+ 	    number_to_chars_bigendian (f, ((oper->X_add_number - 0x20) * 8 + b2b_offset), 1);
+ 	  }
+ 	else
+ 	  {
+ 	    number_to_chars_bigendian (f, (oper->X_add_number + b2b_offset), 1);
+ 	  }
+ 	break;
+       default:
+ 	if (!check_range (oper->X_add_number, mode))
+ 	  {
+ 	    as_bad (_("Operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	number_to_chars_bigendian (f, (oper->X_add_number & 0xFF), 1);
+ 	break;
+       }
+     }
+   else if (oper->X_op != O_register)
+     {
+       switch (mode) {
+       case I51_OP_IMM8:
+ 	/* Now create an 8-bit fixup.  If there was some %hi or %lo
+ 	 modifier, generate the reloc accordingly.  */
+ 	fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 		     oper, false,
+ 		     ((opmode & I51_OP_HIGH_ADDR)
+ 		      ? BFD_RELOC_I51_8_HIGH
+ 		      : ((opmode & I51_OP_LOW_ADDR)
+ 			 ? BFD_RELOC_I51_8_LOW : BFD_RELOC_8)));
+ 	number_to_chars_bigendian (f, 0, 1);
+ 	break;
+       case I51_OP_JUMP_REL:
+ 	/* Now create an 8-bit relative jump fixup */
+ 	fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 		     oper, true, BFD_RELOC_I51_7_PCREL);
+ 	number_to_chars_bigendian (f, 0, 1);
+ 	break;
+       case I51_OP_BIT:
+ 	/* Now create an 8-bit bit B2B area fixup */
+ 	fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 		     oper, false,
+ 		     (opmode & I51_OP_B2B 
+ 		      ? BFD_RELOC_I51_8_B2B : BFD_RELOC_I51_8_BIT));
+ 	number_to_chars_bigendian (f, (opmode & I51_OP_B2B
+ 				       ? b2b_offset : 0), 1);
+ 	break;
+       }
+     }
+   else
+     {
+       as_fatal (_("Operand `%x' not recognized in fixup8."), oper->X_op);
+     }
+ }
+ 
+ /* Put a 11 bit expression described by 'oper'.  If this expression contains
+    unresolved symbols, generate an 11-bit fixup.  */
+ static void
+ fixup11 (oper, opcode, mode, opmode)
+      expressionS *oper;
+      unsigned int opcode;
+      int mode;
+      int opmode ATTRIBUTE_UNUSED;
+ {
+   char *f;
+ 
+   f = frag_more (2);
+ 
+   if (oper->X_op == O_constant)
+     {
+       if (!check_range (oper->X_add_number, mode))
+ 	{
+ 	  as_bad (_("Operand out of 11-bit range: `%ld'."),
+ 		  oper->X_add_number);
+ 	}
+       number_to_chars_bigendian (f, ((oper->X_add_number & 0x0700) << 5) | (opcode << 8) | (oper->X_add_number & 0x00FF), 2);
+     }
+   else if (oper->X_op != O_register)
+     {
+       switch (mode) {
+       case I51_OP_JUMP_INPAGE:
+ 	/* Now create an 11-bit inpage jump fixup */
+ 	fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 		     oper, false,BFD_RELOC_I51_11);
+ 	number_to_chars_bigendian (f, (opcode << 8), 2);
+ 	break;
+       }
+     }
+   else
+     {
+       as_fatal (_("Operand `%x' not recognized in fixup8."), oper->X_op);
+     }
+ }
+ 
+ /* Put a 2 byte expression described by 'oper'.  If this expression contains
+    unresolved symbols, generate a 16-bit fixup.  */
+ static void
+ fixup16 (oper, mode, opmode)
+      expressionS *oper;
+      int mode;
+      int opmode ATTRIBUTE_UNUSED;
+ {
+   char *f;
+ 
+   f = frag_more (2);
+ 
+   if (oper->X_op == O_constant)
+     {
+       if (!check_range (oper->X_add_number, mode))
+ 	{
+ 	  as_bad (_("Operand out of 16-bit range: `%ld'."),
+ 		  oper->X_add_number);
+ 	}
+       number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFF, 2);
+     }
+   else if (oper->X_op != O_register)
+     {
+       fixS *fixp;
+ 
+       /* Now create a 16-bit fixup.  */
+       fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ 			  oper,
+ 			  false,
+ 			  BFD_RELOC_16);
+       number_to_chars_bigendian (f, 0, 2);
+     }
+   else
+     {
+       as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
+     }
+ }
+ 
+ int
+ i51_section_flags (flags, attr, type)
+      int flags;
+      int attr;
+      int type ATTRIBUTE_UNUSED;
+ {
+   if (attr & SHF_REGBANK)
+     flags |= SEC_IS_COMMON;
+ 
+   return flags;
+ }
+ 
+ static void
+ i51_using (par)
+      int par ATTRIBUTE_UNUSED;
+ {
+   switch (*input_line_pointer++)
+     {
+     case '0':  /* Reg bank 0 */
+       regbank = 0;
+       break;
+     case '1':  /* Reg bank 1 */
+       regbank = 8;
+       break;
+     case '2':  /* Reg bank 2 */
+       regbank = 16;
+       break;
+     case '3':  /* Reg bank 3 */
+       regbank = 24;
+       break;
+     default:
+       as_bad ("unsupported register bank");
+       return;
+     }
+   if (regbank > regused) regused = regbank;
+ }
+ 
+ /*
+ void
+ i51_set (name)
+      char *name;
+ {
+   register symbolS *symbolP;
+ 
+   if ((symbol_find (name) == NULL) && (md_undefined_symbol (name) == NULL))
+     {
+ 	symbolP = symbol_new (name, absolute_section, 0, &zero_address_frag);
+ 	symbol_table_insert (symbolP);
+     }
+ }
+ */
+ 
+ void
+ i51_cleanup ()
+ {
+   symbolS *symbolP;
+ 
+   if (regbank != 0xFF)
+     {
+ 
+   symbolP = symbol_find_or_make ("__RB__");
+ 
+   S_SET_VALUE (symbolP, (valueT) regused+8);
+   S_SET_EXTERNAL (symbolP);
+   S_SET_SEGMENT (symbolP, &scom_section);
+ 
+   know (symbolP->sy_frag == &zero_address_frag);
+ 
+       regbank = 0xFF;
+       regused = 0;
+     }
+ }
+ 
+ void
+ i51_common (common_segment)
+      int common_segment;
+ {
+   char *name;
+   char c;
+   char *p;
+   int temp, size;
+   symbolS *symbolP;
+   int align;
+ 
+   if (flag_mri)
+     {
+       as_bad (_("not implemented in MRI mode"));
+       return;
+     }
+ 
+   name = input_line_pointer;
+   c = get_symbol_end ();
+   /* just after name is now '\0' */
+   p = input_line_pointer;
+   *p = c;
+   SKIP_WHITESPACE ();
+   if (*input_line_pointer != ',')
+     {
+       as_bad (_("Expected comma after symbol-name"));
+       ignore_rest_of_line ();
+       return;
+     }
+   input_line_pointer++;		/* skip ',' */
+   if ((temp = get_absolute_expression ()) < 0)
+     {
+       as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+       ignore_rest_of_line ();
+       return;
+     }
+   size = temp;
+   *p = 0;
+   symbolP = symbol_find_or_make (name);
+   *p = c;
+   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+     {
+       as_bad (_("Ignoring attempt to re-define symbol"));
+       ignore_rest_of_line ();
+       return;
+     }
+   if (S_GET_VALUE (symbolP) != 0)
+     {
+       if (S_GET_VALUE (symbolP) != (valueT) size)
+ 	{
+ 	  as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+ 		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ 	}
+     }
+   know (symbolP->sy_frag == &zero_address_frag);
+   if (*input_line_pointer != ',')
+     temp = 0;
+   else
+     {
+       input_line_pointer++;
+       SKIP_WHITESPACE ();
+       temp = get_absolute_expression ();
+       if (temp < 0)
+ 	{
+ 	  temp = 0;
+ 	  as_warn (_("Common alignment negative; 0 assumed"));
+ 	}
+     }
+   if (temp)
+     {
+       /* convert to a power of 2 alignment */
+       for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
+       if (temp != 1)
+ 	{
+ 	  as_bad (_("Common alignment not a power of 2"));
+ 	  ignore_rest_of_line ();
+ 	  return;
+ 	}
+     }
+   else
+     align = 0;
+   if (symbol_get_obj (symbolP)->local)
+     {
+       segT old_sec;
+       int old_subsec;
+       char *pfrag;
+       flagword applicable;
+ 
+       /* allocate_?bss: */
+       old_sec = now_seg;
+       old_subsec = now_subseg;
+ 
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+ 
+       switch (common_segment & 0x7F)
+ 	{
+ 	case 0: //comm
+ 	  record_alignment (bss_section, align);
+ 	  subseg_set (bss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == bss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, bss_section);
+ 	  break;
+ 	case 1: //rcomm
+ 	  if (rbss_section == NULL)
+ 	    {
+ 	      rbss_section = subseg_new (".rbss", 0);
+ 	      bfd_set_section_flags (stdoutput, rbss_section, applicable);
+ 	      seg_info (rbss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (rbss_section, align);
+ 	  subseg_set (rbss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == rbss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, rbss_section);
+ 	  break;
+ 	case 2: //bitcomm
+ 	  if (bitbss_section == NULL)
+ 	    {
+ 	      bitbss_section = subseg_new (".bitbss", 0);
+ 	      bfd_set_section_flags (stdoutput, bitbss_section, applicable);
+ 	      seg_info (bitbss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (bitbss_section, align);
+ 	  subseg_set (bitbss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == bitbss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, bitbss_section);
+ 	  break;
+ 	case 3: //icomm
+ 	  if (ibss_section == NULL)
+ 	    {
+ 	      ibss_section = subseg_new (".ibss", 0);
+ 	      bfd_set_section_flags (stdoutput, ibss_section, applicable);
+ 	      seg_info (ibss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (ibss_section, align);
+ 	  subseg_set (ibss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == ibss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, ibss_section);
+ 	  break;
+ 	case 4: //xcomm
+ 	  if (xbss_section == NULL)
+ 	    {
+ 	      xbss_section = subseg_new (".xbss", 0);
+ 	      bfd_set_section_flags (stdoutput, xbss_section, applicable);
+ 	      seg_info (xbss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (xbss_section, align);
+ 	  subseg_set (xbss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == xbss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, xbss_section);
+ 	  break;
+ 	case 5: //ecomm
+ 	  if (ebss_section == NULL)
+ 	    {
+ 	      ebss_section = subseg_new (".ebss", 0);
+ 	      bfd_set_section_flags (stdoutput, ebss_section, applicable);
+ 	      seg_info (ebss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (ebss_section, align);
+ 	  subseg_set (ebss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == ebss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, ebss_section);
+ 	  break;
+ 	case 6: //bcomm
+ 	  if (bbss_section == NULL)
+ 	    {
+ 	      bbss_section = subseg_new (".bbss", 0);
+ 	      bfd_set_section_flags (stdoutput, bbss_section, applicable);
+ 	      seg_info (bbss_section)->bss = 1;
+ 	    }
+ 	  record_alignment (bbss_section, align);
+ 	  subseg_set (bbss_section, 0);
+ 	  if (align)
+ 	    frag_align (align, 0, 0);
+ 	  if (S_GET_SEGMENT (symbolP) == bbss_section)
+ 	    symbol_get_frag (symbolP)->fr_symbol = 0;
+ 	  symbol_set_frag (symbolP, frag_now);
+ 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ 			    (offsetT) size, (char *) 0);
+ 	  *pfrag = 0;
+ 	  S_SET_SIZE (symbolP, size);
+ 	  S_SET_SEGMENT (symbolP, bbss_section);
+ 	  break;
+ 	}
+       S_CLEAR_EXTERNAL (symbolP);
+       subseg_set (old_sec, old_subsec);
+     }
+   else
+     {
+       S_SET_VALUE (symbolP, (valueT) size);
+       S_SET_ALIGN (symbolP, temp);
+       S_SET_EXTERNAL (symbolP);
+       switch (common_segment) {
+       case 0: //comm
+ 	S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+ 	break;
+       case 1: //rcomm
+ 	S_SET_SEGMENT (symbolP, &rcom_section);
+ 	break;
+       case 2: //bitcomm
+ 	S_SET_SEGMENT (symbolP, &bitcom_section);
+ 	break;
+       case 3: //icomm
+ 	S_SET_SEGMENT (symbolP, &icom_section);
+ 	break;
+       case 4: //xcomm
+ 	S_SET_SEGMENT (symbolP, &xcom_section);
+ 	break;
+       case 5: //ecomm
+ 	S_SET_SEGMENT (symbolP, &ecom_section);
+ 	break;
+       case 6: //bcomm
+ 	S_SET_SEGMENT (symbolP, &bcom_section);
+ 	break;
+       }
+     }
+   
+   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
+ 
+   demand_empty_rest_of_line ();
+   return;
+ }
+ 
+ void
+ i51_rbss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (rbss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       rbss_section = subseg_new (".rbss", 0);
+       bfd_set_section_flags (stdoutput, rbss_section, applicable);
+       seg_info (rbss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (rbss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_bss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   obj_elf_section_change_hook ();
+   subseg_set (bss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_bbss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (bbss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       bbss_section = subseg_new (".bbss", 0);
+       bfd_set_section_flags (stdoutput, bbss_section, applicable);
+       seg_info (bbss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (bbss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_ibss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (ibss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       ibss_section = subseg_new (".ibss", 0);
+       bfd_set_section_flags (stdoutput, ibss_section, applicable);
+       seg_info (ibss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (ibss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_xbss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (xbss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       xbss_section = subseg_new (".xbss", 0);
+       bfd_set_section_flags (stdoutput, xbss_section, applicable);
+       seg_info (xbss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (xbss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_ebss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (ebss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       ebss_section = subseg_new (".ebss", 0);
+       bfd_set_section_flags (stdoutput, ebss_section, applicable);
+       seg_info (ebss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (ebss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_bitbss (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (bitbss_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= SEC_ALLOC;
+       bitbss_section = subseg_new (".bitbss", 0);
+       bfd_set_section_flags (stdoutput, bitbss_section, applicable);
+       seg_info (bitbss_section)->bss = 1;
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (bitbss_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_rdata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (rdata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       rdata_section = subseg_new (".rdata", 0);
+       bfd_set_section_flags (stdoutput, rdata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (rdata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_bdata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (bdata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       bdata_section = subseg_new (".bdata", 0);
+       bfd_set_section_flags (stdoutput, bdata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (bdata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_idata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (idata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       idata_section = subseg_new (".idata", 0);
+       bfd_set_section_flags (stdoutput, idata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (idata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_xdata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (xdata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       xdata_section = subseg_new (".xdata", 0);
+       bfd_set_section_flags (stdoutput, xdata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (xdata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_edata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (edata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       edata_section = subseg_new (".edata", 0);
+       bfd_set_section_flags (stdoutput, edata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (edata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_bitdata (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (bitdata_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       bitdata_section = subseg_new (".bitdata", 0);
+       bfd_set_section_flags (stdoutput, bitdata_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (bitdata_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ i51_eeprom (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   flagword applicable;
+   if (eeprom_section == NULL)
+     {
+       applicable = bfd_applicable_section_flags (stdoutput);
+       applicable &= (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+       eeprom_section = subseg_new (".eeprom", 0);
+       bfd_set_section_flags (stdoutput, eeprom_section, applicable);
+     }
+   obj_elf_section_change_hook ();
+   subseg_set (eeprom_section, (subsegT) get_absolute_expression ());
+   demand_empty_rest_of_line ();
+ }
+ 
+ void
+ pcodeOperand (oper, mode, separator)
+      expressionS *oper;
+      enum PADRMODE *mode;
+      int separator;
+ {
+   SKIP_WHITESPACE ();
+   if ((*input_line_pointer != '\0') && (*input_line_pointer != '\x0D') && (*input_line_pointer != '\x0A') && (*input_line_pointer != ';'))
+     {
+       if (separator)
+ 	{
+ 	  if (*input_line_pointer != ',')
+ 	    {
+ 	      as_bad (_("Expected comma after pcode operand"));
+ 	      ignore_rest_of_line ();
+ 	      return;
+ 	    }
+ 	  input_line_pointer++;		/* skip ',' */
+ 	  SKIP_WHITESPACE ();
+ 	}
+       //search #, #BYTE, #SWAP, #SHL8, BYTE, SWAP, SHL8, @BYTE, @SWAP, @
+       if      (strncmp (input_line_pointer, "#BYTE", 5) == 0) { *mode = DIRECTBYTE; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "#SWAP", 5) == 0) { *mode = DIRECTSWAP; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "#SHL8", 5) == 0) { *mode = DIRECTSHL8; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "#WORD", 5) == 0) { *mode = DIRECTWORD; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "#",     1) == 0) { *mode = DIRECTWORD; input_line_pointer += 1; }
+       else if (strncmp (input_line_pointer, "BYTE",  4) == 0) { *mode = DIRECTBYTE; input_line_pointer += 4; }
+       else if (strncmp (input_line_pointer, "SWAP",  4) == 0) { *mode = DIRECTSWAP; input_line_pointer += 4; }
+       else if (strncmp (input_line_pointer, "SHL8",  4) == 0) { *mode = DIRECTSHL8; input_line_pointer += 4; }
+       else if (strncmp (input_line_pointer, "WORD",  4) == 0) { *mode = DIRECTWORD; input_line_pointer += 4; }
+       else if (strncmp (input_line_pointer, "@BYTE", 5) == 0) { *mode = INDIRECTBYTE; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "@SWAP", 5) == 0) { *mode = INDIRECTSWAP; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "@WORD", 5) == 0) { *mode = INDIRECTWORD; input_line_pointer += 5; }
+       else if (strncmp (input_line_pointer, "@",     1) == 0) { *mode = INDIRECTWORD; input_line_pointer += 1; }
+       else                                                    { *mode = DIRECTWORD; }
+       SKIP_WHITESPACE ();
+       expression (oper);
+     }
+   else
+     {
+       oper->X_op = O_constant;
+       oper->X_add_number = 0;
+       *mode = DIRECTBYTE;
+     }
+ }
+ 
+ 
+ void
+ writePcodeOperand (oper, mode, swapable)
+      expressionS *oper;
+      enum PADRMODE *mode;
+      int swapable ATTRIBUTE_UNUSED;
+ {
+   char *f;
+   fixS *fixp;
+ 
+   switch (*mode) {
+   case DIRECTBYTE:
+   case DIRECTSHL8:
+   case INDIRECTWORD:
+   case INDIRECTSWAP:
+     // byte mode
+       if (oper->X_op == O_constant)
+ 	{
+ 	  if (0x00FF & oper->X_add_number)
+ 	    {
+ 	      f = frag_more (1);
+ 	      number_to_chars_bigendian (f, 0x00FF & oper->X_add_number, 1);
+ 	    }
+ 	}
+       else
+ 	{
+ 	  f = frag_more (1);
+ 	  /* Now create a 8-bit fixup. */
+ 	  fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 			      oper,
+ 			      false,
+ 			      BFD_RELOC_8);
+ 	  number_to_chars_bigendian (f, 0, 1);
+ 	}
+       break;
+   case INDIRECTBYTE:
+     // indirect byte mode
+       if (oper->X_op == O_constant)
+ 	{
+ 	  if (0x00FF & oper->X_add_number)
+ 	    {
+ 	      f = frag_more (1);
+ 	      number_to_chars_bigendian (f, 0x00FF & (oper->X_add_number - 1), 1);
+ 	    }
+ 	}
+       else
+ 	{
+ 	  f = frag_more (1);
+ 	  /* Now create a 8-bit fixup. */
+ 	  fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
+ 			      oper,
+ 			      false,
+ 			      BFD_RELOC_8);
+ 	  number_to_chars_bigendian (f, -1, 1);
+ 	}
+       break;
+   case DIRECTWORD:
+     // word mode
+     if (oper->X_op == O_constant)
+       {
+ 	if (0xFF00 & oper->X_add_number)  //MSB
+ 	  {
+ 	    f = frag_more (1);
+ 	    number_to_chars_bigendian (f, 0x00FF & (oper->X_add_number >> 8), 1);
+ 	  }
+ 	if (0x00FF & oper->X_add_number)  //LSB
+ 	  {
+ 	    f = frag_more (1);
+ 	    number_to_chars_bigendian (f, 0x00FF & oper->X_add_number, 1);
+ 	  }
+       }
+     else
+       {
+ 	f = frag_more (2);
+ 	/* Now create a 16-bit fixup. */
+ 	fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ 			    oper,
+ 			    false,
+ 			    BFD_RELOC_16);
+ 	number_to_chars_bigendian (f, 0, 2);
+       }
+     break;
+   case DIRECTSWAP:
+     //direct swap word mode
+     if (oper->X_op == O_constant)
+       { //direct swap mode
+ 	if (0x00FF & oper->X_add_number)  //LSB
+ 	  {
+ 	    f = frag_more (1);
+ 	    number_to_chars_bigendian (f, 0x00FF & oper->X_add_number, 1);
+ 	  }
+ 	if (0xFF00 & oper->X_add_number)  //MSB
+ 	  {
+ 	    f = frag_more (1);
+ 	    number_to_chars_bigendian (f, 0x00FF & (oper->X_add_number >> 8), 1);
+ 	  }
+       }
+     else
+       {
+ 	f = frag_more (2);
+ 	/* Now create a 16-bit fixup. */
+ 	fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ 			    oper,
+ 			    false,
+ 			    BFD_RELOC_16);
+ 	number_to_chars_bigendian (f, 0, 2);
+       }
+     break;
+   }
+ }
+ 
+ unsigned short
+ decodePcodeOperand (oper, mode, swapable)
+      expressionS *oper;
+      enum PADRMODE *mode;
+      int swapable;
+ {
+   unsigned short pflags;
+ 
+   pflags = 0;
+ 
+   switch (*mode) {
+   case DIRECTBYTE:
+   case INDIRECTWORD:
+   case INDIRECTBYTE:
+     if (oper->X_op == O_constant)
+       {
+ 	if (!check_range (oper->X_add_number, I51_OP_IMM8))
+ 	  {
+ 	    as_bad (_("operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	if (0x00FF & oper->X_add_number)
+ 	  {
+ 	    pflags |= 0x40;
+ 	  }
+       }
+     else
+       {
+ 	pflags |= 0x40;
+       }
+     break;
+   case INDIRECTSWAP:
+     if (oper->X_op == O_constant)
+       {
+ 	if (!check_range (oper->X_add_number, I51_OP_IMM8))
+ 	  {
+ 	    as_bad (_("operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	if (0x00FF & oper->X_add_number)
+ 	  {
+ 	    pflags |= 0x40;   //allocate 8 bit
+ 	  }
+ 	pflags |= 0x02;       //set swap flag
+       }
+     else
+       {
+ 	if (swapable == 0)
+ 	  {
+ 	    as_bad (_("Pcode operand 2 isn't swapable"));
+ 	  }
+ 	pflags |= 0x42;       //allocate 8 bit and set swap flag
+       }
+     break;
+   case DIRECTSHL8:
+     if (oper->X_op == O_constant)
+       {
+ 	if (!check_range (oper->X_add_number, I51_OP_IMM8))
+ 	  {
+ 	    as_bad (_("operand out of 8-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	if (0x00FF & oper->X_add_number)
+ 	  {
+ 	    pflags |= 0x80;
+ 	  }
+       }
+     else
+       {
+ 	pflags |= 0x80;
+       }
+     break;
+   case DIRECTWORD:
+     //word mode
+     if (oper->X_op == O_constant)
+       {
+ 	if (!check_range (oper->X_add_number, I51_OP_IMM16))
+ 	  {
+ 	    as_bad (_("operand out of 16-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	//direct no swap mode
+ 	if (0xFF00 & oper->X_add_number) pflags |= 0x80; //MSB
+ 	if (0x00FF & oper->X_add_number) pflags |= 0x40; //LSB
+       }
+     else
+       {
+ 	pflags |= 0xC0;
+       }
+     break;
+   case DIRECTSWAP:
+     //word mode
+     if (oper->X_op == O_constant)
+       {
+ 	if (!check_range (oper->X_add_number, I51_OP_IMM16))
+ 	  {
+ 	    as_bad (_("operand out of 16-bit range: `%ld'."),
+ 		    oper->X_add_number);
+ 	  }
+ 	//direct swap mode (#SWAP)
+ 	if (0x00FF & oper->X_add_number) pflags |= 0x80; //LSB
+ 	if (0xFF00 & oper->X_add_number) pflags |= 0x40; //MSB
+ 	pflags |= 0x02;       //swap flag
+       }
+     else
+       {
+ 	if (swapable == 0)
+ 	  {
+ 	    as_bad (_("Pcode operand 2 isn't swapable"));
+ 	  }
+ 	pflags |= 0xC2;       //allocate 16 bit and set swap flag
+       }
+     break;
+   }
+   switch (*mode) {
+   case INDIRECTWORD:
+   case INDIRECTBYTE:
+   case INDIRECTSWAP:
+     pflags |= 0x8000;         //indirect flag
+   default:
+     break;
+   }
+   return pflags;
+ }
+ 
+ void
+ i51_pcode (ignore)
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   char *f;
+   unsigned short pflags;
+   unsigned short temppflags;
+ 
+   expression (&op_expr1);
+   pcodeOperand (&op_expr2, &p2mode, 0);
+   pcodeOperand (&op_expr3, &p3mode, 1);
+   pcodeOperand (&op_expr4, &p4mode, 1);
+   demand_empty_rest_of_line ();
+ 
+   pflags     = decodePcodeOperand (&op_expr2, &p2mode, 1);
+   temppflags = decodePcodeOperand (&op_expr3, &p3mode, 0);
+   pflags    |= (temppflags & 0x00C0) >> 2;                 //data allocation
+   pflags    |= (temppflags & 0x8000) >> 1;                 //indirect flag
+   temppflags = decodePcodeOperand (&op_expr4, &p4mode, 1);
+   pflags    |= (temppflags & 0x00C0) >> 4;                 //data allocation
+   pflags    |= (temppflags & 0x8000) >> 2;                 //indirect flag
+   pflags    |= (temppflags & 0x0002) >> 1;                 //swap flag
+ 
+   /* pcode exec address */
+   f = frag_more (2);
+   temppflags = pflags & 0xE000;
+   if (op_expr1.X_op == O_constant)
+     {
+       if (op_expr1.X_add_number > 0x1FFF)
+ 	{
+ 	  as_bad (_("Pcode exec address out of 13-bit range: `%ld'."),
+ 		  op_expr4.X_add_number);
+ 	}
+       if (op_expr1.X_add_number < 0x0100)
+ 	{
+ 	  as_bad (_("Pcode exec addrss uderflow: `%ld'."),
+ 		  op_expr4.X_add_number);
+ 	}
+       temppflags |= op_expr1.X_add_number & 0x1FFF;
+       number_to_chars_bigendian (f, temppflags, 2);
+     }
+   else if (op_expr1.X_op != O_register)
+     {
+       fixS *fixp;
+ 
+       /* Now create a 13-bit fixup.  */
+       fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
+ 			  &op_expr1,
+ 			  false,
+ 			  BFD_RELOC_I51_13_PCODE);
+       number_to_chars_bigendian (f, temppflags, 2);
+     }
+   else
+     {
+       as_fatal (_("Operand `%x' not recognized in pcode."), op_expr1.X_op);
+     }
+ 
+   /* pcode flags */
+   f = frag_more (1);
+   number_to_chars_bigendian (f, pflags & 0xFF, 1);
+   /* 1th pcode operand */
+   writePcodeOperand (&op_expr2, &p2mode, 1);
+   /* 2nd pcode operand */
+   writePcodeOperand (&op_expr3, &p3mode, 0);
+   /* 3th pcode operand */
+   writePcodeOperand (&op_expr4, &p4mode, 1);
+ }
diff -crN binutils.null/gas/config/tc-i51.h binutils-2.11.2.i51.new/gas/config/tc-i51.h
*** binutils.null/gas/config/tc-i51.h	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/gas/config/tc-i51.h	Sun Dec 30 10:49:56 2001
***************
*** 0 ****
--- 1,165 ----
+ /* This file is tc-i51.h
+    Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+    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, 59 Temple Place - Suite 330, Boston, MA
+    02111-1307, USA.  */
+ 
+ #ifndef BFD_ASSEMBLER
+  #error MCS-51 support requires BFD_ASSEMBLER
+ #endif
+ 
+ #define TC_I51
+ /*   By convention, you should define this macro in the `.h' file.  For
+      example, `tc-m68k.h' defines `TC_M68K'.  You might have to use this
+      if it is necessary to add CPU specific code to the object format
+      file.  */
+ 
+ #define TARGET_FORMAT "elf32-i51"
+ /*   This macro is the BFD target name to use when creating the output
+      file.  This will normally depend upon the `OBJ_FMT' macro.  */
+ 
+ #define TARGET_ARCH bfd_arch_i51
+ /*   This macro is the BFD architecture to pass to `bfd_set_arch_mach'.  */
+ 
+ #define TARGET_MACH 0
+ /*   This macro is the BFD machine number to pass to
+      `bfd_set_arch_mach'.  If it is not defined, GAS will use 0.  */
+ 
+ #define TARGET_BYTES_BIG_ENDIAN 1
+ /*   You should define this macro to be non-zero if the target is big
+      endian, and zero if the target is little endian.  */
+ 
+ #define ONLY_STANDARD_ESCAPES
+ /*   If you define this macro, GAS will warn about the use of
+      nonstandard escape sequences in a string.  */
+ 
+ /* Support for SHF_REGBANK */
+ extern int i51_section_flags PARAMS ((int, int, int));
+ 
+ //#define md_elf_section_letter(LETTER, PTR_MSG)	i51_section_letter (LETTER, PTR_MSG)
+ //#define md_elf_section_word(STR, LEN)		i51_section_word (STR, LEN)
+ #define md_elf_section_flags(FLAGS, ATTR, TYPE)	i51_section_flags (FLAGS, ATTR, TYPE)
+ 
+ #define md_operand(x)
+ /*   GAS will call this function for any expression that can not be
+      recognized.  When the function is called, `input_line_pointer'
+      will point to the start of the expression.  */
+ 
+ //void i51_parse_cons_expression (expressionS *exp, int nbytes);
+ //#define TC_PARSE_CONS_EXPRESSION(EXPR,N) avr_parse_cons_expression (EXPR,N)
+ /*
+      You may define this macro to parse an expression used in a data
+      allocation pseudo-op such as `.word'.  You can use this to
+      recognize relocation directives that may appear in such directives.*/
+ 
+ //void avr_cons_fix_new(fragS *frag,int where, int nbytes, expressionS *exp);
+ 
+ //#define TC_CONS_FIX_NEW(FRAG,WHERE,N,EXP) avr_cons_fix_new(FRAG,WHERE,N,EXP)
+ /*   You may define this macro to generate a fixup for a data
+      allocation pseudo-op.  */
+ 
+ #define md_number_to_chars number_to_chars_bigendian
+ /*   This should just call either `number_to_chars_bigendian' or
+      `number_to_chars_littleendian', whichever is appropriate.  On
+      targets like the MIPS which support options to change the
+      endianness, which function to call is a runtime decision.  On
+      other targets, `md_number_to_chars' can be a simple macro.  */
+ 
+ #define WORKING_DOT_WORD
+ /*
+ `md_short_jump_size'
+ `md_long_jump_size'
+ `md_create_short_jump'
+ `md_create_long_jump'
+      If `WORKING_DOT_WORD' is defined, GAS will not do broken word
+      processing (*note Broken words::.).  Otherwise, you should set
+      `md_short_jump_size' to the size of a short jump (a jump that is
+      just long enough to jump around a long jmp) and
+      `md_long_jump_size' to the size of a long jump (a jump that can go
+      anywhere in the function), You should define
+      `md_create_short_jump' to create a short jump around a long jump,
+      and define `md_create_long_jump' to create a long jump.  */
+ 
+ #define MD_APPLY_FIX3
+ 
+ //#define TC_HANDLES_FX_DONE
+ 
+ //#undef RELOC_EXPANSION_POSSIBLE
+ /*   If you define this macro, it means that `tc_gen_reloc' may return
+      multiple relocation entries for a single fixup.  In this case, the
+      return value of `tc_gen_reloc' is a pointer to a null terminated
+      array.  */
+ 
+ #define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+ /*   If you define this macro, it should return the offset between the
+      address of a PC relative fixup and the position from which the PC
+      relative adjustment should be made.  On many processors, the base
+      of a PC relative instruction is the next instruction, so this
+      macro would return the length of an instruction.  */
+ 
+ //extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+ 
+ /* Specific sections:
+      bit register area */
+ #define ELF_TC_SPECIAL_SECTIONS \
+   /* internal (onchip) memory */ \
+   /* 0x00..0x1F register, direct, indirect addresable */ \
+   { ".rdata",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE }, \
+   { ".rbss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE }, \
+   /* 0x20..0x2F bit, direct, indirect  addressable */ \
+   { ".bdata",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE }, \
+   { ".bbss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE }, \
+   /* 0x30..0x7F direct, indirect addresable */ \
+   /* * *   standart section   * * */ \
+   /* .data */ \
+   /* .bss */ \
+   /* 0x80..0xFF indirect addressable */ \
+   { ".idata",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE }, \
+   { ".ibss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE }, \
+   /* external (but in some case onchip) memory */ \
+   /* 0x0000..0xFFFF external memory, movx addressable */ \
+   { ".xdata",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE }, \
+   { ".xbss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE }, \
+   /* 0x0000..0xFFFF optional onchip "external" memory, movx addressable */ \
+   { ".edata",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE }, \
+   { ".ebss",	SHT_NOBITS,	SHF_ALLOC + SHF_WRITE }, \
+   /* 0x0000..0xFFFF optionla onchip eeprom memory, movx addressable */ \
+   { ".eeprom",	SHT_PROGBITS,	SHF_ALLOC + SHF_WRITE },
+ 
+ #define LISTING_WORD_SIZE 1
+ /*   The number of bytes to put into a word in a listing.  This affects
+      the way the bytes are clumped together in the listing.  For
+      example, a value of 2 might print `1234 5678' where a value of 1
+      would print `12 34 56 78'.  The default value is 4.  */
+ 
+ //#define LEX_DOLLAR 0
+ /* AVR port uses `$' as a logical line separator */
+ 
+ //#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) (P2VAR) = 0
+ /*   An `.lcomm' directive with no explicit alignment parameter will
+      use this macro to set P2VAR to the alignment that a request for
+      SIZE bytes will have.  The alignment is expressed as a power of
+      two.  If no alignment should take place, the macro definition
+      should do nothing.  Some targets define a `.bss' directive that is
+      also affected by this macro.  The default definition will set
+      P2VAR to the truncated power of two of sizes up to eight bytes.  */
+ 
+ extern void i51_cleanup PARAMS ((void));
+ #define md_cleanup() i51_cleanup()
+ #define md_after_pass_hook() i51_cleanup()
diff -crN binutils.null/include/elf/i51.h binutils-2.11.2.i51.new/include/elf/i51.h
*** binutils.null/include/elf/i51.h	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/include/elf/i51.h	Sun Dec 30 10:48:51 2001
***************
*** 0 ****
--- 1,58 ----
+ /* MCS-51 ELF support for BFD.
+    Copyright (C) 2001 Free Software Foundation, Inc.
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+ 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #ifndef _ELF_I51_H
+ #define _ELF_I51_H
+ 
+ #include "elf/reloc-macros.h"
+ 
+ /* Relocations.  */
+ START_RELOC_NUMBERS (elf_i51_reloc_type)
+      RELOC_NUMBER (R_I51_NONE,			0)
+      RELOC_NUMBER (R_I51_R1,			1)
+      RELOC_NUMBER (R_I51_R3,			2)
+      RELOC_NUMBER (R_I51_7_PCREL,		3)
+      RELOC_NUMBER (R_I51_11, 			4)
+      RELOC_NUMBER (R_I51_8_BIT,			5)
+      RELOC_NUMBER (R_I51_8,			6)
+      RELOC_NUMBER (R_I51_L,			7)
+      RELOC_NUMBER (R_I51_H,			8)
+      RELOC_NUMBER (R_I51_16,			9)
+      RELOC_NUMBER (R_I51_8_B2B,			10)
+      RELOC_NUMBER (R_I51_13_PCODE,		11)
+ END_RELOC_NUMBERS (R_I51_max)
+ 
+ #define SHF_CDATA   0xE0000000 /* Processor-specific - common data mask */
+ #define SHF_REGBANK 0x20000000 /* Processor-specific - register bank */
+ #define SHF_RDATA   0x40000000 /* Processor-specific - rdata */
+ #define SHF_BDATA   0x60000000 /* Processor-specific - bdata */
+ #define SHF_IDATA   0x80000000 /* Processor-specific - idata */
+ #define SHF_XDATA   0xA0000000 /* Processor-specific - xdata */
+ #define SHF_EDATA   0xC0000000 /* Processor-specific - edata */
+ 
+ #define SHN_I51_REGBANK 0xff00 /* Register bank common */
+ #define SHN_I51_RDATA_C 0xff01 /* rdata common */
+ #define SHN_I51_BDATA_C 0xff02 /* bdata common */
+ #define SHN_I51_IDATA_C 0xff03 /* idata common */
+ #define SHN_I51_XDATA_C 0xff04 /* xdata common */
+ #define SHN_I51_EDATA_C 0xff05 /* edata common */
+ #define SHN_I51_BITDATA_C 0xff06 /* bitdata common */
+ 
+ #endif /* _ELF_I51_H */
diff -crN binutils.null/include/opcode/i51.h binutils-2.11.2.i51.new/include/opcode/i51.h
*** binutils.null/include/opcode/i51.h	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/include/opcode/i51.h	Wed Dec 26 16:20:51 2001
***************
*** 0 ****
--- 1,153 ----
+ /* ARGS:
+   A - A reg
+   B - bit
+   C - AB reg
+   D - data
+   N - none
+   R - R0..R7
+   r - C reg
+   P - DPTR
+   @ - @A+DPTR
+   X - @A+PC
+   I - @R0, @R1
+   J - jump rel
+   / - /C
+   T - @DPTR
+   # - #data
+   d - data16
+   1 - jump addr 11
+   6 - jump addr 16
+ */
+ 
+ /* MRELOC
+   N - none                - IIIIIIII
+   I - register indirect   - IIIIIIIr
+   i - reg. indirect, data - IIIIIIIr dddddddd
+   R - register            - IIIIIrrr
+   r - register,data       - IIIIIrrr dddddddd
+   7 - relative jump 8 bit - IIIIIIII aaaaaaaa
+   1 - jump 11 bit         - aaaIIIII aaaaaaaa
+   6 - data/jump 16 bit    - IIIIIIII aaaaaaaa aaaaaaaa
+   D - data 8 bit          - IIIIIIII dddddddd
+   d - data,data 8 bit     - IIIIIIII dddddddd dddddddd
+   a - addr,data 8 bit     - IIIIIIII aaaaaaaa dddddddd
+   B - bitdata 8 bit       - IIIIIIII bbbbbbbb
+   J - bit, r. jump 8 bit  - IIIIIIII bbbbbbbb aaaaaaaa
+   X - reg. indirect, r. jump 8 bit - IIIIIIIr dddddddd aaaaaaaa
+   Y - register, rel. jump 8 bit    - IIIIIrrr dddddddd aaaaaaaa
+   Z - data 8 bit, r. jump 8 bit    - IIIIIIII dddddddd aaaaaaaa
+   W - register, rel. jump 8 bit    - IIIIIrrr aaaaaaaa
+ */
+ 
+ I51_INS ("acall", "1NN", 0x82, "aaa10001", '1', 0x11, 0x1F)
+ I51_INS ("add",   "ARN", 0x01, "00101rrr", 'R', 0x28, 0xF8)
+ I51_INS ("add",   "AIN", 0x01, "0010011r", 'I', 0x26, 0xFE)
+ I51_INS ("add",   "ADN", 0x02, "00100101", 'D', 0x25, 0xFF)
+ I51_INS ("add",   "A#N", 0x82, "00100100", 'D', 0x24, 0xFF)
+ I51_INS ("addc",  "ARN", 0x01, "00111rrr", 'R', 0x38, 0xF8)
+ I51_INS ("addc",  "AIN", 0x01, "0011011r", 'I', 0x36, 0xFE)
+ I51_INS ("addc",  "ADN", 0x02, "00110101", 'D', 0x35, 0xFF)
+ I51_INS ("addc",  "A#N", 0x82, "00110100", 'D', 0x34, 0xFF)
+ I51_INS ("ajmp",  "1NN", 0x82, "aaa00001", '1', 0x01, 0x1F)
+ I51_INS ("anl",   "ARN", 0x01, "01011rrr", 'R', 0x58, 0xF8)
+ I51_INS ("anl",   "AIN", 0x01, "0101011i", 'I', 0x56, 0xFE)
+ I51_INS ("anl",   "ADN", 0x02, "01010101", 'D', 0x55, 0xFF)
+ I51_INS ("anl",   "A#N", 0x02, "01010100", 'D', 0x54, 0xFF)
+ I51_INS ("anl",   "rBN", 0x02, "10000010", 'B', 0x82, 0xFF)
+ I51_INS ("anl",   "r/N", 0x02, "10110000", 'B', 0xB0, 0xFF)
+ I51_INS ("anl",   "DAN", 0x02, "01010010", 'D', 0x52, 0xFF)
+ I51_INS ("anl",   "D#N", 0x83, "01010011", 'a', 0x53, 0xFF)
+ I51_INS ("cjne",  "A#J", 0x03, "10110100", 'Z', 0xB4, 0xFF)
+ I51_INS ("cjne",  "R#J", 0x03, "10111rrr", 'Y', 0xB8, 0xF8)
+ I51_INS ("cjne",  "I#J", 0x03, "1011011r", 'X', 0xB6, 0xFE)
+ I51_INS ("cjne",  "ADJ", 0x83, "10110101", 'Z', 0xB5, 0xFF)
+ I51_INS ("clr",   "ANN", 0x01, "11100100", 'N', 0xE4, 0xFF)
+ I51_INS ("clr",   "rNN", 0x01, "11000011", 'N', 0xC3, 0xFF)
+ I51_INS ("clr",   "BNN", 0x82, "11000010", 'B', 0xC2, 0xFF)
+ I51_INS ("cpl",   "ANN", 0x01, "11110100", 'N', 0xF4, 0xFF)
+ I51_INS ("cpl",   "rNN", 0x01, "10110011", 'N', 0xB3, 0xFF)
+ I51_INS ("cpl",   "BNN", 0x82, "10110010", 'B', 0xB2, 0xFF)
+ I51_INS ("da",    "ANN", 0x81, "11010100", 'N', 0xD4, 0xFF)
+ I51_INS ("dec",   "ANN", 0x01, "00010100", 'N', 0x14, 0xFF)
+ I51_INS ("dec",   "RNN", 0x01, "00011rrr", 'R', 0x18, 0xF8)
+ I51_INS ("dec",   "INN", 0x01, "0001011r", 'I', 0x16, 0xFE)
+ I51_INS ("dec",   "DNN", 0x82, "00010101", 'D', 0x15, 0xFF)
+ I51_INS ("div",   "CNN", 0x81, "10000100", 'N', 0x84, 0xFF)
+ I51_INS ("djnz",  "RJN", 0x02, "11011rrr", 'W', 0xD8, 0xF8)
+ I51_INS ("djnz",  "DJN", 0x83, "11010101", 'Z', 0xD5, 0xFF)
+ I51_INS ("inc",   "ANN", 0x01, "00000100", 'N', 0x04, 0xFF)
+ I51_INS ("inc",   "RNN", 0x01, "00001rrr", 'R', 0x08, 0xF8)
+ I51_INS ("inc",   "INN", 0x01, "0000011r", 'I', 0x06, 0xFE)
+ I51_INS ("inc",   "PNN", 0x01, "10100011", 'N', 0xA3, 0xFF)
+ I51_INS ("inc",   "DNN", 0x82, "00000101", 'D', 0x05, 0xFF)
+ I51_INS ("jb",    "BJN", 0x83, "00100000", 'J', 0x20, 0xFF)
+ I51_INS ("jbc",   "BJN", 0x83, "00010000", 'J', 0x10, 0xFF)
+ I51_INS ("jc",    "JNN", 0x82, "01000000", '7', 0x40, 0xFF)
+ I51_INS ("jmp",   "@NN", 0x81, "01110011", 'N', 0x73, 0xFF)
+ I51_INS ("jnb",   "BJN", 0x83, "00110000", 'J', 0x30, 0xFF)
+ I51_INS ("jnc",   "JNN", 0x82, "01010000", '7', 0x50, 0xFF)
+ I51_INS ("jnz",   "JNN", 0x82, "01110000", '7', 0x70, 0xFF)
+ I51_INS ("jz",    "JNN", 0x82, "01100000", '7', 0x60, 0xFF)
+ I51_INS ("lcall", "6NN", 0x83, "00010010", '6', 0x12, 0xFF)
+ I51_INS ("ljmp",  "6NN", 0x83, "00000010", '6', 0x02, 0xFF)
+ I51_INS ("mov",   "ARN", 0x01, "11101rrr", 'R', 0xE8, 0xF8)
+ I51_INS ("mov",   "AIN", 0x01, "1110011r", 'I', 0xE6, 0xFE)
+ I51_INS ("mov",   "ADN", 0x02, "11100101", 'D', 0xE5, 0xFF)
+ I51_INS ("mov",   "A#N", 0x02, "01110100", 'D', 0x74, 0xFF)
+ I51_INS ("mov",   "RAN", 0x01, "11111rrr", 'R', 0xF8, 0xF8)
+ I51_INS ("mov",   "RDN", 0x02, "10101rrr", 'r', 0xA8, 0xF8)
+ I51_INS ("mov",   "R#N", 0x02, "01111rrr", 'r', 0x78, 0xF8)
+ I51_INS ("mov",   "IAN", 0x01, "1111011r", 'I', 0xF6, 0xFE)
+ I51_INS ("mov",   "IDN", 0x02, "1010011r", 'r', 0xA6, 0xFE)
+ I51_INS ("mov",   "I#N", 0x02, "0111011r", 'r', 0x76, 0xFE)
+ I51_INS ("mov",   "rBN", 0x02, "10100010", 'B', 0xA2, 0xFF)
+ I51_INS ("mov",   "P#N", 0x03, "10010000", '6', 0x90, 0xFF)
+ I51_INS ("mov",   "BrN", 0x02, "10010010", 'B', 0x92, 0xFF)
+ I51_INS ("mov",   "DAN", 0x02, "11110101", 'D', 0xF5, 0xFF)
+ I51_INS ("mov",   "DRN", 0x02, "10001rrr", 'r', 0x88, 0xF8)
+ I51_INS ("mov",   "DIN", 0x02, "1000011r", 'r', 0x86, 0xFE)
+ I51_INS ("mov",   "DDN", 0x03, "10000101", 'd', 0x85, 0xFF)
+ I51_INS ("mov",   "D#N", 0x83, "01110101", 'a', 0x75, 0xFF)
+ I51_INS ("movc",  "A@N", 0x01, "10010011", 'N', 0x93, 0xFF)
+ I51_INS ("movc",  "AXN", 0x81, "10000011", 'N', 0x83, 0xFF)
+ I51_INS ("movx",  "AIN", 0x01, "1110001r", 'I', 0xE2, 0xFE)
+ I51_INS ("movx",  "ATN", 0x01, "11100000", 'N', 0xE0, 0xFF)
+ I51_INS ("movx",  "IAN", 0x01, "1111001r", 'I', 0xF2, 0xFE)
+ I51_INS ("movx",  "TAN", 0x81, "11110000", 'N', 0xF0, 0xFF)
+ I51_INS ("mul",   "CNN", 0x81, "10100100", 'N', 0xA4, 0xFF)
+ I51_INS ("nop",   "NNN", 0x81, "00000000", 'N', 0x00, 0xFF)
+ I51_INS ("orl",   "ARN", 0x01, "01001rrr", 'R', 0x48, 0xF8)
+ I51_INS ("orl",   "AIN", 0x01, "0100011i", 'I', 0x46, 0xFE)
+ I51_INS ("orl",   "ADN", 0x02, "01000101", 'D', 0x45, 0xFF)
+ I51_INS ("orl",   "A#N", 0x02, "01000100", 'D', 0x44, 0xFF)
+ I51_INS ("orl",   "rBN", 0x02, "01110010", 'B', 0x72, 0xFF)
+ I51_INS ("orl",   "r/N", 0x02, "10100000", 'B', 0xA0, 0xFF)
+ I51_INS ("orl",   "DAN", 0x02, "01000010", 'D', 0x42, 0xFF)
+ I51_INS ("orl",   "D#N", 0x83, "01000011", 'a', 0x43, 0xFF)
+ I51_INS ("pop",   "DNN", 0x82, "11010000", 'D', 0xD0, 0xFF)
+ I51_INS ("push",  "DNN", 0x82, "11000000", 'D', 0xC0, 0xFF)
+ I51_INS ("ret",   "NNN", 0x81, "00100010", 'N', 0x22, 0xFF)
+ I51_INS ("reti",  "NNN", 0x81, "00110010", 'N', 0x32, 0xFF)
+ I51_INS ("rl",    "ANN", 0x81, "00100011", 'N', 0x23, 0xFF)
+ I51_INS ("rlc",   "ANN", 0x81, "00110011", 'N', 0x33, 0xFF)
+ I51_INS ("rr",    "ANN", 0x81, "00000011", 'N', 0x03, 0xFF)
+ I51_INS ("rrc",   "ANN", 0x81, "00010011", 'N', 0x13, 0xFF)
+ I51_INS ("setb",  "rNN", 0x01, "11010011", 'N', 0xD3, 0xFF)
+ I51_INS ("setb",  "BNN", 0x82, "11010010", 'B', 0xD2, 0xFF)
+ I51_INS ("sjmp",  "JNN", 0x82, "10000000", '7', 0x80, 0xFF)
+ I51_INS ("subb",  "ARN", 0x01, "10011rrr", 'R', 0x98, 0xF8)
+ I51_INS ("subb",  "AIN", 0x01, "1001011r", 'I', 0x96, 0xFE)
+ I51_INS ("subb",  "ADN", 0x02, "10010101", 'D', 0x95, 0xFF)
+ I51_INS ("subb",  "A#N", 0x82, "10010100", 'D', 0x94, 0xFF)
+ I51_INS ("swap",  "ANN", 0x81, "11000100", 'N', 0xC4, 0xFF)
+ I51_INS ("xch",   "ARN", 0x01, "11001rrr", 'R', 0xC8, 0xF8)
+ I51_INS ("xch",   "AIN", 0x01, "1100011r", 'I', 0xC6, 0xFE)
+ I51_INS ("xch",   "ADN", 0x82, "11000101", 'D', 0xC5, 0xFF)
+ I51_INS ("xchd",  "AIN", 0x81, "1101011r", 'I', 0xD6, 0xFE)
+ I51_INS ("xrl",   "ARN", 0x01, "01101rrr", 'R', 0x68, 0xF8)
+ I51_INS ("xrl",   "AIN", 0x01, "0110011i", 'I', 0x66, 0xFE)
+ I51_INS ("xrl",   "ADN", 0x02, "01100101", 'D', 0x65, 0xFF)
+ I51_INS ("xrl",   "A#N", 0x02, "01100100", 'D', 0x64, 0xFF)
+ I51_INS ("xrl",   "DAN", 0x02, "01100010", 'D', 0x62, 0xFF)
+ I51_INS ("xrl",   "D#N", 0x83, "01100011", 'a', 0x63, 0xFF)
+ 
diff -crN binutils.null/ld/emulparams/elf32_i51.sh binutils-2.11.2.i51.new/ld/emulparams/elf32_i51.sh
*** binutils.null/ld/emulparams/elf32_i51.sh	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/ld/emulparams/elf32_i51.sh	Wed Dec 26 16:20:51 2001
***************
*** 0 ****
--- 1,13 ----
+ SCRIPT_NAME=elf32i51
+ TEMPLATE_NAME=generic
+ OUTPUT_FORMAT="elf32-i51"
+ ARCH=i51
+ MACHINE=
+ TEXT_START_ADDR=0
+ TEXT_LENGTH=8K
+ DATA_LENGTH=256
+ XDATA_LENGTH=64K
+ EDATA_LENGTH=64K
+ EEPROM_LENGTH=2K
+ EMBEDDED=yes
+ MAXPAGESIZE=0x0800
diff -crN binutils.null/ld/scripttempl/elf32i51.sc binutils-2.11.2.i51.new/ld/scripttempl/elf32i51.sc
*** binutils.null/ld/scripttempl/elf32i51.sc	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/ld/scripttempl/elf32i51.sc	Wed Dec 26 16:20:51 2001
***************
*** 0 ****
--- 1,235 ----
+ cat <<EOF
+ OUTPUT_FORMAT("${OUTPUT_FORMAT}","${OUTPUT_FORMAT}","${OUTPUT_FORMAT}")
+ OUTPUT_ARCH(${ARCH})
+ 
+ MEMORY
+ {
+   text   (rx)   : ORIGIN = 0, LENGTH = $TEXT_LENGTH
+   bit    (rw!x) : ORIGIN = 0, LENGTH = 0x80
+   data   (rw!x) : ORIGIN = 0, LENGTH = $DATA_LENGTH
+   xdata  (rw!x) : ORIGIN = 0, LENGTH = $XDATA_LENGTH
+   edata  (rw!x) : ORIGIN = 0, LENGTH = $EDATA_LENGTH
+   eeprom (rw!x) : ORIGIN = 0, LENGTH = $EEPROM_LENGTH
+ }
+ 
+ SECTIONS
+ {
+   /* Read-only sections, merged into text segment: */
+   ${TEXT_DYNAMIC+${DYNAMIC}}
+   .hash        ${RELOCATING-0} : { *(.hash)		}
+   .dynsym      ${RELOCATING-0} : { *(.dynsym)		}
+   .dynstr      ${RELOCATING-0} : { *(.dynstr)		}
+   .gnu.version ${RELOCATING-0} : { *(.gnu.version)	}
+   .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d)	}
+   .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r)	}
+ 
+   .rel.init    ${RELOCATING-0} : { *(.rel.init)	}
+   .rela.init   ${RELOCATING-0} : { *(.rela.init)	}
+   .rel.text    ${RELOCATING-0} :
+     {
+       *(.rel.text)
+       ${RELOCATING+*(.rel.text.*)}
+       ${RELOCATING+*(.rel.gnu.linkonce.t*)}
+     }
+   .rela.text   ${RELOCATING-0} :
+     {
+       *(.rela.text)
+       ${RELOCATING+*(.rela.text.*)}
+       ${RELOCATING+*(.rela.gnu.linkonce.t*)}
+     }
+   .rel.fini    ${RELOCATING-0} : { *(.rel.fini)	}
+   .rela.fini   ${RELOCATING-0} : { *(.rela.fini)	}
+   .rel.rodata  ${RELOCATING-0} :
+     {
+       *(.rel.rodata)
+       ${RELOCATING+*(.rel.rodata.*)}
+       ${RELOCATING+*(.rel.gnu.linkonce.r*)}
+     }
+   .rela.rodata ${RELOCATING-0} :
+     {
+       *(.rela.rodata)
+       ${RELOCATING+*(.rela.rodata.*)}
+       ${RELOCATING+*(.rela.gnu.linkonce.r*)}
+     }
+   .rel.data    ${RELOCATING-0} :
+     {
+       *(.rel.data)
+       ${RELOCATING+*(.rel.data.*)}
+       ${RELOCATING+*(.rel.gnu.linkonce.d*)}
+     }
+   .rela.data   ${RELOCATING-0} :
+     {
+       *(.rela.data)
+       ${RELOCATING+*(.rela.data.*)}
+       ${RELOCATING+*(.rela.gnu.linkonce.d*)}
+     }
+   .rel.ctors   ${RELOCATING-0} : { *(.rel.ctors)	}
+   .rela.ctors  ${RELOCATING-0} : { *(.rela.ctors)	}
+   .rel.dtors   ${RELOCATING-0} : { *(.rel.dtors)	}
+   .rela.dtors  ${RELOCATING-0} : { *(.rela.dtors)	}
+   .rel.got     ${RELOCATING-0} : { *(.rel.got)		}
+   .rela.got    ${RELOCATING-0} : { *(.rela.got)		}
+   .rel.bss     ${RELOCATING-0} : { *(.rel.bss)		}
+   .rela.bss    ${RELOCATING-0} : { *(.rela.bss)		}
+   .rel.plt     ${RELOCATING-0} : { *(.rel.plt)		}
+   .rela.plt    ${RELOCATING-0} : { *(.rela.plt)		}
+ 
+   /* Internal text space or external memory */
+ 
+   .text :
+   {
+     *(.init)
+     *(.progmem.gcc*)
+     *(.progmem*)
+     *(.text)
+     *(.text.*)
+     *(.fini)
+     ${RELOCATING+ _etext = . ; }
+   } ${RELOCATING+ > text}
+ 
+   .reg	${RELOCATING+ 0} :
+      ${RELOCATING+ AT (ADDR (.text) + SIZEOF (.text))}
+   {
+     *(.regbank)
+     ${RELOCATING+ PROVIDE (__reg_start = .) ; }
+     *(.rdata*)
+     ${RELOCATING+ PROVIDE (__reg_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .rbss	${RELOCATING+ SIZEOF(.reg)} :
+   {
+     ${RELOCATING+ PROVIDE (__rbss_start = .) ; }
+     *(.rbss*)
+     ${RELOCATING+ PROVIDE (__rbss_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .bdata ${RELOCATING+ ((MAX (0x20, ( SIZEOF(.rbss) + ADDR(.rbss)))))} :
+   {
+     ${RELOCATING+ PROVIDE (__bdata_start = .) ; }
+     *(.bdata*)
+     ${RELOCATING+ PROVIDE (__bdata_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .bbss	${RELOCATING+ (SIZEOF(.bdata) + ADDR(.bdata))} :
+   {
+     ${RELOCATING+ PROVIDE (__bbss_start = .) ; }
+     *(.bbss*)
+     ${RELOCATING+ PROVIDE (__bbss_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .bit	${RELOCATING+ ((((SIZEOF(.bbss) + ADDR(.bbss)) - 0x20) * 8 ))} :
+   {
+     ${RELOCATING+ PROVIDE (__bit_start = .) ; }
+     *(.bitdata*)
+     ${RELOCATING+ PROVIDE (__bit_end = .) ; }
+   } ${RELOCATING+ > bit}
+ 
+   .bitbss ${RELOCATING+ SIZEOF(.bit) + ADDR(.bit)} :
+   {
+     ${RELOCATING+ PROVIDE (__bbss_start = .) ; }
+     *(.bitbss*)
+     ${RELOCATING+ PROVIDE (__bbss_end = .) ; }
+   } ${RELOCATING+ > bit}
+ 
+   .data	${RELOCATING+ (((SIZEOF(.bit) + SIZEOF(.bitbss) + 7) / 8) + SIZEOF(.bbss) + ADDR(.bbss))} :
+   {
+     ${RELOCATING+ PROVIDE (__data_start = .) ; }
+     *(.data)
+     *(.gnu.linkonce.d*)
+     ${RELOCATING+ PROVIDE (__data_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} :
+   {
+     ${RELOCATING+ PROVIDE (__bss_start = .) ; }
+     *(.bss*)
+     *(COMMON)
+     ${RELOCATING+ PROVIDE (__bss_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .idata ${RELOCATING+ SIZEOF(.bss) + ADDR(.bss)} :
+   {
+     ${RELOCATING+ PROVIDE (__idata_start = .) ; }
+     *(.idata)
+     ${RELOCATING+ PROVIDE (__idata_end = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .ibss ${RELOCATING+ SIZEOF(.idata) + ADDR(.idata)} :
+   {
+     ${RELOCATING+ PROVIDE (__ibss_start = .) ; }
+     *(.ibss)
+     ${RELOCATING+ PROVIDE (__ibss_end = .) ; }
+     ${RELOCATING+ PROVIDE (stack = .) ; }
+   } ${RELOCATING+ > data}
+ 
+   .xdata ${RELOCATING-0}:
+   {
+     ${RELOCATING+ PROVIDE (__xdata_start = .) ; }
+     *(.xdata*)
+     ${RELOCATING+ PROVIDE (__xdata_end = .) ; }
+   } ${RELOCATING+ > xdata}
+ 
+   .ixdata ${RELOCATING+ SIZEOF(.xdata)}:
+   {
+     ${RELOCATING+ PROVIDE (__ixdata_start = .) ; }
+     *(.xbss*)
+     ${RELOCATING+ PROVIDE (__ixdata_end = .) ; }
+   } ${RELOCATING+ > xdata}
+ 
+   .edata ${RELOCATING-0}:
+   {
+     ${RELOCATING+ PROVIDE (__edata_start = .) ; }
+     *(.edata*)
+     ${RELOCATING+ PROVIDE (__edata_end = .) ; }
+   } ${RELOCATING+ > edata}
+ 
+   .iedata ${RELOCATING+ SIZEOF(.edata)}:
+   {
+     ${RELOCATING+ PROVIDE (__iedata_start = .) ; }
+     *(.ebss*)
+     ${RELOCATING+ PROVIDE (__iedata_end = .) ; }
+   } ${RELOCATING+ > edata}
+ 
+   .eeprom ${RELOCATING-0}:
+   {
+     ${RELOCATING+ PROVIDE (__eeprom_start = .) ; }
+     *(.eeprom*)
+     ${RELOCATING+ PROVIDE (__eeprom_end = .) ; }
+   } ${RELOCATING+ > eeprom}
+ 
+   /* Stabs debugging sections.  */
+   .stab 0 : { *(.stab) }
+   .stabstr 0 : { *(.stabstr) }
+   .stab.excl 0 : { *(.stab.excl) }
+   .stab.exclstr 0 : { *(.stab.exclstr) }
+   .stab.index 0 : { *(.stab.index) }
+   .stab.indexstr 0 : { *(.stab.indexstr) }
+   .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.  */
+ 
+   /* DWARF 1 */
+   .debug          0 : { *(.debug) }
+   .line           0 : { *(.line) }
+ 
+   /* GNU DWARF 1 extensions */
+   .debug_srcinfo  0 : { *(.debug_srcinfo) }
+   .debug_sfnames  0 : { *(.debug_sfnames) }
+ 
+   /* DWARF 1.1 and DWARF 2 */
+   .debug_aranges  0 : { *(.debug_aranges) }
+   .debug_pubnames 0 : { *(.debug_pubnames) }
+ 
+   /* DWARF 2 */
+   .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) }
+ }
+ EOF
+ 
diff -crN binutils.null/opcodes/i51-dis.c binutils-2.11.2.i51.new/opcodes/i51-dis.c
*** binutils.null/opcodes/i51-dis.c	Thu Jan  1 01:00:00 1970
--- binutils-2.11.2.i51.new/opcodes/i51-dis.c	Wed Dec 26 16:20:51 2001
***************
*** 0 ****
--- 1,282 ----
+ /* Disassemble MCS-51 instructions.
+    Copyright 2001 Free Software Foundation, Inc.
+ 
+    Contributed by Radek Benedikt <benedikt@lphard.cz>
+ 
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #include <assert.h>
+ #include "sysdep.h"
+ #include "dis-asm.h"
+ #include "opintl.h"
+ 
+ 
+ struct i51_opcodes_s
+ {
+   char *name;
+   char *args;
+   int insn_size;		/* in bytes */
+   unsigned char bin_opcode;
+   unsigned char bin_mask;
+ };
+ 
+ #define I51_INS(NAME, ARGS, SIZE, OPCODE, MRELOC, BIN, MASK) \
+ {NAME, ARGS, SIZE, BIN, MASK},
+ 
+ struct i51_opcodes_s i51_opcodes[] =
+ {
+   #include "opcode/i51.h"
+   {NULL, NULL, 0, 0, 0}
+ };
+ 
+ static unsigned char
+ i51dis_opcode (addr, info)
+      bfd_vma addr;
+      disassemble_info *info;
+ {
+   bfd_byte buffer[1];
+   int status;
+   status = info->read_memory_func(addr, buffer, 1, info);
+   if (status != 0)
+     {
+       info->memory_error_func(status, addr, info);
+       return -1;
+     }
+   return buffer[0];
+ }
+ 
+ static unsigned short
+ i51dis_op16 (addr, info)
+      bfd_vma addr;
+      disassemble_info *info;
+ {
+   bfd_byte buffer[2];
+   int status;
+   status = info->read_memory_func(addr, buffer, 2, info);
+   if (status != 0)
+     {
+       info->memory_error_func(status, addr, info);
+       return -1;
+     }
+   return bfd_getb16(buffer);
+ }
+ 
+ int
+ print_insn_i51(addr, info)
+      bfd_vma addr;
+      disassemble_info *info;
+ {
+   unsigned int insn;
+   unsigned int opdata;
+   unsigned char rel_addr;
+   struct i51_opcodes_s *opcode;
+   void *stream = info->stream;
+   fprintf_ftype prin = info->fprintf_func;
+   int ok = 0;
+   int offset = 0;
+   char op1[10], op2[10], op3[10], comment1[40], comment2[40];
+   int inslen = 1;
+ 
+   insn = i51dis_opcode (addr, info);
+   addr++;  
+   for (opcode = i51_opcodes; opcode->name; opcode++)
+     {
+       if ((insn & opcode->bin_mask) == opcode->bin_opcode)
+ 	break;
+     }
+   
+   op1[0] = 0;
+   op2[0] = 0;
+   op3[0] = 0;
+   comment1[0] = 0;
+   comment2[0] = 0;
+ 
+   if (opcode->name)
+     {
+       inslen = (opcode->insn_size) & 0x03;
+       ok = 1;
+       switch (opcode->args[0]) {
+ 	case 'N':	//none
+ 	  break;
+ 	case 'A':	//A reg
+ 	  sprintf (op1,"A");
+ 	  break;
+ 	case 'C':	//AB reg
+ 	  sprintf (op1,"AB");
+ 	  break;
+ 	case 'r':	//C reg
+ 	  sprintf (op1,"C");
+ 	  break;
+ 	case 'P':	//DPTR
+ 	  sprintf (op1,"DPTR");
+ 	  break;
+ 	case '@':	//@A+DPTR
+ 	  sprintf (op1,"@A+DPTR");
+ 	  break;
+ 	case 'T':	//@DPTR
+ 	  sprintf (op1,"@DPTR");
+ 	  break;
+ 	case 'D':	//data
+ 	case 'B':	//bit
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ 	  offset++;
+ 	  sprintf (op1,"0x%02X",opdata);
+ 	  break;
+ 	case 'R':	//R0..R7
+ 	  sprintf (op1,"R%c",(insn&0x07)+'0');
+ 	  break;
+ 	case 'I':	//@R0, @R1
+ 	  sprintf (op1,"@R%c",(insn&0x01)+'0');
+ 	  break;
+ 	case 'J':	//jump rel
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ //
+ 	  rel_addr = opdata+2;
+ 	  if (rel_addr & 0x80) {
+ 	    sprintf (op1,".-0x%02X",0x100-rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata - 0x100);
+ 	  } else {
+ 	    sprintf (op1,".+0x%02X",rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata);
+ 	  }
+ 	  break;
+ 	case '1':	//jump addr 11
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ 	  sprintf (op1,"0x%04lX", (addr&0xF800)+(((insn>>5)&0x07)<<8)+opdata);
+ 	  break;
+ 	case '6':	//jump addr 16
+ 	  opdata = i51dis_op16 (addr, info);
+ 	  addr++;
+ 	  sprintf (op1,"0x%04X",opdata);
+ 	  break;
+       }
+       switch (opcode->args[1]) {
+ 	case 'N':	//none
+ 	  break;
+ 	case 'A':	//A reg
+ 	  sprintf (op2,"A");
+ 	  break;
+ 	case 'r':	//C reg
+ 	  sprintf (op2,"C");
+ 	  break;
+ 	case '@':	//@A+DPTR
+ 	  sprintf (op2,"@A+DPTR");
+ 	  break;
+ 	case 'X':	//@A+PC
+ 	  sprintf (op2,"@A+PC");
+ 	  break;
+ 	case '/':	// /C
+ 	  sprintf (op2,"/C");
+ 	  break;
+ 	case 'T':	//@DPTR
+ 	  sprintf (op2,"@DPTR");
+ 	  break;
+ 	case 'B':	//bit
+ 	case 'D':	//data
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ 	  offset++;
+ 	  sprintf (op2,"0x%02X",opdata);
+ 	  break;
+ 	case 'R':	//R0..R7
+ 	  sprintf (op2,"R%c",(insn&0x07)+'0');
+ 	  break;
+ 	case 'I':	//@R0, @R1
+ 	  sprintf (op2,"@R%c",(insn&0x01)+'0');
+ 	  break;
+ 	case 'J':	//jump rel
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ //
+ 	  rel_addr = opdata+2+offset;
+ 	  if (rel_addr & 0x80) {
+ 	    sprintf (op2,".-0x%02X",0x100-rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata - 0x100);
+ 	  } else {
+ 	    sprintf (op2,".+0x%02X",rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata);
+ 	  }
+ 	  break;
+ 	case '#':	//#data
+ 	  if(opcode->args[0] == 'P') {
+ 	    opdata = i51dis_op16 (addr, info);
+ 	    addr+=2;
+ 	    sprintf (op2,"#0x%04X",opdata);
+ 	  } else {
+ 	    opdata = i51dis_opcode (addr, info);
+ 	    addr++;
+ 	    offset++;
+ 	    sprintf (op2,"#0x%02X",opdata);
+ 	    if ((opdata >= ' ') && (opdata < 0x7F)) {
+ 	      sprintf (comment1, "#%u\t#'%c'", opdata, opdata);
+ 	    } else {
+ 	      sprintf (comment1, "#%u", opdata);
+ 	    }
+ 	  }
+ 	  break;
+       }
+       switch (opcode->args[2]) {
+ 	case 'N':	//none
+ 	  break;
+ 	case 'J':	//jump rel
+ 	  opdata = i51dis_opcode (addr, info);
+ 	  addr++;
+ //
+ 	  rel_addr = opdata+2+offset;
+ 	  if (rel_addr & 0x80) {
+ 	    sprintf (op3,".-0x%02X",0x100-rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata - 0x100);
+ 	  } else {
+ 	    sprintf (op3,".+0x%02X",rel_addr);
+ 	    sprintf (comment1, "0x%04lX", addr + opdata);
+ 	  }
+ 	  break;
+       }
+     }
+ 
+   if (!ok)
+     {
+       /* Unknown opcode, or invalid combination of operands.  */
+       sprintf (op1, "0x%02X", insn);
+       sprintf (comment1, "????");
+       comment2[0] = 0;
+     }
+ 
+   (*prin) (stream, "%s", ok ? opcode->name : ".byte");
+ 
+   if (*op1)
+     (*prin) (stream, "\t%s", op1);
+ 
+   if (*op2)
+     (*prin) (stream, ", %s", op2);
+ 
+   if (*op3)
+     (*prin) (stream, ", %s", op3);
+ 
+   if (*comment1) {
+     if (*op2)
+       (*prin) (stream, "\t; %s", comment1);
+     else
+       (*prin) (stream, "\t\t; %s", comment1);
+   }
+ 
+   if (*comment2)
+     (*prin) (stream, " %s", comment2);
+ 
+   return inslen;
+ }

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

* Re: MCS51 patch - part 1 of 2 - new files (for binutils 2.11.2)
  2001-12-30 14:38 MCS51 patch - part 1 of 2 - new files (for binutils 2.11.2) Radek Benedikt
@ 2002-01-02  9:41 ` Nick Clifton
  0 siblings, 0 replies; 2+ messages in thread
From: Nick Clifton @ 2002-01-02  9:41 UTC (permalink / raw)
  To: Radek Benedikt; +Cc: binutils

Hi Radek,

> Patch for Intel/Atmel/... MCS-51 cpu family (8051, 8052, 8031, 8032, ...)

Thanks very much for submitting these patches.  Before I start to look
at them however, I must ask if you have a binutils Copright assignment
on file with the FSF ?  Without such an assignment we cannot consider
accepting your patches :-(.

Cheers
        Nick


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

end of thread, other threads:[~2002-01-02 17:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-12-30 14:38 MCS51 patch - part 1 of 2 - new files (for binutils 2.11.2) Radek Benedikt
2002-01-02  9:41 ` Nick Clifton

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