stm8-binutils-gdb/binutils_patches/0001-First-commit-for-stm8-...

4893 lines
138 KiB
Diff
Raw Blame History

From 22cbcafce0c08683209fe1bba2b7faef111764d4 Mon Sep 17 00:00:00 2001
From: Ake Rehnman <ake_rehnman_at_gmail_com>
Date: Fri, 24 Feb 2017 11:51:54 +0100
Subject: [PATCH 1/10] First commit for stm8-binutils-gdb
# Conflicts:
# bfd/archures.c
# bfd/bfd-in2.h
# bfd/libbfd.h
# bfd/reloc.c
# gas/configure.tgt
# gdb/configure.tgt
---
bfd/Makefile.am | 12 +-
bfd/Makefile.in | 14 +-
bfd/archures.c | 4 +
bfd/bfd-in2.h | 5 +
bfd/config.bfd | 6 +
bfd/configure | 1 +
bfd/configure.ac | 1 +
bfd/cpu-stm8.c | 40 ++
bfd/cpu-stm8.h | 6 +
bfd/elf32-stm8.c | 285 +++++++++++
bfd/elfcode.h | 22 +-
bfd/libbfd.h | 1 +
bfd/reloc.c | 5 +
bfd/targets.c | 2 +
config.sub | 6 +-
gas/Makefile.am | 6 +-
gas/Makefile.in | 21 +-
gas/config/tc-stm8.c | 1026 ++++++++++++++++++++++++++++++++++++++++
gas/config/tc-stm8.h | 97 ++++
gas/configure.tgt | 4 +-
gdb/configure.tgt | 5 +
gdb/stm8-tdep.c | 1130 ++++++++++++++++++++++++++++++++++++++++++++
include/dis-asm.h | 1 +
include/elf/stm8.h | 38 ++
include/opcode/stm8.h | 82 ++++
ld/Makefile.am | 7 +-
ld/Makefile.in | 7 +-
ld/configure.tgt | 2 +
ld/emulparams/elf32stm8.sh | 14 +
ld/scripttempl/elfstm8.sc | 232 +++++++++
opcodes/Makefile.am | 4 +-
opcodes/Makefile.in | 6 +-
opcodes/configure | 1 +
opcodes/configure.ac | 1 +
opcodes/disassemble.c | 6 +
opcodes/stm8-dis.c | 412 ++++++++++++++++
opcodes/stm8-opc.c | 799 +++++++++++++++++++++++++++++++
37 files changed, 4286 insertions(+), 25 deletions(-)
create mode 100644 bfd/cpu-stm8.c
create mode 100644 bfd/cpu-stm8.h
create mode 100644 bfd/elf32-stm8.c
create mode 100644 gas/config/tc-stm8.c
create mode 100644 gas/config/tc-stm8.h
create mode 100644 gdb/stm8-tdep.c
create mode 100644 include/elf/stm8.h
create mode 100644 include/opcode/stm8.h
create mode 100644 ld/emulparams/elf32stm8.sh
create mode 100644 ld/scripttempl/elfstm8.sc
create mode 100644 opcodes/stm8-dis.c
create mode 100644 opcodes/stm8-opc.c
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index f727ebeb28..83e090ac6d 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -176,7 +176,8 @@ ALL_MACHINES = \
cpu-xstormy16.lo \
cpu-xtensa.lo \
cpu-z80.lo \
- cpu-z8k.lo
+ cpu-z8k.lo \
+ cpu-stm8.lo
ALL_MACHINES_CFILES = \
cpu-aarch64.c \
@@ -266,7 +267,8 @@ ALL_MACHINES_CFILES = \
cpu-xstormy16.c \
cpu-xtensa.c \
cpu-z80.c \
- cpu-z8k.c
+ cpu-z8k.c \
+ cpu-stm8.c
# The .o files needed by all of the 32 bit vectors that are configured into
# target_vector in targets.c if configured with --enable-targets=all.
@@ -465,7 +467,8 @@ BFD32_BACKENDS = \
xcofflink.lo \
xsym.lo \
xtensa-isa.lo \
- xtensa-modules.lo
+ xtensa-modules.lo \
+ elf32-stm8.lo
BFD32_BACKENDS_CFILES = \
aout-adobe.c \
@@ -661,7 +664,8 @@ BFD32_BACKENDS_CFILES = \
xcofflink.c \
xsym.c \
xtensa-isa.c \
- xtensa-modules.c
+ xtensa-modules.c \
+ elf32-stm8.c
# The .o files needed by all of the 64 bit vectors that are configured into
# target_vector in targets.c if configured with --enable-targets=all
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 40608238b7..e26cfc58c5 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -509,7 +509,8 @@ ALL_MACHINES = \
cpu-xstormy16.lo \
cpu-xtensa.lo \
cpu-z80.lo \
- cpu-z8k.lo
+ cpu-z8k.lo \
+ cpu-stm8.lo
ALL_MACHINES_CFILES = \
cpu-aarch64.c \
@@ -599,7 +600,8 @@ ALL_MACHINES_CFILES = \
cpu-xstormy16.c \
cpu-xtensa.c \
cpu-z80.c \
- cpu-z8k.c
+ cpu-z8k.c \
+ cpu-stm8.c
# The .o files needed by all of the 32 bit vectors that are configured into
@@ -799,7 +801,8 @@ BFD32_BACKENDS = \
xcofflink.lo \
xsym.lo \
xtensa-isa.lo \
- xtensa-modules.lo
+ xtensa-modules.lo \
+ elf32-stm8.lo
BFD32_BACKENDS_CFILES = \
aout-adobe.c \
@@ -995,7 +998,8 @@ BFD32_BACKENDS_CFILES = \
xcofflink.c \
xsym.c \
xtensa-isa.c \
- xtensa-modules.c
+ xtensa-modules.c \
+ elf32-stm8.c
# The .o files needed by all of the 64 bit vectors that are configured into
@@ -1446,6 +1450,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-sh.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-sparc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-spu.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-stm8.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-tic30.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-tic4x.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-tic54x.Plo@am__quote@
@@ -1542,6 +1547,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-sh64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-sparc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-spu.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-stm8.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-tic6x.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-tilegx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-tilepro.Plo@am__quote@
diff --git a/bfd/archures.c b/bfd/archures.c
index e83c57a2f3..d23bb2c77a 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -537,6 +537,8 @@ DESCRIPTION
.#define bfd_mach_wasm32 1
. bfd_arch_pru, {* PRU. *}
.#define bfd_mach_pru 0
+. bfd_arch_stm8, {* ST STM8 *}
+.#define bfd_mach_stm8 1
. bfd_arch_last
. };
*/
@@ -670,6 +672,7 @@ extern const bfd_arch_info_type bfd_xc16x_arch;
extern const bfd_arch_info_type bfd_xgate_arch;
extern const bfd_arch_info_type bfd_z80_arch;
extern const bfd_arch_info_type bfd_z8k_arch;
+extern const bfd_arch_info_type bfd_stm8_arch;
static const bfd_arch_info_type * const bfd_archures_list[] =
{
@@ -762,6 +765,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
&bfd_xgate_arch,
&bfd_z80_arch,
&bfd_z8k_arch,
+ &bfd_stm8_arch,
#endif
0
};
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index f4b3720b4b..78221ddcc1 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2398,6 +2398,8 @@ enum bfd_architecture
#define bfd_mach_wasm32 1
bfd_arch_pru, /* PRU. */
#define bfd_mach_pru 0
+ bfd_arch_stm8, /* ST STM8 */
+#define bfd_mach_stm8 1
bfd_arch_last
};
@@ -6512,6 +6514,9 @@ assembler and not (currently) written to any object files. */
BFD_RELOC_WASM32_CODE_POINTER,
BFD_RELOC_WASM32_INDEX,
BFD_RELOC_WASM32_PLT_SIG,
+
+/* STM8 bit field immediate for BTJx, BCPL, BSET, BRES instruction. */
+ BFD_RELOC_STM8_BIT_FLD,
BFD_RELOC_UNUSED };
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
diff --git a/bfd/config.bfd b/bfd/config.bfd
index f04a993f06..ec98fc050f 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -203,6 +203,7 @@ xtensa*) targ_archs=bfd_xtensa_arch ;;
xgate) targ_archs=bfd_xgate_arch ;;
z80|r800) targ_archs=bfd_z80_arch ;;
z8k*) targ_archs=bfd_z8k_arch ;;
+stm8*) targ_archs=bfd_stm8_arch ;;
*) targ_archs=bfd_${targ_cpu}_arch ;;
esac
@@ -1850,6 +1851,11 @@ case "${targ}" in
targ_underscore=yes
;;
+ stm8-*-elf*)
+ targ_defvec=stm8_elf32_vec
+ targ_underscore=yes
+ ;;
+
*-*-ieee*)
targ_defvec=ieee_vec
;;
diff --git a/bfd/configure b/bfd/configure
index 32ee062e80..463d0bedb6 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -14641,6 +14641,7 @@ do
xtensa_elf32_le_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
z80_coff_vec) tb="$tb coff-z80.lo reloc16.lo $coffgen" ;;
z8k_coff_vec) tb="$tb coff-z8k.lo reloc16.lo $coff" ;;
+ stm8_elf32_vec) tb="$tb elf32-stm8.lo elf32.lo $elf" ;;
# These appear out of order in targets.c
srec_vec) tb="$tb srec.lo" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 2342f3faea..d093fbe418 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -723,6 +723,7 @@ do
xtensa_elf32_le_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
z80_coff_vec) tb="$tb coff-z80.lo reloc16.lo $coffgen" ;;
z8k_coff_vec) tb="$tb coff-z8k.lo reloc16.lo $coff" ;;
+ stm8_elf32_vec) tb="$tb elf32-stm8.lo elf32.lo $elf" ;;
# These appear out of order in targets.c
srec_vec) tb="$tb srec.lo" ;;
diff --git a/bfd/cpu-stm8.c b/bfd/cpu-stm8.c
new file mode 100644
index 0000000000..feb6cf805e
--- /dev/null
+++ b/bfd/cpu-stm8.c
@@ -0,0 +1,40 @@
+/* BFD support for the STM8 processor.
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Written by <20>ke Rehnman (at) gmail dot com
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_stm8_arch =
+{
+ 8, /* bits per word */
+ 24, /* bits per address */
+ 8, /* bits per byte */
+ bfd_arch_stm8, /* architecture */
+ bfd_mach_stm8, /* machine */
+ "stm8", /* architecture name */
+ "stm8", /* printable name */
+ 4, /* section align power */
+ TRUE, /* the default ? */
+ bfd_default_compatible, /* architecture comparison fn */
+ bfd_default_scan, /* string to architecture convert fn */
+ bfd_arch_default_fill,
+ 0,
+};
diff --git a/bfd/cpu-stm8.h b/bfd/cpu-stm8.h
new file mode 100644
index 0000000000..665642ca3e
--- /dev/null
+++ b/bfd/cpu-stm8.h
@@ -0,0 +1,6 @@
+#ifndef __CPU_STM8_H
+#define __CPU_STM8_H
+
+extern bfd_stm8_arch;
+
+#endif
diff --git a/bfd/elf32-stm8.c b/bfd/elf32-stm8.c
new file mode 100644
index 0000000000..37995553c3
--- /dev/null
+++ b/bfd/elf32-stm8.c
@@ -0,0 +1,285 @@
+/* STM8-specific support for 32-bit ELF
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Written by <20>ke Rehnman (at) gmail dot com
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfd_stdint.h"
+#include "libiberty.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#include "elf/stm8.h"
+//#include "elf32-avr.h"
+#include "bfd_stdint.h"
+
+bfd_reloc_status_type
+bfd_elf_stm8_spec_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry,
+ asymbol *symbol,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED);
+
+static reloc_howto_type elf32_stm8_howto_table_1[] =
+{
+ HOWTO (R_STM8_NONE, /* type */
+ 0, /* rightshift */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_NONE", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 8 bit offset. */
+ HOWTO (R_STM8_8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_8", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 16 bit absolute relocation. */
+ HOWTO (R_STM8_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+//use this with unpatched bfd_get_reloc_size
+ HOWTO (R_STM8_24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */ //the relocation use bfd_get_32 so our relocation end up in the upper 24 bits and so relocation value has to be shifted 8 bits to the left
+ complain_overflow_unsigned, /* complain_on_overflow */
+ //bfd_elf_stm8_spec_reloc, /* special_function */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_24", /* name */
+ FALSE, /* partial_inplace */
+ 0xff000000, /* src_mask */
+ 0x00ffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+// HOWTO (R_STM8_24, /* type */
+// 0, /* rightshift */
+// 99, /* size (0 = byte, 1 = short, 2 = long, 99 = 24 bit) */
+// 24, /* bitsize */
+// FALSE, /* pc_relative */
+// 0, /* bitpos */ //the relocation use bfd_get_32 so our relocation end up in the upper 24 bits and so relocation value has to be shifted 8 bits to the left
+// complain_overflow_unsigned, /* complain_on_overflow */
+// bfd_elf_generic_reloc, /* special_function */
+// "R_STM8_24", /* name */
+// FALSE, /* partial_inplace */
+// 0x00, /* src_mask */
+// 0xffffff, /* dst_mask */
+// FALSE), /* pcrel_offset */
+
+ HOWTO (R_STM8_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_32", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 8 bit PC relative relocation. */
+ HOWTO (R_STM8_8_PCREL, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_STM8_8_PCREL", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+};
+
+//stupid bfd_elf_generic_reloc cant handle 24-bit relocations
+//so we have to write our own...
+bfd_reloc_status_type
+bfd_elf_stm8_spec_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry,
+ asymbol *symbol,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section ATTRIBUTE_UNUSED,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ if (output_bfd != NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset+1;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd == NULL)
+ return bfd_reloc_continue;
+ reloc_entry->address += input_section->output_offset-1;
+ return bfd_reloc_continue;
+}
+
+static reloc_howto_type *
+elf32_stm8_howto_from_type (unsigned int r_type)
+{
+ if (r_type < ARRAY_SIZE (elf32_stm8_howto_table_1))
+ return &elf32_stm8_howto_table_1[r_type];
+
+ return NULL;
+}
+
+static void
+elf32_stm8_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc,
+ Elf_Internal_Rela * elf_reloc)
+{
+ unsigned int r_type;
+
+ r_type = ELF32_R_TYPE (elf_reloc->r_info);
+ bfd_reloc->howto = elf32_stm8_howto_from_type (r_type);
+}
+
+struct elf32_stm8_reloc_map
+ {
+ bfd_reloc_code_real_type bfd_reloc_val;
+ unsigned char elf_reloc_val;
+ };
+
+/* All entries in this list must also be present in elf32_stm8_howto_table. */
+static const struct elf32_stm8_reloc_map elf32_stm8_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_STM8_NONE },
+ { BFD_RELOC_8, R_STM8_8 },
+ { BFD_RELOC_16, R_STM8_16 },
+ { BFD_RELOC_24, R_STM8_24 },
+ { BFD_RELOC_32, R_STM8_32 },
+ { BFD_RELOC_8_PCREL, R_STM8_8_PCREL}
+};
+
+static reloc_howto_type *
+elf32_stm8_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (elf32_stm8_reloc_map); i ++)
+ if (elf32_stm8_reloc_map[i].bfd_reloc_val == code)
+ return elf32_stm8_howto_from_type (elf32_stm8_reloc_map[i].elf_reloc_val);
+
+ return NULL;
+}
+
+static reloc_howto_type *
+elf32_stm8_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (elf32_stm8_howto_table_1); i++)
+ if (elf32_stm8_howto_table_1[i].name != NULL
+ && strcasecmp (elf32_stm8_howto_table_1[i].name, r_name) == 0)
+ return &elf32_stm8_howto_table_1[i];
+
+ return NULL;
+}
+
+static void
+elf32_stm8_post_process_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+// i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
+// i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_ARM;
+// i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+ i_ehdrp->e_ident[EI_ABIVERSION] = 0;
+}
+
+static bfd_boolean
+elf32_stm8_modify_segment_map (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ struct elf_segment_map *m;
+ return TRUE;
+ m = elf_seg_map (abfd);
+ while (m)
+ {
+ m->includes_filehdr = 0;
+ m->includes_phdrs = 0;
+ m = m->next;
+ }
+ return TRUE;
+}
+
+
+#define elf_backend_post_process_headers elf32_stm8_post_process_headers
+#define elf_backend_modify_segment_map elf32_stm8_modify_segment_map
+
+#define bfd_elf32_bfd_reloc_type_lookup elf32_stm8_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup elf32_stm8_reloc_name_lookup
+
+#define ELF_ARCH bfd_arch_stm8
+//#define ELF_TARGET_ID AVR_ELF_DATA
+#define ELF_TARGET_ID GENERIC_ELF_DATA
+#define ELF_MACHINE_CODE EM_STM8
+//#define ELF_OSABI ELFOSABI_STANDALONE
+//#define ELF_MACHINE_ALT1 EM_STM8_OLD
+#define ELF_MAXPAGESIZE 1
+//#define TARGET_LITTLE_SYM stm8_elf32_vec
+//#define TARGET_LITTLE_NAME "elf32-stm8"
+#define TARGET_BIG_SYM stm8_elf32_vec
+#define TARGET_BIG_NAME "elf32-stm8"
+
+#define elf_info_to_howto elf32_stm8_info_to_howto
+#define elf_info_to_howto_rel NULL
+
+#include "elf32-target.h"
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 00a900124a..eec2588464 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1468,12 +1468,22 @@ elf_slurp_reloc_table_from_section (bfd *abfd,
relent->addend = rela.r_addend;
- if ((entsize == sizeof (Elf_External_Rela)
- && ebd->elf_info_to_howto != NULL)
- || ebd->elf_info_to_howto_rel == NULL)
- (*ebd->elf_info_to_howto) (abfd, relent, &rela);
- else
- (*ebd->elf_info_to_howto_rel) (abfd, relent, &rela);
+// Ake Rehnman 2017-02-21
+// bug fixed, preventing call to elf_info_to_howto_rel
+// if elf_info_to_howto is NULL
+// if ((entsize == sizeof (Elf_External_Rela)
+// && ebd->elf_info_to_howto != NULL)
+// || ebd->elf_info_to_howto_rel == NULL)
+// (*ebd->elf_info_to_howto) (abfd, relent, &rela);
+// else
+// (*ebd->elf_info_to_howto_rel) (abfd, relent, &rela);
+ if (entsize == sizeof (Elf_External_Rela))
+ {
+ if (ebd->elf_info_to_howto)
+ (*ebd->elf_info_to_howto) (abfd, relent, &rela);
+ else if (ebd->elf_info_to_howto_rel)
+ (*ebd->elf_info_to_howto_rel) (abfd, relent, &rela);
+ }
}
if (allocated != NULL)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 2f5f16e776..fca8c19eed 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3188,6 +3188,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_WASM32_CODE_POINTER",
"BFD_RELOC_WASM32_INDEX",
"BFD_RELOC_WASM32_PLT_SIG",
+ "BFD_RELOC_STM8_BIT_FLD",
"@@overflow: BFD_RELOC_UNUSED@@",
};
#endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index a1353a281b..c7b862aab5 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -7931,6 +7931,11 @@ ENUMX
ENUMDOC
WebAssembly relocations.
+ENUM
+ BFD_RELOC_STM8_BIT_FLD
+ENUMDOC
+ STM8 bit field immediate for BTJx, BCPL, BSET, BRES instruction.
+
ENDSENUM
BFD_RELOC_UNUSED
CODE_FRAGMENT
diff --git a/bfd/targets.c b/bfd/targets.c
index 43102d428b..0e6f7dae2e 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -930,6 +930,7 @@ extern const bfd_target xtensa_elf32_be_vec;
extern const bfd_target xtensa_elf32_le_vec;
extern const bfd_target z80_coff_vec;
extern const bfd_target z8k_coff_vec;
+extern const bfd_target stm8_elf32_vec;
/* These are always included. */
extern const bfd_target srec_vec;
@@ -1174,6 +1175,7 @@ static const bfd_target * const _bfd_target_vector[] =
&m68hc11_elf32_vec,
&m68hc12_elf32_vec,
+ &stm8_elf32_vec,
#if 0
&m68k_aout_4knbsd_vec,
diff --git a/config.sub b/config.sub
index 40ea5dfe11..d4a68493c0 100755
--- a/config.sub
+++ b/config.sub
@@ -318,7 +318,8 @@ case $basic_machine in
| wasm32 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
+ | z8k | z80 \
+ | stm8)
basic_machine=$basic_machine-unknown
;;
c54x)
@@ -452,7 +453,8 @@ case $basic_machine in
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
- | z8k-* | z80-*)
+ | z8k-* | z80-* \
+ | stm8-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 5aa68f3c6a..b6af0cf2ca 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -203,7 +203,8 @@ TARGET_CPU_CFILES = \
config/tc-xtensa.c \
config/tc-z80.c \
config/tc-z8k.c \
- config/xtensa-relax.c
+ config/xtensa-relax.c \
+ config/tc-stm8.c
TARGET_CPU_HFILES = \
config/tc-aarch64.h \
@@ -279,7 +280,8 @@ TARGET_CPU_HFILES = \
config/tc-xtensa.h \
config/tc-z80.h \
config/tc-z8k.h \
- config/xtensa-relax.h
+ config/xtensa-relax.h \
+ config/tc-stm8.h
# OBJ files in config
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 51e96e52c1..b6d76c5348 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -499,7 +499,8 @@ TARGET_CPU_CFILES = \
config/tc-xtensa.c \
config/tc-z80.c \
config/tc-z8k.c \
- config/xtensa-relax.c
+ config/xtensa-relax.c \
+ config/tc-stm8.c
TARGET_CPU_HFILES = \
config/tc-aarch64.h \
@@ -575,7 +576,8 @@ TARGET_CPU_HFILES = \
config/tc-xtensa.h \
config/tc-z80.h \
config/tc-z8k.h \
- config/xtensa-relax.h
+ config/xtensa-relax.h \
+ config/tc-stm8.h
# OBJ files in config
@@ -920,6 +922,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-sh64.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-sparc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-spu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-stm8.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-tic30.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-tic4x.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-tic54x.Po@am__quote@
@@ -2011,6 +2014,20 @@ xtensa-relax.obj: config/xtensa-relax.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xtensa-relax.obj `if test -f 'config/xtensa-relax.c'; then $(CYGPATH_W) 'config/xtensa-relax.c'; else $(CYGPATH_W) '$(srcdir)/config/xtensa-relax.c'; fi`
+tc-stm8.o: config/tc-stm8.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-stm8.o -MD -MP -MF $(DEPDIR)/tc-stm8.Tpo -c -o tc-stm8.o `test -f 'config/tc-stm8.c' || echo '$(srcdir)/'`config/tc-stm8.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-stm8.Tpo $(DEPDIR)/tc-stm8.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-stm8.c' object='tc-stm8.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-stm8.o `test -f 'config/tc-stm8.c' || echo '$(srcdir)/'`config/tc-stm8.c
+
+tc-stm8.obj: config/tc-stm8.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-stm8.obj -MD -MP -MF $(DEPDIR)/tc-stm8.Tpo -c -o tc-stm8.obj `if test -f 'config/tc-stm8.c'; then $(CYGPATH_W) 'config/tc-stm8.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-stm8.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-stm8.Tpo $(DEPDIR)/tc-stm8.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-stm8.c' object='tc-stm8.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-stm8.obj `if test -f 'config/tc-stm8.c'; then $(CYGPATH_W) 'config/tc-stm8.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-stm8.c'; fi`
+
obj-aout.o: config/obj-aout.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT obj-aout.o -MD -MP -MF $(DEPDIR)/obj-aout.Tpo -c -o obj-aout.o `test -f 'config/obj-aout.c' || echo '$(srcdir)/'`config/obj-aout.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/obj-aout.Tpo $(DEPDIR)/obj-aout.Po
diff --git a/gas/config/tc-stm8.c b/gas/config/tc-stm8.c
new file mode 100644
index 0000000000..84e667278e
--- /dev/null
+++ b/gas/config/tc-stm8.c
@@ -0,0 +1,1026 @@
+/* tc-stm8.c -- Assembler for the STM8.
+ Written by Ake Rehnman 2017-02-21,
+ ake.rehnman (at) gmail dot com
+
+ Copyright (C) 2007-2017 Free Software Foundation, Inc.
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "as.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include "opcode/stm8.h"
+
+typedef enum {
+ OP_ILLEGAL = 0,
+ OP_IMM,
+ OP_SHORTMEM,
+ OP_MEM,
+ OP_INDX,
+ OP_INDY,
+ OP_OFF_X,
+ OP_OFF_Y,
+ OP_OFF_SP,
+ OP_PTRW,
+ OP_PTRE,
+ OP_PTRW_X,
+ OP_PTRW_Y,
+ OP_PTRE_X,
+ OP_PTRE_Y,
+ OP_REGISTER
+} stm8_operand_t;
+
+static struct hash_control *stm8_hash;
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = "{";
+
+int md_short_jump_size = 3;
+int md_long_jump_size = 4;
+
+/* The target specific pseudo-ops which we support. */
+/* example:
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"arch", avr_set_arch, 0},
+ { NULL, NULL, 0}
+};
+*/
+const pseudo_typeS md_pseudo_table[] =
+{
+ { NULL, NULL, 0}
+};
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant.
+ As in 0f12.456
+ or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* On the Z8000, a PC-relative offset is relative to the address of the
+ instruction plus its size. */
+long
+md_pcrel_from (fixS *fixP)
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+ return ieee_md_atof (type, litP, sizeP, TRUE);
+}
+
+void
+md_show_usage (FILE *stream)
+{
+ fprintf (stream, _("\
+ STM8 options:\n\
+ "));
+}
+
+const char *md_shortopts = "";
+
+struct option md_longopts[] =
+ {
+ {NULL, no_argument, NULL, 0}
+ };
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+void
+md_begin (void)
+{
+ const struct stm8_opcodes_s *opcode;
+ stm8_hash = 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 = stm8_opcodes; opcode->name; opcode++)
+ hash_insert (stm8_hash, opcode->name, (char *) opcode);
+
+ //add register names to symbol table
+
+ symbol_table_insert (symbol_create ("A", reg_section,
+ ST8_REG_A, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("X", reg_section,
+ ST8_REG_X, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("Y", reg_section,
+ ST8_REG_Y, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("SP", reg_section,
+ ST8_REG_SP, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("CC", reg_section,
+ ST8_REG_CC, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("XL", reg_section,
+ ST8_REG_XL, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("XH", reg_section,
+ ST8_REG_XH, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("YL", reg_section,
+ ST8_REG_YL, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("YH", reg_section,
+ ST8_REG_YH, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("a", reg_section,
+ ST8_REG_A, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("x", reg_section,
+ ST8_REG_X, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("y", reg_section,
+ ST8_REG_Y, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("sp", reg_section,
+ ST8_REG_SP, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("cc", reg_section,
+ ST8_REG_CC, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("xl", reg_section,
+ ST8_REG_XL, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("xh", reg_section,
+ ST8_REG_XH, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("yl", reg_section,
+ ST8_REG_YL, &zero_address_frag));
+
+ symbol_table_insert (symbol_create ("yh", reg_section,
+ ST8_REG_YH, &zero_address_frag));
+
+}
+
+static inline char *
+skip_space (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_end;
+ int size = 0;
+
+ /* Drop leading whitespace. */
+ from = skip_space (from);
+ *to = 0;
+
+ /* Find the op code end. */
+ for (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;
+}
+
+void
+md_operand (expressionS * exp __attribute__((unused)))
+{
+ /* In case of a syntax error, escape back to try next syntax combo. */
+ as_bad(_("stm8: call to md_operand"));
+}
+
+void print_fixup (fixS *);
+
+
+
+/* Attempt to simplify or eliminate a fixup. To indicate that a fixup
+ has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL,
+ we will have to generate a reloc entry. */
+void
+md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
+{
+ long val = * (long *) valP;
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ print_fixup(fixP);
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ if (fixP->fx_addsy)
+ {
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 0;
+ }
+ else
+ *buf++ = val;
+ break;
+
+ case BFD_RELOC_16:
+ if (fixP->fx_addsy)
+ {
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 0;
+ }
+ else
+ {
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ }
+ break;
+
+ case BFD_RELOC_24:
+ if (fixP->fx_addsy)
+ {
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 0;
+ fixP->fx_where--;
+ }
+ else
+ {
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ }
+ break;
+
+ case BFD_RELOC_32:
+ if (fixP->fx_addsy)
+ {
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 0;
+ }
+ else
+ {
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ }
+ break;
+
+ case BFD_RELOC_8_PCREL:
+ if (fixP->fx_addsy)
+ {
+ fixP->fx_pcrel_adjust = -1;
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 0;
+ }
+ else
+ {
+ if (val > 127 || val < -128)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relative jump out of range"));
+ *buf++ = val;
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 1;
+ }
+ break;
+
+ case BFD_RELOC_STM8_BIT_FLD:
+ if (val > 7 || val < 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("bitfield out of range %ld"),val);
+ *buf++ += val*2;
+ fixP->fx_no_overflow = 1;
+ fixP->fx_done = 1;
+ break;
+
+ default:
+ printf(_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
+ abort ();
+ }
+
+ if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
+}
+
+/* Generate a machine dependent reloc from a fixup. */
+
+arelent*
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
+ fixS *fixp ATTRIBUTE_UNUSED)
+{
+ arelent *reloc;
+
+ print_fixup(fixp);
+
+ reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->addend = fixp->fx_offset;
+ if (fixp->fx_r_type == BFD_RELOC_8_PCREL)
+ reloc->addend = fixp->fx_offset+ fixp->fx_pcrel_adjust;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+
+ if (! reloc->howto)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot represent %s relocation in object file"),
+ bfd_get_reloc_code_name (fixp->fx_r_type));
+ abort ();
+ }
+ return reloc;
+}
+
+valueT
+md_section_align (segT seg, valueT size)
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ valueT mask = ((valueT) 1 << align) - 1;
+
+ return (size + mask) & ~mask;
+}
+
+int
+md_parse_option (int c __attribute__((unused)), const char *arg __attribute__((unused)))
+{
+ return 1;
+}
+
+symbolS *
+md_undefined_symbol (char *name)
+{
+ return 0;
+ //Hande the case where a symbol has .w or .e suffix attached.
+ //This is actually quite stupid because the operand length is the
+ //same independent of whether it is .w or .e
+ char *p;
+ symbolS *symbolP=NULL;
+
+ if ((p=strstr(name,".w")))
+ {
+ if (*(p+2) == 0)
+ {
+ *p = 0;
+ symbolP = symbol_find (name);
+ //*p = '.';
+ }
+ }
+ if ((p=strstr(name,".l")))
+ {
+ if (*(p+2) == 0)
+ {
+ *p = 0;
+ symbolP = symbol_find (name);
+ //*p = '.';
+ }
+ }
+ if ((p=strstr(name,".e")))
+ {
+ if (*(p+2) == 0)
+ {
+ *p = 0;
+ symbolP = symbol_find (name);
+ //*p = '.';
+ }
+ }
+ return symbolP;
+}
+
+
+void
+md_create_long_jump (char *ptr __attribute__((unused)),
+ addressT from_addr ATTRIBUTE_UNUSED,
+ addressT to_addr __attribute__((unused)),
+ fragS *frag __attribute__((unused)),
+ symbolS *to_symbol __attribute__((unused)))
+{
+ as_bad(_("long_jump"));
+}
+
+void
+md_create_short_jump (char *ptr __attribute__((unused)),
+ addressT from_addr __attribute__((unused)),
+ addressT to_addr ATTRIBUTE_UNUSED,
+ fragS *frag ATTRIBUTE_UNUSED,
+ symbolS *to_symbol ATTRIBUTE_UNUSED)
+{
+ as_bad(_("short_jump"));
+}
+
+/* Put number into target byte order. */
+
+void
+md_number_to_chars (char *ptr, valueT use, int nbytes)
+{
+ number_to_chars_bigendian (ptr, use, nbytes);
+}
+
+int
+md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
+ segT segment_type ATTRIBUTE_UNUSED)
+{
+ as_bad (_("call to md_estimate_size_before_relax\n"));
+ return 0;
+}
+
+void
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+ segT sec ATTRIBUTE_UNUSED,
+ fragS *fragP ATTRIBUTE_UNUSED)
+{
+ as_bad (_("call to md_convert_frag\n"));
+}
+
+static
+char* match_parentheses(char* str)
+{
+ char *p;
+ int cnt=0;
+
+ p = str;
+ while (*p != 0)
+ {
+ if (*p == '(') cnt++;
+ if (*p == ')')
+ {
+ if (--cnt == 0)
+ return p;
+ }
+ p++;
+ }
+ return 0;
+}
+
+static
+int split_words(char *str, char **chunks)
+{
+ int i;
+ char *p;
+
+ p = str;
+ for (i=0;i<3;i++)
+ {
+ chunks[i] = str;
+ if (*str == 0)
+ break;
+ while(*p != 0)
+ {
+ if (*p=='(')
+ {
+ p = match_parentheses(str);
+ if (p == 0) return 0;
+ }
+ if (*p==',')
+ {
+ *p = 0;
+ p++;
+ break;
+ }
+ p++;
+ }
+ str = p;
+ }
+ return i;
+}
+
+static
+int read_arg_ptr(char *str, expressionS *exps)
+{
+ char *s;
+ char *p;
+ char c;
+
+ if ((str[0]=='[') && (strstr(str,"]")))
+ {
+ s = str;
+ s++;
+ input_line_pointer=s;
+
+ /* first eat up .w and .e */
+ if ((p = strstr(s,".w]")))
+ {
+ c = *p;
+ *p = 0;
+ }
+ else
+ if ((p = strstr(s,".e]")))
+ {
+ c = *p;
+ *p = 0;
+ }
+
+ expression(exps);
+ print_expr(exps);
+
+ /* restore c */
+ if (p)
+ *p = c;
+
+ //return default pointer len
+ if (*input_line_pointer == ']')
+ {
+ input_line_pointer+=1;
+ return 2;
+ } else
+ if ((*input_line_pointer == '.') && (*(input_line_pointer+1) == 'w'))
+ {
+ input_line_pointer+=2;
+ return 2;
+ } else
+ if ((*input_line_pointer == '.') && (*(input_line_pointer+1) == 'e'))
+ {
+ input_line_pointer+=2;
+ return 3;
+ }
+ else
+ {
+ as_bad("Expected ']' or '.e' or '.w' but found '%c'",*input_line_pointer);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+char* toupperstr(char *str);
+
+char* toupperstr(char *str)
+{
+ for(int i = 0; str[i]; i++){
+ str[i] = toupper(str[i]);
+ }
+ return str;
+}
+
+//expressionS last_exp;
+/* In: argument
+ Out: value
+ Modifies: type */
+static
+int read_arg(char *str, expressionS *exps)
+{
+ int ret;
+ const char *name ATTRIBUTE_UNUSED;
+ /* There is a number of addressing modes in ST8 architecture.
+ We need to properly handle each of them in order to find a proper opcode. */
+ if(!str) return(0);
+
+ //Immidate
+ if(str[0]=='#')
+ {
+ str++;
+ exps->X_md = OP_IMM;
+ input_line_pointer = str;
+ expression(exps);
+ print_expr(exps);
+ return 1;
+ }
+
+ char strx[256];
+ strncpy(strx,str,sizeof(strx));
+ toupperstr(strx);
+
+ //decode ptr operand
+ if (str[0]=='[')
+ {
+ ret = read_arg_ptr(str, exps);
+ if (ret>0)
+ {
+ if (ret == 2)
+ {
+ exps->X_md=OP_PTRW;
+ return 1;
+ }
+ if (ret == 3)
+ {
+ exps->X_md=OP_PTRE;
+ return 1;
+ }
+ }
+ else
+ return 0;
+ }
+ //decode index operands
+ //index X
+ else if ((str[0]=='(') && (strstr(strx,"(X)")))
+ {
+ exps->X_md=OP_INDX;
+ return 1;
+ }
+ //index Y
+ else if ((str[0]=='(') && (strstr(strx,"(Y)")))
+ {
+ exps->X_md=OP_INDY;
+ return 1;
+ }
+ //offset,X
+ else if ((str[0]=='(') && (strstr(strx,",X)")))
+ {
+ str++;
+ if (str[0]=='[')
+ {
+ ret = read_arg_ptr(str, exps);
+ if (ret==2)
+ {
+ exps->X_md=OP_PTRW_X;
+ return 1;
+ }
+ if (ret==3)
+ {
+ exps->X_md=OP_PTRE_X;
+ return 1;
+ }
+ return 0;
+ }
+ str=strtok(str,",");
+ input_line_pointer=str;
+ expression(exps);
+ print_expr(exps);
+ exps->X_md=OP_OFF_X;
+ return 1;
+ }
+ //offset,Y
+ else if ((str[0]=='(') && (strstr(strx,",Y)")))
+ {
+ str++;
+ if (str[0]=='[')
+ {
+ ret = read_arg_ptr(str, exps);
+ if (ret==2)
+ {
+ exps->X_md=OP_PTRW_Y;
+ return 1;
+ }
+ if (ret==3)
+ {
+ exps->X_md=OP_PTRE_Y;
+ return 1;
+ }
+ return 0;
+ }
+ str=strtok(str,",");
+ input_line_pointer=str;
+ expression(exps);
+ print_expr(exps);
+ exps->X_md=OP_OFF_X;
+ return 1;
+ }
+ //offset,SP
+ else if ((str[0]=='(') && (strstr(strx,",SP)")))
+ {
+ str++;
+ str=strtok(str,",");
+ input_line_pointer=str;
+ expression(exps);
+ print_expr(exps);
+ exps->X_md=OP_OFF_SP;
+ return 1;
+ }
+
+ char *p;
+ char c;
+ if ((p = strstr(str,".short")))
+ {
+ c = *p;
+ *p = 0;
+ exps->X_md = OP_SHORTMEM;
+ input_line_pointer = str;
+ expression(exps);
+ print_expr(exps);
+ *p = c;
+ input_line_pointer += 6;
+ return 1;
+ }
+
+ input_line_pointer = str;
+ expression(exps);
+ print_expr(exps);
+
+ if (exps->X_op == O_register)
+ {
+ exps->X_md = OP_REGISTER;
+ return 1;
+ }
+
+ if (exps->X_op != O_illegal)
+ {
+ exps->X_md = OP_MEM;
+ return 1;
+ }
+
+ /* Can't parse an expression, notifying caller about that. */
+ return(0);
+}
+
+static
+int read_args(char *str, expressionS exps[])
+{
+ char *chunks[3];
+ int count = split_words(str, chunks);
+ int i;
+ for(i = 0; i < count; i++)
+ {
+ int ret = read_arg(chunks[i], &(exps[i]));
+ if(!ret) as_bad("Invalid operand: %s", chunks[i]);
+ }
+ return(count);
+}
+
+static
+void stm8_bfd_out(struct stm8_opcodes_s op, expressionS exp[], int count, char *frag)
+{
+ int i;
+
+ for(i = 0; i < count; i++)
+ {
+ int where = frag - frag_now->fr_literal;
+
+ if (exp[i].X_op != O_illegal)
+ {
+ switch(op.constraints[i])
+ {
+ case ST8_EXTMEM:
+ case ST8_EXTOFF_X:
+ case ST8_EXTOFF_Y:
+ fix_new_exp(frag_now, where, 3, &exp[i], FALSE, BFD_RELOC_24);
+ bfd_put_bits(0xaaaaaaaa, frag, 24, true);
+ frag+=3;
+ break;
+ case ST8_LONGPTRW_Y:
+ case ST8_LONGPTRW_X:
+ case ST8_LONGPTRW:
+ case ST8_LONGPTRE:
+ case ST8_LONGOFF_Y:
+ case ST8_LONGOFF_X:
+ case ST8_WORD:
+ case ST8_LONGMEM:
+ fix_new_exp(frag_now, where, 2, &exp[i], FALSE, BFD_RELOC_16);
+ bfd_put_bits(0xaaaaaaaa, frag, 16, true);
+ frag+=2;
+ break;
+ case ST8_SHORTPTRW_Y:
+ case ST8_SHORTPTRW_X:
+ case ST8_SHORTPTRW:
+ case ST8_SHORTOFF_Y:
+ case ST8_SHORTOFF_X:
+ case ST8_SHORTOFF_SP:
+ case ST8_BYTE:
+ case ST8_SHORTMEM:
+ fix_new_exp(frag_now, where, 1, &exp[i], FALSE, BFD_RELOC_8);
+ bfd_put_bits(0xaaaaaaaa, frag, 8, true);
+ frag+=1;
+ break;
+ case ST8_PCREL:
+ fix_new_exp(frag_now, where, 1, &exp[i], TRUE, BFD_RELOC_8_PCREL);
+ bfd_put_bits(0xaaaaaaaa, frag, 8, true);
+ frag+=1;
+ break;
+ case ST8_BIT_0:
+ fix_new_exp(frag_now, where-3, 1, &exp[i], FALSE, BFD_RELOC_STM8_BIT_FLD);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static
+int cmpspec(stm8_addr_mode_t addr_mode[], expressionS exps[], int count)
+{
+ int i, ret = 0;
+ unsigned int value;
+ stm8_operand_t operand;
+
+ for(i = 0; i < count; i++) {
+ operand = exps[i].X_md;
+ if (!addr_mode || !operand)
+ continue; // End
+ if (exps[i].X_op == O_constant)
+ value = exps[i].X_add_number;
+ else
+ value = -1;
+
+ switch (operand)
+ {
+ case OP_REGISTER:
+ if (addr_mode[i] == (stm8_addr_mode_t)exps[i].X_add_number)
+ continue;
+ break;
+ case OP_IMM:
+ if (addr_mode[i] == ST8_BYTE)
+ continue;
+ if (addr_mode[i] == ST8_WORD)
+ continue;
+ if (addr_mode[i] == ST8_BIT_0)
+ continue;
+ break;
+ case OP_INDX:
+ if (addr_mode[i] == ST8_INDX)
+ continue;
+ break;
+ case OP_INDY:
+ if (addr_mode[i] == ST8_INDY)
+ continue;
+ break;
+ case OP_OFF_X:
+ if (addr_mode[i] == ST8_SHORTOFF_X)
+ if (value < 0x100)
+ continue;
+ if (addr_mode[i] == ST8_LONGOFF_X)
+ continue;
+ if (addr_mode[i] == ST8_EXTOFF_X)
+ continue;
+ break;
+ case OP_OFF_Y:
+ if (addr_mode[i] == ST8_SHORTOFF_Y)
+ if (value < 0x100)
+ continue;
+ if (addr_mode[i] == ST8_LONGOFF_Y)
+ continue;
+ if (addr_mode[i] == ST8_EXTOFF_Y)
+ continue;
+ break;
+ case OP_OFF_SP:
+ if (addr_mode[i] == ST8_SHORTOFF_SP)
+ continue;
+ break;
+ case OP_PTRW:
+ if (addr_mode[i] == ST8_SHORTPTRW)
+ if (value < 0x100)
+ continue;
+ if (addr_mode[i] == ST8_LONGPTRW)
+ continue;
+ break;
+ case OP_PTRW_X:
+ if (addr_mode[i] == ST8_SHORTPTRW_X)
+ if (value < 0x100)
+ continue;
+ if (addr_mode[i] == ST8_LONGPTRW_X)
+ continue;
+ break;
+ case OP_PTRW_Y:
+ if (addr_mode[i] == ST8_SHORTPTRW_Y)
+ if (value < 0x100)
+ continue;
+ if (addr_mode[i] == ST8_LONGPTRW_Y)
+ continue;
+ break;
+ case OP_PTRE:
+ if (addr_mode[i] == ST8_LONGPTRE)
+ continue;
+ break;
+ case OP_PTRE_X:
+ if (addr_mode[i] == ST8_LONGPTRE_X)
+ continue;
+ break;
+ case OP_PTRE_Y:
+ if (addr_mode[i] == ST8_LONGPTRE_Y)
+ continue;
+ break;
+ case OP_MEM:
+ if (addr_mode[i] == ST8_PCREL)
+ continue;
+ if (addr_mode[i] == ST8_EXTMEM)
+ continue;
+ if (addr_mode[i] == ST8_LONGMEM)
+ continue;
+ break;
+ case OP_SHORTMEM:
+ if (addr_mode[i] == ST8_SHORTMEM)
+ continue;
+ break;
+ case OP_ILLEGAL:
+ as_fatal(_("BUG: OP_ILLEGAL"));
+ return 1;
+ }
+
+// if (operand == ST8_DIRECT)
+// {
+// if (addr_mode[i] == ST8_SHORTMEM) continue;
+// }
+
+ //not a match
+ ret++;
+ }
+ return(ret);
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to. */
+
+void
+md_assemble (char *str)
+{
+ char op[11];
+ char *t = input_line_pointer;
+ char *str_orig = strdup(str);
+ str = skip_space(extract_word(str, op, sizeof(op)));
+ //stm8_operand_t spec[3];
+ expressionS exps[3];
+ //memset(spec, 0, sizeof(stm8_operand_t) * 3);
+ memset(exps, 0, sizeof(expressionS) * 3);
+
+ int count = read_args(str, exps);
+ struct stm8_opcodes_s *opcode = (struct stm8_opcodes_s *)hash_find(stm8_hash, op);
+
+ if (opcode == NULL) {
+ as_bad (_("unknown opcode `%s'"), op);
+ return;
+ }
+
+ int i;
+ for(i = 0; opcode[i].name != NULL; i++)
+ {
+ if (!strcmp(op, opcode[i].name))
+ if(!cmpspec(opcode[i].constraints, exps, count))
+ {
+ int insn_size = stm8_compute_insn_size(opcode[i]);
+ char *frag = frag_more(insn_size);
+ int opcode_length = stm8_opcode_size(opcode[i].bin_opcode);
+ bfd_put_bits(opcode[i].bin_opcode, frag, opcode_length * 8, true);
+ frag += opcode_length;
+ stm8_bfd_out(opcode[i], exps, count, frag);
+ break;
+ }
+ }
+ if(!opcode[i].name)
+ as_bad("Invalid instruction: %s", str_orig);
+ input_line_pointer = t;
+ free(str_orig);
+}
+
+
+/* If you define this macro, it should return the position from which
+ the PC relative adjustment for a PC relative fixup 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, plus the address of the PC relative fixup. The latter
+ can be calculated as fixp->fx_where +
+ fixp->fx_frag->fr_address. */
+
+long
+md_pcrel_from_section (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_size + fixp->fx_where + fixp->fx_frag->fr_address;
+ //return fixp->fx_frag->fr_address+fixp->fx_frag->fr_fix;
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+int stm8_need_index_operator()
+{
+ return 1;
+}
+
+operatorT stm8_operator (const char *name ATTRIBUTE_UNUSED, unsigned int operands ATTRIBUTE_UNUSED, char *pc ATTRIBUTE_UNUSED)
+{
+ return O_absent;
+}
+
+void stm8_check_label (symbolS *labelsym ATTRIBUTE_UNUSED)
+{
+}
+
+extern void stm8_symbol_new_hook (symbolS * labelsym)
+{
+ char* name;
+ char* p;
+ int value;
+
+ name = (char*)S_GET_NAME(labelsym);
+ if ((p=strstr(name,".b")))
+ {
+ if (*(p+2)==0)
+ {
+ *p=0;
+ S_SET_NAME(labelsym,name);
+ value=1;
+ symbol_set_tc(labelsym, &value);
+ }
+ }
+}
diff --git a/gas/config/tc-stm8.h b/gas/config/tc-stm8.h
new file mode 100644
index 0000000000..066e72ea43
--- /dev/null
+++ b/gas/config/tc-stm8.h
@@ -0,0 +1,97 @@
+/* This file is tc-stm8.h
+ Copyright (C) 1999-2016 Free Software Foundation, Inc.
+
+ Written by Ake Rehnman 2017-02-21,
+ ake.rehnman (at) gmail dot com
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+/* 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 TC_STM8
+
+/* 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_FORMAT "elf32-stm8"
+
+/* This macro is the BFD architecture to pass to `bfd_set_arch_mach'. */
+#define TARGET_ARCH bfd_arch_stm8
+
+/* 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_MACH 0
+
+/* You should define this macro to be non-zero if the target is big
+ endian, and zero if the target is little endian. */
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+/* If you define this macro, GAS will warn about the use of
+ nonstandard escape sequences in a string. */
+#define ONLY_STANDARD_ESCAPES
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* 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. */
+#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC)
+extern long md_pcrel_from_section (struct fix *, segT);
+
+#define NEED_INDEX_OPERATOR
+extern int stm8_need_index_operator (void);
+//#define md_need_index_operator stm8_need_index_operator
+
+#define NUMBERS_WITH_SUFFIX 1
+
+//#define UNDEFINED_DIFFERENCE_OK
+//#define TC_VALIDATE_FIX_SUB(fix, seg) stm8_validate_fix_sub (fix)
+//extern int stm8_validate_fix_sub (struct fix *);
+
+//#define STM8_FIXUP 128
+
+extern operatorT stm8_operator (const char *name, unsigned int operands, char *);
+#define md_operator stm8_operator
+
+extern void stm8_check_label (symbolS *labelsym);
+//#define tc_check_label(ls) stm8_check_label (ls)
+
+#define tc_symbol_new_hook(sym) stm8_symbol_new_hook (sym)
+extern void stm8_symbol_new_hook (symbolS * labelsym);
+
+#define TC_SYMFIELD_TYPE int
+
+#define md_register_arithmetic 0
+
+
+//int split_words(char *str, char **chunks);
+//int getnumber(const char *str, int *out);
+//int gethex(const char *str, int *out);
+//int getnum(const char *str, int *out);
+//int read_arg(char *str, expressionS *exps);
+//int read_args(char *str, expressionS exps[]);
+//unsigned int bytes_count(unsigned int number);
+//int compute_insn_size(struct stm8_opcodes_s opcode);
+//int cmpspec(stm8_addr_mode_t addr_mode[], expressionS exps[], int count);
+//void stm8_bfd_out(struct stm8_opcodes_s op, expressionS exp[], int count, char *frag);
+//char* match_parentheses(char* str);
+//int read_arg_ptr(char *str, expressionS *exps);
+//int is_ptr_w(stm8_addr_mode_t type);
diff --git a/gas/configure.tgt b/gas/configure.tgt
index afe4e0608c..81770e21ec 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -481,6 +481,8 @@ case ${generic_target} in
z8k-*-coff | z8k-*-sim) fmt=coff ;;
+ stm8-*-elf*) fmt=elf ;;
+
*-*-aout | *-*-scout) fmt=aout ;;
*-*-cloudabi*) fmt=elf ;;
*-*-dragonfly*) fmt=elf em=dragonfly ;;
@@ -497,7 +499,7 @@ case ${generic_target} in
esac
case ${cpu_type} in
- aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k)
+ aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k | stm8)
bfd_gas=yes
;;
esac
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index fb8014a8e8..e128398891 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -744,6 +744,11 @@ xtensa*-*-linux*) gdb_target=linux
gdb_target_obs="xtensa-linux-tdep.o symfile-mem.o linux-tdep.o"
build_gdbserver=yes
;;
+stm8-*-*)
+ # Target: STM8
+ gdb_target_obs="stm8-tdep.o"
+ #gdb_sim=../sim/stm8/libsim.a
+ ;;
esac
diff --git a/gdb/stm8-tdep.c b/gdb/stm8-tdep.c
new file mode 100644
index 0000000000..30b345cfd7
--- /dev/null
+++ b/gdb/stm8-tdep.c
@@ -0,0 +1,1130 @@
+/* Target-dependent code for STM8, for GDB.
+ Written by Ake Rehnman 2017-02-21,
+ ake.rehnman (at) gmail dot com
+
+ Copyright (C) 1996-2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "dis-asm.h"
+#include "objfiles.h"
+#include "target-descriptions.h"
+#include <algorithm>
+#include "dwarf2-frame.h"
+
+enum stm8_regnum
+{
+ STM8_PC_REGNUM,
+ STM8_A_REGNUM,
+ STM8_X_REGNUM,
+ STM8_Y_REGNUM,
+ STM8_SP_REGNUM,
+ STM8_CC_REGNUM,
+ //pseudo register
+ STM8_FP_REGNUM
+};
+
+static const char *stm8_register_names[] =
+{
+ "pc", "a", "x", "y", "sp", "cc"
+};
+
+struct stm8_soft_reg
+{
+ const char *name;
+ CORE_ADDR addr;
+};
+
+unsigned int stm8_debug;
+
+#define STM8_NUM_REGS ARRAY_SIZE (stm8_register_names)
+
+struct gdbarch_tdep
+{
+ struct stm8_soft_reg fp_reg;
+};
+
+enum insn_return_kind {
+ RETURN_RET,
+ RETURN_RETF,
+ RETURN_IRET
+};
+
+static int
+stm8_convert_register_p (struct gdbarch *gdbarch, int regnum,
+ struct type *type)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if ((regnum == STM8_FP_REGNUM) && (TYPE_LENGTH(type) > 2))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* Read a value of type TYPE from register REGNUM in frame FRAME, and
+ return its contents in TO. */
+
+static int
+stm8_register_to_value (struct frame_info *frame, int regnum,
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep)
+{
+ struct type *fpreg_type = register_type (get_frame_arch (frame),
+ STM8_FP_REGNUM);
+
+ /* We only support ptr values. */
+ if ((TYPE_CODE (type) != TYPE_CODE_PTR) && (regnum != STM8_FP_REGNUM) && (TYPE_LENGTH(type) >= TYPE_LENGTH(fpreg_type)))
+ {
+ warning (_("Conversion failure in stm8_register_to_value: regnum = %d "), regnum);
+ *optimizedp = *unavailablep = 0;
+ return 0;
+ }
+
+ /* Convert to TYPE. */
+
+ memset(to,0,TYPE_LENGTH(type));
+
+ if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (fpreg_type),
+ to+TYPE_LENGTH(type)-TYPE_LENGTH(fpreg_type), optimizedp, unavailablep))
+ return 0;
+
+ *optimizedp = *unavailablep = 0;
+ return 1;
+}
+
+
+/* Look in the symbol table for the address of a pseudo register
+ in memory. If we don't find it, pretend the register is not used
+ and not available. */
+static void
+stm8_get_register_info (struct stm8_soft_reg *reg, const char *name)
+{
+ struct bound_minimal_symbol msymbol;
+
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol.minsym)
+ {
+ reg->addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
+ reg->name = xstrdup (name);
+ }
+ else
+ {
+ reg->name = 0;
+ reg->addr = 0;
+ }
+}
+
+static void
+stm8_initialize_soft_register_info(struct gdbarch_tdep *tdep)
+{
+ stm8_get_register_info(&tdep->fp_reg, "_fp_");
+ if ((tdep->fp_reg.name == 0) && (symfile_objfile))
+ {
+ warning (_("No frame soft register found in the symbol table (_fp_).\n"
+ "Stack backtrace will not work.\n"));
+ }
+}
+
+static const char *
+stm8_register_name (struct gdbarch *gdbarch, int regnum)
+{
+ if (regnum >= 0 && regnum < STM8_NUM_REGS)
+ return stm8_register_names[regnum];
+ if (regnum == STM8_FP_REGNUM)
+ return "fp";
+ return NULL;
+}
+
+static struct type *
+stm8_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ switch (regnum)
+ {
+ case STM8_PC_REGNUM:
+ return builtin_type (gdbarch)->builtin_uint32;
+ case STM8_SP_REGNUM:
+ return builtin_type (gdbarch)->builtin_uint16;
+ case STM8_X_REGNUM:
+ case STM8_Y_REGNUM:
+ return builtin_type (gdbarch)->builtin_uint16;
+ case STM8_FP_REGNUM:
+ return builtin_type (gdbarch)->builtin_uint16;
+ default:
+ return builtin_type (gdbarch)->builtin_uint8;
+ }
+}
+
+static enum register_status
+stm8_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, gdb_byte *buf)
+{
+ enum register_status status;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int regsize = 2;
+
+ switch (regnum)
+ {
+ case STM8_FP_REGNUM:
+ /* Fetch a soft register: translate into a memory read. */
+ memset (buf, 0, regsize);
+ if (tdep->fp_reg.name)
+ {
+ target_read_memory (tdep->fp_reg.addr, buf, 2);
+ }
+ return REG_VALID;
+ default:
+ internal_error (__FILE__, __LINE__, _("invalid regnum"));
+ return REG_UNAVAILABLE;
+ }
+}
+
+static void
+stm8_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, const gdb_byte *buf)
+{
+ enum register_status status;
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ const int regsize = 2;
+
+ switch (regnum)
+ {
+ case STM8_FP_REGNUM:
+ /* Store a soft register: translate into a memory write. */
+ if (tdep->fp_reg.name)
+ {
+ target_write_memory (tdep->fp_reg.addr, buf, 2);
+ }
+ return;
+ default:
+ internal_error (__FILE__, __LINE__, _("invalid regnum"));
+ return;
+ }
+}
+
+
+struct stm8_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+
+ /* Do we have a frame? */
+ int frameless_p;
+
+ /* Frame size. */
+ int framesize;
+
+ /* Frame size. */
+ int stackadj;
+
+ /* Frame register. */
+ int fp_regnum;
+
+ /* Return instruction */
+ enum insn_return_kind return_kind;
+
+ /* Offsets to saved registers. */
+ int register_offsets[STM8_NUM_REGS];
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static const unsigned char *
+stm8_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *lenptr)
+{
+ static gdb_byte stm8_breakpoint[] = { 0x8b };
+
+ *lenptr = sizeof (stm8_breakpoint);
+ return stm8_breakpoint;
+}
+
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
+#if 0
+static int
+stm8_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+ CORE_ADDR pc = *pcptr;
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_breakpoint_kind_from_pc called %8.8lx\n",pc);
+
+ return 1;
+}
+
+static const gdb_byte *
+stm8_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_sw_breakpoint_from_kind called\n");
+
+ enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+
+ static gdb_byte stm8_breakpoint[] = { 0x8b };
+
+ *size = 1;
+
+ return stm8_breakpoint;
+}
+
+#endif
+
+static int dwarf2_to_reg_map[6] =
+{ 0 /* r0 */, 1 /* r1 */, 2 /* r2 */, 3 /* r3 */, /* 0- 3 */
+ 4 /* r4 */, 5 /* r5 */
+};
+
+static int
+stm8_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg)
+{
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_dwarf2_reg_to_regnum called\n");
+ if (reg >= 0 && reg < sizeof (dwarf2_to_reg_map))
+ return dwarf2_to_reg_map[reg];
+ if (reg == 31)
+ return STM8_FP_REGNUM;
+ return -1;
+}
+
+static void
+stm8_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_write_pc called\n");
+ regcache_cooked_write_unsigned (regcache, STM8_PC_REGNUM, pc);
+}
+
+static CORE_ADDR
+stm8_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ gdb_byte buf[4];
+ CORE_ADDR pc;
+
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ frame_unwind_register (next_frame, STM8_PC_REGNUM, buf);
+ pc = extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_unwind_pc called: pc=%8.8lx\n",pc);
+ return pc;
+}
+
+static CORE_ADDR
+stm8_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ ULONGEST sp;
+
+ sp = frame_unwind_register_unsigned (next_frame, STM8_SP_REGNUM);
+ sp = gdbarch_addr_bits_remove (gdbarch, sp);
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_unwind_sp called: sp=%8.8llx\n",sp);
+ return sp;
+}
+
+#if 0
+static struct value *
+stm8_dwarf2_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
+{
+ CORE_ADDR pc;
+
+ switch (regnum)
+ {
+ case STM8_PC_REGNUM:
+ pc = frame_unwind_register_unsigned (this_frame, AARCH64_PC_REGNUM);
+ return frame_unwind_got_constant (this_frame, regnum, lr);
+
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("Unexpected register %d"), regnum);
+ }
+}
+
+static void
+stm8_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
+{
+ switch (regnum)
+ {
+ case STM8_PC_REGNUM:
+ reg->how = DWARF2_FRAME_REG_FN;
+ reg->loc.fn = stm8_dwarf2_prev_register;
+ break;
+ case STM8_SP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_CFA;
+ break;
+ }
+}
+#endif
+
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that
+ dummy frame. The frame ID's base needs to match the TOS value
+ saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+ breakpoint. */
+
+static struct frame_id
+stm8_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ fprintf_unfiltered (gdb_stdlog, "stm8_dummy_id called\n");
+
+ return frame_id_build
+ (get_frame_register_signed (this_frame, STM8_SP_REGNUM),
+ get_frame_pc (this_frame));
+}
+
+
+/* Allocate and initialize a frame cache. */
+
+static struct stm8_frame_cache *
+stm8_alloc_frame_cache (void)
+{
+ struct stm8_frame_cache *cache;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct stm8_frame_cache);
+
+ // /* Base address. */
+ cache->base = 0;
+ cache->pc = 0;
+
+ /* Frameless until proven otherwise. */
+ cache->frameless_p = 1;
+
+ return cache;
+}
+
+/* Figure out what return type this function has. */
+static enum insn_return_kind
+stm8_get_return_insn (CORE_ADDR pc)
+{
+ const char *name;
+ CORE_ADDR func_addr, func_end, stop;
+
+ if (find_pc_partial_function (pc, &name, &func_addr, &func_end))
+ {
+ gdb_byte buf[1];
+ //func_end is pointing to last insn+1 ???
+ if (!target_read_code (func_end-1, buf, sizeof (buf)))
+ {
+ switch (buf[0])
+ {
+ case 0x81:
+ return RETURN_RET;
+ case 0x87:
+ return RETURN_RETF;
+ case 0x80:
+ return RETURN_IRET;
+ }
+ }
+ }
+
+ //defaut to RET
+ if (stm8_debug)
+ fprintf_unfiltered(gdb_stdlog, "WARNING: stm8_get_return_insn: No return instruction found in function %s start_addr = %8.8lx end_addr = %8.8lx\n", name, func_addr, func_end);
+ return RETURN_RET;
+}
+
+/* Find the start of this function. */
+static CORE_ADDR
+stm8_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ CORE_ADDR current_pc,
+ struct stm8_frame_cache *cache)
+{
+ const char *name;
+ CORE_ADDR func_addr, func_end, stop;
+ unsigned long insn;
+ int done;
+ gdb_byte buf[4];
+
+ if (stm8_debug)
+ fprintf_unfiltered(gdb_stdlog, "stm8_analyze_prologue called (pc=%8.8lx current_pc=%8.8lx)\n",pc,current_pc);
+
+ /* Initialize info about frame. */
+ cache->framesize = 0;
+ cache->fp_regnum = STM8_FP_REGNUM;
+ cache->frameless_p = 1;
+ cache->stackadj = 0;
+
+ /* Find the start of this function. */
+ find_pc_partial_function (pc, &name, &func_addr, &func_end);
+ if (func_addr < pc)
+ pc = func_addr;
+
+ if (current_pc < pc)
+ return current_pc;
+
+ /* Start decoding the prologue. We start by checking two special cases:
+
+ 1. We're about to return
+ 2. We're at the first insn of the prologue.
+
+ If we're about to return, our frame has already been deallocated.
+ If we are stopped at the first instruction of a prologue,
+ then our frame has not yet been set up. */
+
+ /* Get the first insn from memory. */
+ if (target_read_code (pc, buf, sizeof (buf)))
+ return current_pc;
+
+ //RET?
+ if (buf[0] == 0x81)
+ {
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_analyze_prologue: current_pc is RTS so we dont have a frame!\n");
+ return pc;
+ }
+
+ /* Start at beginning of function and analyze until we get to the
+ current pc, or the end of the function, whichever is first. */
+ stop = (current_pc < func_end ? current_pc : func_end);
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_analyze_prologue: name=%s, func_addr=%s, stop=%s\n",
+ name, paddress (gdbarch, func_addr),
+ paddress (gdbarch, stop));
+
+ /* scan the prologue */
+ pc = func_addr;
+ done = 0;
+ while ((pc < stop) && !done)
+ {
+ if (target_read_code (pc, buf, sizeof (buf)))
+ return current_pc;
+
+ insn = buf[0];
+ if (buf[0] == 0x90)
+ insn = (insn << 8) + buf[1];
+
+ switch (insn)
+ {
+ case 0x3b:
+ //PUSH extmem
+ cache->framesize += 1;
+ pc += 3;
+ break;
+ case 0x9096:
+ //LDW Y, SP
+ pc += 2;
+ break;
+ case 0x90cf:
+ //LDW extmem, Y
+ pc += 4;
+ cache->frameless_p = 0;
+ break;
+ case 0x52:
+ //SUB SP,#xx?
+ cache->framesize += buf[1];
+ pc+=2;
+ break;
+ case 0x88:
+ //PUSH A?
+ cache->framesize += 1;
+ pc++;
+ break;
+ case 0x89:
+ //PUSH X?
+ cache->framesize += 2;
+ pc++;
+ break;
+ case 0x9089:
+ //PUSH Y?
+ cache->framesize += 2;
+ pc+=2;
+ break;
+ default:
+ done = 1;
+ }
+
+ }
+
+ if (stm8_debug)
+ if (cache->frameless_p)
+ fprintf_unfiltered (gdb_stdlog, "stm8_analyze_prologue: this function is frameless! No pc adjustment was done.\n");
+
+ return pc;
+}
+
+/* Return PC of first real instruction of the function starting at
+ START_PC. */
+
+static CORE_ADDR
+stm8_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
+{
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue called: start_pc=%8.8lx\n", start_pc);
+
+ struct symtab_and_line sal;
+ CORE_ADDR func_start, func_end, ostart_pc;
+ struct stm8_frame_cache cache;
+
+ /* This is the preferred method, find the end of the prologue by
+ using the debugging information. Debugging info does not always
+ give the right answer since parameters are stored on stack after this.
+ Always analyze the prologue. */
+ if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end))
+ {
+ sal = find_pc_line (func_start, 0);
+
+ if (sal.end < func_end
+ && start_pc <= sal.end)
+ start_pc = sal.end;
+ }
+
+ ostart_pc = stm8_analyze_prologue (gdbarch, func_start, 0xffffffffUL,
+ &cache);
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue: start_pc=%8.8lx ostart_pc=%8.8lx\n",start_pc,ostart_pc);
+
+ if (ostart_pc > start_pc)
+ return ostart_pc;
+ return start_pc;
+}
+
+/* Normal frames.
+
+ The STM8 frame is typically:
+
+ args
+ return lo addr
+ return hi addr
+ prev fp lo
+ prev fp hi
+ locals <- fp
+sp-> empty
+ */
+
+static struct stm8_frame_cache *
+stm8_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache called (next_frame=%p)\n",next_frame);
+
+ struct stm8_frame_cache *cache;
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ CORE_ADDR start_pc, current_pc, current_sp, fp;
+ int retsize;
+
+ if (*this_cache)
+ return (struct stm8_frame_cache *) *this_cache;
+
+ cache = stm8_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+ start_pc = get_frame_func (next_frame);
+
+ cache->return_kind = stm8_get_return_insn (start_pc);
+
+ current_pc = get_frame_pc (next_frame);
+ current_sp = get_frame_sp (next_frame);
+
+ /* Analyze the function prologue. */
+ if (start_pc != 0)
+ stm8_analyze_prologue (gdbarch, start_pc, current_pc,
+ (struct stm8_frame_cache *) *this_cache);
+
+ /* get our fp by unwinding it from the next frame
+ * if we don't have a fp we use sp instead but if there
+ * are arguments on the stack unwinding will be
+ * unpredictable.
+ */
+ //fp = frame_unwind_register_unsigned (next_frame, cache->fp_regnum);
+ fp = get_frame_register_unsigned (next_frame, cache->fp_regnum);
+ if (fp == 0)
+ {
+ cache->base = 0;
+ cache->frameless_p = 1;
+ //return (struct stm8_frame_cache *) (*this_cache);
+ }
+
+ switch (cache->return_kind)
+ {
+ case RETURN_RET:
+ retsize = 2;
+ break;
+ case RETURN_RETF:
+ retsize = 3;
+ break;
+ case RETURN_IRET:
+ retsize = 9;
+ break;
+ }
+
+ if (cache->frameless_p)
+ {
+ cache->base = current_sp + cache->framesize;
+ if (cache->return_kind == RETURN_IRET)
+ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1 + 6;
+ else
+ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1;
+ trad_frame_set_value (cache->saved_regs,
+ STM8_SP_REGNUM,
+ cache->base+retsize);
+ }
+ else
+ {
+ /* fp points to our base */
+ cache->base = fp;
+ if (cache->return_kind == RETURN_IRET)
+ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1 + 2 + 6;
+ else
+ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1 + 2;
+ cache->saved_regs[STM8_FP_REGNUM].addr = fp + 1;
+ trad_frame_set_value (cache->saved_regs,
+ STM8_SP_REGNUM,
+ cache->base+retsize+2);
+ }
+
+
+ if (stm8_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) base=%4.4lx curr_pc=%4.4lx curr_sp=%4.4lx fp_regnum=%d fp=%4.4lx framesize=%4.4x stackadj=%4.4x retsize=%d\n",
+ next_frame, cache->base, current_pc, current_sp, cache->fp_regnum, fp, cache->framesize, cache->stackadj, retsize);
+
+ CORE_ADDR frame_pc;
+ CORE_ADDR frame_sp;
+ CORE_ADDR frame_fp;
+ frame_pc = value_as_long(trad_frame_get_prev_register (next_frame, cache->saved_regs, STM8_PC_REGNUM));
+ frame_sp = value_as_long(trad_frame_get_prev_register (next_frame, cache->saved_regs, STM8_SP_REGNUM));
+
+ // this is stupid, trad_frame_get_prev_register can't get a
+ // register value unless we have a valid frame id
+ // hopefully this will get resolved in the future :)
+ if (cache->saved_regs[STM8_FP_REGNUM].addr > 0)
+ frame_fp = value_as_long(trad_frame_get_prev_register (next_frame, cache->saved_regs, STM8_FP_REGNUM));
+ else
+ frame_fp = fp;
+
+ frame_pc = frame_pc >> 16;
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) pc=%8.8llx *pc=%8.8lx\n", next_frame, cache->saved_regs[STM8_PC_REGNUM].addr, frame_pc);
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) sp=%8.8llx *sp=%8.8lx\n", next_frame, cache->saved_regs[STM8_SP_REGNUM].addr, frame_sp);
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) fp=%8.8llx *fp=%8.8lx\n", next_frame, cache->saved_regs[STM8_FP_REGNUM].addr, frame_fp);
+ }
+
+ return (struct stm8_frame_cache *) (*this_cache);
+}
+
+
+/* Given a GDB frame, determine the address of the calling function's
+ frame. This will be used to create a new GDB frame struct. */
+static void
+stm8_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct stm8_frame_cache *cache =
+ stm8_frame_cache (next_frame, this_cache);
+ CORE_ADDR func;
+ CORE_ADDR base;
+
+ func = get_frame_func (next_frame);
+ base = cache->base;
+
+ /* This marks the outermost frame. */
+ if (base == 0)
+ return;
+
+ (*this_id) = frame_id_build (base, func);
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_this_id: base=%8.8lx pc=%8.8lx\n",base, func);
+}
+
+static struct value *
+stm8_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
+{
+ struct value *value;
+ struct stm8_frame_cache *info = stm8_frame_cache (this_frame,
+ this_cache);
+
+ value = trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+
+ /* Take into account the STM8 specific call.
+ * Different lengths if it is CALL or CALLF */
+ if (regnum == STM8_PC_REGNUM)
+ {
+ CORE_ADDR pc = value_as_long (value);
+ if (info->return_kind == RETURN_RET)
+ pc >>= 16;
+ else
+ pc >>= 8;
+
+ release_value (value);
+ value_free (value);
+
+ value = frame_unwind_got_constant (this_frame, regnum, pc);
+ }
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_prev_register: regnum(%d)=%8.8llx\n", regnum, value_as_long(value));
+
+ return value;
+}
+
+static void
+stm8_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *valbuf)
+{
+ int len;
+
+ len = TYPE_LENGTH (type);
+
+ if (len == 1)
+ regcache_raw_write_part (regcache, STM8_A_REGNUM, 0, 1, valbuf);
+ else if (len == 2)
+ regcache_raw_write_part (regcache, STM8_X_REGNUM, 0, 2, valbuf);
+ else if (len == 4)
+ {
+ regcache_raw_write_part (regcache, STM8_X_REGNUM, 0, 2, valbuf+2);
+ regcache_raw_write_part (regcache, STM8_Y_REGNUM, 0, 2, valbuf);
+ }
+ else
+ error (_("return of value > 4 is not supported."));
+}
+
+/* Given a return value in `regcache' with a type `type',
+ extract and copy its value into `valbuf'. */
+
+static void
+stm8_extract_return_value (struct type *type, struct regcache *regcache,
+ void *valbuf)
+{
+ gdb_byte buf[2];
+
+ switch (TYPE_LENGTH (type))
+ {
+ case 1:
+ regcache_raw_read (regcache, STM8_A_REGNUM, buf);
+ memcpy (valbuf, buf, 1);
+ break;
+
+ case 2:
+ regcache_raw_read (regcache, STM8_X_REGNUM, buf);
+ memcpy (valbuf, buf, 2);
+ break;
+
+ case 4:
+ regcache_raw_read (regcache, STM8_X_REGNUM, buf);
+ memcpy ((char*) valbuf + 2, buf, 2);
+ regcache_raw_read (regcache, STM8_Y_REGNUM, buf);
+ memcpy (valbuf, buf, 2);
+ break;
+
+ default:
+ error (_("bad size for return value"));
+ }
+}
+
+static enum return_value_convention
+stm8_return_value (struct gdbarch *gdbarch, struct value *function,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+ || TYPE_CODE (valtype) == TYPE_CODE_UNION
+ || TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+ || TYPE_LENGTH (valtype) > 4)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ {
+ if (readbuf != NULL)
+ stm8_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf != NULL)
+ stm8_store_return_value (valtype, regcache, writebuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+}
+
+static const struct frame_unwind stm8_frame_unwind = {
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ stm8_frame_this_id,
+ stm8_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+static CORE_ADDR
+stm8_frame_base_address (struct frame_info *next_frame,
+ void **this_cache)
+{
+ struct stm8_frame_cache *cache =
+ stm8_frame_cache (next_frame, this_cache);
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_base_address: fb=%8.8lx\n", cache->base);
+
+ return cache->base;
+}
+
+static CORE_ADDR
+stm8_frame_args_address (struct frame_info *this_frame, void **this_cache)
+{
+ CORE_ADDR addr;
+ struct stm8_frame_cache *info
+ = stm8_frame_cache (this_frame, this_cache);
+
+ addr = info->base;
+ if (info->return_kind == RETURN_IRET)
+ addr += 12; //2 bytes fp + 9 bytes regs + 1
+ else if (info->return_kind == RETURN_RETF)
+ addr += 6; //2 bytes fp + 3 bytes pc + 1
+ else
+ addr += 5; //2 bytes fp + 2 bytes pc + 1
+
+ if (stm8_debug)
+ fprintf_unfiltered (gdb_stdlog, "stm8_frame_args_address: addr = %8.8lx\n",addr);
+
+ return addr;
+}
+
+static const struct frame_base stm8_frame_base =
+{
+ &stm8_frame_unwind,
+ stm8_frame_base_address,
+ stm8_frame_base_address,
+ stm8_frame_args_address
+};
+
+static const struct frame_base *
+stm8_frame_base_sniffer (struct frame_info *this_frame)
+{
+ return &stm8_frame_base;
+}
+
+struct target_desc *tdesc_stm8;
+static void
+initialize_tdesc_stm8 (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.stm8.core");
+ tdesc_create_reg (feature, "pc", 0, 1, "general", 32, "uint32");
+ tdesc_create_reg (feature, "a", 1, 1, "general", 8, "uint8");
+ tdesc_create_reg (feature, "x", 2, 1, "general", 16, "uint16");
+ tdesc_create_reg (feature, "y", 3, 1, "general", 16, "uint16");
+ tdesc_create_reg (feature, "sp", 4, 1, "general", 16, "uint16");
+ tdesc_create_reg (feature, "cc", 5, 1, "general", 8, "uint16");
+
+ tdesc_stm8 = result;
+}
+
+
+/* Initialize the gdbarch structure for the STM8. */
+
+static struct gdbarch *
+stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+ struct gdbarch_list *best_arch;
+ struct tdesc_arch_data *tdesc_data = NULL;
+ const struct target_desc *tdesc = info.target_desc;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ {
+ tdep = gdbarch_tdep (arches->gdbarch);
+ stm8_initialize_soft_register_info(tdep);
+ return arches->gdbarch;
+ }
+ if (tdesc == NULL)
+ tdesc = tdesc_stm8;
+
+ /* Check any target description for validity. */
+ if (tdesc_has_registers (tdesc))
+ {
+ const struct tdesc_feature *feature;
+ int valid_p;
+ int i;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.stm8.core");
+ if (feature == NULL)
+ return NULL;
+ tdesc_data = tdesc_data_alloc ();
+
+ valid_p = 1;
+ for (int i = 0; i < STM8_NUM_REGS; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ stm8_register_names[i]);
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ }
+
+ /* None found, create a new architecture from the information provided. */
+ tdep = XNEW (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ /* Initialize soft registers */
+ stm8_initialize_soft_register_info(tdep);
+
+ set_gdbarch_num_regs (gdbarch, STM8_NUM_REGS);
+ set_gdbarch_register_name (gdbarch, stm8_register_name);
+ set_gdbarch_register_type (gdbarch, stm8_register_type);
+ set_tdesc_pseudo_register_type (gdbarch, stm8_register_type);
+ set_tdesc_pseudo_register_name (gdbarch, stm8_register_name);
+
+ set_gdbarch_num_pseudo_regs (gdbarch, 1);
+ set_gdbarch_pseudo_register_read (gdbarch, stm8_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, stm8_pseudo_register_write);
+
+ set_gdbarch_convert_register_p (gdbarch, stm8_convert_register_p);
+ set_gdbarch_register_to_value (gdbarch, stm8_register_to_value);
+
+ /* Register numbers of various important registers. */
+ set_gdbarch_sp_regnum (gdbarch, STM8_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, STM8_PC_REGNUM);
+ set_gdbarch_ps_regnum (gdbarch, STM8_CC_REGNUM);
+
+ //set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+ //set_gdbarch_addr_bit (gdbarch, 3 * TARGET_CHAR_BIT);
+
+ /* Map Dwarf2 registers to GDB registers. */
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, stm8_dwarf2_reg_to_regnum);
+
+ /* Call dummy code. */
+ set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+
+ set_gdbarch_return_value (gdbarch, stm8_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, stm8_skip_prologue);
+
+ /* Stack grows downward. */
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+#if 0
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, stm8_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, stm8_sw_breakpoint_from_kind);
+#endif
+ set_gdbarch_breakpoint_from_pc (gdbarch, stm8_breakpoint_from_pc);
+
+ //set_gdbarch_frame_args_skip (gdbarch, 8);
+
+ set_gdbarch_print_insn (gdbarch, print_insn_stm8);
+
+ set_gdbarch_write_pc (gdbarch, stm8_write_pc);
+
+ set_gdbarch_unwind_pc (gdbarch, stm8_unwind_pc);
+ set_gdbarch_unwind_sp (gdbarch, stm8_unwind_sp);
+ set_gdbarch_dummy_id (gdbarch, stm8_dummy_id);
+
+ frame_base_set_default (gdbarch, &stm8_frame_base);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ //gdbarch_init_osabi (info, gdbarch);
+
+ //dwarf2 cfi unwinder
+ //dwarf2_frame_set_init_reg (gdbarch, stm8_dwarf2_frame_init_reg);
+
+ dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &stm8_frame_unwind);
+ frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
+ frame_base_append_sniffer (gdbarch, stm8_frame_base_sniffer);
+
+// /* Create a type for PC. We can't use builtin types here, as they may not
+// be defined. */
+// tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+// tdep->func_void_type = make_function_type (tdep->void_type, NULL);
+// tdep->pc_type = arch_pointer_type (gdbarch, 4 * TARGET_CHAR_BIT, NULL,
+// tdep->func_void_type);
+//
+// set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+// set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+// set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+// set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+// set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+// set_gdbarch_addr_bit (gdbarch, 32);
+//
+// set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+// set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+// set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+//
+// set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+// set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
+// set_gdbarch_long_double_format (gdbarch, floatformats_ieee_single);
+//
+//
+// set_gdbarch_push_dummy_call (gdbarch, stm8_push_dummy_call);
+//
+// set_gdbarch_dwarf2_reg_to_regnum (gdbarch, stm8_dwarf_reg_to_regnum);
+//
+// set_gdbarch_address_to_pointer (gdbarch, avr_address_to_pointer);
+// set_gdbarch_pointer_to_address (gdbarch, avr_pointer_to_address);
+// set_gdbarch_integer_to_address (gdbarch, avr_integer_to_address);
+//
+// frame_base_set_default (gdbarch, &stm8_frame_base);
+//
+// set_gdbarch_dummy_id (gdbarch, stm8_dummy_id);
+//
+//
+
+ if (tdesc_data != NULL)
+ tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+
+ return gdbarch;
+}
+
+static void
+show_stm8_debug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("stm8 debugging is %s.\n"), value);
+}
+
+extern initialize_file_ftype _initialize_stm8_tdep; /* -Wmissing-prototypes */
+
+void
+_initialize_stm8_tdep (void)
+{
+ stm8_debug = 0;
+ register_gdbarch_init (bfd_arch_stm8, stm8_gdbarch_init);
+ initialize_tdesc_stm8 ();
+
+ add_setshow_zuinteger_cmd ("stm8", class_maintenance, &stm8_debug, _("\
+Set stm8 debugging."), _("\
+Show stm8 debugging."), _("\
+When non-zero, stm8 debugging is enabled."),
+NULL,
+show_stm8_debug,
+&setdebuglist, &showdebuglist);
+
+}
diff --git a/include/dis-asm.h b/include/dis-asm.h
index eebdaf874f..234dfed263 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -248,6 +248,7 @@ extern int print_insn_rl78 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g10 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g13 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g14 (bfd_vma, disassemble_info *);
+extern int print_insn_stm8 (bfd_vma, disassemble_info *);
extern disassembler_ftype arc_get_disassembler (bfd *);
extern disassembler_ftype cris_get_disassembler (bfd *);
diff --git a/include/elf/stm8.h b/include/elf/stm8.h
new file mode 100644
index 0000000000..4f70335431
--- /dev/null
+++ b/include/elf/stm8.h
@@ -0,0 +1,38 @@
+/* STM8 ELF support for BFD.
+ Written by Ake Rehnman 2017-02-21,
+ ake.rehnman (at) gmail dot com
+
+ Copyright (C) 1999-2016 Free Software Foundation, Inc.
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _ELF_STM8_H
+#define _ELF_STM8_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocations. */
+START_RELOC_NUMBERS (elf_avr_reloc_type)
+ RELOC_NUMBER (R_STM8_NONE, 0)
+ RELOC_NUMBER (R_STM8_8, 1)
+ RELOC_NUMBER (R_STM8_16, 2)
+ RELOC_NUMBER (R_STM8_24, 3)
+ RELOC_NUMBER (R_STM8_32, 4)
+ RELOC_NUMBER (R_STM8_8_PCREL, 5)
+END_RELOC_NUMBERS (R_STM8_max)
+
+#endif /* _ELF_STM_H */
diff --git a/include/opcode/stm8.h b/include/opcode/stm8.h
new file mode 100644
index 0000000000..a40ff0aaaa
--- /dev/null
+++ b/include/opcode/stm8.h
@@ -0,0 +1,82 @@
+/* include/opcode/stm8.h -- Assembler for the STM8.
+ Written by Ake Rehnman 2017-02-21,
+ ake.rehnman (at) gmail dot com
+
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _STM8_H_
+#define _STM8_H_
+
+typedef enum {
+ ST8_END = 0,
+ ST8_BIT_0,
+ ST8_BIT_1,
+ ST8_BIT_2,
+ ST8_BIT_3,
+ ST8_BIT_4,
+ ST8_BIT_5,
+ ST8_BIT_6,
+ ST8_BIT_7,
+ ST8_PCREL,
+ ST8_REG_CC,
+ ST8_REG_A,
+ ST8_REG_X,
+ ST8_REG_Y,
+ ST8_REG_SP,
+ ST8_REG_XL,
+ ST8_REG_XH,
+ ST8_REG_YL,
+ ST8_REG_YH,
+ ST8_BYTE, //IMM8
+ ST8_WORD, //IMM16
+ ST8_SHORTMEM, //DIR8
+ ST8_LONGMEM, //DIR16
+ ST8_EXTMEM, //DIR24
+ ST8_INDX,
+ ST8_INDY,
+ ST8_SHORTOFF_X,
+ ST8_LONGOFF_X,
+ ST8_EXTOFF_X,
+ ST8_SHORTOFF_Y,
+ ST8_LONGOFF_Y,
+ ST8_EXTOFF_Y,
+ ST8_SHORTOFF_SP,
+ ST8_SHORTPTRW,
+ ST8_LONGPTRW,
+ ST8_SHORTPTRW_X,
+ ST8_LONGPTRW_X,
+ ST8_SHORTPTRW_Y,
+ ST8_LONGPTRW_Y,
+ ST8_LONGPTRE,
+ ST8_LONGPTRE_X,
+ ST8_LONGPTRE_Y
+} stm8_addr_mode_t;
+
+struct stm8_opcodes_s
+{
+ const char * name;
+ stm8_addr_mode_t constraints[5];
+ unsigned int bin_opcode;
+};
+
+extern const struct stm8_opcodes_s stm8_opcodes[];
+
+extern int stm8_compute_insn_size(struct stm8_opcodes_s opcode);
+
+extern unsigned int stm8_opcode_size(unsigned int number);
+
+#endif /* _STM8_H_ */
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 6243c12528..edac1c77fc 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -516,7 +516,8 @@ ALL_64_EMULATION_SOURCES = \
eshelf64.c \
eshelf64_nbsd.c \
eshlelf64.c \
- eshlelf64_nbsd.c
+ eshlelf64_nbsd.c \
+ eelf32stm8.c
ALL_64_EMULATIONS = $(ALL_64_EMULATION_SOURCES:.c=.@OBJEXT@)
@@ -2093,6 +2094,10 @@ eshlelf64_nbsd.c: $(srcdir)/emulparams/shlelf64_nbsd.sh \
$(srcdir)/emulparams/shelf64_nbsd.sh \
$(srcdir)/emulparams/shelf32_nbsd.sh $(srcdir)/emulparams/shelf32.sh \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+
+eelf32stm8.c: $(srcdir)/emulparams/elf32stm8.sh \
+ $(ELF_DEPS) $(srcdir)/scripttempl/elfstm8.sc ${GEN_DEPENDS}
+
# We need this for automake to use YLWRAP.
diff --git a/ld/Makefile.in b/ld/Makefile.in
index 760c037f9d..a73392c0d6 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -884,7 +884,8 @@ ALL_64_EMULATION_SOURCES = \
eshelf64.c \
eshelf64_nbsd.c \
eshlelf64.c \
- eshlelf64_nbsd.c
+ eshlelf64_nbsd.c \
+ eelf32stm8.c
ALL_64_EMULATIONS = $(ALL_64_EMULATION_SOURCES:.c=.@OBJEXT@)
ALL_EMUL_EXTRA_OFILES = \
@@ -1282,6 +1283,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcwindiss.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32stm8.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx_be.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilepro.Po@am__quote@
@@ -3658,6 +3660,9 @@ eshlelf64_nbsd.c: $(srcdir)/emulparams/shlelf64_nbsd.sh \
$(srcdir)/emulparams/shelf32_nbsd.sh $(srcdir)/emulparams/shelf32.sh \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+eelf32stm8.c: $(srcdir)/emulparams/elf32stm8.sh \
+ $(ELF_DEPS) $(srcdir)/scripttempl/elfstm8.sc ${GEN_DEPENDS}
+
check-DEJAGNU: site.exp
srcroot=`cd $(srcdir) && pwd`; export srcroot; \
r=`pwd`; export r; \
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 6183a85b3d..3f6e0f28f4 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -877,6 +877,8 @@ z80-*-coff) targ_emul=z80
;;
z8k-*-coff) targ_emul=z8002; targ_extra_emuls=z8001
;;
+stm8-*-elf32) targ_emul=elf32stm8
+ ;;
*-*-ieee*) targ_emul=vanilla
;;
*-tandem-none) targ_emul=st2000
diff --git a/ld/emulparams/elf32stm8.sh b/ld/emulparams/elf32stm8.sh
new file mode 100644
index 0000000000..c37c9e51da
--- /dev/null
+++ b/ld/emulparams/elf32stm8.sh
@@ -0,0 +1,14 @@
+ARCH=stm8
+MACHINE=stm8
+SCRIPT_NAME=elfstm8
+OUTPUT_FORMAT="elf32-stm8"
+MAXPAGESIZE=1
+EMBEDDED=yes
+TEMPLATE_NAME=elf32
+
+TEXT_LENGTH=1024K
+DATA_ORIGIN=0x802000
+DATA_LENGTH=0xffa0
+
+
+
diff --git a/ld/scripttempl/elfstm8.sc b/ld/scripttempl/elfstm8.sc
new file mode 100644
index 0000000000..0ce6b56741
--- /dev/null
+++ b/ld/scripttempl/elfstm8.sc
@@ -0,0 +1,232 @@
+# Adapted from mips.sc
+#
+# Copyright (C) 2014-2016 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# These variables may be overridden by the emulation file. The
+# defaults are appropriate for a DECstation running Ultrix.
+
+test -z "$ENTRY" && ENTRY=_start
+
+#test -z "$TEXT_START_ADDR" && TEXT_START_ADDR="0x0"
+
+CTOR=".ctors ${CONSTRUCTING-0} :
+ {
+ ${CONSTRUCTING+${CTOR_START}}
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+
+ KEEP (*crtbegin.o(.ctors))
+
+ /* We don't want to include the .ctor section from
+ from the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ ${CONSTRUCTING+${CTOR_END}}
+ }"
+
+DTOR=" .dtors ${CONSTRUCTING-0} :
+ {
+ ${CONSTRUCTING+${DTOR_START}}
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ ${CONSTRUCTING+${DTOR_END}}
+ }"
+
+cat <<EOF
+/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+
+OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+ "${LITTLE_OUTPUT_FORMAT}")
+/*${LIB_SEARCH_DIRS}*/
+${RELOCATING+${LIB_SEARCH_DIRS}}
+
+${RELOCATING+ENTRY (${ENTRY})}
+
+_TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x50;
+_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0;
+_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400;
+
+SECTIONS
+{
+ .vectors.reset 0x8000 : { KEEP (*(.vectors.reset)) } = 0
+
+ ${RELOCATING+. = _TEXT_START_ADDR;}
+
+ ${RELOCATING+ _ftext = .;}
+ .text : {
+ ${RELOCATING+*(.text)}
+ ${RELOCATING+*(.text.*)}
+ ${RELOCATING+*(.gnu.linkonce.t.*)}
+ }
+ ${RELOCATING+ _etext = .;}
+
+ .init : { KEEP (*(.init)) } =0
+ .fini : { KEEP (*(.fini)) } =0
+
+ ${RELOCATING+PROVIDE (__CTOR_LIST__ = .);}
+ ${RELOCATING+PROVIDE (___CTOR_LIST__ = .);}
+ ${RELOCATING+${CTOR}}
+ ${RELOCATING+PROVIDE (__CTOR_END__ = .);}
+ ${RELOCATING+PROVIDE (___CTOR_END__ = .);}
+
+ ${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
+ ${RELOCATING+PROVIDE (___DTOR_LIST__ = .);}
+ ${RELOCATING+${DTOR}}
+ ${RELOCATING+PROVIDE (__DTOR_END__ = .);}
+ ${RELOCATING+PROVIDE (___DTOR_END__ = .);}
+
+ ${RELOCATING+ . = ALIGN(4);}
+ ${RELOCATING+ _frodata = . ;}
+ .rodata : {
+ ${RELOCATING+*(.rodata)}
+ ${RELOCATING+*(.rodata.*)}
+ ${RELOCATING+*(.gnu.linkonce.r.*)}
+ ${CONSTRUCTING+CONSTRUCTORS}; /* Is this needed? */
+ }
+ ${RELOCATING+ _erodata = .;}
+
+ /* Alignments by 8 to ensure that _SDA2_BASE_ on a word boundary */
+ /* Note that .sdata2 and .sbss2 must be contiguous */
+ ${RELOCATING+. = ALIGN(8);}
+ ${RELOCATING+ _ssrw = .;}
+ .sdata2 : {
+ ${RELOCATING+*(.sdata2)}
+ ${RELOCATING+*(.sdata2.*)}
+ ${RELOCATING+*(.gnu.linkonce.s2.*)}
+ }
+ ${RELOCATING+. = ALIGN(4);}
+ .sbss2 : {
+ ${RELOCATING+PROVIDE (__sbss2_start = .);}
+ ${RELOCATING+*(.sbss2)}
+ ${RELOCATING+*(.sbss2.*)}
+ ${RELOCATING+*(.gnu.linkonce.sb2.*)}
+ ${RELOCATING+PROVIDE (__sbss2_end = .);}
+ }
+ ${RELOCATING+. = ALIGN(8);}
+ ${RELOCATING+ _essrw = .;}
+ ${RELOCATING+ _ssrw_size = _essrw - _ssrw;}
+ ${RELOCATING+ PROVIDE (_SDA2_BASE_ = _ssrw + (_ssrw_size / 2 ));}
+
+ ${RELOCATING+ . = ALIGN(4);}
+ ${RELOCATING+ _fdata = .;}
+ .data : {
+ ${RELOCATING+*(.data)}
+ ${RELOCATING+*(.gnu.linkonce.d.*)}
+ ${CONSTRUCTING+CONSTRUCTORS}; /* Is this needed? */
+ }
+ ${RELOCATING+ _edata = . ;}
+
+ /* Added to handle pic code */
+ .got : {
+ ${RELOCATING+*(.got)}
+ }
+
+ .got1 : {
+ ${RELOCATING+*(.got1)}
+ }
+
+ .got2 : {
+ ${RELOCATING+*(.got2)}
+ }
+
+ /* Added by Sathya to handle C++ exceptions */
+ .eh_frame : {
+ ${RELOCATING+*(.eh_frame)}
+ }
+
+ .jcr : {
+ ${RELOCATING+*(.jcr)}
+ }
+
+ .gcc_except_table : {
+ ${RELOCATING+*(.gcc_except_table)}
+ }
+
+ /* Alignments by 8 to ensure that _SDA_BASE_ on a word boundary */
+ /* Note that .sdata and .sbss must be contiguous */
+ ${RELOCATING+. = ALIGN(8);}
+ ${RELOCATING+ _ssro = .;}
+ .sdata : {
+ ${RELOCATING+*(.sdata)}
+ ${RELOCATING+*(.sdata.*)}
+ ${RELOCATING+*(.gnu.linkonce.s.*)}
+ }
+ ${RELOCATING+. = ALIGN(4);}
+ .sbss : {
+ ${RELOCATING+PROVIDE (__sbss_start = .);}
+ ${RELOCATING+*(.sbss)}
+ ${RELOCATING+*(.sbss.*)}
+ ${RELOCATING+*(.gnu.linkonce.sb.*)}
+ ${RELOCATING+PROVIDE (__sbss_end = .);}
+ }
+ ${RELOCATING+. = ALIGN(8);}
+ ${RELOCATING+ _essro = .;}
+ ${RELOCATING+ _ssro_size = _essro - _ssro;}
+ ${RELOCATING+PROVIDE (_SDA_BASE_ = _ssro + (_ssro_size / 2 ));}
+
+ ${RELOCATING+ . = ALIGN(4);}
+ ${RELOCATING+ _fbss = .;}
+ .bss : {
+ ${RELOCATING+PROVIDE (__bss_start = .);}
+ ${RELOCATING+*(.bss)}
+ ${RELOCATING+*(.bss.*)}
+ ${RELOCATING+*(.gnu.linkonce.b.*)}
+ ${RELOCATING+*(COMMON)}
+ ${RELOCATING+. = ALIGN(. != 0 ? 4 : 1);}
+
+ ${RELOCATING+PROVIDE (__bss_end = .);}
+
+ }
+
+ ${RELOCATING+ . = ALIGN(4);}
+
+ .heap : {
+ ${RELOCATING+ _heap = .;}
+ ${RELOCATING+ _heap_start = .;}
+ ${RELOCATING+ . += _HEAP_SIZE;}
+ ${RELOCATING+ _heap_end = .;}
+ }
+
+ ${RELOCATING+ . = ALIGN(4);}
+
+ .stack : {
+ ${RELOCATING+ _stack_end = .;}
+ ${RELOCATING+ . += _STACK_SIZE;}
+ ${RELOCATING+ . = ALIGN(. != 0 ? 8 : 1);}
+ ${RELOCATING+ _stack = .;}
+ ${RELOCATING+ _end = .;}
+ }
+
+ .tdata : {
+ ${RELOCATING+*(.tdata)}
+ ${RELOCATING+*(.tdata.*)}
+ ${RELOCATING+*(.gnu.linkonce.td.*)}
+ }
+ .tbss : {
+ ${RELOCATING+*(.tbss)}
+ ${RELOCATING+*(.tbss.*)}
+ ${RELOCATING+*(.gnu.linkonce.tb.*)}
+ }
+}
+EOF
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index 2458027922..8c3ce6f326 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -274,7 +274,9 @@ TARGET_LIBOPCODES_CFILES = \
xgate-dis.c \
xgate-opc.c \
z80-dis.c \
- z8k-dis.c
+ z8k-dis.c \
+ stm8-dis.c \
+ stm8-opc.c
# C source files that correspond to .o's ending up in libopcodes.
LIBOPCODES_CFILES = \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index a130efc3bf..79b081f42e 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -576,7 +576,9 @@ TARGET_LIBOPCODES_CFILES = \
xgate-dis.c \
xgate-opc.c \
z80-dis.c \
- z8k-dis.c
+ z8k-dis.c \
+ stm8-dis.c \
+ stm8-opc.c
# C source files that correspond to .o's ending up in libopcodes.
@@ -953,6 +955,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sparc-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spu-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spu-opc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stm8-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stm8-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tic30-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tic4x-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tic54x-dis.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index 17530f54b9..00e7970773 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12732,6 +12732,7 @@ if test x${all_targets} = xfalse ; then
bfd_xtensa_arch) ta="$ta xtensa-dis.lo" ;;
bfd_z80_arch) ta="$ta z80-dis.lo" ;;
bfd_z8k_arch) ta="$ta z8k-dis.lo" ;;
+ bfd_stm8_arch) ta="$ta stm8-dis.lo stm8-opc.lo" ;;
"") ;;
*) as_fn_error "*** unknown target architecture $arch" "$LINENO" 5 ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index b07f3f3629..b1d52045a1 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -356,6 +356,7 @@ if test x${all_targets} = xfalse ; then
bfd_xtensa_arch) ta="$ta xtensa-dis.lo" ;;
bfd_z80_arch) ta="$ta z80-dis.lo" ;;
bfd_z8k_arch) ta="$ta z8k-dis.lo" ;;
+ bfd_stm8_arch) ta="$ta stm8-dis.lo stm8-opc.lo" ;;
"") ;;
*) AC_MSG_ERROR(*** unknown target architecture $arch) ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index ae48f5367b..6f307bea6b 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -102,6 +102,7 @@
#define ARCH_xtensa
#define ARCH_z80
#define ARCH_z8k
+#define ARCH_stm8
#define INCLUDE_SHMEDIA
#endif
@@ -515,6 +516,11 @@ disassembler (enum bfd_architecture a,
disassemble = print_insn_z8002;
break;
#endif
+#ifdef ARCH_stm8
+ case bfd_arch_stm8:
+ disassemble = print_insn_stm8;
+ break;
+#endif
#ifdef ARCH_vax
case bfd_arch_vax:
disassemble = print_insn_vax;
diff --git a/opcodes/stm8-dis.c b/opcodes/stm8-dis.c
new file mode 100644
index 0000000000..751c62c2b7
--- /dev/null
+++ b/opcodes/stm8-dis.c
@@ -0,0 +1,412 @@
+/* Disassemble STM8 instructions.
+ Copyright (C) 1999-2016 Free Software Foundation, Inc.
+
+ Contributed by Ake Rehnman
+
+ This file is part of libopcodes.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include <assert.h>
+#include "dis-asm.h"
+#include "opintl.h"
+#include "libiberty.h"
+
+#include "opcode/stm8.h"
+
+disassemble_info *dinfo;
+bfd_vma daddr;
+int instrlen;
+bfd_vma lastlabeladdr;
+unsigned char buffer[16];
+
+int stm8_dis(bfd_vma addr, unsigned int op);
+int stm8_operands(char *s, unsigned char buf[], stm8_addr_mode_t arg);
+const char* find_symbol(unsigned int addr);
+int find_symbol_x(bfd_vma addr);
+
+
+static int
+fetch_data (unsigned char *buf, bfd_vma addr, disassemble_info *info, int n)
+{
+ int r;
+
+ r = info->read_memory_func (addr, buf, n, info);
+ return r;
+}
+
+int find_symbol_x(bfd_vma addr)
+{
+ return dinfo->symbol_at_address_func(addr,dinfo);
+}
+
+const char* find_symbol(unsigned int addr)
+{
+ int i;
+
+ for (i=0;i<(dinfo->symtab_size);i++)
+ {
+ if ((dinfo->symtab[i]->value+dinfo->symtab[i]->section->vma) == addr)
+ return dinfo->symtab[i]->name;
+ }
+ lastlabeladdr = addr;
+ return 0;
+}
+
+int stm8_operands(char *s, unsigned char buf[], stm8_addr_mode_t arg)
+{
+ unsigned int val;
+ const char *sym;
+
+ switch(arg)
+ {
+ case ST8_REG_A:
+ sprintf(s,"A");
+ break;
+ case ST8_REG_X:
+ sprintf(s,"X");
+ break;
+ case ST8_REG_Y:
+ sprintf(s,"Y");
+ break;
+ case ST8_REG_SP:
+ sprintf(s,"SP");
+ break;
+ case ST8_REG_CC:
+ sprintf(s,"CC");
+ break;
+ case ST8_REG_XL:
+ sprintf(s,"XL");
+ break;
+ case ST8_REG_XH:
+ sprintf(s,"XH");
+ break;
+ case ST8_REG_YL:
+ sprintf(s,"YL");
+ break;
+ case ST8_REG_YH:
+ sprintf(s,"YH");
+ break;
+ case ST8_BIT_0:
+ sprintf(s,"#0");
+ break;
+ case ST8_BIT_1:
+ sprintf(s,"#1");
+ break;
+ case ST8_BIT_2:
+ sprintf(s,"#2");
+ break;
+ case ST8_BIT_3:
+ sprintf(s,"#3");
+ break;
+ case ST8_BIT_4:
+ sprintf(s,"#4");
+ break;
+ case ST8_BIT_5:
+ sprintf(s,"#5");
+ break;
+ case ST8_BIT_6:
+ sprintf(s,"#6");
+ break;
+ case ST8_BIT_7:
+ sprintf(s,"#7");
+ break;
+ case ST8_BYTE:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"#%s",sym);
+ else
+ sprintf(s,"#0x%2.2x",val);
+ return 1;
+ break;
+ case ST8_WORD:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"#%s",sym);
+ else
+ sprintf(s,"#0x%4.4x",val);
+ return 2;
+ break;
+ case ST8_PCREL:
+ val = (char)buf[0];
+ val += (daddr + instrlen);
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"%s",sym);
+ else
+ sprintf(s,"0x%4.4x",val);
+ return 1;
+ break;
+ case ST8_SHORTMEM:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"%s",sym);
+ else
+ sprintf(s,"0x%2.2x",val);
+ return 1;
+ break;
+ case ST8_INDX:
+ sprintf(s,"(X)");
+ break;
+ case ST8_SHORTOFF_X:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,X)",sym);
+ else
+ sprintf(s,"(0x%2.2x,X)",val);
+ return 1;
+ break;
+ case ST8_INDY:
+ sprintf(s,"(Y)");
+ break;
+ case ST8_SHORTOFF_Y:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,Y)",sym);
+ else
+ sprintf(s,"(0x%2.2x,Y)",val);
+ return 1;
+ break;
+ case ST8_SHORTOFF_SP:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,SP)",sym);
+ else
+ sprintf(s,"(0x%2.2x,SP)",val);
+ return 1;
+ break;
+ case ST8_SHORTPTRW:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"[%s.w]",sym);
+ else
+ sprintf(s,"[0x%2.2x.w]",val);
+ return 1;
+ break;
+ case ST8_SHORTPTRW_X:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.w],X)",sym);
+ else
+ sprintf(s,"([0x%2.2x.w],X)",val);
+ return 1;
+ break;
+ case ST8_SHORTPTRW_Y:
+ val = buf[0];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.w],Y)",sym);
+ else
+ sprintf(s,"([0x%2.2x.w],Y)",val);
+ return 1;
+ break;
+ case ST8_LONGMEM:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"%s",sym);
+ else
+ sprintf(s,"0x%4.4x",val);
+ return 2;
+ break;
+ case ST8_LONGOFF_X:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,X)",sym);
+ else
+ sprintf(s,"(0x%4.4x,X)",val);
+ return 2;
+ break;
+ case ST8_LONGOFF_Y:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,Y)",sym);
+ else
+ sprintf(s,"(0x%4.4x,Y)",val);
+ return 2;
+ break;
+ case ST8_LONGPTRW:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"[%s.w]",sym);
+ else
+ sprintf(s,"[0x%4.4x.w]",val);
+ return 2;
+ break;
+ case ST8_LONGPTRW_X:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.w],X)",sym);
+ else
+ sprintf(s,"([0x%4.4x.w],X)",val);
+ return 2;
+ break;
+ case ST8_LONGPTRW_Y:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.w],Y)",sym);
+ else
+ sprintf(s,"([0x%4.4x.w],Y)",val);
+ return 2;
+ break;
+ case ST8_LONGPTRE:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"[%s.e]",sym);
+ else
+ sprintf(s,"[0x%4.4x.e]",val);
+ return 2;
+ break;
+ case ST8_LONGPTRE_X:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.e],X)",sym);
+ else
+ sprintf(s,"([0x%4.4x.e],X)",val);
+ return 2;
+ break;
+ case ST8_LONGPTRE_Y:
+ val = (buf[0]<<8)+buf[1];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"([%s.e],Y)",sym);
+ else
+ sprintf(s,"([0x%4.4x.e],Y)",val);
+ return 2;
+ break;
+ case ST8_EXTMEM:
+ val = (buf[0]<<16)+(buf[1]<<8)+buf[2];
+// if (find_symbol_x(val))
+// dinfo->print_address_func(val,dinfo);
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"%s",sym);
+ else
+ sprintf(s,"0x%6.6x",val);
+ return 3;
+ break;
+ case ST8_EXTOFF_X:
+ val = (buf[0]<<16)+(buf[1]<<8)+buf[2];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,X)",sym);
+ else
+ sprintf(s,"(0x%6.6x,X)",val);
+ return 3;
+ break;
+ case ST8_EXTOFF_Y:
+ val = (buf[0]<<16)+(buf[1]<<8)+buf[2];
+ sym = find_symbol(val);
+ if (sym)
+ sprintf(s,"(%s,Y)",sym);
+ else
+ sprintf(s,"(0x%6.6x,Y)",val);
+ return 3;
+ break;
+ case ST8_END:
+ break;
+ }
+ return 0;
+}
+
+int stm8_dis(bfd_vma addr, unsigned int op)
+{
+ unsigned char buf[8];
+ unsigned char *bufp;
+ char s[256];
+ int i=0;
+ int j;
+ char c;
+ int operandlen;
+
+ while (stm8_opcodes[i].name)
+ {
+ if (op == stm8_opcodes[i].bin_opcode)
+ {
+ bufp=buf;
+ s[0] = 0;
+ dinfo->fprintf_func(dinfo->stream, "%s",stm8_opcodes[i].name);
+ operandlen = stm8_compute_insn_size(stm8_opcodes[i])-stm8_opcode_size(op);
+ instrlen += operandlen;
+ if (fetch_data(buf,addr,dinfo,operandlen))
+ return 0;
+ lastlabeladdr = 0;
+ for (j=0;j<5;j++)
+ {
+ s[0]=0;
+ bufp+=stm8_operands(s, bufp, stm8_opcodes[i].constraints[j]);
+ if (s[0])
+ {
+ if (j==0) c=' '; else c=',';
+ dinfo->fprintf_func(dinfo->stream, "%c%s",c,s);
+ }
+ }
+ if (lastlabeladdr)
+ {
+ dinfo->fprintf_func(dinfo->stream, " ;");
+ dinfo->print_address_func(lastlabeladdr, dinfo);
+ }
+ return operandlen;
+ }
+ i++;
+ }
+ return 0;
+}
+
+#define PDY 0x90
+#define PIX 0x92
+#define PIY 0x91
+#define PWSP 0x72
+
+int print_insn_stm8 (bfd_vma addr, disassemble_info *info)
+{
+ unsigned int op;
+
+ instrlen = 0;
+ dinfo = info;
+ daddr = addr;
+ if (!fetch_data(buffer, addr, info, 1))
+ {
+ op = buffer[0];
+ instrlen++;
+ if ((buffer[0]==PDY) || (buffer[0]==PIX) || (buffer[0]==PIY) || (buffer[0]==PWSP))
+ {
+ if (fetch_data(buffer, addr, info, 2))
+ return -1;
+ instrlen++;
+ op = buffer[0]<<8;
+ op += buffer[1];
+ }
+ stm8_dis(addr+instrlen, op);
+ }
+ return instrlen;
+}
diff --git a/opcodes/stm8-opc.c b/opcodes/stm8-opc.c
new file mode 100644
index 0000000000..3a600d66d3
--- /dev/null
+++ b/opcodes/stm8-opc.c
@@ -0,0 +1,799 @@
+/* stm8-opc.c -- Table of opcodes for the STM8 processor.
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
+ Contributed by Ake Rehnman ake dot rehnman (at) gmail dot com
+
+ This file is part of the GNU opcodes library.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include "libiberty.h"
+#include "symcat.h"
+#include "opcode/stm8.h"
+
+const struct stm8_opcodes_s stm8_opcodes[] =
+{
+//nop
+{"nop", {}, 0x9D},
+//adc
+{"adc", {ST8_REG_A, ST8_BYTE}, 0xA9},
+{"adc", {ST8_REG_A, ST8_SHORTMEM}, 0xB9},
+{"adc", {ST8_REG_A, ST8_LONGMEM}, 0xC9},
+{"adc", {ST8_REG_A, ST8_INDX}, 0xF9},
+{"adc", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE9},
+{"adc", {ST8_REG_A, ST8_LONGOFF_X}, 0xD9},
+{"adc", {ST8_REG_A, ST8_INDY}, 0x90F9},
+{"adc", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E9},
+{"adc", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D9},
+{"adc", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x19},
+{"adc", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C9},
+{"adc", {ST8_REG_A, ST8_LONGPTRW}, 0x72C9},
+{"adc", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D9},
+{"adc", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D9},
+{"adc", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D9},
+//add
+{"add", {ST8_REG_A, ST8_BYTE}, 0xAB},
+{"add", {ST8_REG_A, ST8_SHORTMEM}, 0xBB},
+{"add", {ST8_REG_A, ST8_LONGMEM}, 0xCB},
+{"add", {ST8_REG_A, ST8_INDX}, 0xFB},
+{"add", {ST8_REG_A, ST8_SHORTOFF_X}, 0xEB},
+{"add", {ST8_REG_A, ST8_LONGOFF_X}, 0xDB},
+{"add", {ST8_REG_A, ST8_INDY}, 0x90FB},
+{"add", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90EB},
+{"add", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90DB},
+{"add", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x1B},
+{"add", {ST8_REG_A, ST8_SHORTPTRW}, 0x92CB},
+{"add", {ST8_REG_A, ST8_LONGPTRW}, 0x72CB},
+{"add", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92DB},
+{"add", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72DB},
+{"add", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91DB},
+//addw
+{"addw", {ST8_REG_X, ST8_WORD}, 0x1C},
+{"addw", {ST8_REG_X, ST8_LONGMEM}, 0x72BB},
+{"addw", {ST8_REG_X, ST8_SHORTOFF_SP}, 0x72FB},
+{"addw", {ST8_REG_Y, ST8_WORD}, 0x72A9},
+{"addw", {ST8_REG_Y, ST8_LONGMEM}, 0x72B9},
+{"addw", {ST8_REG_Y, ST8_SHORTOFF_SP}, 0x72F9},
+{"addw", {ST8_REG_SP, ST8_BYTE}, 0x5B},
+//and
+{"and", {ST8_REG_A, ST8_BYTE}, 0xA4},
+{"and", {ST8_REG_A, ST8_SHORTMEM}, 0xB4},
+{"and", {ST8_REG_A, ST8_LONGMEM}, 0xC4},
+{"and", {ST8_REG_A, ST8_INDX}, 0xF4},
+{"and", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE4},
+{"and", {ST8_REG_A, ST8_LONGOFF_X}, 0xD4},
+{"and", {ST8_REG_A, ST8_INDY}, 0x90F4},
+{"and", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E4},
+{"and", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D4},
+{"and", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x14},
+{"and", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C4},
+{"and", {ST8_REG_A, ST8_LONGPTRW}, 0x72C4},
+{"and", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D4},
+{"and", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D4},
+{"and", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D4},
+//bccm
+//{"bccm", {ST8_LONGMEM, ST8_BYTE}, 0x90xx},
+//bcp
+{"bcp", {ST8_REG_A, ST8_BYTE}, 0xA5},
+{"bcp", {ST8_REG_A, ST8_SHORTMEM}, 0xB5},
+{"bcp", {ST8_REG_A, ST8_LONGMEM}, 0xC5},
+{"bcp", {ST8_REG_A, ST8_INDX}, 0xF5},
+{"bcp", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE5},
+{"bcp", {ST8_REG_A, ST8_LONGOFF_X}, 0xD5},
+{"bcp", {ST8_REG_A, ST8_INDY}, 0x90F5},
+{"bcp", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E5},
+{"bcp", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D5},
+{"bcp", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x15},
+{"bcp", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C5},
+{"bcp", {ST8_REG_A, ST8_LONGPTRW}, 0x72C5},
+{"bcp", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D5},
+{"bcp", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D5},
+{"bcp", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D5},
+//bcpl
+{"bcpl", {ST8_LONGMEM, ST8_BIT_0}, 0x9010},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_1}, 0x9012},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_2}, 0x9014},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_3}, 0x9016},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_4}, 0x9018},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_5}, 0x901a},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_6}, 0x901c},
+{"bcpl", {ST8_LONGMEM, ST8_BIT_7}, 0x901e},
+//break
+{"break", {}, 0x8B},
+//bres
+{"bres", {ST8_LONGMEM, ST8_BIT_0}, 0x7211},
+{"bres", {ST8_LONGMEM, ST8_BIT_1}, 0x7213},
+{"bres", {ST8_LONGMEM, ST8_BIT_2}, 0x7215},
+{"bres", {ST8_LONGMEM, ST8_BIT_3}, 0x7217},
+{"bres", {ST8_LONGMEM, ST8_BIT_4}, 0x7219},
+{"bres", {ST8_LONGMEM, ST8_BIT_5}, 0x721b},
+{"bres", {ST8_LONGMEM, ST8_BIT_6}, 0x721d},
+{"bres", {ST8_LONGMEM, ST8_BIT_7}, 0x721f},
+//bset
+{"bset", {ST8_LONGMEM, ST8_BIT_0}, 0x7210},
+{"bset", {ST8_LONGMEM, ST8_BIT_1}, 0x7212},
+{"bset", {ST8_LONGMEM, ST8_BIT_2}, 0x7214},
+{"bset", {ST8_LONGMEM, ST8_BIT_3}, 0x7216},
+{"bset", {ST8_LONGMEM, ST8_BIT_4}, 0x7218},
+{"bset", {ST8_LONGMEM, ST8_BIT_5}, 0x721a},
+{"bset", {ST8_LONGMEM, ST8_BIT_6}, 0x721c},
+{"bset", {ST8_LONGMEM, ST8_BIT_7}, 0x721e},
+//btjf
+{"btjf", {ST8_LONGMEM, ST8_BIT_0, ST8_PCREL}, 0x7201},
+{"btjf", {ST8_LONGMEM, ST8_BIT_1, ST8_PCREL}, 0x7203},
+{"btjf", {ST8_LONGMEM, ST8_BIT_2, ST8_PCREL}, 0x7205},
+{"btjf", {ST8_LONGMEM, ST8_BIT_3, ST8_PCREL}, 0x7207},
+{"btjf", {ST8_LONGMEM, ST8_BIT_4, ST8_PCREL}, 0x7209},
+{"btjf", {ST8_LONGMEM, ST8_BIT_5, ST8_PCREL}, 0x720b},
+{"btjf", {ST8_LONGMEM, ST8_BIT_6, ST8_PCREL}, 0x720d},
+{"btjf", {ST8_LONGMEM, ST8_BIT_7, ST8_PCREL}, 0x720f},
+//btjt
+{"btjt", {ST8_LONGMEM, ST8_BIT_0, ST8_PCREL}, 0x7200},
+{"btjt", {ST8_LONGMEM, ST8_BIT_1, ST8_PCREL}, 0x7202},
+{"btjt", {ST8_LONGMEM, ST8_BIT_2, ST8_PCREL}, 0x7204},
+{"btjt", {ST8_LONGMEM, ST8_BIT_3, ST8_PCREL}, 0x7206},
+{"btjt", {ST8_LONGMEM, ST8_BIT_4, ST8_PCREL}, 0x7208},
+{"btjt", {ST8_LONGMEM, ST8_BIT_5, ST8_PCREL}, 0x720a},
+{"btjt", {ST8_LONGMEM, ST8_BIT_6, ST8_PCREL}, 0x720c},
+{"btjt", {ST8_LONGMEM, ST8_BIT_7, ST8_PCREL}, 0x720e},
+//call
+{"call", {ST8_LONGMEM}, 0xCD},
+{"call", {ST8_INDX}, 0xFD},
+{"call", {ST8_SHORTOFF_X}, 0xED},
+{"call", {ST8_LONGOFF_X}, 0xDD},
+{"call", {ST8_INDY}, 0x90FD},
+{"call", {ST8_SHORTOFF_Y}, 0x90ED},
+{"call", {ST8_LONGOFF_Y}, 0x90DD},
+{"call", {ST8_SHORTPTRW}, 0x92CD},
+{"call", {ST8_LONGPTRW}, 0x72CD},
+{"call", {ST8_SHORTPTRW_X}, 0x92DD},
+{"call", {ST8_LONGPTRW_X}, 0x72DD},
+{"call", {ST8_SHORTPTRW_Y}, 0x91DD},
+//callf
+{"callf", {ST8_EXTMEM}, 0x8D},
+{"callf", {ST8_LONGPTRE}, 0x928D},
+//callr
+{"callr", {ST8_PCREL}, 0xAD},
+//ccf
+{"ccf", {}, 0x8C},
+//clr
+{"clr", {ST8_REG_A}, 0x4F},
+{"clr", {ST8_SHORTMEM}, 0x3F},
+{"clr", {ST8_LONGMEM}, 0x725F},
+{"clr", {ST8_INDX}, 0x7F},
+{"clr", {ST8_SHORTOFF_X}, 0x6F},
+{"clr", {ST8_LONGOFF_X}, 0x724F},
+{"clr", {ST8_INDY}, 0x907F},
+{"clr", {ST8_SHORTOFF_Y}, 0x906F},
+{"clr", {ST8_LONGOFF_Y}, 0x904F},
+{"clr", {ST8_SHORTOFF_SP}, 0x0F},
+{"clr", {ST8_SHORTPTRW}, 0x923F},
+{"clr", {ST8_LONGPTRW}, 0x723F},
+{"clr", {ST8_SHORTPTRW_X}, 0x926F},
+{"clr", {ST8_LONGPTRW_X}, 0x726F},
+{"clr", {ST8_SHORTPTRW_Y}, 0x916F},
+//clrw
+{"clrw", {ST8_REG_X}, 0x5F},
+{"clrw", {ST8_REG_Y}, 0x905F},
+//cp
+{"cp", {ST8_REG_A, ST8_BYTE}, 0xA1},
+{"cp", {ST8_REG_A, ST8_SHORTMEM}, 0xB1},
+{"cp", {ST8_REG_A, ST8_LONGMEM}, 0xC1},
+{"cp", {ST8_REG_A, ST8_INDX}, 0xF1},
+{"cp", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE1},
+{"cp", {ST8_REG_A, ST8_LONGOFF_X}, 0xD1},
+{"cp", {ST8_REG_A, ST8_INDY}, 0x90F1},
+{"cp", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E1},
+{"cp", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D1},
+{"cp", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x11},
+{"cp", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C1},
+{"cp", {ST8_REG_A, ST8_LONGPTRW}, 0x72C1},
+{"cp", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D1},
+{"cp", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D1},
+{"cp", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D1},
+//cpw
+{"cpw", {ST8_REG_X, ST8_WORD}, 0xA3},
+{"cpw", {ST8_REG_X, ST8_SHORTMEM}, 0xB3},
+{"cpw", {ST8_REG_X, ST8_LONGMEM}, 0xC3},
+{"cpw", {ST8_REG_X, ST8_INDY}, 0x90F3},
+{"cpw", {ST8_REG_X, ST8_SHORTOFF_Y}, 0x90E3},
+{"cpw", {ST8_REG_X, ST8_LONGOFF_Y}, 0x90D3},
+{"cpw", {ST8_REG_X, ST8_SHORTOFF_SP}, 0x13},
+{"cpw", {ST8_REG_X, ST8_SHORTPTRW}, 0x92C3},
+{"cpw", {ST8_REG_X, ST8_LONGPTRW}, 0x72C3},
+{"cpw", {ST8_REG_X, ST8_SHORTPTRW_Y}, 0x91D3},
+{"cpw", {ST8_REG_Y, ST8_WORD}, 0x90A3},
+{"cpw", {ST8_REG_Y, ST8_SHORTMEM}, 0x90B3},
+{"cpw", {ST8_REG_Y, ST8_LONGMEM}, 0x90C3},
+{"cpw", {ST8_REG_Y, ST8_INDX}, 0xF3},
+{"cpw", {ST8_REG_Y, ST8_SHORTOFF_X}, 0xE3},
+{"cpw", {ST8_REG_Y, ST8_LONGOFF_X}, 0xD3},
+{"cpw", {ST8_REG_Y, ST8_SHORTPTRW}, 0x91C3},
+{"cpw", {ST8_REG_Y, ST8_LONGPTRW}, 0x92D3},
+{"cpw", {ST8_REG_Y, ST8_SHORTPTRW_X}, 0x72D3},
+//cpl
+{"cpl", {ST8_REG_A}, 0x43},
+{"cpl", {ST8_SHORTMEM}, 0x33},
+{"cpl", {ST8_LONGMEM}, 0x7253},
+{"cpl", {ST8_INDX}, 0x73},
+{"cpl", {ST8_SHORTOFF_X}, 0x63},
+{"cpl", {ST8_LONGOFF_X}, 0x7243},
+{"cpl", {ST8_INDY}, 0x9073},
+{"cpl", {ST8_SHORTOFF_Y}, 0x9063},
+{"cpl", {ST8_LONGOFF_Y}, 0x9043},
+{"cpl", {ST8_SHORTOFF_SP}, 0x03},
+{"cpl", {ST8_SHORTPTRW}, 0x9233},
+{"cpl", {ST8_LONGPTRW}, 0x7233},
+{"cpl", {ST8_SHORTPTRW_X}, 0x9263},
+{"cpl", {ST8_LONGPTRW_X}, 0x7263},
+{"cpl", {ST8_SHORTPTRW_Y}, 0x9163},
+//cplw
+{"clrw", {ST8_REG_X}, 0x53},
+{"clrw", {ST8_REG_Y}, 0x9053},
+//dec
+{"dec", {ST8_REG_A}, 0x4A},
+{"dec", {ST8_SHORTMEM}, 0x3A},
+{"dec", {ST8_LONGMEM}, 0x725A},
+{"dec", {ST8_INDX}, 0x7A},
+{"dec", {ST8_SHORTOFF_X}, 0x6A},
+{"dec", {ST8_LONGOFF_X}, 0x724A},
+{"dec", {ST8_INDY}, 0x907A},
+{"dec", {ST8_SHORTOFF_Y}, 0x906A},
+{"dec", {ST8_LONGOFF_Y}, 0x904A},
+{"dec", {ST8_SHORTOFF_SP}, 0x0A},
+{"dec", {ST8_SHORTPTRW}, 0x923A},
+{"dec", {ST8_LONGPTRW}, 0x723A},
+{"dec", {ST8_SHORTPTRW_X}, 0x926A},
+{"dec", {ST8_LONGPTRW_X}, 0x726A},
+{"dec", {ST8_SHORTPTRW_Y}, 0x916A},
+//decw
+{"decw", {ST8_REG_X}, 0x5A},
+{"decw", {ST8_REG_Y}, 0x905A},
+//div
+{"div", {ST8_REG_X, ST8_REG_A}, 0x62},
+{"div", {ST8_REG_Y, ST8_REG_A}, 0x9062},
+//divw
+{"divw", {ST8_REG_X, ST8_REG_Y}, 0x65},
+//exg
+{"exg", {ST8_REG_A, ST8_REG_XL}, 0x41},
+{"exg", {ST8_REG_A, ST8_REG_YL}, 0x61},
+{"exg", {ST8_REG_A, ST8_LONGMEM}, 0x31},
+//exgw
+{"exgw", {ST8_REG_X, ST8_REG_Y}, 0x51},
+//halt
+{"halt", {}, 0x8E},
+//inc
+{"inc", {ST8_REG_A}, 0x4C},
+{"inc", {ST8_SHORTMEM}, 0x3C},
+{"inc", {ST8_LONGMEM}, 0x725C},
+{"inc", {ST8_INDX}, 0x7C},
+{"inc", {ST8_SHORTOFF_X}, 0x6C},
+{"inc", {ST8_LONGOFF_X}, 0x724C},
+{"inc", {ST8_INDY}, 0x907C},
+{"inc", {ST8_SHORTOFF_Y}, 0x906C},
+{"inc", {ST8_LONGOFF_Y}, 0x904C},
+{"inc", {ST8_SHORTOFF_SP}, 0x0C},
+{"inc", {ST8_SHORTPTRW}, 0x923C},
+{"inc", {ST8_LONGPTRW}, 0x723C},
+{"inc", {ST8_SHORTPTRW_X}, 0x926C},
+{"inc", {ST8_LONGPTRW_X}, 0x726C},
+{"inc", {ST8_SHORTPTRW_Y}, 0x916C},
+//incw
+{"incw", {ST8_REG_X}, 0x5C},
+{"incw", {ST8_REG_Y}, 0x905C},
+//int
+{"int", {ST8_EXTMEM}, 0x82},
+//iret
+{"iret", {}, 0x80},
+//jp
+{"jp", {ST8_LONGMEM}, 0xCC},
+{"jp", {ST8_INDX}, 0xFC},
+{"jp", {ST8_SHORTOFF_X}, 0xEC},
+{"jp", {ST8_LONGOFF_X}, 0xDC},
+{"jp", {ST8_INDY}, 0x90FC},
+{"jp", {ST8_SHORTOFF_Y}, 0x90EC},
+{"jp", {ST8_LONGOFF_Y}, 0x90DC},
+{"jp", {ST8_SHORTPTRW}, 0x92CC},
+{"jp", {ST8_LONGPTRW}, 0x72CC},
+{"jp", {ST8_SHORTPTRW_X}, 0x92DC},
+{"jp", {ST8_LONGPTRW_X}, 0x72DC},
+{"jp", {ST8_SHORTPTRW_Y}, 0x91DC},
+//jpf
+{"jpf", {ST8_EXTMEM}, 0xAC},
+{"jpf", {ST8_LONGPTRE}, 0x92AC},
+//jrxx
+{"jra", {ST8_PCREL}, 0x20},
+{"jrc", {ST8_PCREL}, 0x25},
+{"jreq", {ST8_PCREL}, 0x27},
+{"jrf", {ST8_PCREL}, 0x21},
+{"jrh", {ST8_PCREL}, 0x9029},
+{"jrih", {ST8_PCREL}, 0x902F},
+{"jril", {ST8_PCREL}, 0x902E},
+{"jrm", {ST8_PCREL}, 0x902D},
+{"jrmi", {ST8_PCREL}, 0x2B},
+{"jrnc", {ST8_PCREL}, 0x24},
+{"jrne", {ST8_PCREL}, 0x26},
+{"jrnh", {ST8_PCREL}, 0x9028},
+{"jrnm", {ST8_PCREL}, 0x902C},
+{"jrnv", {ST8_PCREL}, 0x28},
+{"jrpl", {ST8_PCREL}, 0x2A},
+{"jrsge", {ST8_PCREL}, 0x2E},
+{"jrsgt", {ST8_PCREL}, 0x2C},
+{"jrsle", {ST8_PCREL}, 0x2D},
+{"jrslt", {ST8_PCREL}, 0x2F},
+{"jrt", {ST8_PCREL}, 0x20},
+{"jruge", {ST8_PCREL}, 0x24},
+{"jrugt", {ST8_PCREL}, 0x22},
+{"jrule", {ST8_PCREL}, 0x23},
+{"jrult", {ST8_PCREL}, 0x25},
+{"jrv", {ST8_PCREL}, 0x29},
+//ld
+{"ld", {ST8_REG_A, ST8_BYTE}, 0xA6},
+{"ld", {ST8_REG_A, ST8_SHORTMEM}, 0xB6},
+{"ld", {ST8_REG_A, ST8_LONGMEM}, 0xC6},
+{"ld", {ST8_REG_A, ST8_INDX}, 0xF6},
+{"ld", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE6},
+{"ld", {ST8_REG_A, ST8_LONGOFF_X}, 0xD6},
+{"ld", {ST8_REG_A, ST8_INDY}, 0x90F6},
+{"ld", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E6},
+{"ld", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D6},
+{"ld", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x7B},
+{"ld", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C6},
+{"ld", {ST8_REG_A, ST8_LONGPTRW}, 0x72C6},
+{"ld", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D6},
+{"ld", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D6},
+{"ld", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D6},
+{"ld", {ST8_SHORTMEM, ST8_REG_A}, 0xB7},
+{"ld", {ST8_LONGMEM, ST8_REG_A}, 0xC7},
+{"ld", {ST8_INDX, ST8_REG_A}, 0xF7},
+{"ld", {ST8_SHORTOFF_X, ST8_REG_A}, 0xE7},
+{"ld", {ST8_LONGOFF_X, ST8_REG_A}, 0xD7},
+{"ld", {ST8_INDY, ST8_REG_A}, 0x90F7},
+{"ld", {ST8_SHORTOFF_Y, ST8_REG_A}, 0x90E7},
+{"ld", {ST8_LONGOFF_Y, ST8_REG_A}, 0x90D7},
+{"ld", {ST8_SHORTOFF_SP, ST8_REG_A}, 0x6B},
+{"ld", {ST8_SHORTPTRW, ST8_REG_A}, 0x92C7},
+{"ld", {ST8_LONGPTRW, ST8_REG_A}, 0x72C7},
+{"ld", {ST8_SHORTPTRW_X, ST8_REG_A}, 0x92D7},
+{"ld", {ST8_LONGPTRW_X, ST8_REG_A}, 0x72D7},
+{"ld", {ST8_SHORTPTRW_Y, ST8_REG_A}, 0x91D7},
+{"ld", {ST8_REG_XL, ST8_REG_A}, 0x97},
+{"ld", {ST8_REG_A, ST8_REG_XL}, 0x9F},
+{"ld", {ST8_REG_YL, ST8_REG_A}, 0x9097},
+{"ld", {ST8_REG_A, ST8_REG_YL}, 0x909F},
+{"ld", {ST8_REG_XH, ST8_REG_A}, 0x95},
+{"ld", {ST8_REG_A, ST8_REG_XH}, 0x9E},
+{"ld", {ST8_REG_YH, ST8_REG_A}, 0x9095},
+{"ld", {ST8_REG_A, ST8_REG_YH}, 0x909E},
+//ldf
+{"ldf", {ST8_REG_A, ST8_EXTMEM}, 0xBC},
+{"ldf", {ST8_REG_A, ST8_EXTOFF_X}, 0xAF},
+{"ldf", {ST8_REG_A, ST8_EXTOFF_Y}, 0x90AF},
+{"ldf", {ST8_REG_A, ST8_LONGPTRE_X}, 0x92AF},
+{"ldf", {ST8_REG_A, ST8_LONGPTRE_Y}, 0x91AF},
+{"ldf", {ST8_REG_A, ST8_LONGPTRE}, 0x92BC},
+{"ldf", {ST8_EXTMEM, ST8_REG_A}, 0xBD},
+{"ldf", {ST8_EXTOFF_X, ST8_REG_A}, 0xA7},
+{"ldf", {ST8_EXTOFF_Y, ST8_REG_A}, 0x90A7},
+{"ldf", {ST8_LONGPTRE_X, ST8_REG_A}, 0x92A7},
+{"ldf", {ST8_LONGPTRE_Y, ST8_REG_A}, 0x91A7},
+{"ldf", {ST8_LONGPTRE, ST8_REG_A}, 0x92BD},
+//ldw
+{"ldw", {ST8_REG_X, ST8_WORD}, 0xAE},
+{"ldw", {ST8_REG_X, ST8_SHORTMEM}, 0xBE},
+{"ldw", {ST8_REG_X, ST8_LONGMEM}, 0xCE},
+{"ldw", {ST8_REG_X, ST8_INDX}, 0xFE},
+{"ldw", {ST8_REG_X, ST8_SHORTOFF_X}, 0xEE},
+{"ldw", {ST8_REG_X, ST8_LONGOFF_X}, 0xDE},
+{"ldw", {ST8_REG_X, ST8_SHORTOFF_SP}, 0x1E},
+{"ldw", {ST8_REG_X, ST8_SHORTPTRW}, 0x92CE},
+{"ldw", {ST8_REG_X, ST8_LONGPTRW}, 0x72CE},
+{"ldw", {ST8_REG_X, ST8_SHORTPTRW_X}, 0x92DE},
+{"ldw", {ST8_REG_X, ST8_LONGPTRW_X}, 0x72DE},
+{"ldw", {ST8_SHORTMEM, ST8_REG_X}, 0xBF},
+{"ldw", {ST8_LONGMEM, ST8_REG_X}, 0xCF},
+{"ldw", {ST8_INDX, ST8_REG_Y}, 0xFF},
+{"ldw", {ST8_SHORTOFF_X, ST8_REG_Y}, 0xEF},
+{"ldw", {ST8_LONGOFF_X, ST8_REG_Y}, 0xDF},
+{"ldw", {ST8_SHORTOFF_SP, ST8_REG_X}, 0x1F},
+{"ldw", {ST8_SHORTPTRW, ST8_REG_X}, 0x92CF},
+{"ldw", {ST8_LONGPTRW, ST8_REG_X}, 0x72CF},
+{"ldw", {ST8_SHORTPTRW_X, ST8_REG_Y}, 0x92DF},
+{"ldw", {ST8_LONGPTRW_X, ST8_REG_Y}, 0x72DF},
+{"ldw", {ST8_REG_Y, ST8_WORD}, 0x90AE},
+{"ldw", {ST8_REG_Y, ST8_SHORTMEM}, 0x90BE},
+{"ldw", {ST8_REG_Y, ST8_LONGMEM}, 0x90CE},
+{"ldw", {ST8_REG_Y, ST8_INDY}, 0x90FE},
+{"ldw", {ST8_REG_Y, ST8_SHORTOFF_Y}, 0x90EE},
+{"ldw", {ST8_REG_Y, ST8_LONGOFF_Y}, 0x90DE},
+{"ldw", {ST8_REG_Y, ST8_SHORTOFF_SP}, 0x16},
+{"ldw", {ST8_REG_Y, ST8_SHORTPTRW}, 0x91CE},
+{"ldw", {ST8_REG_Y, ST8_SHORTPTRW_Y}, 0x91DE},
+{"ldw", {ST8_SHORTMEM, ST8_REG_Y}, 0x90BF},
+{"ldw", {ST8_LONGMEM, ST8_REG_Y}, 0x90CF},
+{"ldw", {ST8_INDY, ST8_REG_X}, 0x90FF},
+{"ldw", {ST8_SHORTOFF_Y, ST8_REG_X}, 0x90EF},
+{"ldw", {ST8_LONGOFF_Y, ST8_REG_X}, 0x90DF},
+{"ldw", {ST8_SHORTOFF_SP, ST8_REG_Y}, 0x17},
+{"ldw", {ST8_SHORTPTRW, ST8_REG_Y}, 0x91CF},
+{"ldw", {ST8_SHORTPTRW_Y, ST8_REG_X}, 0x91DF},
+{"ldw", {ST8_REG_Y, ST8_REG_X}, 0x9093},
+{"ldw", {ST8_REG_X, ST8_REG_Y}, 0x93},
+{"ldw", {ST8_REG_X, ST8_REG_SP}, 0x96},
+{"ldw", {ST8_REG_SP, ST8_REG_X}, 0x94},
+{"ldw", {ST8_REG_Y, ST8_REG_SP}, 0x9096},
+{"ldw", {ST8_REG_SP, ST8_REG_Y}, 0x9094},
+//mov
+{"mov", {ST8_LONGMEM, ST8_BYTE}, 0x35},
+{"mov", {ST8_SHORTMEM, ST8_SHORTMEM}, 0x45},
+{"mov", {ST8_LONGMEM, ST8_LONGMEM}, 0x55},
+//mul
+{"mul", {ST8_REG_X, ST8_REG_A}, 0x42},
+{"mul", {ST8_REG_Y, ST8_REG_A}, 0x9042},
+//neg
+{"neg", {ST8_REG_A}, 0x40},
+{"neg", {ST8_SHORTMEM}, 0x30},
+{"neg", {ST8_LONGMEM}, 0x7250},
+{"neg", {ST8_INDX}, 0x70},
+{"neg", {ST8_SHORTOFF_X}, 0x60},
+{"neg", {ST8_LONGOFF_X}, 0x7240},
+{"neg", {ST8_INDY}, 0x9070},
+{"neg", {ST8_SHORTOFF_Y}, 0x9060},
+{"neg", {ST8_LONGOFF_Y}, 0x9040},
+{"neg", {ST8_SHORTOFF_SP}, 0x00},
+{"neg", {ST8_SHORTPTRW}, 0x9230},
+{"neg", {ST8_LONGPTRW}, 0x7230},
+{"neg", {ST8_SHORTPTRW_X}, 0x9260},
+{"neg", {ST8_LONGPTRW_X}, 0x7260},
+{"neg", {ST8_SHORTPTRW_Y}, 0x9160},
+//negw
+{"negw", {ST8_REG_X}, 0x50},
+{"negw", {ST8_REG_Y}, 0x9050},
+//or
+{"or", {ST8_REG_A, ST8_BYTE}, 0xAA},
+{"or", {ST8_REG_A, ST8_SHORTMEM}, 0xBA},
+{"or", {ST8_REG_A, ST8_LONGMEM}, 0xCA},
+{"or", {ST8_REG_A, ST8_INDX}, 0xFA},
+{"or", {ST8_REG_A, ST8_SHORTOFF_X}, 0xEA},
+{"or", {ST8_REG_A, ST8_LONGOFF_X}, 0xDA},
+{"or", {ST8_REG_A, ST8_INDY}, 0x90FA},
+{"or", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90EA},
+{"or", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90DA},
+{"or", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x1A},
+{"or", {ST8_REG_A, ST8_SHORTPTRW}, 0x92CA},
+{"or", {ST8_REG_A, ST8_LONGPTRW}, 0x72CA},
+{"or", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92DA},
+{"or", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72DA},
+{"or", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91DA},
+//pop
+{"pop", {ST8_REG_A}, 0x84},
+{"pop", {ST8_REG_CC}, 0x86},
+{"pop", {ST8_LONGMEM}, 0x32},
+//popw
+{"popw", {ST8_REG_X}, 0x85},
+{"popw", {ST8_REG_Y}, 0x9085},
+//push
+{"push", {ST8_REG_A}, 0x88},
+{"push", {ST8_REG_CC}, 0x8A},
+{"push", {ST8_BYTE}, 0x4B},
+{"push", {ST8_LONGMEM}, 0x3B},
+//pushw
+{"pushw", {ST8_REG_X}, 0x89},
+{"pushw", {ST8_REG_Y}, 0x9089},
+//rcf
+{"rcf", {}, 0x98},
+//ret
+{"ret", {}, 0x81},
+//retf
+{"retf", {}, 0x87},
+//rim
+{"rim", {}, 0x9A},
+//rlc
+{"rlc", {ST8_REG_A}, 0x49},
+{"rlc", {ST8_SHORTMEM}, 0x39},
+{"rlc", {ST8_LONGMEM}, 0x7259},
+{"rlc", {ST8_INDX}, 0x79},
+{"rlc", {ST8_SHORTOFF_X}, 0x69},
+{"rlc", {ST8_LONGOFF_X}, 0x7249},
+{"rlc", {ST8_INDY}, 0x9079},
+{"rlc", {ST8_SHORTOFF_Y}, 0x9069},
+{"rlc", {ST8_LONGOFF_Y}, 0x9049},
+{"rlc", {ST8_SHORTOFF_SP}, 0x09},
+{"rlc", {ST8_SHORTPTRW}, 0x9239},
+{"rlc", {ST8_LONGPTRW}, 0x7239},
+{"rlc", {ST8_SHORTPTRW_X}, 0x9269},
+{"rlc", {ST8_LONGPTRW_X}, 0x7269},
+{"rlc", {ST8_SHORTPTRW_Y}, 0x9169},
+//rlcw
+{"rlcw", {ST8_REG_X}, 0x59},
+{"rlcw", {ST8_REG_Y}, 0x9059},
+//rlwa
+{"rlwa", {ST8_REG_X, ST8_REG_A}, 0x02},
+{"rlwa", {ST8_REG_Y, ST8_REG_A}, 0x9002},
+//rrc
+{"rrc", {ST8_REG_A}, 0x46},
+{"rrc", {ST8_SHORTMEM}, 0x36},
+{"rrc", {ST8_LONGMEM}, 0x7256},
+{"rrc", {ST8_INDX}, 0x76},
+{"rrc", {ST8_SHORTOFF_X}, 0x66},
+{"rrc", {ST8_LONGOFF_X}, 0x7246},
+{"rrc", {ST8_INDY}, 0x9076},
+{"rrc", {ST8_SHORTOFF_Y}, 0x9066},
+{"rrc", {ST8_LONGOFF_Y}, 0x9046},
+{"rrc", {ST8_SHORTOFF_SP}, 0x06},
+{"rrc", {ST8_SHORTPTRW}, 0x9236},
+{"rrc", {ST8_LONGPTRW}, 0x7236},
+{"rrc", {ST8_SHORTPTRW_X}, 0x9266},
+{"rrc", {ST8_LONGPTRW_X}, 0x7266},
+{"rrc", {ST8_SHORTPTRW_Y}, 0x9166},
+//rrcw
+{"rrcw", {ST8_REG_X}, 0x56},
+{"rrcw", {ST8_REG_Y}, 0x9056},
+//rrwa
+{"rrwa", {ST8_REG_X, ST8_REG_A}, 0x01},
+{"rrwa", {ST8_REG_Y, ST8_REG_A}, 0x9001},
+//rvf
+{"rvf", {}, 0x9C},
+//sbc
+{"sbc", {ST8_REG_A, ST8_BYTE}, 0xA2},
+{"sbc", {ST8_REG_A, ST8_SHORTMEM}, 0xB2},
+{"sbc", {ST8_REG_A, ST8_LONGMEM}, 0xC2},
+{"sbc", {ST8_REG_A, ST8_INDX}, 0xF2},
+{"sbc", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE2},
+{"sbc", {ST8_REG_A, ST8_LONGOFF_X}, 0xD2},
+{"sbc", {ST8_REG_A, ST8_INDY}, 0x90F2},
+{"sbc", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E2},
+{"sbc", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D2},
+{"sbc", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x12},
+{"sbc", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C2},
+{"sbc", {ST8_REG_A, ST8_LONGPTRW}, 0x72C2},
+{"sbc", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D2},
+{"sbc", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D2},
+{"sbc", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D2},
+//scf
+{"scf", {}, 0x99},
+//sim
+{"sim", {}, 0x9B},
+//sll
+{"sll", {ST8_REG_A}, 0x48},
+{"sll", {ST8_SHORTMEM}, 0x38},
+{"sll", {ST8_LONGMEM}, 0x7258},
+{"sll", {ST8_INDX}, 0x78},
+{"sll", {ST8_SHORTOFF_X}, 0x68},
+{"sll", {ST8_LONGOFF_X}, 0x7248},
+{"sll", {ST8_INDY}, 0x9078},
+{"sll", {ST8_SHORTOFF_Y}, 0x9068},
+{"sll", {ST8_LONGOFF_Y}, 0x9048},
+{"sll", {ST8_SHORTOFF_SP}, 0x08},
+{"sll", {ST8_SHORTPTRW}, 0x9238},
+{"sll", {ST8_LONGPTRW}, 0x7238},
+{"sll", {ST8_SHORTPTRW_X}, 0x9268},
+{"sll", {ST8_LONGPTRW_X}, 0x7268},
+{"sll", {ST8_SHORTPTRW_Y}, 0x9168},
+//sllw
+{"sllw", {ST8_REG_X}, 0x58},
+{"sllw", {ST8_REG_Y}, 0x9058},
+//sla
+{"sla", {ST8_REG_A}, 0x48},
+{"sla", {ST8_SHORTMEM}, 0x38},
+{"sla", {ST8_LONGMEM}, 0x7258},
+{"sla", {ST8_INDX}, 0x78},
+{"sla", {ST8_SHORTOFF_X}, 0x68},
+{"sla", {ST8_LONGOFF_X}, 0x7248},
+{"sla", {ST8_INDY}, 0x9078},
+{"sla", {ST8_SHORTOFF_Y}, 0x9068},
+{"sla", {ST8_LONGOFF_Y}, 0x9048},
+{"sla", {ST8_SHORTOFF_SP}, 0x08},
+{"sla", {ST8_SHORTPTRW}, 0x9238},
+{"sla", {ST8_LONGPTRW}, 0x7238},
+{"sla", {ST8_SHORTPTRW_X}, 0x9268},
+{"sla", {ST8_LONGPTRW_X}, 0x7268},
+{"sla", {ST8_SHORTPTRW_Y}, 0x9168},
+//slaw
+{"slaw", {ST8_REG_X}, 0x58},
+{"slaw", {ST8_REG_Y}, 0x9058},
+//sra
+{"sra", {ST8_REG_A}, 0x47},
+{"sra", {ST8_SHORTMEM}, 0x37},
+{"sra", {ST8_LONGMEM}, 0x7257},
+{"sra", {ST8_INDX}, 0x77},
+{"sra", {ST8_SHORTOFF_X}, 0x67},
+{"sra", {ST8_LONGOFF_X}, 0x7247},
+{"sra", {ST8_INDY}, 0x9077},
+{"sra", {ST8_SHORTOFF_Y}, 0x9067},
+{"sra", {ST8_LONGOFF_Y}, 0x9047},
+{"sra", {ST8_SHORTOFF_SP}, 0x07},
+{"sra", {ST8_SHORTPTRW}, 0x9237},
+{"sra", {ST8_LONGPTRW}, 0x7237},
+{"sra", {ST8_SHORTPTRW_X}, 0x9267},
+{"sra", {ST8_LONGPTRW_X}, 0x7267},
+{"sra", {ST8_SHORTPTRW_Y}, 0x9167},
+//sraw
+{"sraw", {ST8_REG_X}, 0x57},
+{"sraw", {ST8_REG_Y}, 0x9057},
+//srl
+{"srl", {ST8_REG_A}, 0x44},
+{"srl", {ST8_SHORTMEM}, 0x34},
+{"srl", {ST8_LONGMEM}, 0x7254},
+{"srl", {ST8_INDX}, 0x74},
+{"srl", {ST8_SHORTOFF_X}, 0x64},
+{"srl", {ST8_LONGOFF_X}, 0x7244},
+{"srl", {ST8_INDY}, 0x9074},
+{"srl", {ST8_SHORTOFF_Y}, 0x9064},
+{"srl", {ST8_LONGOFF_Y}, 0x9044},
+{"srl", {ST8_SHORTOFF_SP}, 0x04},
+{"srl", {ST8_SHORTPTRW}, 0x9234},
+{"srl", {ST8_LONGPTRW}, 0x7234},
+{"srl", {ST8_SHORTPTRW_X}, 0x9264},
+{"srl", {ST8_LONGPTRW_X}, 0x7264},
+{"srl", {ST8_SHORTPTRW_Y}, 0x9164},
+//sraw
+{"srlw", {ST8_REG_X}, 0x54},
+{"srlw", {ST8_REG_Y}, 0x9054},
+//sub
+{"sub", {ST8_REG_A, ST8_BYTE}, 0xA0},
+{"sub", {ST8_REG_A, ST8_SHORTMEM}, 0xB0},
+{"sub", {ST8_REG_A, ST8_LONGMEM}, 0xC0},
+{"sub", {ST8_REG_A, ST8_INDX}, 0xF0},
+{"sub", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE0},
+{"sub", {ST8_REG_A, ST8_LONGOFF_X}, 0xD0},
+{"sub", {ST8_REG_A, ST8_INDY}, 0x90F0},
+{"sub", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E0},
+{"sub", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D0},
+{"sub", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x10},
+{"sub", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C0},
+{"sub", {ST8_REG_A, ST8_LONGPTRW}, 0x72C0},
+{"sub", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D0},
+{"sub", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D0},
+{"sub", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D0},
+{"sub", {ST8_REG_SP, ST8_BYTE}, 0x52},
+//subw
+{"subw", {ST8_REG_X, ST8_WORD}, 0x1D},
+{"subw", {ST8_REG_X, ST8_LONGMEM}, 0x72B0},
+{"subw", {ST8_REG_X, ST8_SHORTOFF_SP}, 0x72F0},
+{"subw", {ST8_REG_Y, ST8_WORD}, 0x72A2},
+{"subw", {ST8_REG_Y, ST8_LONGMEM}, 0x72B2},
+{"subw", {ST8_REG_Y, ST8_SHORTOFF_SP}, 0x72F2},
+//swap
+{"swap", {ST8_REG_A}, 0x4E},
+{"swap", {ST8_SHORTMEM}, 0x3E},
+{"swap", {ST8_LONGMEM}, 0x725E},
+{"swap", {ST8_INDX}, 0x7E},
+{"swap", {ST8_SHORTOFF_X}, 0x6E},
+{"swap", {ST8_LONGOFF_X}, 0x724E},
+{"swap", {ST8_INDY}, 0x907E},
+{"swap", {ST8_SHORTOFF_Y}, 0x906E},
+{"swap", {ST8_LONGOFF_Y}, 0x904E},
+{"swap", {ST8_SHORTOFF_SP}, 0x0E},
+{"swap", {ST8_SHORTPTRW}, 0x923E},
+{"swap", {ST8_LONGPTRW}, 0x723E},
+{"swap", {ST8_SHORTPTRW_X}, 0x926E},
+{"swap", {ST8_LONGPTRW_X}, 0x726E},
+{"swap", {ST8_SHORTPTRW_Y}, 0x916E},
+//swapw
+{"swapw", {ST8_REG_X}, 0x5E},
+{"swapw", {ST8_REG_Y}, 0x905E},
+//tnz
+{"tnz", {ST8_REG_A}, 0x4D},
+{"tnz", {ST8_SHORTMEM}, 0x3D},
+{"tnz", {ST8_LONGMEM}, 0x725D},
+{"tnz", {ST8_INDX}, 0x7D},
+{"tnz", {ST8_SHORTOFF_X}, 0x6D},
+{"tnz", {ST8_LONGOFF_X}, 0x724D},
+{"tnz", {ST8_INDY}, 0x907D},
+{"tnz", {ST8_SHORTOFF_Y}, 0x906D},
+{"tnz", {ST8_LONGOFF_Y}, 0x904D},
+{"tnz", {ST8_SHORTOFF_SP}, 0x0D},
+{"tnz", {ST8_SHORTPTRW}, 0x923D},
+{"tnz", {ST8_LONGPTRW}, 0x723D},
+{"tnz", {ST8_SHORTPTRW_X}, 0x926D},
+{"tnz", {ST8_LONGPTRW_X}, 0x726D},
+{"tnz", {ST8_SHORTPTRW_Y}, 0x916D},
+//tnzw
+{"tnzw", {ST8_REG_X}, 0x5D},
+{"tnzw", {ST8_REG_Y}, 0x905D},
+//trap
+{"trap", {}, 0x83},
+//wfe
+{"wfe", {}, 0x728F},
+//wfi
+{"wfi", {}, 0x8F},
+//xor
+{"xor", {ST8_REG_A, ST8_BYTE}, 0xA8},
+{"xor", {ST8_REG_A, ST8_SHORTMEM}, 0xB8},
+{"xor", {ST8_REG_A, ST8_LONGMEM}, 0xC8},
+{"xor", {ST8_REG_A, ST8_INDX}, 0xF8},
+{"xor", {ST8_REG_A, ST8_SHORTOFF_X}, 0xE8},
+{"xor", {ST8_REG_A, ST8_LONGOFF_X}, 0xD8},
+{"xor", {ST8_REG_A, ST8_INDY}, 0x90F8},
+{"xor", {ST8_REG_A, ST8_SHORTOFF_Y}, 0x90E8},
+{"xor", {ST8_REG_A, ST8_LONGOFF_Y}, 0x90D8},
+{"xor", {ST8_REG_A, ST8_SHORTOFF_SP}, 0x18},
+{"xor", {ST8_REG_A, ST8_SHORTPTRW}, 0x92C8},
+{"xor", {ST8_REG_A, ST8_LONGPTRW}, 0x72C8},
+{"xor", {ST8_REG_A, ST8_SHORTPTRW_X}, 0x92D8},
+{"xor", {ST8_REG_A, ST8_LONGPTRW_X}, 0x72D8},
+{"xor", {ST8_REG_A, ST8_SHORTPTRW_Y}, 0x91D8},
+ {NULL, {ST8_END}, 0},
+};
+
+unsigned int stm8_opcode_size(unsigned int number)
+{
+ int i;
+ for(i = sizeof(int); i > 0; i--) {
+ if(number & 0xFF << (i-1)*8)
+ return(i);
+ }
+ return(1);
+}
+
+int stm8_compute_insn_size(struct stm8_opcodes_s opcode) {
+ int i, ret = 0;
+ for(i = 0; opcode.constraints[i] != ST8_END; i++) {
+ switch(opcode.constraints[i]) {
+ case ST8_PCREL:
+ case ST8_SHORTMEM:
+ case ST8_BYTE:
+ case ST8_SHORTPTRW_Y:
+ case ST8_SHORTPTRW_X:
+ case ST8_SHORTPTRW:
+ case ST8_SHORTOFF_X:
+ case ST8_SHORTOFF_Y:
+ case ST8_SHORTOFF_SP:
+ ret++;
+ break;
+ case ST8_LONGPTRE_Y:
+ case ST8_LONGPTRE_X:
+ case ST8_LONGPTRW_Y:
+ case ST8_LONGPTRW_X:
+ case ST8_LONGPTRE:
+ case ST8_LONGPTRW:
+ case ST8_LONGOFF_X:
+ case ST8_LONGOFF_Y:
+ case ST8_LONGMEM:
+ case ST8_WORD:
+ ret += 2;
+ break;
+ case ST8_EXTMEM:
+ case ST8_EXTOFF_X:
+ case ST8_EXTOFF_Y:
+ ret += 3;
+ break;
+ case ST8_END:
+ case ST8_BIT_0:
+ case ST8_BIT_1:
+ case ST8_BIT_2:
+ case ST8_BIT_3:
+ case ST8_BIT_4:
+ case ST8_BIT_5:
+ case ST8_BIT_6:
+ case ST8_BIT_7:
+ case ST8_REG_CC:
+ case ST8_REG_A:
+ case ST8_REG_X:
+ case ST8_REG_Y:
+ case ST8_REG_SP:
+ case ST8_REG_XL:
+ case ST8_REG_XH:
+ case ST8_REG_YL:
+ case ST8_REG_YH:
+ case ST8_INDX:
+ case ST8_INDY:
+ break;
+ }
+ }
+ ret += stm8_opcode_size(opcode.bin_opcode);
+ return(ret);
+}
--
2.12.2