aboutsummaryrefslogtreecommitdiff
path: root/binutils_patches/0006-Numerous-changes-and-bug-fixes.patch
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-29 01:20:21 +0100
committerXavier ASUS <xavi92psx@gmail.com>2019-10-29 01:20:21 +0100
commit394922bfd2c9182f3268bff664d4c46a1a6590f7 (patch)
treea47bfafc4d2ec8a3b06020ae2570e4837bb6bee6 /binutils_patches/0006-Numerous-changes-and-bug-fixes.patch
downloadstm8-binutils-gdb-394922bfd2c9182f3268bff664d4c46a1a6590f7.tar.gz
First commit, forked from sourceforge tar
Diffstat (limited to 'binutils_patches/0006-Numerous-changes-and-bug-fixes.patch')
-rw-r--r--binutils_patches/0006-Numerous-changes-and-bug-fixes.patch1670
1 files changed, 1670 insertions, 0 deletions
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?= <ake_rehnman_at_gmail_com>
+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 <ake_rehnman_at_gmail_com>
+---
+ 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 <<EOF
+-/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
+-
+- Copying and distribution of this script, with or without modification,
+- are permitted in any medium without royalty provided the copyright
+- notice and this notice are preserved. */
+-
+-OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+- "${LITTLE_OUTPUT_FORMAT}")
+-/*${LIB_SEARCH_DIRS}*/
+-${RELOCATING+${LIB_SEARCH_DIRS}}
+-
+-${RELOCATING+ENTRY (${ENTRY})}
+-
+-_TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x50;
+-_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0;
+-_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400;
+-
+-SECTIONS
+-{
+- .vectors.reset 0x8000 : { KEEP (*(.vectors.reset)) } = 0
+-
+- ${RELOCATING+. = _TEXT_START_ADDR;}
+-
+- ${RELOCATING+ _ftext = .;}
+- .text : {
+- ${RELOCATING+*(.text)}
+- ${RELOCATING+*(.text.*)}
+- ${RELOCATING+*(.gnu.linkonce.t.*)}
+- }
+- ${RELOCATING+ _etext = .;}
+-
+- .init : { KEEP (*(.init)) } =0
+- .fini : { KEEP (*(.fini)) } =0
+-
+- ${RELOCATING+PROVIDE (__CTOR_LIST__ = .);}
+- ${RELOCATING+PROVIDE (___CTOR_LIST__ = .);}
+- ${RELOCATING+${CTOR}}
+- ${RELOCATING+PROVIDE (__CTOR_END__ = .);}
+- ${RELOCATING+PROVIDE (___CTOR_END__ = .);}
+-
+- ${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
+- ${RELOCATING+PROVIDE (___DTOR_LIST__ = .);}
+- ${RELOCATING+${DTOR}}
+- ${RELOCATING+PROVIDE (__DTOR_END__ = .);}
+- ${RELOCATING+PROVIDE (___DTOR_END__ = .);}
+-
+- ${RELOCATING+ . = ALIGN(4);}
+- ${RELOCATING+ _frodata = . ;}
+- .rodata : {
+- ${RELOCATING+*(.rodata)}
+- ${RELOCATING+*(.rodata.*)}
+- ${RELOCATING+*(.gnu.linkonce.r.*)}
+- ${CONSTRUCTING+CONSTRUCTORS}; /* Is this needed? */
+- }
+- ${RELOCATING+ _erodata = .;}
+-
+- /* Alignments by 8 to ensure that _SDA2_BASE_ on a word boundary */
+- /* Note that .sdata2 and .sbss2 must be contiguous */
+- ${RELOCATING+. = ALIGN(8);}
+- ${RELOCATING+ _ssrw = .;}
+- .sdata2 : {
+- ${RELOCATING+*(.sdata2)}
+- ${RELOCATING+*(.sdata2.*)}
+- ${RELOCATING+*(.gnu.linkonce.s2.*)}
+- }
+- ${RELOCATING+. = ALIGN(4);}
+- .sbss2 : {
+- ${RELOCATING+PROVIDE (__sbss2_start = .);}
+- ${RELOCATING+*(.sbss2)}
+- ${RELOCATING+*(.sbss2.*)}
+- ${RELOCATING+*(.gnu.linkonce.sb2.*)}
+- ${RELOCATING+PROVIDE (__sbss2_end = .);}
+- }
+- ${RELOCATING+. = ALIGN(8);}
+- ${RELOCATING+ _essrw = .;}
+- ${RELOCATING+ _ssrw_size = _essrw - _ssrw;}
+- ${RELOCATING+ PROVIDE (_SDA2_BASE_ = _ssrw + (_ssrw_size / 2 ));}
+-
+- ${RELOCATING+ . = ALIGN(4);}
+- ${RELOCATING+ _fdata = .;}
+- .data : {
+- ${RELOCATING+*(.data)}
+- ${RELOCATING+*(.gnu.linkonce.d.*)}
+- ${CONSTRUCTING+CONSTRUCTORS}; /* Is this needed? */
+- }
+- ${RELOCATING+ _edata = . ;}
+-
+- /* Added to handle pic code */
+- .got : {
+- ${RELOCATING+*(.got)}
+- }
+-
+- .got1 : {
+- ${RELOCATING+*(.got1)}
+- }
+-
+- .got2 : {
+- ${RELOCATING+*(.got2)}
+- }
+-
+- /* Added by Sathya to handle C++ exceptions */
+- .eh_frame : {
+- ${RELOCATING+*(.eh_frame)}
+- }
+-
+- .jcr : {
+- ${RELOCATING+*(.jcr)}
+- }
+-
+- .gcc_except_table : {
+- ${RELOCATING+*(.gcc_except_table)}
+- }
+-
+- /* Alignments by 8 to ensure that _SDA_BASE_ on a word boundary */
+- /* Note that .sdata and .sbss must be contiguous */
+- ${RELOCATING+. = ALIGN(8);}
+- ${RELOCATING+ _ssro = .;}
+- .sdata : {
+- ${RELOCATING+*(.sdata)}
+- ${RELOCATING+*(.sdata.*)}
+- ${RELOCATING+*(.gnu.linkonce.s.*)}
+- }
+- ${RELOCATING+. = ALIGN(4);}
+- .sbss : {
+- ${RELOCATING+PROVIDE (__sbss_start = .);}
+- ${RELOCATING+*(.sbss)}
+- ${RELOCATING+*(.sbss.*)}
+- ${RELOCATING+*(.gnu.linkonce.sb.*)}
+- ${RELOCATING+PROVIDE (__sbss_end = .);}
+- }
+- ${RELOCATING+. = ALIGN(8);}
+- ${RELOCATING+ _essro = .;}
+- ${RELOCATING+ _ssro_size = _essro - _ssro;}
+- ${RELOCATING+PROVIDE (_SDA_BASE_ = _ssro + (_ssro_size / 2 ));}
+-
+- ${RELOCATING+ . = ALIGN(4);}
+- ${RELOCATING+ _fbss = .;}
+- .bss : {
+- ${RELOCATING+PROVIDE (__bss_start = .);}
+- ${RELOCATING+*(.bss)}
+- ${RELOCATING+*(.bss.*)}
+- ${RELOCATING+*(.gnu.linkonce.b.*)}
+- ${RELOCATING+*(COMMON)}
+- ${RELOCATING+. = ALIGN(. != 0 ? 4 : 1);}
+-
+- ${RELOCATING+PROVIDE (__bss_end = .);}
+-
+- }
+-
+- ${RELOCATING+ . = ALIGN(4);}
+-
+- .heap : {
+- ${RELOCATING+ _heap = .;}
+- ${RELOCATING+ _heap_start = .;}
+- ${RELOCATING+ . += _HEAP_SIZE;}
+- ${RELOCATING+ _heap_end = .;}
+- }
+-
+- ${RELOCATING+ . = ALIGN(4);}
+-
+- .stack : {
+- ${RELOCATING+ _stack_end = .;}
+- ${RELOCATING+ . += _STACK_SIZE;}
+- ${RELOCATING+ . = ALIGN(. != 0 ? 8 : 1);}
+- ${RELOCATING+ _stack = .;}
+- ${RELOCATING+ _end = .;}
+- }
+-
+- .tdata : {
+- ${RELOCATING+*(.tdata)}
+- ${RELOCATING+*(.tdata.*)}
+- ${RELOCATING+*(.gnu.linkonce.td.*)}
+- }
+- .tbss : {
+- ${RELOCATING+*(.tbss)}
+- ${RELOCATING+*(.tbss.*)}
+- ${RELOCATING+*(.gnu.linkonce.tb.*)}
+- }
+-}
+-EOF
+diff --git a/ld/scripttempl/stm8.sc b/ld/scripttempl/stm8.sc
+new file mode 100644
+index 0000000000..642b906d4f
+--- /dev/null
++++ b/ld/scripttempl/stm8.sc
+@@ -0,0 +1,270 @@
++# Copyright (C) 2014-2018 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.
++
++test -z "$ENTRY" && ENTRY=_start
++
++cat <<EOF
++/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
++
++ Copying and distribution of this script, with or without modification,
++ are permitted in any medium without royalty provided the copyright
++ notice and this notice are preserved. */
++
++${RELOCATING+ENTRY (${ENTRY})}
++
++OUTPUT_FORMAT("${OUTPUT_FORMAT}","${OUTPUT_FORMAT}","${OUTPUT_FORMAT}")
++OUTPUT_ARCH(${ARCH})
++
++__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : $TEXT_LENGTH;
++__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : $DATA_LENGTH;
++__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K;
++__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K;
++__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K;
++__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K;
++__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K;
++
++MEMORY
++{
++ data (rw!x) : ORIGIN = 0x0, LENGTH = __DATA_REGION_LENGTH__
++ eeprom (rw!x) : ORIGIN = 0x4000, LENGTH = __EEPROM_REGION_LENGTH__
++ fuse (rw!x) : ORIGIN = 0x5000, LENGTH = __FUSE_REGION_LENGTH__
++ lock (rw!x) : ORIGIN = 0x5100, LENGTH = __LOCK_REGION_LENGTH__
++ text (rx) : ORIGIN = 0x8000, LENGTH = __TEXT_REGION_LENGTH__
++ signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__
++ user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__
++}
++
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ ${TEXT_DYNAMIC+${DYNAMIC}}
++ .hash ${RELOCATING-0} : { *(.hash) }
++ .dynsym ${RELOCATING-0} : { *(.dynsym) }
++ .dynstr ${RELOCATING-0} : { *(.dynstr) }
++ .gnu.version ${RELOCATING-0} : { *(.gnu.version) }
++ .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
++ .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
++
++ .rel.init ${RELOCATING-0} : { *(.rel.init) }
++ .rela.init ${RELOCATING-0} : { *(.rela.init) }
++ .rel.text ${RELOCATING-0} :
++ {
++ *(.rel.text)
++ ${RELOCATING+*(.rel.text.*)}
++ ${RELOCATING+*(.rel.gnu.linkonce.t*)}
++ }
++ .rela.text ${RELOCATING-0} :
++ {
++ *(.rela.text)
++ ${RELOCATING+*(.rela.text.*)}
++ ${RELOCATING+*(.rela.gnu.linkonce.t*)}
++ }
++ .rel.fini ${RELOCATING-0} : { *(.rel.fini) }
++ .rela.fini ${RELOCATING-0} : { *(.rela.fini) }
++ .rel.rodata ${RELOCATING-0} :
++ {
++ *(.rel.rodata)
++ ${RELOCATING+*(.rel.rodata.*)}
++ ${RELOCATING+*(.rel.gnu.linkonce.r*)}
++ }
++ .rela.rodata ${RELOCATING-0} :
++ {
++ *(.rela.rodata)
++ ${RELOCATING+*(.rela.rodata.*)}
++ ${RELOCATING+*(.rela.gnu.linkonce.r*)}
++ }
++ .rel.data ${RELOCATING-0} :
++ {
++ *(.rel.data)
++ ${RELOCATING+*(.rel.data.*)}
++ ${RELOCATING+*(.rel.gnu.linkonce.d*)}
++ }
++ .rela.data ${RELOCATING-0} :
++ {
++ *(.rela.data)
++ ${RELOCATING+*(.rela.data.*)}
++ ${RELOCATING+*(.rela.gnu.linkonce.d*)}
++ }
++ .rel.ctors ${RELOCATING-0} : { *(.rel.ctors) }
++ .rela.ctors ${RELOCATING-0} : { *(.rela.ctors) }
++ .rel.dtors ${RELOCATING-0} : { *(.rel.dtors) }
++ .rela.dtors ${RELOCATING-0} : { *(.rela.dtors) }
++ .rel.got ${RELOCATING-0} : { *(.rel.got) }
++ .rela.got ${RELOCATING-0} : { *(.rela.got) }
++ .rel.bss ${RELOCATING-0} : { *(.rel.bss) }
++ .rela.bss ${RELOCATING-0} : { *(.rela.bss) }
++ .rel.plt ${RELOCATING-0} : { *(.rel.plt) }
++ .rela.plt ${RELOCATING-0} : { *(.rela.plt) }
++
++ /* Internal text space or external memory. */
++ .text ${RELOCATING-0} :
++ {
++ *(.vectors)
++ KEEP(*(.vectors))
++
++ /* For data that needs to reside in the lower 64k of progmem. */
++ ${RELOCATING+ *(.progmem.gcc*)}
++
++ /* PR 13812: Placing the trampolines here gives a better chance
++ that they will be in range of the code that uses them. */
++ ${RELOCATING+. = ALIGN(2);}
++ ${CONSTRUCTING+ __trampolines_start = . ; }
++ /* The jump trampolines for the 16-bit limited relocs will reside here. */
++ *(.trampolines)
++ ${RELOCATING+ *(.trampolines*)}
++ ${CONSTRUCTING+ __trampolines_end = . ; }
++
++ /* avr-libc expects these data to reside in lower 64K. */
++ ${RELOCATING+ *libprintf_flt.a:*(.progmem.data)}
++ ${RELOCATING+ *libc.a:*(.progmem.data)}
++
++ ${RELOCATING+ *(.progmem*)}
++
++ ${RELOCATING+. = ALIGN(2);}
++
++ /* For future tablejump instruction arrays for 3 byte pc devices.
++ We don't relax jump/call instructions within these sections. */
++ *(.jumptables)
++ ${RELOCATING+ *(.jumptables*)}
++
++ /* For code that needs to reside in the lower 128k progmem. */
++ *(.lowtext)
++ ${RELOCATING+ *(.lowtext*)}
++
++ ${CONSTRUCTING+ __ctors_start = . ; }
++ ${CONSTRUCTING+ *(.ctors) }
++ ${CONSTRUCTING+ __ctors_end = . ; }
++ ${CONSTRUCTING+ __dtors_start = . ; }
++ ${CONSTRUCTING+ *(.dtors) }
++ ${CONSTRUCTING+ __dtors_end = . ; }
++ KEEP(SORT(*)(.ctors))
++ KEEP(SORT(*)(.dtors))
++
++ /* From this point on, we don't bother about wether the insns are
++ below or above the 16 bits boundary. */
++ *(.init0) /* Start here after reset. */
++ KEEP (*(.init0))
++ *(.init1)
++ KEEP (*(.init1))
++ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
++ KEEP (*(.init2))
++ *(.init3)
++ KEEP (*(.init3))
++ *(.init4) /* Initialize data and BSS. */
++ KEEP (*(.init4))
++ *(.init5)
++ KEEP (*(.init5))
++ *(.init6) /* C++ constructors. */
++ KEEP (*(.init6))
++ *(.init7)
++ KEEP (*(.init7))
++ *(.init8)
++ KEEP (*(.init8))
++ *(.init9) /* Call main(). */
++ KEEP (*(.init9))
++ *(.text)
++ ${RELOCATING+. = ALIGN(2);}
++ ${RELOCATING+ *(.text.*)}
++ ${RELOCATING+. = ALIGN(2);}
++ *(.fini9) /* _exit() starts here. */
++ KEEP (*(.fini9))
++ *(.fini8)
++ KEEP (*(.fini8))
++ *(.fini7)
++ KEEP (*(.fini7))
++ *(.fini6) /* C++ destructors. */
++ KEEP (*(.fini6))
++ *(.fini5)
++ KEEP (*(.fini5))
++ *(.fini4)
++ KEEP (*(.fini4))
++ *(.fini3)
++ KEEP (*(.fini3))
++ *(.fini2)
++ KEEP (*(.fini2))
++ *(.fini1)
++ KEEP (*(.fini1))
++ *(.fini0) /* Infinite loop after program termination. */
++ KEEP (*(.fini0))
++ ${RELOCATING+ _etext = . ; }
++ } ${RELOCATING+ > 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 <<EOF
++}
++EOF
+diff --git a/opcodes/stm8-dis.c b/opcodes/stm8-dis.c
+index 751c62c2b7..2eee63060b 100644
+--- a/opcodes/stm8-dis.c
++++ b/opcodes/stm8-dis.c
+@@ -1,5 +1,5 @@
+ /* Disassemble STM8 instructions.
+- Copyright (C) 1999-2016 Free Software Foundation, Inc.
++ Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+ Contributed by Ake Rehnman
+
+@@ -344,32 +344,65 @@ int stm8_dis(bfd_vma addr, unsigned int op)
+ unsigned char *bufp;
+ char s[256];
+ int i=0;
+- int j;
+ char c;
+ int operandlen;
++ int operand, dir;
+
+ 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++)
++ 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
+