commit 394922bfd2c9182f3268bff664d4c46a1a6590f7 Author: Xavier ASUS Date: Tue Oct 29 01:20:21 2019 +0100 First commit, forked from sourceforge tar diff --git a/README.txt b/README.txt new file mode 100755 index 0000000..da6d8be --- /dev/null +++ b/README.txt @@ -0,0 +1 @@ +See https://stm8-binutils-gdb.sourceforge.io/ for installation and usage. diff --git a/binutils_patches/0001-First-commit-for-stm8-binutils-gdb.patch b/binutils_patches/0001-First-commit-for-stm8-binutils-gdb.patch new file mode 100644 index 0000000..c5da0fd --- /dev/null +++ b/binutils_patches/0001-First-commit-for-stm8-binutils-gdb.patch @@ -0,0 +1,4893 @@ +From 22cbcafce0c08683209fe1bba2b7faef111764d4 Mon Sep 17 00:00:00 2001 +From: Ake Rehnman +Date: Fri, 24 Feb 2017 11:51:54 +0100 +Subject: [PATCH 1/6] 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 Å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 Å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 ++#include ++#include ++#include ++#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 . */ ++ ++#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 ++#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 < ++#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 ++#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 + diff --git a/binutils_patches/0002-added-clear_proceed_status-in-run_command_1-causing-.patch b/binutils_patches/0002-added-clear_proceed_status-in-run_command_1-causing-.patch new file mode 100644 index 0000000..5493d1b --- /dev/null +++ b/binutils_patches/0002-added-clear_proceed_status-in-run_command_1-causing-.patch @@ -0,0 +1,25 @@ +From 613571635409f08c9eb0460e011616dd16250ecb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=85ke=20Rehnman?= +Date: Sat, 4 Mar 2017 00:06:10 +0100 +Subject: [PATCH 2/6] added clear_proceed_status in run_command_1 causing run + command to hang. + +--- + gdb/infcmd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gdb/infcmd.c b/gdb/infcmd.c +index 976276b694..2050634c29 100644 +--- a/gdb/infcmd.c ++++ b/gdb/infcmd.c +@@ -675,6 +675,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how) + + /* Start the target running. Do not use -1 continuation as it would skip + breakpoint right at the entry point. */ ++ clear_proceed_status (0); + proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0); + + /* Since there was no error, there's no need to finish the thread +-- +2.12.2 + diff --git a/binutils_patches/0003-Changed-the-run-functionality-to-mimic-running-nativ.patch b/binutils_patches/0003-Changed-the-run-functionality-to-mimic-running-nativ.patch new file mode 100644 index 0000000..f0c5153 --- /dev/null +++ b/binutils_patches/0003-Changed-the-run-functionality-to-mimic-running-nativ.patch @@ -0,0 +1,130 @@ +From a98428b14d141be893403aa7c7935012aef1f8e5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=85ke=20Rehnman?= +Date: Sat, 4 Mar 2017 23:47:44 +0100 +Subject: [PATCH 3/6] Changed the run functionality to mimic running native + code. + +In addition two new remote settings were added to facilitate debugging with +IDE's like eclipse. These settings will make gdb behave like if it is debugging +native code removing the necessity to use remote, load and continue commands. + +set remote run-connect on (default is on) +The run-connect setting makes gdb automatically connect to localhost port 3333 +(openocd server port) when run command is entered. + +set remote run-load on (default is on) +The run-load setting makes gdb automatically load the program when run command +is entered. + +# Conflicts: +# gdb/remote.c +--- + gdb/remote.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 48 insertions(+), 2 deletions(-) + +diff --git a/gdb/remote.c b/gdb/remote.c +index a426508723..208bf4609b 100644 +--- a/gdb/remote.c ++++ b/gdb/remote.c +@@ -76,6 +76,9 @@ + #include "environ.h" + #include "common/byte-vector.h" + ++int remote_run_connect = 1; ++int remote_run_load = 1; ++ + /* Per-program-space data key. */ + static const struct program_space_data *remote_pspace_data; + +@@ -9669,6 +9672,17 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), + + extended_remote_set_inferior_cwd (rs); + ++ //akre ++ if (remote_run_connect) ++ { ++ ops->to_open("localhost:3333", from_tty); ++ if (remote_run_load) ++ generic_load (exec_file, from_tty); ++ init_thread_list (); ++ run_worked = 0; ++ } ++ else ++ { + /* Now restart the remote server. */ + run_worked = extended_remote_run (args) != -1; + if (!run_worked) +@@ -9683,7 +9697,7 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), + /* Fall back to "R". */ + extended_remote_restart (); + } +- ++ } + if (!have_inferiors ()) + { + /* Clean up from the last time we ran, before we mark the target +@@ -13673,6 +13687,14 @@ Specify the serial device it is connected to\n\ + remote_thread_handle_to_thread_info; + } + ++//akre ++// ++static int ++extended_remote_can_run (struct target_ops *self) ++{ ++ return remote_run_connect; ++} ++ + /* Set up the extended remote vector by making a copy of the standard + remote vector and adding to it. */ + +@@ -13694,6 +13716,9 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; + extended_remote_ops.to_post_attach = extended_remote_post_attach; + extended_remote_ops.to_supports_disable_randomization + = extended_remote_supports_disable_randomization; ++ ++ extended_remote_ops.to_can_run ++ = extended_remote_can_run; + } + + static int +@@ -13707,7 +13732,11 @@ remote_can_async_p (struct target_ops *ops) + return 0; + + /* We're async whenever the serial device is. */ +- return serial_can_async_p (rs->remote_desc); ++ //akre check if we have a remote connection ++ if (rs->remote_desc) ++ return serial_can_async_p (rs->remote_desc); ++ else ++ return 0; + } + + static int +@@ -13991,6 +14020,23 @@ the packets being used"), + &remote_show_cmdlist, "show remote ", + 0 /* allow-unknown */, &showlist); + ++//akre ++ add_setshow_boolean_cmd ("run-connect", class_support, ++ &remote_run_connect, _("\ ++Enable connecting to localhost:3333 with run command."), _(" \ ++Show remote-run-connect."), _(" \ ++If set remote target is connected automatically when program is run."), ++ NULL, NULL, ++ &remote_set_cmdlist, &remote_show_cmdlist); ++ ++ add_setshow_boolean_cmd ("run-load", class_support, ++ &remote_run_load, _("\ ++Enable loading with run command."), _(" \ ++Show remote-run-load."), _(" \ ++If set remote target is loaded automatically when program is run."), ++ NULL, NULL, ++ &remote_set_cmdlist, &remote_show_cmdlist); ++ + add_cmd ("compare-sections", class_obscure, compare_sections_command, _("\ + Compare section data on target to the exec file.\n\ + Argument is a single section name (default: all loaded sections).\n\ +-- +2.12.2 + diff --git a/binutils_patches/0004-Added-debug-option-to-gas-to-enable-debugging-printo.patch b/binutils_patches/0004-Added-debug-option-to-gas-to-enable-debugging-printo.patch new file mode 100644 index 0000000..418ce5a --- /dev/null +++ b/binutils_patches/0004-Added-debug-option-to-gas-to-enable-debugging-printo.patch @@ -0,0 +1,180 @@ +From 85f95b1d46d4ab7bff529f9f0de5cc3263a205bf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=85ke=20Rehnman?= +Date: Sun, 23 Apr 2017 21:26:53 +0200 +Subject: [PATCH 4/6] Added --debug option to gas to enable debugging printout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Ã…ke Rehnman +--- + gas/config/tc-stm8.c | 58 +++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 42 insertions(+), 16 deletions(-) + +diff --git a/gas/config/tc-stm8.c b/gas/config/tc-stm8.c +index 84e667278e..1fa4503ce2 100644 +--- a/gas/config/tc-stm8.c ++++ b/gas/config/tc-stm8.c +@@ -54,6 +54,7 @@ const char line_separator_chars[] = "{"; + + int md_short_jump_size = 3; + int md_long_jump_size = 4; ++int stm8_debug = 0; + + /* The target specific pseudo-ops which we support. */ + /* example: +@@ -95,17 +96,38 @@ md_show_usage (FILE *stream) + fprintf (stream, _("\ + STM8 options:\n\ + ")); ++ fprintf (stream, _("\ ++ --debug turn on debug messages\n")); + } + ++enum options ++{ ++ OPTION_DEBUG = OPTION_MD_BASE + 1, ++}; ++ + const char *md_shortopts = ""; + + struct option md_longopts[] = + { ++ { "debug", no_argument, NULL, OPTION_DEBUG }, + {NULL, no_argument, NULL, 0} + }; + + size_t md_longopts_size = sizeof (md_longopts); + ++int ++md_parse_option (int c, const char *arg __attribute__((unused))) ++{ ++ switch (c) ++ { ++ case OPTION_DEBUG: ++ stm8_debug = 1; ++ return 1; ++ } ++ return 0; ++} ++ ++ + void + md_begin (void) + { +@@ -228,7 +250,8 @@ 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); ++ if (stm8_debug) ++ print_fixup(fixP); + + switch (fixP->fx_r_type) + { +@@ -329,7 +352,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, + { + arelent *reloc; + +- print_fixup(fixp); ++ if (stm8_debug) ++ print_fixup(fixp); + + reloc = XNEW (arelent); + reloc->sym_ptr_ptr = XNEW (asymbol *); +@@ -359,12 +383,6 @@ md_section_align (segT seg, valueT size) + 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) + { +@@ -529,7 +547,8 @@ int read_arg_ptr(char *str, expressionS *exps) + } + + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + + /* restore c */ + if (p) +@@ -565,7 +584,8 @@ char* toupperstr(char *str); + + char* toupperstr(char *str) + { +- for(int i = 0; str[i]; i++){ ++ int i; ++ for(i = 0; str[i]; i++){ + str[i] = toupper(str[i]); + } + return str; +@@ -591,7 +611,8 @@ int read_arg(char *str, expressionS *exps) + exps->X_md = OP_IMM; + input_line_pointer = str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + return 1; + } + +@@ -654,7 +675,8 @@ int read_arg(char *str, expressionS *exps) + str=strtok(str,","); + input_line_pointer=str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + exps->X_md=OP_OFF_X; + return 1; + } +@@ -680,7 +702,8 @@ int read_arg(char *str, expressionS *exps) + str=strtok(str,","); + input_line_pointer=str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + exps->X_md=OP_OFF_X; + return 1; + } +@@ -691,7 +714,8 @@ int read_arg(char *str, expressionS *exps) + str=strtok(str,","); + input_line_pointer=str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + exps->X_md=OP_OFF_SP; + return 1; + } +@@ -705,7 +729,8 @@ int read_arg(char *str, expressionS *exps) + exps->X_md = OP_SHORTMEM; + input_line_pointer = str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + *p = c; + input_line_pointer += 6; + return 1; +@@ -713,7 +738,8 @@ int read_arg(char *str, expressionS *exps) + + input_line_pointer = str; + expression(exps); +- print_expr(exps); ++ if (stm8_debug) ++ print_expr(exps); + + if (exps->X_op == O_register) + { +-- +2.12.2 + diff --git a/binutils_patches/0005-Fixed-printf-formatting-warnings.patch b/binutils_patches/0005-Fixed-printf-formatting-warnings.patch new file mode 100644 index 0000000..e76c9b2 --- /dev/null +++ b/binutils_patches/0005-Fixed-printf-formatting-warnings.patch @@ -0,0 +1,174 @@ +From c5d6641a345485cab823426a5b364a8126e7eda3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=85ke=20Rehnman?= +Date: Sun, 23 Apr 2017 21:30:18 +0200 +Subject: [PATCH 5/6] Fixed printf formatting warnings Removed target + description registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Ã…ke Rehnman +--- + gdb/stm8-tdep.c | 38 ++++++++++++++++++++------------------ + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/gdb/stm8-tdep.c b/gdb/stm8-tdep.c +index 30b345cfd7..fd4b96c6c0 100644 +--- a/gdb/stm8-tdep.c ++++ b/gdb/stm8-tdep.c +@@ -34,7 +34,6 @@ + #include "dis-asm.h" + #include "objfiles.h" + #include "target-descriptions.h" +-#include + #include "dwarf2-frame.h" + + enum stm8_regnum +@@ -279,7 +278,7 @@ 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_breakpoint_kind_from_pc called %8.8lx\n", (unsigned long)pc); + + return 1; + } +@@ -336,19 +335,19 @@ stm8_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) + 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_unwind_pc called: pc=%8.8lx\n", (unsigned long)pc); + return pc; + } + + static CORE_ADDR + stm8_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) + { +- ULONGEST sp; ++ CORE_ADDR 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_unwind_sp called: sp=%8.8lx\n", (unsigned long)sp); + return sp; + } + +@@ -451,7 +450,7 @@ stm8_get_return_insn (CORE_ADDR pc) + + //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); ++ 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, (unsigned long)func_addr, (unsigned long)func_end); + return RETURN_RET; + } + +@@ -468,7 +467,7 @@ stm8_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + 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); ++ fprintf_unfiltered(gdb_stdlog, "stm8_analyze_prologue called (pc=%8.8lx current_pc=%8.8lx)\n", (unsigned long)pc, (unsigned long)current_pc); + + /* Initialize info about frame. */ + cache->framesize = 0; +@@ -582,7 +581,7 @@ 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue called: start_pc=%8.8lx\n", (unsigned long)start_pc); + + struct symtab_and_line sal; + CORE_ADDR func_start, func_end, ostart_pc; +@@ -605,7 +604,7 @@ stm8_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) + &cache); + + if (stm8_debug) +- fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue: start_pc=%8.8lx ostart_pc=%8.8lx\n",start_pc,ostart_pc); ++ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue: start_pc=%8.8lx ostart_pc=%8.8lx\n", (unsigned long)start_pc, (unsigned long)ostart_pc); + + if (ostart_pc > start_pc) + return ostart_pc; +@@ -629,7 +628,7 @@ 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); ++ 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); +@@ -712,7 +711,7 @@ stm8_frame_cache (struct frame_info *next_frame, void **this_cache) + 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); ++ next_frame, (unsigned long)cache->base, (unsigned long)current_pc, (unsigned long)current_sp, cache->fp_regnum, (unsigned long)fp, cache->framesize, cache->stackadj, retsize); + + CORE_ADDR frame_pc; + CORE_ADDR frame_sp; +@@ -729,9 +728,9 @@ stm8_frame_cache (struct frame_info *next_frame, void **this_cache) + 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) pc=%8.8lx *pc=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_PC_REGNUM].addr, (unsigned long)frame_pc); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) sp=%8.8lx *sp=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_SP_REGNUM].addr, (unsigned long)frame_sp); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) fp=%8.8lx *fp=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_FP_REGNUM].addr, (unsigned long)frame_fp); + } + + return (struct stm8_frame_cache *) (*this_cache); +@@ -759,7 +758,7 @@ stm8_frame_this_id (struct frame_info *next_frame, void **this_cache, + (*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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_this_id: base=%8.8lx pc=%8.8lx\n", (unsigned long)base, (unsigned long)func); + } + + static struct value * +@@ -789,7 +788,7 @@ stm8_frame_prev_register (struct frame_info *this_frame, + } + + if (stm8_debug) +- fprintf_unfiltered (gdb_stdlog, "stm8_frame_prev_register: regnum(%d)=%8.8llx\n", regnum, value_as_long(value)); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_prev_register: regnum(%d)=%8.8lx\n", regnum, (unsigned long)value_as_long(value)); + + return value; + } +@@ -885,7 +884,7 @@ stm8_frame_base_address (struct frame_info *next_frame, + stm8_frame_cache (next_frame, this_cache); + + if (stm8_debug) +- fprintf_unfiltered (gdb_stdlog, "stm8_frame_base_address: fb=%8.8lx\n", cache->base); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_base_address: fb=%8.8lx\n", (unsigned long)cache->base); + + return cache->base; + } +@@ -906,7 +905,7 @@ stm8_frame_args_address (struct frame_info *this_frame, void **this_cache) + 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); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_args_address: addr = %8.8lx\n", (unsigned long)addr); + + return addr; + } +@@ -966,6 +965,9 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + if (tdesc == NULL) + tdesc = tdesc_stm8; + ++ //override target registers... /ARE ++ tdesc = tdesc_stm8; ++ + /* Check any target description for validity. */ + if (tdesc_has_registers (tdesc)) + { +-- +2.12.2 + diff --git a/binutils_patches/0006-Numerous-changes-and-bug-fixes.patch b/binutils_patches/0006-Numerous-changes-and-bug-fixes.patch new file mode 100644 index 0000000..e27c022 --- /dev/null +++ b/binutils_patches/0006-Numerous-changes-and-bug-fixes.patch @@ -0,0 +1,1670 @@ +From 3447c315a86e833246c70404af4b6f6946751b45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=85ke=20Rehnman?= +Date: Sat, 3 Mar 2018 10:54:22 +0100 +Subject: [PATCH 6/6] Numerous changes and bug fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +* Changed bfd address size to 32 bits +* Fixed reversed operands for mov insn in gas +* Removed fp support in gdb and added dwarf register mapping for sdcc +* Changed ld script template +* Fixed reversed operand for mov insn in disassembly + +Signed-off-by: Ã…ke Rehnman +--- + bfd/cpu-stm8.c | 3 +- + gas/config/tc-stm8.c | 34 ++- + gdb/remote.c | 22 +- + gdb/stm8-tdep.c | 535 ++++++++++++++++++++++----------------------- + include/opcode/stm8.h | 2 + + ld/Makefile.in | 2 +- + ld/emulparams/elf32stm8.sh | 3 +- + ld/scripttempl/elfstm8.sc | 232 -------------------- + ld/scripttempl/stm8.sc | 270 +++++++++++++++++++++++ + opcodes/stm8-dis.c | 53 ++++- + opcodes/stm8-opc.c | 9 +- + 11 files changed, 630 insertions(+), 535 deletions(-) + delete mode 100644 ld/scripttempl/elfstm8.sc + create mode 100644 ld/scripttempl/stm8.sc + +diff --git a/bfd/cpu-stm8.c b/bfd/cpu-stm8.c +index feb6cf805e..d858d0fd8e 100644 +--- a/bfd/cpu-stm8.c ++++ b/bfd/cpu-stm8.c +@@ -25,7 +25,8 @@ + const bfd_arch_info_type bfd_stm8_arch = + { + 8, /* bits per word */ +- 24, /* bits per address */ ++ 32, /* bits per address */ ++// 24, /* bits per address */ + 8, /* bits per byte */ + bfd_arch_stm8, /* architecture */ + bfd_mach_stm8, /* machine */ +diff --git a/gas/config/tc-stm8.c b/gas/config/tc-stm8.c +index 1fa4503ce2..38fa50722a 100644 +--- a/gas/config/tc-stm8.c ++++ b/gas/config/tc-stm8.c +@@ -704,7 +704,7 @@ int read_arg(char *str, expressionS *exps) + expression(exps); + if (stm8_debug) + print_expr(exps); +- exps->X_md=OP_OFF_X; ++ exps->X_md=OP_OFF_Y; + return 1; + } + //offset,SP +@@ -775,19 +775,29 @@ static + void stm8_bfd_out(struct stm8_opcodes_s op, expressionS exp[], int count, char *frag) + { + int i; ++ int arg = 0; ++ int dir = 1; ++ ++ /* if count is negative the arguments are reversed */ ++ if (count < 0) ++ { ++ count = -count; ++ arg = count - 1; ++ dir = -1; ++ } + +- for(i = 0; i < count; i++) ++ for(i = 0; i < count; i++, arg += dir) + { + int where = frag - frag_now->fr_literal; + +- if (exp[i].X_op != O_illegal) ++ if (exp[arg].X_op != O_illegal) + { +- switch(op.constraints[i]) ++ switch(op.constraints[arg]) + { + case ST8_EXTMEM: + case ST8_EXTOFF_X: + case ST8_EXTOFF_Y: +- fix_new_exp(frag_now, where, 3, &exp[i], FALSE, BFD_RELOC_24); ++ fix_new_exp(frag_now, where, 3, &exp[arg], FALSE, BFD_RELOC_24); + bfd_put_bits(0xaaaaaaaa, frag, 24, true); + frag+=3; + break; +@@ -799,7 +809,7 @@ void stm8_bfd_out(struct stm8_opcodes_s op, expressionS exp[], int count, char * + case ST8_LONGOFF_X: + case ST8_WORD: + case ST8_LONGMEM: +- fix_new_exp(frag_now, where, 2, &exp[i], FALSE, BFD_RELOC_16); ++ fix_new_exp(frag_now, where, 2, &exp[arg], FALSE, BFD_RELOC_16); + bfd_put_bits(0xaaaaaaaa, frag, 16, true); + frag+=2; + break; +@@ -811,17 +821,17 @@ void stm8_bfd_out(struct stm8_opcodes_s op, expressionS exp[], int count, char * + case ST8_SHORTOFF_SP: + case ST8_BYTE: + case ST8_SHORTMEM: +- fix_new_exp(frag_now, where, 1, &exp[i], FALSE, BFD_RELOC_8); ++ fix_new_exp(frag_now, where, 1, &exp[arg], 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); ++ fix_new_exp(frag_now, where, 1, &exp[arg], 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); ++ fix_new_exp(frag_now, where-3, 1, &exp[arg], FALSE, BFD_RELOC_STM8_BIT_FLD); + break; + default: + break; +@@ -986,6 +996,12 @@ md_assemble (char *str) + 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; ++ ++ /* mov insn operands are reversed */ ++ if ((opcode[i].bin_opcode == 0x35) || (opcode[i].bin_opcode == 0x45) || (opcode[i].bin_opcode == 0x55)) ++ { ++ count = -count; ++ } + stm8_bfd_out(opcode[i], exps, count, frag); + break; + } +diff --git a/gdb/remote.c b/gdb/remote.c +index 208bf4609b..0fb35a069c 100644 +--- a/gdb/remote.c ++++ b/gdb/remote.c +@@ -9654,6 +9654,15 @@ extended_remote_create_inferior (struct target_ops *ops, + if (extended_remote_supports_disable_randomization (ops)) + extended_remote_disable_randomization (disable_randomization); + ++ //akre ++ if (remote_run_connect) ++ { ++ ops->to_open("localhost:3333", from_tty); ++ if (remote_run_load) ++ generic_load (exec_file, from_tty); ++ init_thread_list (); ++ } ++ + /* If startup-with-shell is on, we inform gdbserver to start the + remote inferior using a shell. */ + if (packet_support (PACKET_QStartupWithShell) != PACKET_DISABLE) +@@ -9672,17 +9681,6 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), + + extended_remote_set_inferior_cwd (rs); + +- //akre +- if (remote_run_connect) +- { +- ops->to_open("localhost:3333", from_tty); +- if (remote_run_load) +- generic_load (exec_file, from_tty); +- init_thread_list (); +- run_worked = 0; +- } +- else +- { + /* Now restart the remote server. */ + run_worked = extended_remote_run (args) != -1; + if (!run_worked) +@@ -9697,7 +9695,7 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), + /* Fall back to "R". */ + extended_remote_restart (); + } +- } ++ + if (!have_inferiors ()) + { + /* Clean up from the last time we ran, before we mark the target +diff --git a/gdb/stm8-tdep.c b/gdb/stm8-tdep.c +index fd4b96c6c0..99276d5cf8 100644 +--- a/gdb/stm8-tdep.c ++++ b/gdb/stm8-tdep.c +@@ -2,7 +2,7 @@ + Written by Ake Rehnman 2017-02-21, + ake.rehnman (at) gmail dot com + +- Copyright (C) 1996-2016 Free Software Foundation, Inc. ++ Copyright (C) 1996-2018 Free Software Foundation, Inc. + + This file is part of GDB. + +@@ -44,19 +44,24 @@ enum stm8_regnum + STM8_Y_REGNUM, + STM8_SP_REGNUM, + STM8_CC_REGNUM, +- //pseudo register +- STM8_FP_REGNUM ++ //pseudo registers ++ STM8_XH_REGNUM, ++ STM8_XL_REGNUM, ++ STM8_YH_REGNUM, ++ STM8_YL_REGNUM, + }; + +-static const char *stm8_register_names[] = ++#define STM8_NUM_PSEUDOREGS 4 ++ ++enum stm8_producer + { +- "pc", "a", "x", "y", "sp", "cc" ++ GCC_PRODUCER, ++ SDCC_PRODUCER + }; + +-struct stm8_soft_reg ++static const char *stm8_register_names[] = + { +- const char *name; +- CORE_ADDR addr; ++ "pc", "a", "x", "y", "sp", "cc" + }; + + unsigned int stm8_debug; +@@ -65,7 +70,13 @@ unsigned int stm8_debug; + + struct gdbarch_tdep + { +- struct stm8_soft_reg fp_reg; ++ enum stm8_producer producer; ++ /* Type for void. */ ++ struct type *void_type; ++ /* Type for a function returning void. */ ++ struct type *func_void_type; ++ /* Type for a pointer to a function. Used for the type of PC. */ ++ struct type *pc_type; + }; + + enum insn_return_kind { +@@ -80,10 +91,19 @@ stm8_convert_register_p (struct gdbarch *gdbarch, int regnum, + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + +- if ((regnum == STM8_FP_REGNUM) && (TYPE_LENGTH(type) > 2)) ++ if ((regnum == STM8_SP_REGNUM) && (TYPE_LENGTH(type) > 2)) ++ { ++ return 1; ++ } ++ if ((regnum == STM8_X_REGNUM) && (TYPE_LENGTH(type) > 2)) ++ { ++ return 1; ++ } ++ if ((regnum == STM8_Y_REGNUM) && (TYPE_LENGTH(type) > 2)) + { + return 1; + } ++ + return 0; + } + +@@ -95,60 +115,43 @@ 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)) ++ if (!get_frame_register_bytes (frame, regnum, 0, 2, ++ to+TYPE_LENGTH(type)-2, 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) ++static stm8_producer ++stm8_get_producer() + { +- struct bound_minimal_symbol msymbol; ++ struct objfile *objfile; ++ struct compunit_symtab *cust; + +- 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; +- } ++ if (current_program_space != NULL) ++ { ++ ALL_COMPUNITS(objfile, cust) ++ { ++ if (cust ++ && COMPUNIT_PRODUCER (cust) != NULL ++ && startswith (COMPUNIT_PRODUCER (cust), "SDCC")) ++ { ++ return SDCC_PRODUCER; ++ } ++ } ++ } ++ return GCC_PRODUCER; + } + + 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")); +- } ++ tdep->producer = stm8_get_producer(); + } + + static const char * +@@ -156,8 +159,21 @@ 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"; ++ ++ if (stm8_get_producer() == SDCC_PRODUCER) ++ { ++ switch (regnum) ++ { ++ case STM8_XH_REGNUM : ++ return "xh"; ++ case STM8_XL_REGNUM : ++ return "xl"; ++ case STM8_YH_REGNUM : ++ return "yh"; ++ case STM8_YL_REGNUM : ++ return "yl"; ++ } ++ } + return NULL; + } + +@@ -175,8 +191,6 @@ stm8_register_type (struct gdbarch *gdbarch, int regnum) + 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; + } +@@ -190,17 +204,43 @@ stm8_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int regsize = 2; ++ gdb_byte tmp[4]; ++ + + switch (regnum) + { +- case STM8_FP_REGNUM: +- /* Fetch a soft register: translate into a memory read. */ +- memset (buf, 0, regsize); +- if (tdep->fp_reg.name) ++ case STM8_XH_REGNUM: ++ status = regcache_raw_read(regcache, STM8_X_REGNUM, tmp); ++ if (status == REG_VALID) + { +- target_read_memory (tdep->fp_reg.addr, buf, 2); ++ buf[0] = tmp[0]; + } +- return REG_VALID; ++ return status; ++ ++ case STM8_XL_REGNUM: ++ status = regcache_raw_read(regcache, STM8_X_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ buf[0] = tmp[1]; ++ } ++ return status; ++ ++ case STM8_YH_REGNUM: ++ status = regcache_raw_read(regcache, STM8_Y_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ buf[0] = tmp[0]; ++ } ++ return status; ++ ++ case STM8_YL_REGNUM: ++ status = regcache_raw_read(regcache, STM8_Y_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ buf[0] = tmp[1]; ++ } ++ return status; ++ + default: + internal_error (__FILE__, __LINE__, _("invalid regnum")); + return REG_UNAVAILABLE; +@@ -215,16 +255,47 @@ stm8_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const int regsize = 2; ++ gdb_byte tmp[4]; + + switch (regnum) + { +- case STM8_FP_REGNUM: +- /* Store a soft register: translate into a memory write. */ +- if (tdep->fp_reg.name) ++ ++ case STM8_XH_REGNUM: ++ status = regcache_raw_read(regcache, STM8_X_REGNUM, tmp); ++ if (status == REG_VALID) + { +- target_write_memory (tdep->fp_reg.addr, buf, 2); +- } +- return; ++ tmp[0] = buf[0]; ++ regcache_raw_write (regcache, STM8_X_REGNUM, tmp); ++ } ++ return; ++ ++ case STM8_XL_REGNUM: ++ status = regcache_raw_read(regcache, STM8_X_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ tmp[1] = buf[0]; ++ regcache_raw_write (regcache, STM8_X_REGNUM, tmp); ++ } ++ return; ++ ++ case STM8_YH_REGNUM: ++ status = regcache_raw_read(regcache, STM8_Y_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ tmp[0] = buf[0]; ++ regcache_raw_write (regcache, STM8_Y_REGNUM, tmp); ++ } ++ return; ++ ++ case STM8_YL_REGNUM: ++ status = regcache_raw_read(regcache, STM8_Y_REGNUM, tmp); ++ if (status == REG_VALID) ++ { ++ tmp[1] = buf[0]; ++ regcache_raw_write (regcache, STM8_Y_REGNUM, tmp); ++ } ++ return; ++ + default: + internal_error (__FILE__, __LINE__, _("invalid regnum")); + return; +@@ -271,7 +342,6 @@ stm8_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, + } + + /* Implement the breakpoint_kind_from_pc gdbarch method. */ +-#if 0 + static int + stm8_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) + { +@@ -298,23 +368,55 @@ stm8_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) + return stm8_breakpoint; + } + +-#endif ++static int dwarf2_to_reg_map_sdcc[] = ++{ ++ STM8_A_REGNUM, //a ++ STM8_XL_REGNUM, //xl ++ STM8_XH_REGNUM, //xh ++ STM8_YL_REGNUM, //yl ++ STM8_YH_REGNUM, //yh ++ STM8_CC_REGNUM, //cc ++ STM8_X_REGNUM, //x ++ STM8_Y_REGNUM, //y ++ STM8_SP_REGNUM, //sp ++ STM8_PC_REGNUM, //pc ++ -1 ++}; + +-static int dwarf2_to_reg_map[6] = +-{ 0 /* r0 */, 1 /* r1 */, 2 /* r2 */, 3 /* r3 */, /* 0- 3 */ +- 4 /* r4 */, 5 /* r5 */ ++static int dwarf2_to_reg_map_gcc[] = ++{ STM8_A_REGNUM, //a ++ STM8_X_REGNUM, //x ++ STM8_Y_REGNUM, //y ++ STM8_SP_REGNUM, //sp ++ -1 + }; + + 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; ++ int ret = -1; ++ ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ static int * t; ++ ++ if (stm8_get_producer() == SDCC_PRODUCER) ++ t = dwarf2_to_reg_map_sdcc; ++ else ++ t = dwarf2_to_reg_map_gcc; ++ ++ for (int i = 0; (t[i] > 0) && (i < 32); i++) ++ { ++ if (i == reg) ++ { ++ ret = t[i]; ++ break; ++ } ++ } ++ ++ if ((stm8_debug>1) && (ret>=0)) ++ fprintf_unfiltered (gdb_stdlog, "stm8_dwarf2_reg_to_regnum called reg=%d ret=%d\n",reg,t[reg]); ++ ++ return ret; + } + + static void +@@ -333,7 +435,10 @@ stm8_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) + + 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 (frame_relative_level(next_frame) < 0) ++ pc = extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr); ++ else ++ pc = extract_typed_address (buf, tdep->pc_type); + if (stm8_debug) + fprintf_unfiltered (gdb_stdlog, "stm8_unwind_pc called: pc=%8.8lx\n", (unsigned long)pc); + return pc; +@@ -351,58 +456,6 @@ stm8_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) + 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. */ + +@@ -471,7 +524,6 @@ stm8_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + + /* Initialize info about frame. */ + cache->framesize = 0; +- cache->fp_regnum = STM8_FP_REGNUM; + cache->frameless_p = 1; + cache->stackadj = 0; + +@@ -505,7 +557,7 @@ stm8_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, + } + + /* Start at beginning of function and analyze until we get to the +- current pc, or the end of the function, whichever is first. */ ++ current pc, or the end of the function, whichever is first. */ + stop = (current_pc < func_end ? current_pc : func_end); + + if (stm8_debug) +@@ -585,6 +637,7 @@ stm8_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) + + struct symtab_and_line sal; + CORE_ADDR func_start, func_end, ostart_pc; ++ CORE_ADDR post_prologue_pc; + struct stm8_frame_cache cache; + + /* This is the preferred method, find the end of the prologue by +@@ -593,18 +646,23 @@ stm8_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) + Always analyze the prologue. */ + if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end)) + { +- sal = find_pc_line (func_start, 0); ++ post_prologue_pc = skip_prologue_using_sal (gdbarch, func_start); + +- if (sal.end < func_end +- && start_pc <= sal.end) +- start_pc = sal.end; ++ if (stm8_debug) ++ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue: post_prologue_pc=%8.8lx\n", ++ (unsigned long)post_prologue_pc); ++ ++ if (post_prologue_pc != 0) ++ return std::max (start_pc, post_prologue_pc); + } + + 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", (unsigned long)start_pc, (unsigned long)ostart_pc); ++ fprintf_unfiltered (gdb_stdlog, "stm8_skip_prologue: start_pc=%8.8lx ostart_pc=%8.8lx func_start=%8.8lx func_end=%8.8lx sal.end=%8.8lx\n", ++ (unsigned long)start_pc, (unsigned long)ostart_pc, ++ (unsigned long)func_start, (unsigned long)func_end, (unsigned long)sal.end); + + if (ostart_pc > start_pc) + return ostart_pc; +@@ -632,7 +690,7 @@ stm8_frame_cache (struct frame_info *next_frame, void **this_cache) + + struct stm8_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (next_frame); +- CORE_ADDR start_pc, current_pc, current_sp, fp; ++ CORE_ADDR start_pc, current_pc, current_sp; + int retsize; + + if (*this_cache) +@@ -655,22 +713,9 @@ stm8_frame_cache (struct frame_info *next_frame, void **this_cache) + 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) + { ++ default: + case RETURN_RET: + retsize = 2; + break; +@@ -682,61 +727,33 @@ stm8_frame_cache (struct frame_info *next_frame, void **this_cache) + 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); +- } ++ cache->base = current_sp; ++ if (cache->return_kind == RETURN_IRET) ++ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1 + 6; + 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); +- } +- ++ cache->saved_regs[STM8_PC_REGNUM].addr = cache->base + 1; ++ trad_frame_set_value (cache->saved_regs, ++ STM8_SP_REGNUM, ++ cache->base+retsize); + + 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, (unsigned long)cache->base, (unsigned long)current_pc, (unsigned long)current_sp, cache->fp_regnum, (unsigned long)fp, cache->framesize, cache->stackadj, retsize); ++ fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) base=%4.4lx curr_pc=%4.4lx curr_sp=%4.4lx framesize=%4.4x stackadj=%4.4x retsize=%d\n", ++ next_frame, (unsigned long)cache->base, (unsigned long)current_pc, (unsigned long)current_sp, 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.8lx *pc=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_PC_REGNUM].addr, (unsigned long)frame_pc); + fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) sp=%8.8lx *sp=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_SP_REGNUM].addr, (unsigned long)frame_sp); +- fprintf_unfiltered (gdb_stdlog, "stm8_frame_cache: (next_frame=%p) fp=%8.8lx *fp=%8.8lx\n", next_frame, (unsigned long)cache->saved_regs[STM8_FP_REGNUM].addr, (unsigned long)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 +@@ -771,22 +788,6 @@ stm8_frame_prev_register (struct frame_info *this_frame, + + 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.8lx\n", regnum, (unsigned long)value_as_long(value)); + +@@ -876,53 +877,53 @@ static const struct frame_unwind stm8_frame_unwind = { + 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", (unsigned long)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", (unsigned long)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; +-} ++//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", (unsigned long)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", (unsigned long)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 +@@ -937,7 +938,7 @@ initialize_tdesc_stm8 (void) + 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_create_reg (feature, "cc", 5, 1, "general", 8, "uint8"); + + tdesc_stm8 = result; + } +@@ -952,7 +953,7 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + struct gdbarch_tdep *tdep; + struct gdbarch_list *best_arch; + struct tdesc_arch_data *tdesc_data = NULL; +- const struct target_desc *tdesc = info.target_desc; ++ const struct target_desc *tdesc = info.target_desc = 0; //override target desc if any + + /* If there is already a candidate, use it. */ + arches = gdbarch_list_lookup_by_info (arches, &info); +@@ -965,9 +966,6 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + if (tdesc == NULL) + tdesc = tdesc_stm8; + +- //override target registers... /ARE +- tdesc = tdesc_stm8; +- + /* Check any target description for validity. */ + if (tdesc_has_registers (tdesc)) + { +@@ -1005,7 +1003,7 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + 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_num_pseudo_regs (gdbarch, STM8_NUM_PSEUDOREGS); + set_gdbarch_pseudo_register_read (gdbarch, stm8_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, stm8_pseudo_register_write); + +@@ -1033,10 +1031,9 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + /* 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); +@@ -1047,9 +1044,9 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + + set_gdbarch_unwind_pc (gdbarch, stm8_unwind_pc); + set_gdbarch_unwind_sp (gdbarch, stm8_unwind_sp); +- set_gdbarch_dummy_id (gdbarch, stm8_dummy_id); ++ ////set_gdbarch_dummy_id (gdbarch, stm8_dummy_id); + +- frame_base_set_default (gdbarch, &stm8_frame_base); ++ ////frame_base_set_default (gdbarch, &stm8_frame_base); + + /* Hook in ABI-specific overrides, if they have been registered. */ + //gdbarch_init_osabi (info, gdbarch); +@@ -1060,14 +1057,16 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + 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); ++ ////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); ++ tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void"); ++ tdep->func_void_type = make_function_type (tdep->void_type, NULL); ++ tdep->pc_type = arch_type (gdbarch, TYPE_CODE_PTR, 2*TARGET_CHAR_BIT, NULL); ++ TYPE_TARGET_TYPE (tdep->pc_type) = tdep->func_void_type; ++ TYPE_UNSIGNED (tdep->pc_type) = 1; ++ + // + // set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); + // set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT); +@@ -1089,9 +1088,9 @@ stm8_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + // + // 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); ++// set_gdbarch_address_to_pointer (gdbarch, stm8_address_to_pointer); ++// set_gdbarch_pointer_to_address (gdbarch, stm8_pointer_to_address); ++// set_gdbarch_integer_to_address (gdbarch, stm8_integer_to_address); + // + // frame_base_set_default (gdbarch, &stm8_frame_base); + // +diff --git a/include/opcode/stm8.h b/include/opcode/stm8.h +index a40ff0aaaa..d131527d86 100644 +--- a/include/opcode/stm8.h ++++ b/include/opcode/stm8.h +@@ -79,4 +79,6 @@ extern int stm8_compute_insn_size(struct stm8_opcodes_s opcode); + + extern unsigned int stm8_opcode_size(unsigned int number); + ++int stm8_num_opcode_operands(struct stm8_opcodes_s opcode); ++ + #endif /* _STM8_H_ */ +diff --git a/ld/Makefile.in b/ld/Makefile.in +index a73392c0d6..4d64b3c75c 100644 +--- a/ld/Makefile.in ++++ b/ld/Makefile.in +@@ -3661,7 +3661,7 @@ eshlelf64_nbsd.c: $(srcdir)/emulparams/shlelf64_nbsd.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + + eelf32stm8.c: $(srcdir)/emulparams/elf32stm8.sh \ +- $(ELF_DEPS) $(srcdir)/scripttempl/elfstm8.sc ${GEN_DEPENDS} ++ $(ELF_DEPS) $(srcdir)/scripttempl/stm8.sc ${GEN_DEPENDS} + + check-DEJAGNU: site.exp + srcroot=`cd $(srcdir) && pwd`; export srcroot; \ +diff --git a/ld/emulparams/elf32stm8.sh b/ld/emulparams/elf32stm8.sh +index c37c9e51da..960ca3885f 100644 +--- a/ld/emulparams/elf32stm8.sh ++++ b/ld/emulparams/elf32stm8.sh +@@ -1,6 +1,7 @@ + ARCH=stm8 + MACHINE=stm8 +-SCRIPT_NAME=elfstm8 ++SCRIPT_NAME=stm8 ++#SCRIPT_NAME=elfstm8 + OUTPUT_FORMAT="elf32-stm8" + MAXPAGESIZE=1 + EMBEDDED=yes +diff --git a/ld/scripttempl/elfstm8.sc b/ld/scripttempl/elfstm8.sc +deleted file mode 100644 +index 0ce6b56741..0000000000 +--- a/ld/scripttempl/elfstm8.sc ++++ /dev/null +@@ -1,232 +0,0 @@ +-# 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 < text} ++ ++ .data ${RELOCATING-0} : ++ { ++ ${RELOCATING+ PROVIDE (__data_start = .) ; } ++ *(.data) ++ ${RELOCATING+ *(.data*)} ++ *(.rodata) /* We need to include .rodata here if gcc is used */ ++ ${RELOCATING+ *(.rodata*)} /* with -fdata-sections. */ ++ *(.gnu.linkonce.d*) ++ ${RELOCATING+. = ALIGN(2);} ++ ${RELOCATING+ _edata = . ; } ++ ${RELOCATING+ PROVIDE (__data_end = .) ; } ++ } ${RELOCATING+ > data ${RELOCATING+AT> text}} ++ ++ .bss ${RELOCATING+ ADDR(.data) + SIZEOF (.data)} ${RELOCATING-0} :${RELOCATING+ AT (ADDR (.bss))} ++ { ++ ${RELOCATING+ PROVIDE (__bss_start = .) ; } ++ *(.bss) ++ ${RELOCATING+ *(.bss*)} ++ *(COMMON) ++ ${RELOCATING+ PROVIDE (__bss_end = .) ; } ++ } ${RELOCATING+ > data} ++ ++ ${RELOCATING+ __data_load_start = LOADADDR(.data); } ++ ${RELOCATING+ __data_load_end = __data_load_start + SIZEOF(.data); } ++ ++ /* Global data not cleared after reset. */ ++ .noinit ${RELOCATING+ ADDR(.bss) + SIZEOF (.bss)} ${RELOCATING-0}: ${RELOCATING+ AT (ADDR (.noinit))} ++ { ++ ${RELOCATING+ PROVIDE (__noinit_start = .) ; } ++ *(.noinit*) ++ ${RELOCATING+ PROVIDE (__noinit_end = .) ; } ++ ${RELOCATING+ _end = . ; } ++ ${RELOCATING+ PROVIDE (__heap_start = .) ; } ++ } ${RELOCATING+ > data} ++ ++ .eeprom ${RELOCATING-0}: ++ { ++ /* See .data above... */ ++ KEEP(*(.eeprom*)) ++ ${RELOCATING+ __eeprom_end = . ; } ++ } ${RELOCATING+ > eeprom} ++ ++ .fuse ${RELOCATING-0}: ++ { ++ KEEP(*(.fuse)) ++ KEEP(*(.lfuse)) ++ KEEP(*(.hfuse)) ++ KEEP(*(.efuse)) ++ } ${RELOCATING+ > fuse} ++ ++ .lock ${RELOCATING-0}: ++ { ++ KEEP(*(.lock*)) ++ } ${RELOCATING+ > lock} ++ ++ .signature ${RELOCATING-0}: ++ { ++ KEEP(*(.signature*)) ++ } ${RELOCATING+ > signature} ++ ++ /* Stabs debugging sections. */ ++ .stab 0 : { *(.stab) } ++ .stabstr 0 : { *(.stabstr) } ++ .stab.excl 0 : { *(.stab.excl) } ++ .stab.exclstr 0 : { *(.stab.exclstr) } ++ .stab.index 0 : { *(.stab.index) } ++ .stab.indexstr 0 : { *(.stab.indexstr) } ++ .comment 0 : { *(.comment) } ++ .note.gnu.build-id : { *(.note.gnu.build-id) } ++EOF ++ ++. $srcdir/scripttempl/DWARF.sc ++ ++cat <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++) ++ c = ' '; ++ ++ for (int curr_operand = 0; curr_operand < stm8_num_opcode_operands(stm8_opcodes[i]); curr_operand++) + { +- s[0]=0; +- bufp+=stm8_operands(s, bufp, stm8_opcodes[i].constraints[j]); +- if (s[0]) ++ bufp = buf; ++ dir = 1; ++ operand = 0; ++ ++ /* mov insn operands are reversed */ ++ if ((op == 0x35) || (op == 0x45) || (op == 0x55)) + { +- if (j==0) c=' '; else c=','; +- dinfo->fprintf_func(dinfo->stream, "%c%s",c,s); ++ dir = -1; ++ operand = stm8_num_opcode_operands(stm8_opcodes[i]) - 1; ++ } ++ ++ for (int j = 0; j < stm8_num_opcode_operands(stm8_opcodes[i]); j++, operand += dir) ++ { ++ s[0] = 0; ++ bufp += stm8_operands(s, bufp, stm8_opcodes[i].constraints[operand]); ++ if (operand == curr_operand) ++ { ++ if (s[0]) ++ { ++ dinfo->fprintf_func(dinfo->stream, "%c%s",c,s); ++ c = ','; ++ } ++ break; ++ } + } + } ++ ++ ++// c = ' '; ++// for (j=0; j<5; j++, operand += dir) ++// { ++// s[0]=0; ++// bufp += stm8_operands(s, bufp, stm8_opcodes[i].constraints[operand]); ++// if (s[0]) ++// { ++// dinfo->fprintf_func(dinfo->stream, "%c%s",c,s); ++// c = ','; ++// } ++// } ++ + if (lastlabeladdr) + { + dinfo->fprintf_func(dinfo->stream, " ;"); +diff --git a/opcodes/stm8-opc.c b/opcodes/stm8-opc.c +index 3a600d66d3..9516d859f2 100644 +--- a/opcodes/stm8-opc.c ++++ b/opcodes/stm8-opc.c +@@ -1,5 +1,5 @@ + /* stm8-opc.c -- Table of opcodes for the STM8 processor. +- Copyright (C) 2007-2016 Free Software Foundation, Inc. ++ Copyright (C) 2007-2018 Free Software Foundation, Inc. + Contributed by Ake Rehnman ake dot rehnman (at) gmail dot com + + This file is part of the GNU opcodes library. +@@ -729,6 +729,13 @@ const struct stm8_opcodes_s stm8_opcodes[] = + {NULL, {ST8_END}, 0}, + }; + ++int stm8_num_opcode_operands(struct stm8_opcodes_s opcode) ++{ ++ int i; ++ for(i = 0; opcode.constraints[i]; i++); ++ return i; ++} ++ + unsigned int stm8_opcode_size(unsigned int number) + { + int i; +-- +2.12.2 + diff --git a/configure_binutils.sh b/configure_binutils.sh new file mode 100755 index 0000000..3c17d01 --- /dev/null +++ b/configure_binutils.sh @@ -0,0 +1,12 @@ +#!/bin/sh +cd binutils-2.30 +if [ x$HOST=x"" ]; then + _HOST=$(./config.guess) +else + _HOST=$HOST +fi +if [ x$PREFIX != x"" ]; then + _PREFIX="-prefix=$PREFIX" +fi + +./configure --host=$_HOST --target=stm8-none-elf32 $_PREFIX --program-prefix=stm8- diff --git a/patch_binutils.sh b/patch_binutils.sh new file mode 100755 index 0000000..b5c621c --- /dev/null +++ b/patch_binutils.sh @@ -0,0 +1,10 @@ +#!/bin/sh +wget -nc https://ftp.gnu.org/gnu/binutils/binutils-2.30.tar.xz +wget -nc https://ftp.gnu.org/gnu/gdb/gdb-8.1.tar.xz +mkdir -p binutils-2.30 +tar -xvf gdb-8.1.tar.xz --strip-components=1 --directory=binutils-2.30 +tar -xvf binutils-2.30.tar.xz +for f in ./binutils_patches/*.patch +do +patch -N -p 1 -d binutils-2.30 <$f +done