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/10] 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