* 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).