* PATCH: new gdb port: moxie-elf
@ 2009-04-23 11:57 green
2009-04-23 18:29 ` Joel Brobecker
0 siblings, 1 reply; 9+ messages in thread
From: green @ 2009-04-23 11:57 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 543 bytes --]
Here's the gdb patch that goes with the sim patch I just submitted[1].
[1] http://sourceware.org/ml/gdb-patches/2009-04/msg00645.html
Thanks,
Anthony Green
2009-04-23 Anthony Green <green@moxielogic.com>
* moxie-tdep.h: New file.
* moxie-tdep.c: New file.
* configure.tgt: Add moxie-elf.
[-- Attachment #2: moxie-gdb.patch --]
[-- Type: text/plain, Size: 16605 bytes --]
diff -ruN usrc/gdb/configure.tgt src/gdb/configure.tgt
--- usrc/gdb/configure.tgt 2009-04-17 10:22:25.000000000 -0400
+++ src/gdb/configure.tgt 2009-04-23 07:29:18.000000000 -0400
@@ -114,6 +114,11 @@
gdb_sim=../sim/frv/libsim.a
;;
+moxie-*-elf)
+ gdb_target_obs="moxie-tdep.o"
+ gdb_sim=../sim/moxie/libsim.a
+ ;;
+
h8300-*-*)
# Target: H8300 with HMS monitor and H8 simulator
gdb_target_obs="h8300-tdep.o monitor.o dsrec.o"
diff -ruN usrc/gdb/moxie-tdep.c src/gdb/moxie-tdep.c
--- usrc/gdb/moxie-tdep.c 1969-12-31 19:00:00.000000000 -0500
+++ src/gdb/moxie-tdep.c 2009-04-23 07:18:09.000000000 -0400
@@ -0,0 +1,500 @@
+/* Target-dependent code for Moxie
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "language.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+
+#include "gdb_assert.h"
+
+#include "moxie-tdep.h"
+
+/* Local functions */
+
+extern void _initialize_moxie_tdep (void);
+
+/* Use an invalid address value as 'not available' marker. */
+enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+
+struct moxie_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+ LONGEST framesize;
+ CORE_ADDR saved_regs[MOXIE_NUM_REGS];
+ CORE_ADDR saved_sp;
+};
+
+static CORE_ADDR
+moxie_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~1;
+}
+
+const static unsigned char *
+moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
+ CORE_ADDR *pcptr, int *lenptr)
+{
+ static unsigned char breakpoint[] = { 0x35, 0x00 };
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+char *moxie_register_names[] = {
+ "$fp", "$sp", "$r0", "$r1", "$r2",
+ "$r3", "$r4", "$r5", "$r6", "$r7",
+ "$r8", "$r9", "$r10", "$r11", "$r12",
+ "$r13", "$pc", "$cc" };
+
+static const char *
+moxie_register_name (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= MOXIE_NUM_REGS)
+ return NULL;
+ return moxie_register_names[reg_nr];
+}
+
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+static struct type *
+moxie_register_type (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr == MOXIE_PC_REGNUM)
+ return builtin_type (gdbarch)->builtin_func_ptr;
+ else if (reg_nr == MOXIE_SP_REGNUM || reg_nr == MOXIE_FP_REGNUM)
+ return builtin_type (gdbarch)->builtin_data_ptr;
+ else
+ return builtin_type_int32;
+}
+
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ Things always get returned in RET1_REGNUM, RET2_REGNUM. */
+
+static void
+moxie_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ CORE_ADDR regval;
+ int len = TYPE_LENGTH (type);
+
+ regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval);
+
+ if (len > 4)
+ {
+ regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4, len - 4);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval);
+ }
+}
+
+/* Function: moxie_scan_prologue
+ Decode the instructions within the given address range.
+ Decide when we must have reached the end of the function prologue.
+ If a frame_info pointer is provided, fill in its saved_regs etc.
+
+ Returns the address of the first instruction after the prologue. */
+
+static CORE_ADDR
+moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
+ struct moxie_frame_cache *cache,
+ struct frame_info *this_frame)
+{
+ CORE_ADDR next_addr;
+ ULONGEST inst, inst2;
+ LONGEST offset;
+ int regnum;
+
+ /* Record where the jsra instruction saves the PC and FP */
+ cache->saved_regs[MOXIE_PC_REGNUM] = -4;
+ cache->saved_regs[MOXIE_FP_REGNUM] = 0;
+ cache->framesize = 0;
+
+ if (start_addr >= end_addr)
+ return end_addr;
+
+ for (next_addr = start_addr;
+ next_addr < end_addr; )
+ {
+ inst = read_memory_unsigned_integer (next_addr, 2);
+
+ if (inst >= 0x0614 && inst <= 0x061f) /* push %r2 .. push %r13 */
+ {
+ regnum = inst & 0x000f;
+ cache->framesize += 4;
+ cache->saved_regs[regnum] = cache->framesize;
+ next_addr += 2;
+ }
+
+ /* optional stack allocation for args and local vars <= 4 byte */
+ else if (inst == 0x01f0) /* ldi.l $r13, X */
+ {
+ offset = read_memory_integer (next_addr + 2, 4);
+ inst2 = read_memory_unsigned_integer (next_addr + 6, 2);
+
+ if (inst2 == 0x051f) /* add.l $sp, $r13 */
+ {
+ cache->framesize += offset;
+ }
+
+ return (next_addr + 8);
+ }
+ else /* Not a prologue instruction. */
+ break;
+ }
+
+ return next_addr;
+}
+
+/* Function: skip_prologue
+ Find end of function prologue */
+
+#define DEFAULT_SEARCH_LIMIT 128
+
+CORE_ADDR
+moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr = 0, func_end = 0;
+ char *func_name;
+
+ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
+ {
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ struct moxie_frame_cache cache;
+ CORE_ADDR plg_end;
+
+ memset (&cache, 0, sizeof cache);
+
+ plg_end = moxie_analyze_prologue (func_addr, func_end, &cache, NULL);
+
+ /* Found a function. */
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
+ /* Don't use line number debug info for assembly source files. */
+ if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
+ {
+ /* Found a line number, use it as end of prologue. */
+ return sal.end;
+ }
+ }
+ /* No useable line symbol. Use result of prologue parsing method. */
+ return plg_end;
+ }
+
+ /* No function symbol -- just return the PC. */
+
+ return (CORE_ADDR) pc;
+}
+
+struct moxie_unwind_cache
+{
+ /* The previous frame's inner most stack address. Used as this
+ frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+ /* The frame's base, optionally used by the high-level debug info. */
+ CORE_ADDR base;
+ int size;
+ /* How far the SP and r13 (FP) have been offset from the start of
+ the stack frame (as defined by the previous frame's stack
+ pointer). */
+ LONGEST sp_offset;
+ LONGEST r13_offset;
+ int uses_frame;
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static CORE_ADDR
+moxie_read_pc (struct regcache *regcache)
+{
+ ULONGEST pc;
+ regcache_cooked_read_unsigned (regcache, MOXIE_PC_REGNUM, &pc);
+ return pc;
+}
+
+static void
+moxie_write_pc (struct regcache *regcache, CORE_ADDR val)
+{
+ regcache_cooked_write_unsigned (regcache, MOXIE_PC_REGNUM, val);
+}
+
+static CORE_ADDR
+moxie_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_SP_REGNUM);
+}
+
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+static void
+moxie_extract_return_value (struct type *type, struct regcache *regcache,
+ void *dst)
+{
+ bfd_byte *valbuf = dst;
+ int len = TYPE_LENGTH (type);
+ ULONGEST tmp;
+
+ /* By using store_unsigned_integer we avoid having to do
+ anything special for small big-endian values. */
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &tmp);
+ store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), tmp);
+
+ /* Ignore return values more than 8 bytes in size because the moxie
+ returns anything more than 8 bytes in the stack. */
+ if (len > 4)
+ {
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp);
+ store_unsigned_integer (valbuf + len - 4, 4, tmp);
+ }
+}
+
+enum return_value_convention
+moxie_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ if (TYPE_LENGTH (valtype) > 8)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ {
+ if (readbuf != NULL)
+ moxie_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf != NULL)
+ moxie_store_return_value (valtype, regcache, writebuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+}
+
+static struct moxie_frame_cache *
+moxie_alloc_frame_cache (void)
+{
+ struct moxie_frame_cache *cache;
+ int i;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache);
+
+ cache->base = 0;
+ cache->saved_sp = 0;
+ cache->pc = 0;
+ cache->framesize = 0;
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ cache->saved_regs[i] = REG_UNAVAIL;
+
+ return cache;
+}
+
+static struct moxie_frame_cache *
+moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache;
+ CORE_ADDR current_pc;
+ int i;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = moxie_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
+ if (cache->base == 0)
+ return cache;
+
+ cache->pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+ if (cache->pc)
+ moxie_analyze_prologue (cache->pc, current_pc, cache, this_frame);
+
+ cache->saved_sp = cache->base - cache->framesize;
+
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ if (cache->saved_regs[i] != REG_UNAVAIL)
+ cache->saved_regs[i] = cache->base - cache->saved_regs[i];
+
+ return cache;
+}
+
+static CORE_ADDR
+moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
+}
+
+/* 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
+moxie_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache, struct frame_id *this_id)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ *this_id = frame_id_build (cache->saved_sp, cache->pc);
+}
+
+static struct value *
+moxie_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+ gdb_assert (regnum >= 0);
+
+ if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
+ return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+
+ if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
+ return frame_unwind_got_memory (this_frame, regnum,
+ cache->saved_regs[regnum]);
+
+ return frame_unwind_got_register (this_frame, regnum, regnum);
+}
+
+static const struct frame_unwind moxie_frame_unwind = {
+ NORMAL_FRAME,
+ moxie_frame_this_id,
+ moxie_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+static CORE_ADDR
+moxie_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_cache);
+ return cache->base;
+}
+
+static const struct frame_base moxie_frame_base = {
+ &moxie_frame_unwind,
+ moxie_frame_base_address,
+ moxie_frame_base_address,
+ moxie_frame_base_address
+};
+
+/* 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
+moxie_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, MOXIE_SP_REGNUM);
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+
+static gdbarch_init_ftype moxie_gdbarch_init;
+
+static struct gdbarch *
+moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* Allocate space for the new architecture. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ set_gdbarch_read_pc (gdbarch, moxie_read_pc);
+ set_gdbarch_write_pc (gdbarch, moxie_write_pc);
+ set_gdbarch_unwind_sp (gdbarch, moxie_unwind_sp);
+
+ set_gdbarch_num_regs (gdbarch, MOXIE_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, MOXIE_SP_REGNUM);
+ set_gdbarch_register_name (gdbarch, moxie_register_name);
+ set_gdbarch_register_type (gdbarch, moxie_register_type);
+
+ set_gdbarch_return_value (gdbarch, moxie_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, moxie_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_breakpoint_from_pc (gdbarch, moxie_breakpoint_from_pc);
+ set_gdbarch_frame_align (gdbarch, moxie_frame_align);
+
+ frame_base_set_default (gdbarch, &moxie_frame_base);
+
+ /* Methods for saving / extracting a dummy frame's ID. The ID's
+ stack address must match the SP value returned by
+ PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
+ set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
+
+ /* Return the unwound PC value. */
+ set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
+
+ set_gdbarch_print_insn (gdbarch, print_insn_moxie);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ /* Hook in the default unwinders. */
+ frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
+
+ /* Support simple overlay manager. */
+ set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
+
+ return gdbarch;
+}
+
+void
+_initialize_moxie_tdep (void)
+{
+ register_gdbarch_init (bfd_arch_moxie, moxie_gdbarch_init);
+}
diff -ruN usrc/gdb/moxie-tdep.h src/gdb/moxie-tdep.h
--- usrc/gdb/moxie-tdep.h 1969-12-31 19:00:00.000000000 -0500
+++ src/gdb/moxie-tdep.h 2009-04-23 07:18:18.000000000 -0400
@@ -0,0 +1,45 @@
+/* Target-dependent code for Moxie
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef MOXIE_TDEP_H
+#define MOXIE_TDEP_H
+
+struct gdbarch_tdep
+{
+ /* gdbarch target dependent data here. Currently unused for MOXIE. */
+};
+
+/* moxie register names. */
+
+enum moxie_regnum
+{
+ MOXIE_FP_REGNUM = 0,
+ MOXIE_SP_REGNUM = 1,
+ R0_REGNUM = 2,
+ R1_REGNUM = 3,
+ MOXIE_PC_REGNUM = 16,
+ MOXIE_CC_REGNUM = 17,
+ RET1_REGNUM = R0_REGNUM,
+ ARG1_REGNUM = R0_REGNUM,
+ ARGN_REGNUM = R1_REGNUM,
+};
+
+#define MOXIE_NUM_REGS 18
+
+#endif /* moxie-tdep.h */
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: PATCH: new gdb port: moxie-elf
2009-04-23 11:57 PATCH: new gdb port: moxie-elf green
@ 2009-04-23 18:29 ` Joel Brobecker
2009-04-23 21:25 ` Anthony Green
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Joel Brobecker @ 2009-04-23 18:29 UTC (permalink / raw)
To: green; +Cc: gdb-patches
Hi Anthony,
I'm a little unclear about the ownership of the patches you are
submitting. I think I located you in the FSF assignment files,
but it seems to be listing you as an individual instead of you
as part of Moxie Logic. Is Moxie Logic a company that might have
a claim on these changes?
> 2009-04-23 Anthony Green <green@moxielogic.com>
>
> * moxie-tdep.h: New file.
> * moxie-tdep.c: New file.
> * configure.tgt: Add moxie-elf.
Overall, these look good to me. I do have a few comments, however.
First, generally speaking, we would like you to provide a short
description in the form of a comment at the beginning of every
function. For the functions that implement gdbarch "methods",
we would like a short comment explaining which gdbarch method
the function implements. Please do not explain what the function
does if it duplicates the gdbarch documentation.
> +moxie-*-elf)
> + gdb_target_obs="moxie-tdep.o"
> + gdb_sim=../sim/moxie/libsim.a
The second line means that you won't be able to build for moxie-elf
unless the simulator part is approved and checked in. If getting
the sim parts in takes a bit of time, you may elect to keep that
line out of the patch, and resubmit it later, after the sim patch
is in.
> +const static unsigned char *
> +moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
> + CORE_ADDR *pcptr, int *lenptr)
> +{
> + static unsigned char breakpoint[] = { 0x35, 0x00 };
> + *lenptr = sizeof (breakpoint);
> + return breakpoint;
> +}
The style in GDB is to skip a line after the variable declarations.
For instance:
static unsigned char breakpoint[] = { 0x35, 0x00 };
*lenptr = sizeof (breakpoint);
> +/* Return the GDB type object for the "standard" data type
> + of data in register N. */
This is an instance were the comment duplicates the gdbarch documentation.
We'd like to avoid that. That way, if we were to ever change the specs
of that method, we don't have to change that comment. Can you take care
of all such comments?
I can suggest, as an example:
/* Implement the "register_type" gdbarch method. */
> + Things always get returned in RET1_REGNUM, RET2_REGNUM. */
Suggest embedding the comment inside the function body. But that's
just a suggestion. If you prefer it in the function description,
that's also fine.
> +/* Function: moxie_scan_prologue
I would prefer if you did not repeat the name of the function
(I think BFD does that), especially when the name is wrong :-).
> + /* Record where the jsra instruction saves the PC and FP */
I'm sorry to hit you with what really amounts to nitpicking on style
issues, but the GNU Coding Style is specific on this, and once you've
learnt it, it won't feel so painful. Period at the end of the sentence,
please...
> + for (next_addr = start_addr;
> + next_addr < end_addr; )
Any reason why you decided to plit this over two lines? I'm pretty
sure that gdb_indent.sh would join the two back into a single line...
> + if (inst >= 0x0614 && inst <= 0x061f) /* push %r2 .. push %r13 */
I find the comment a little confusing. Does it mean "push %rN" where
N is anywhere between 2 to 13? Not a huge deal, however.
> + /* optional stack allocation for args and local vars <= 4 byte */
Style: Upper case letter at the beginning of the sentence, and period
at the end. Thank you!
> +/* Function: skip_prologue
> + Find end of function prologue */
Same as before - let's not repeat the function name nor the gdbarch
documentation.
> +#define DEFAULT_SEARCH_LIMIT 128
Does not seem to be used anywhere...
> +CORE_ADDR
> +moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
I think this function can be made static.
Also, I am wondering if you could rewrite the function using
skip_prologue_using_sal - this function handles a lot of cases
that your implementation doesn't.
You can look at various implementations that use that function
for inspiration on how they implemented it (rs6000-tdep, mips-tdep,
for instance).
> + /* Ignore return values more than 8 bytes in size because the moxie
> + returns anything more than 8 bytes in the stack. */
Style: Missing space at the end of your sentence.
> +static gdbarch_init_ftype moxie_gdbarch_init;
Is that really necessary? Since your init function is defined before
being used, I'd lose this declaration.
> + /* Return the unwound PC value. */
This comment is unnecessary, IMO.
--
Joel
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: PATCH: new gdb port: moxie-elf
2009-04-23 18:29 ` Joel Brobecker
@ 2009-04-23 21:25 ` Anthony Green
2009-04-23 23:41 ` Anthony Green
2009-05-01 3:20 ` Anthony Green
2 siblings, 0 replies; 9+ messages in thread
From: Anthony Green @ 2009-04-23 21:25 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
Joel Brobecker wrote:
> Hi Anthony,
>
> I'm a little unclear about the ownership of the patches you are
> submitting. I think I located you in the FSF assignment files,
> but it seems to be listing you as an individual instead of you
> as part of Moxie Logic. Is Moxie Logic a company that might have
> a claim on these changes?
>
No, moxie logic is the project umbrella name. There is no company.
>> 2009-04-23 Anthony Green <green@moxielogic.com>
>>
>> * moxie-tdep.h: New file.
>> * moxie-tdep.c: New file.
>> * configure.tgt: Add moxie-elf.
>>
>
> Overall, these look good to me. I do have a few comments, however.
>
> First, generally speaking, we would like you to provide a short
> description in the form of a comment at the beginning of every
> function. For the functions that implement gdbarch "methods",
> we would like a short comment explaining which gdbarch method
> the function implements. Please do not explain what the function
> does if it duplicates the gdbarch documentation.
>
>
Ok.
>> +moxie-*-elf)
>> + gdb_target_obs="moxie-tdep.o"
>> + gdb_sim=../sim/moxie/libsim.a
>>
>
> The second line means that you won't be able to build for moxie-elf
> unless the simulator part is approved and checked in. If getting
> the sim parts in takes a bit of time, you may elect to keep that
> line out of the patch, and resubmit it later, after the sim patch
> is in.
>
>
Good idea.
>> +const static unsigned char *
>> +moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
>> + CORE_ADDR *pcptr, int *lenptr)
>> +{
>> + static unsigned char breakpoint[] = { 0x35, 0x00 };
>> + *lenptr = sizeof (breakpoint);
>> + return breakpoint;
>> +}
>>
>
> The style in GDB is to skip a line after the variable declarations.
> For instance:
>
> static unsigned char breakpoint[] = { 0x35, 0x00 };
>
> *lenptr = sizeof (breakpoint);
>
>
Ok.
>> +/* Return the GDB type object for the "standard" data type
>> + of data in register N. */
>>
>
> This is an instance were the comment duplicates the gdbarch documentation.
> We'd like to avoid that. That way, if we were to ever change the specs
> of that method, we don't have to change that comment. Can you take care
> of all such comments?
>
> I can suggest, as an example:
>
> /* Implement the "register_type" gdbarch method. */
>
>
Ok.
>> + Things always get returned in RET1_REGNUM, RET2_REGNUM. */
>>
>
> Suggest embedding the comment inside the function body. But that's
> just a suggestion. If you prefer it in the function description,
> that's also fine.
>
>
>> +/* Function: moxie_scan_prologue
>>
>
> I would prefer if you did not repeat the name of the function
> (I think BFD does that), especially when the name is wrong :-).
>
>
Ok.
>> + /* Record where the jsra instruction saves the PC and FP */
>>
>
> I'm sorry to hit you with what really amounts to nitpicking on style
> issues, but the GNU Coding Style is specific on this, and once you've
> learnt it, it won't feel so painful. Period at the end of the sentence,
> please...
>
>
Ok.
>> + for (next_addr = start_addr;
>> + next_addr < end_addr; )
>>
>
> Any reason why you decided to plit this over two lines? I'm pretty
> sure that gdb_indent.sh would join the two back into a single line...
>
>
No reason. I'll run gdb_indent.sh as well.
>> + if (inst >= 0x0614 && inst <= 0x061f) /* push %r2 .. push %r13 */
>>
>
> I find the comment a little confusing. Does it mean "push %rN" where
> N is anywhere between 2 to 13? Not a huge deal, however.
>
That's right. I'll make this more clear.
>
>> + /* optional stack allocation for args and local vars <= 4 byte */
>>
>
> Style: Upper case letter at the beginning of the sentence, and period
> at the end. Thank you!
>
Ok.
>
>> +/* Function: skip_prologue
>> + Find end of function prologue */
>>
>
> Same as before - let's not repeat the function name nor the gdbarch
> documentation.
>
>
>> +#define DEFAULT_SEARCH_LIMIT 128
>>
>
> Does not seem to be used anywhere...
>
>
Oops.
>> +CORE_ADDR
>> +moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
>>
>
> I think this function can be made static.
>
> Also, I am wondering if you could rewrite the function using
> skip_prologue_using_sal - this function handles a lot of cases
> that your implementation doesn't.
>
> You can look at various implementations that use that function
> for inspiration on how they implemented it (rs6000-tdep, mips-tdep,
> for instance).
>
Thanks - I'll look at those.
>
>> + /* Ignore return values more than 8 bytes in size because the moxie
>> + returns anything more than 8 bytes in the stack. */
>>
>
> Style: Missing space at the end of your sentence.
>
>
>> +static gdbarch_init_ftype moxie_gdbarch_init;
>>
>
> Is that really necessary? Since your init function is defined before
> being used, I'd lose this declaration.
>
>
Ok.
>> + /* Return the unwound PC value. */
>>
>
> This comment is unnecessary, IMO.
>
>
Thanks for taking the time to review, Joel. I'll make the suggested
changes and resubmit.
AG
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: PATCH: new gdb port: moxie-elf
2009-04-23 18:29 ` Joel Brobecker
2009-04-23 21:25 ` Anthony Green
@ 2009-04-23 23:41 ` Anthony Green
2009-04-24 0:01 ` Joel Brobecker
2009-05-01 3:20 ` Anthony Green
2 siblings, 1 reply; 9+ messages in thread
From: Anthony Green @ 2009-04-23 23:41 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 916 bytes --]
Joel Brobecker wrote:
>> 2009-04-23 Anthony Green <green@moxielogic.com>
>>
>> * moxie-tdep.h: New file.
>> * moxie-tdep.c: New file.
>> * configure.tgt: Add moxie-elf.
>>
>
> Overall, these look good to me. I do have a few comments, however.
>
>
Thanks again for spending the time on this patch Joel. Here is an
updated patch that addresses all of your comments. Ok to commit? (I
should have mentioned that my alter ego is green@redhat.com, and I have
Write After Approval permission)
Thanks!
2009-04-23 Anthony Green <green@moxielogic.com>
* moxie-tdep.h: New file.
* moxie-tdep.c: New file.
* configure.tgt: Add moxie-elf.
[-- Attachment #2: moxie-gdb-2.patch --]
[-- Type: text/plain, Size: 17735 bytes --]
diff -ruN usrc/gdb/configure.tgt src/gdb/configure.tgt
--- usrc/gdb/configure.tgt 2009-04-17 10:22:25.000000000 -0400
+++ src/gdb/configure.tgt 2009-04-23 19:29:20.000000000 -0400
@@ -114,6 +114,12 @@
gdb_sim=../sim/frv/libsim.a
;;
+moxie-*-elf)
+ gdb_target_obs="moxie-tdep.o"
+ # Add this once the moxie sim has been committed.
+ # gdb_sim=../sim/moxie/libsim.a
+ ;;
+
h8300-*-*)
# Target: H8300 with HMS monitor and H8 simulator
gdb_target_obs="h8300-tdep.o monitor.o dsrec.o"
diff -ruN usrc/gdb/moxie-tdep.c src/gdb/moxie-tdep.c
--- usrc/gdb/moxie-tdep.c 1969-12-31 19:00:00.000000000 -0500
+++ src/gdb/moxie-tdep.c 2009-04-23 19:26:25.000000000 -0400
@@ -0,0 +1,533 @@
+/* Target-dependent code for Moxie.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "language.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+
+#include "gdb_assert.h"
+
+#include "moxie-tdep.h"
+
+/* Local functions */
+
+extern void _initialize_moxie_tdep (void);
+
+/* Use an invalid address value as 'not available' marker. */
+enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+
+struct moxie_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+ LONGEST framesize;
+ CORE_ADDR saved_regs[MOXIE_NUM_REGS];
+ CORE_ADDR saved_sp;
+};
+
+/* Implement the "frame_align" gdbarch method. */
+
+static CORE_ADDR
+moxie_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~1;
+}
+
+/* Implement the "breakpoint_from_pc" gdbarch method. */
+
+const static unsigned char *
+moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
+ CORE_ADDR *pcptr, int *lenptr)
+{
+ static unsigned char breakpoint[] = { 0x35, 0x00 };
+
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+char *moxie_register_names[] = {
+ "$fp", "$sp", "$r0", "$r1", "$r2",
+ "$r3", "$r4", "$r5", "$r6", "$r7",
+ "$r8", "$r9", "$r10", "$r11", "$r12",
+ "$r13", "$pc", "$cc" };
+
+/* Implement the "register_name" gdbarch method. */
+
+static const char *
+moxie_register_name (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= MOXIE_NUM_REGS)
+ return NULL;
+ return moxie_register_names[reg_nr];
+}
+
+/* Implement the "register_type" gdbarch method. */
+
+static struct type *
+moxie_register_type (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr == MOXIE_PC_REGNUM)
+ return builtin_type (gdbarch)->builtin_func_ptr;
+ else if (reg_nr == MOXIE_SP_REGNUM || reg_nr == MOXIE_FP_REGNUM)
+ return builtin_type (gdbarch)->builtin_data_ptr;
+ else
+ return builtin_type_int32;
+}
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+static void
+moxie_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ CORE_ADDR regval;
+ int len = TYPE_LENGTH (type);
+
+ /* Things always get returned in RET1_REGNUM, RET2_REGNUM. */
+ regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval);
+ if (len > 4)
+ {
+ regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4, len - 4);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval);
+ }
+}
+
+/* Decode the instructions within the given address range. Decide
+ when we must have reached the end of the function prologue. If a
+ frame_info pointer is provided, fill in its saved_regs etc.
+
+ Returns the address of the first instruction after the prologue. */
+
+static CORE_ADDR
+moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
+ struct moxie_frame_cache *cache,
+ struct frame_info *this_frame)
+{
+ CORE_ADDR next_addr;
+ ULONGEST inst, inst2;
+ LONGEST offset;
+ int regnum;
+
+ /* Record where the jsra instruction saves the PC and FP. */
+ cache->saved_regs[MOXIE_PC_REGNUM] = -4;
+ cache->saved_regs[MOXIE_FP_REGNUM] = 0;
+ cache->framesize = 0;
+
+ if (start_addr >= end_addr)
+ return end_addr;
+
+ for (next_addr = start_addr; next_addr < end_addr; )
+ {
+ inst = read_memory_unsigned_integer (next_addr, 2);
+
+ /* Match "push $rN" where N is between 2 and 13 inclusive. */
+ if (inst >= 0x0614 && inst <= 0x061f)
+ {
+ regnum = inst & 0x000f;
+ cache->framesize += 4;
+ cache->saved_regs[regnum] = cache->framesize;
+ next_addr += 2;
+ }
+
+ /* Optional stack allocation for args and local vars <= 4
+ byte. */
+ else if (inst == 0x01f0) /* ldi.l $r12, X */
+ {
+ offset = read_memory_integer (next_addr + 2, 4);
+ inst2 = read_memory_unsigned_integer (next_addr + 6, 2);
+
+ if (inst2 == 0x051f) /* add.l $sp, $r12 */
+ {
+ cache->framesize += offset;
+ }
+
+ return (next_addr + 8);
+ }
+ else /* This is not a prologue instruction. */
+ break;
+ }
+
+ return next_addr;
+}
+
+/* Find the end of function prologue. */
+
+static CORE_ADDR
+moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr = 0, func_end = 0;
+ char *func_name;
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
+ {
+ CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+ else
+ {
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ struct moxie_frame_cache cache;
+ CORE_ADDR plg_end;
+
+ memset (&cache, 0, sizeof cache);
+
+ plg_end = moxie_analyze_prologue (func_addr,
+ func_end, &cache, NULL);
+ /* Found a function. */
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
+ /* Don't use line number debug info for assembly source
+ files. */
+ if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
+ {
+ /* Found a line number, use it as end of
+ prologue. */
+ return sal.end;
+ }
+ }
+ /* No useable line symbol. Use result of prologue parsing
+ method. */
+ return plg_end;
+ }
+ }
+
+ /* No function symbol -- just return the PC. */
+ return (CORE_ADDR) pc;
+}
+
+struct moxie_unwind_cache
+{
+ /* The previous frame's inner most stack address. Used as this
+ frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+ /* The frame's base, optionally used by the high-level debug info. */
+ CORE_ADDR base;
+ int size;
+ /* How far the SP and r13 (FP) have been offset from the start of
+ the stack frame (as defined by the previous frame's stack
+ pointer). */
+ LONGEST sp_offset;
+ LONGEST r13_offset;
+ int uses_frame;
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Implement the "read_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_read_pc (struct regcache *regcache)
+{
+ ULONGEST pc;
+
+ regcache_cooked_read_unsigned (regcache, MOXIE_PC_REGNUM, &pc);
+ return pc;
+}
+
+/* Implement the "write_pc" gdbarch method. */
+
+static void
+moxie_write_pc (struct regcache *regcache, CORE_ADDR val)
+{
+ regcache_cooked_write_unsigned (regcache, MOXIE_PC_REGNUM, val);
+}
+
+/* Implement the "unwind_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_SP_REGNUM);
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+static void
+moxie_extract_return_value (struct type *type, struct regcache *regcache,
+ void *dst)
+{
+ bfd_byte *valbuf = dst;
+ int len = TYPE_LENGTH (type);
+ ULONGEST tmp;
+
+ /* By using store_unsigned_integer we avoid having to do
+ anything special for small big-endian values. */
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &tmp);
+ store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), tmp);
+
+ /* Ignore return values more than 8 bytes in size because the moxie
+ returns anything more than 8 bytes in the stack. */
+ if (len > 4)
+ {
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp);
+ store_unsigned_integer (valbuf + len - 4, 4, tmp);
+ }
+}
+
+/* Implement the "return_value" gdbarch method. */
+
+static enum return_value_convention
+moxie_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ if (TYPE_LENGTH (valtype) > 8)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ {
+ if (readbuf != NULL)
+ moxie_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf != NULL)
+ moxie_store_return_value (valtype, regcache, writebuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+}
+
+/* Allocate and initialize a moxie_frame_cache object. */
+
+static struct moxie_frame_cache *
+moxie_alloc_frame_cache (void)
+{
+ struct moxie_frame_cache *cache;
+ int i;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache);
+
+ cache->base = 0;
+ cache->saved_sp = 0;
+ cache->pc = 0;
+ cache->framesize = 0;
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ cache->saved_regs[i] = REG_UNAVAIL;
+
+ return cache;
+}
+
+/* Populate a moxie_frame_cache object for this_frame. */
+
+static struct moxie_frame_cache *
+moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache;
+ CORE_ADDR current_pc;
+ int i;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = moxie_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
+ if (cache->base == 0)
+ return cache;
+
+ cache->pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+ if (cache->pc)
+ moxie_analyze_prologue (cache->pc, current_pc, cache, this_frame);
+
+ cache->saved_sp = cache->base - cache->framesize;
+
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ if (cache->saved_regs[i] != REG_UNAVAIL)
+ cache->saved_regs[i] = cache->base - cache->saved_regs[i];
+
+ return cache;
+}
+
+/* Implement the "unwind_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
+}
+
+/* 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
+moxie_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache, struct frame_id *this_id)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ *this_id = frame_id_build (cache->saved_sp, cache->pc);
+}
+
+/* Get the value of register regnum in the previous stack frame. */
+
+static struct value *
+moxie_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+
+ gdb_assert (regnum >= 0);
+
+ if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
+ return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+
+ if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
+ return frame_unwind_got_memory (this_frame, regnum,
+ cache->saved_regs[regnum]);
+
+ return frame_unwind_got_register (this_frame, regnum, regnum);
+}
+
+static const struct frame_unwind moxie_frame_unwind = {
+ NORMAL_FRAME,
+ moxie_frame_this_id,
+ moxie_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+/* Return the base address of this_frame. */
+
+static CORE_ADDR
+moxie_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_cache);
+
+ return cache->base;
+}
+
+static const struct frame_base moxie_frame_base = {
+ &moxie_frame_unwind,
+ moxie_frame_base_address,
+ moxie_frame_base_address,
+ moxie_frame_base_address
+};
+
+/* 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
+moxie_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, MOXIE_SP_REGNUM);
+
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+/* Allocate and initialize the moxie gdbarch object. */
+
+static struct gdbarch *
+moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* Allocate space for the new architecture. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ set_gdbarch_read_pc (gdbarch, moxie_read_pc);
+ set_gdbarch_write_pc (gdbarch, moxie_write_pc);
+ set_gdbarch_unwind_sp (gdbarch, moxie_unwind_sp);
+
+ set_gdbarch_num_regs (gdbarch, MOXIE_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, MOXIE_SP_REGNUM);
+ set_gdbarch_register_name (gdbarch, moxie_register_name);
+ set_gdbarch_register_type (gdbarch, moxie_register_type);
+
+ set_gdbarch_return_value (gdbarch, moxie_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, moxie_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_breakpoint_from_pc (gdbarch, moxie_breakpoint_from_pc);
+ set_gdbarch_frame_align (gdbarch, moxie_frame_align);
+
+ frame_base_set_default (gdbarch, &moxie_frame_base);
+
+ /* Methods for saving / extracting a dummy frame's ID. The ID's
+ stack address must match the SP value returned by
+ PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
+ set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
+
+ set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
+
+ set_gdbarch_print_insn (gdbarch, print_insn_moxie);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ /* Hook in the default unwinders. */
+ frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
+
+ /* Support simple overlay manager. */
+ set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
+
+ return gdbarch;
+}
+
+/* Register this machine's init routine. */
+
+void
+_initialize_moxie_tdep (void)
+{
+ register_gdbarch_init (bfd_arch_moxie, moxie_gdbarch_init);
+}
diff -ruN usrc/gdb/moxie-tdep.h src/gdb/moxie-tdep.h
--- usrc/gdb/moxie-tdep.h 1969-12-31 19:00:00.000000000 -0500
+++ src/gdb/moxie-tdep.h 2009-04-23 07:18:18.000000000 -0400
@@ -0,0 +1,45 @@
+/* Target-dependent code for Moxie
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef MOXIE_TDEP_H
+#define MOXIE_TDEP_H
+
+struct gdbarch_tdep
+{
+ /* gdbarch target dependent data here. Currently unused for MOXIE. */
+};
+
+/* moxie register names. */
+
+enum moxie_regnum
+{
+ MOXIE_FP_REGNUM = 0,
+ MOXIE_SP_REGNUM = 1,
+ R0_REGNUM = 2,
+ R1_REGNUM = 3,
+ MOXIE_PC_REGNUM = 16,
+ MOXIE_CC_REGNUM = 17,
+ RET1_REGNUM = R0_REGNUM,
+ ARG1_REGNUM = R0_REGNUM,
+ ARGN_REGNUM = R1_REGNUM,
+};
+
+#define MOXIE_NUM_REGS 18
+
+#endif /* moxie-tdep.h */
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: PATCH: new gdb port: moxie-elf
2009-04-23 23:41 ` Anthony Green
@ 2009-04-24 0:01 ` Joel Brobecker
2009-04-24 1:02 ` Anthony Green
2009-04-24 2:27 ` Anthony Green
0 siblings, 2 replies; 9+ messages in thread
From: Joel Brobecker @ 2009-04-24 0:01 UTC (permalink / raw)
To: Anthony Green; +Cc: gdb-patches
> 2009-04-23 Anthony Green <green@moxielogic.com>
> * moxie-tdep.h: New file.
> * moxie-tdep.c: New file.
> * configure.tgt: Add moxie-elf.
Looks good to me, after you fix the minor style issues reported below.
Can you also send a patch announcing this new port in the NEWS file?
You probably also need to update the MAINTAINERS file in the "Target
Instruction Set Architectures" section to add your architecture to
the list. That way, gdb_buildall.sh will pick it up.
This target compiles with -Werror, right?
> +static CORE_ADDR
> +moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
I see that you decided to keep this function implementation as is.
As long as it works for you, that's fine. I would be a little more
concerned if this had any repercussions on the core-gdb maintainance,
but I don't see this as being a potential problem.
> + /* No function symbol -- just return the PC. */
Just an extra space missing here.
> +/* 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. */
This function description should be removed.
> +/* moxie register names. */
Missing extra space :)
--
Joel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: PATCH: new gdb port: moxie-elf
2009-04-24 0:01 ` Joel Brobecker
@ 2009-04-24 1:02 ` Anthony Green
2009-04-24 2:27 ` Anthony Green
1 sibling, 0 replies; 9+ messages in thread
From: Anthony Green @ 2009-04-24 1:02 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
Joel Brobecker wrote:
>> 2009-04-23 Anthony Green <green@moxielogic.com>
>> * moxie-tdep.h: New file.
>> * moxie-tdep.c: New file.
>> * configure.tgt: Add moxie-elf.
>>
>
> Looks good to me, after you fix the minor style issues reported below.
> Can you also send a patch announcing this new port in the NEWS file?
> You probably also need to update the MAINTAINERS file in the "Target
> Instruction Set Architectures" section to add your architecture to
> the list. That way, gdb_buildall.sh will pick it up.
>
>
Ok, thanks. I'll do all of that.
> This target compiles with -Werror, right?
>
>
Think so. I'll confirm before I commit.
>> +static CORE_ADDR
>> +moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
>>
>
> I see that you decided to keep this function implementation as is.
> As long as it works for you, that's fine. I would be a little more
> concerned if this had any repercussions on the core-gdb maintainance,
> but I don't see this as being a potential problem.
>
>
No, I changed this function to use skip_prologue_using_sal()./
>> + /* No function symbol -- just return the PC. */
>>
>
> Just an extra space missing here.
>
>
>> +/* 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. */
>>
>
> This function description should be removed.
>
>
>> +/* moxie register names. */
>>
>
> Missing extra space :)
>
>
I'll fix all of those and post the patch as committed.
Thanks Joel!
AG
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: PATCH: new gdb port: moxie-elf
2009-04-24 0:01 ` Joel Brobecker
2009-04-24 1:02 ` Anthony Green
@ 2009-04-24 2:27 ` Anthony Green
2009-04-24 3:28 ` Joel Brobecker
1 sibling, 1 reply; 9+ messages in thread
From: Anthony Green @ 2009-04-24 2:27 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 431 bytes --]
Joel Brobecker wrote:
>> 2009-04-23 Anthony Green <green@moxielogic.com>
>> * moxie-tdep.h: New file.
>> * moxie-tdep.c: New file.
>> * configure.tgt: Add moxie-elf.
>>
>
> Looks good to me, after you fix the minor style issues reported below.
>
Final patch, as committed. Thanks Joel!
AG
[-- Attachment #2: moxie-gdb-final.patch --]
[-- Type: text/plain, Size: 18400 bytes --]
2009-04-23 Anthony Green <green@moxielogic.com>
* MAINTAINERS: Add moxie target.
* configure.tgt: Add moxie-*-elf target.
* moxie-tdep.c: New file.
* moxie-tdep.h: New file.
Index: MAINTAINERS
===================================================================
RCS file: /cvs/src/src/gdb/MAINTAINERS,v
retrieving revision 1.413
diff -u -r1.413 MAINTAINERS
--- MAINTAINERS 27 Feb 2009 15:03:47 -0000 1.413
+++ MAINTAINERS 24 Apr 2009 02:24:51 -0000
@@ -294,6 +294,9 @@
(sim/ dies with make -j)
Michael Snyder msnyder@vmware.com
+ moxie --target=moxie-elf ,-Werror
+ Anthony Green green@moxielogic.com
+
ms1 --target=ms1-elf ,-Werror
Kevin Buettner kevinb@redhat.com
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.214
diff -u -r1.214 configure.tgt
--- configure.tgt 17 Apr 2009 14:22:25 -0000 1.214
+++ configure.tgt 24 Apr 2009 02:24:51 -0000
@@ -114,6 +114,12 @@
gdb_sim=../sim/frv/libsim.a
;;
+moxie-*-elf)
+ gdb_target_obs="moxie-tdep.o"
+ # Add this once the moxie sim has been committed.
+ # gdb_sim=../sim/moxie/libsim.a
+ ;;
+
h8300-*-*)
# Target: H8300 with HMS monitor and H8 simulator
gdb_target_obs="h8300-tdep.o monitor.o dsrec.o"
Index: moxie-tdep.c
===================================================================
RCS file: moxie-tdep.c
diff -N moxie-tdep.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ moxie-tdep.c 24 Apr 2009 02:24:52 -0000
@@ -0,0 +1,531 @@
+/* Target-dependent code for Moxie.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "language.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+
+#include "gdb_assert.h"
+
+#include "moxie-tdep.h"
+
+/* Local functions. */
+
+extern void _initialize_moxie_tdep (void);
+
+/* Use an invalid address value as 'not available' marker. */
+enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+
+struct moxie_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+ LONGEST framesize;
+ CORE_ADDR saved_regs[MOXIE_NUM_REGS];
+ CORE_ADDR saved_sp;
+};
+
+/* Implement the "frame_align" gdbarch method. */
+
+static CORE_ADDR
+moxie_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~1;
+}
+
+/* Implement the "breakpoint_from_pc" gdbarch method. */
+
+const static unsigned char *
+moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
+ CORE_ADDR *pcptr, int *lenptr)
+{
+ static unsigned char breakpoint[] = { 0x35, 0x00 };
+
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+/* Moxie register names. */
+
+char *moxie_register_names[] = {
+ "$fp", "$sp", "$r0", "$r1", "$r2",
+ "$r3", "$r4", "$r5", "$r6", "$r7",
+ "$r8", "$r9", "$r10", "$r11", "$r12",
+ "$r13", "$pc", "$cc" };
+
+/* Implement the "register_name" gdbarch method. */
+
+static const char *
+moxie_register_name (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= MOXIE_NUM_REGS)
+ return NULL;
+ return moxie_register_names[reg_nr];
+}
+
+/* Implement the "register_type" gdbarch method. */
+
+static struct type *
+moxie_register_type (struct gdbarch *gdbarch, int reg_nr)
+{
+ if (reg_nr == MOXIE_PC_REGNUM)
+ return builtin_type (gdbarch)->builtin_func_ptr;
+ else if (reg_nr == MOXIE_SP_REGNUM || reg_nr == MOXIE_FP_REGNUM)
+ return builtin_type (gdbarch)->builtin_data_ptr;
+ else
+ return builtin_type_int32;
+}
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+static void
+moxie_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ CORE_ADDR regval;
+ int len = TYPE_LENGTH (type);
+
+ /* Things always get returned in RET1_REGNUM, RET2_REGNUM. */
+ regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval);
+ if (len > 4)
+ {
+ regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4, len - 4);
+ regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval);
+ }
+}
+
+/* Decode the instructions within the given address range. Decide
+ when we must have reached the end of the function prologue. If a
+ frame_info pointer is provided, fill in its saved_regs etc.
+
+ Returns the address of the first instruction after the prologue. */
+
+static CORE_ADDR
+moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
+ struct moxie_frame_cache *cache,
+ struct frame_info *this_frame)
+{
+ CORE_ADDR next_addr;
+ ULONGEST inst, inst2;
+ LONGEST offset;
+ int regnum;
+
+ /* Record where the jsra instruction saves the PC and FP. */
+ cache->saved_regs[MOXIE_PC_REGNUM] = -4;
+ cache->saved_regs[MOXIE_FP_REGNUM] = 0;
+ cache->framesize = 0;
+
+ if (start_addr >= end_addr)
+ return end_addr;
+
+ for (next_addr = start_addr; next_addr < end_addr; )
+ {
+ inst = read_memory_unsigned_integer (next_addr, 2);
+
+ /* Match "push $rN" where N is between 2 and 13 inclusive. */
+ if (inst >= 0x0614 && inst <= 0x061f)
+ {
+ regnum = inst & 0x000f;
+ cache->framesize += 4;
+ cache->saved_regs[regnum] = cache->framesize;
+ next_addr += 2;
+ }
+
+ /* Optional stack allocation for args and local vars <= 4
+ byte. */
+ else if (inst == 0x01f0) /* ldi.l $r12, X */
+ {
+ offset = read_memory_integer (next_addr + 2, 4);
+ inst2 = read_memory_unsigned_integer (next_addr + 6, 2);
+
+ if (inst2 == 0x051f) /* add.l $sp, $r12 */
+ {
+ cache->framesize += offset;
+ }
+
+ return (next_addr + 8);
+ }
+ else /* This is not a prologue instruction. */
+ break;
+ }
+
+ return next_addr;
+}
+
+/* Find the end of function prologue. */
+
+static CORE_ADDR
+moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr = 0, func_end = 0;
+ char *func_name;
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
+ {
+ CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+ else
+ {
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ struct moxie_frame_cache cache;
+ CORE_ADDR plg_end;
+
+ memset (&cache, 0, sizeof cache);
+
+ plg_end = moxie_analyze_prologue (func_addr,
+ func_end, &cache, NULL);
+ /* Found a function. */
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
+ /* Don't use line number debug info for assembly source
+ files. */
+ if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
+ {
+ /* Found a line number, use it as end of
+ prologue. */
+ return sal.end;
+ }
+ }
+ /* No useable line symbol. Use result of prologue parsing
+ method. */
+ return plg_end;
+ }
+ }
+
+ /* No function symbol -- just return the PC. */
+ return (CORE_ADDR) pc;
+}
+
+struct moxie_unwind_cache
+{
+ /* The previous frame's inner most stack address. Used as this
+ frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+ /* The frame's base, optionally used by the high-level debug info. */
+ CORE_ADDR base;
+ int size;
+ /* How far the SP and r13 (FP) have been offset from the start of
+ the stack frame (as defined by the previous frame's stack
+ pointer). */
+ LONGEST sp_offset;
+ LONGEST r13_offset;
+ int uses_frame;
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Implement the "read_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_read_pc (struct regcache *regcache)
+{
+ ULONGEST pc;
+
+ regcache_cooked_read_unsigned (regcache, MOXIE_PC_REGNUM, &pc);
+ return pc;
+}
+
+/* Implement the "write_pc" gdbarch method. */
+
+static void
+moxie_write_pc (struct regcache *regcache, CORE_ADDR val)
+{
+ regcache_cooked_write_unsigned (regcache, MOXIE_PC_REGNUM, val);
+}
+
+/* Implement the "unwind_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_SP_REGNUM);
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+static void
+moxie_extract_return_value (struct type *type, struct regcache *regcache,
+ void *dst)
+{
+ bfd_byte *valbuf = dst;
+ int len = TYPE_LENGTH (type);
+ ULONGEST tmp;
+
+ /* By using store_unsigned_integer we avoid having to do
+ anything special for small big-endian values. */
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &tmp);
+ store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), tmp);
+
+ /* Ignore return values more than 8 bytes in size because the moxie
+ returns anything more than 8 bytes in the stack. */
+ if (len > 4)
+ {
+ regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp);
+ store_unsigned_integer (valbuf + len - 4, 4, tmp);
+ }
+}
+
+/* Implement the "return_value" gdbarch method. */
+
+static enum return_value_convention
+moxie_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ if (TYPE_LENGTH (valtype) > 8)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ {
+ if (readbuf != NULL)
+ moxie_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf != NULL)
+ moxie_store_return_value (valtype, regcache, writebuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+}
+
+/* Allocate and initialize a moxie_frame_cache object. */
+
+static struct moxie_frame_cache *
+moxie_alloc_frame_cache (void)
+{
+ struct moxie_frame_cache *cache;
+ int i;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache);
+
+ cache->base = 0;
+ cache->saved_sp = 0;
+ cache->pc = 0;
+ cache->framesize = 0;
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ cache->saved_regs[i] = REG_UNAVAIL;
+
+ return cache;
+}
+
+/* Populate a moxie_frame_cache object for this_frame. */
+
+static struct moxie_frame_cache *
+moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache;
+ CORE_ADDR current_pc;
+ int i;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = moxie_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
+ if (cache->base == 0)
+ return cache;
+
+ cache->pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+ if (cache->pc)
+ moxie_analyze_prologue (cache->pc, current_pc, cache, this_frame);
+
+ cache->saved_sp = cache->base - cache->framesize;
+
+ for (i = 0; i < MOXIE_NUM_REGS; ++i)
+ if (cache->saved_regs[i] != REG_UNAVAIL)
+ cache->saved_regs[i] = cache->base - cache->saved_regs[i];
+
+ return cache;
+}
+
+/* Implement the "unwind_pc" gdbarch method. */
+
+static CORE_ADDR
+moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
+}
+
+/* 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
+moxie_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache, struct frame_id *this_id)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ *this_id = frame_id_build (cache->saved_sp, cache->pc);
+}
+
+/* Get the value of register regnum in the previous stack frame. */
+
+static struct value *
+moxie_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_prologue_cache);
+
+ gdb_assert (regnum >= 0);
+
+ if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
+ return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+
+ if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
+ return frame_unwind_got_memory (this_frame, regnum,
+ cache->saved_regs[regnum]);
+
+ return frame_unwind_got_register (this_frame, regnum, regnum);
+}
+
+static const struct frame_unwind moxie_frame_unwind = {
+ NORMAL_FRAME,
+ moxie_frame_this_id,
+ moxie_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+/* Return the base address of this_frame. */
+
+static CORE_ADDR
+moxie_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
+ this_cache);
+
+ return cache->base;
+}
+
+static const struct frame_base moxie_frame_base = {
+ &moxie_frame_unwind,
+ moxie_frame_base_address,
+ moxie_frame_base_address,
+ moxie_frame_base_address
+};
+
+static struct frame_id
+moxie_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, MOXIE_SP_REGNUM);
+
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+/* Allocate and initialize the moxie gdbarch object. */
+
+static struct gdbarch *
+moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* Allocate space for the new architecture. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ set_gdbarch_read_pc (gdbarch, moxie_read_pc);
+ set_gdbarch_write_pc (gdbarch, moxie_write_pc);
+ set_gdbarch_unwind_sp (gdbarch, moxie_unwind_sp);
+
+ set_gdbarch_num_regs (gdbarch, MOXIE_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, MOXIE_SP_REGNUM);
+ set_gdbarch_register_name (gdbarch, moxie_register_name);
+ set_gdbarch_register_type (gdbarch, moxie_register_type);
+
+ set_gdbarch_return_value (gdbarch, moxie_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, moxie_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_breakpoint_from_pc (gdbarch, moxie_breakpoint_from_pc);
+ set_gdbarch_frame_align (gdbarch, moxie_frame_align);
+
+ frame_base_set_default (gdbarch, &moxie_frame_base);
+
+ /* Methods for saving / extracting a dummy frame's ID. The ID's
+ stack address must match the SP value returned by
+ PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
+ set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
+
+ set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
+
+ set_gdbarch_print_insn (gdbarch, print_insn_moxie);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ /* Hook in the default unwinders. */
+ frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
+
+ /* Support simple overlay manager. */
+ set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
+
+ return gdbarch;
+}
+
+/* Register this machine's init routine. */
+
+void
+_initialize_moxie_tdep (void)
+{
+ register_gdbarch_init (bfd_arch_moxie, moxie_gdbarch_init);
+}
Index: moxie-tdep.h
===================================================================
RCS file: moxie-tdep.h
diff -N moxie-tdep.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ moxie-tdep.h 24 Apr 2009 02:24:52 -0000
@@ -0,0 +1,43 @@
+/* Target-dependent code for Moxie
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef MOXIE_TDEP_H
+#define MOXIE_TDEP_H
+
+struct gdbarch_tdep
+{
+ /* gdbarch target dependent data here. Currently unused for MOXIE. */
+};
+
+enum moxie_regnum
+{
+ MOXIE_FP_REGNUM = 0,
+ MOXIE_SP_REGNUM = 1,
+ R0_REGNUM = 2,
+ R1_REGNUM = 3,
+ MOXIE_PC_REGNUM = 16,
+ MOXIE_CC_REGNUM = 17,
+ RET1_REGNUM = R0_REGNUM,
+ ARG1_REGNUM = R0_REGNUM,
+ ARGN_REGNUM = R1_REGNUM,
+};
+
+#define MOXIE_NUM_REGS 18
+
+#endif /* moxie-tdep.h */
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: PATCH: new gdb port: moxie-elf
2009-04-24 2:27 ` Anthony Green
@ 2009-04-24 3:28 ` Joel Brobecker
0 siblings, 0 replies; 9+ messages in thread
From: Joel Brobecker @ 2009-04-24 3:28 UTC (permalink / raw)
To: Anthony Green; +Cc: gdb-patches
> Final patch, as committed. Thanks Joel!
Great! Just to be certain, please do not forget about sending an RFA
for a NEWS entry. Eli, who is our documentation master, would be very
disappointed in me if you didn't...
Just something you said:
> No, I changed this function to use skip_prologue_using_sal()./
Ah ha, I missed that part. And indeed, if I look closer, I see it now:
> +static CORE_ADDR
> +moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> + CORE_ADDR func_addr = 0, func_end = 0;
> + char *func_name;
> +
> + /* See if we can determine the end of the prologue via the symbol table.
> + If so, then return either PC, or the PC after the prologue, whichever
> + is greater. */
> + if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
> + {
> + CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
> + if (post_prologue_pc != 0)
> + return max (pc, post_prologue_pc);
> + else
> + {
> + /* Can't determine prologue from the symbol table, need to examine
> + instructions. */
> + struct symtab_and_line sal;
> + struct symbol *sym;
> + struct moxie_frame_cache cache;
> + CORE_ADDR plg_end;
> +
> + memset (&cache, 0, sizeof cache);
> +
> + plg_end = moxie_analyze_prologue (func_addr,
> + func_end, &cache, NULL);
> + /* Found a function. */
> + sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
> + /* Don't use line number debug info for assembly source
> + files. */
> + if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
> + {
> + sal = find_pc_line (func_addr, 0);
> + if (sal.end && sal.end < func_end)
> + {
> + /* Found a line number, use it as end of
> + prologue. */
> + return sal.end;
> + }
> + }
> + /* No useable line symbol. Use result of prologue parsing
> + method. */
> + return plg_end;
> + }
> + }
> +
> + /* No function symbol -- just return the PC. */
> + return (CORE_ADDR) pc;
The following is just an observation, not a request to change your code.
That's a unusual implementation, more specifically in the second part
where skip_prologue_using_sal fails. I am trying to find a case where
skip_prologue_using_sal would return zero and yet you'd be able to
find a prologue end suing the line table and the only thing I can
find is when the function starts with line 2, then goes into line 1.
skip_prologue_using_sal would consider lines 2 and 1 to be part of the
prologue whereas the second part of your function would only consider
the code for line 2. That would probably be wrong.
Most implementations I remember that use skip_prologue_using_sal
actually look like this:
> static CORE_ADDR
> rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
> {
> struct rs6000_framedata frame;
> CORE_ADDR limit_pc, func_addr;
>
> /* See if we can determine the end of the prologue via the symbol table.
> If so, then return either PC, or the PC after the prologue, whichever
> is greater. */
> if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
> {
> CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
> if (post_prologue_pc != 0)
> return max (pc, post_prologue_pc);
> }
>
> /* Can't determine prologue from the symbol table, need to examine
> instructions. */
>
> /* Find an upper limit on the function prologue using the debug
> information. If the debug information could not be used to provide
> that bound, then use an arbitrary large number as the upper bound. */
> limit_pc = skip_prologue_using_sal (pc);
> if (limit_pc == 0)
> limit_pc = pc + 100; /* Magic. */
>
> pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
> return pc;
The idea is: Try skip_prologue_using_sal. If that doesn't work,
then try to find an upper bound for our prologue, again using sals.
If not, then use an arbitrary maximum size for our prologue. Then
skip the prologue by doing instruction analysis. In your case,
you don't seem to need to have an upper bound in order to do prologue
analysis, so you can skiip the part that compute the limit_pc.
Just my 2 cents :)
--
Joel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: PATCH: new gdb port: moxie-elf
2009-04-23 18:29 ` Joel Brobecker
2009-04-23 21:25 ` Anthony Green
2009-04-23 23:41 ` Anthony Green
@ 2009-05-01 3:20 ` Anthony Green
2 siblings, 0 replies; 9+ messages in thread
From: Anthony Green @ 2009-05-01 3:20 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Thu, 2009-04-23 at 11:28 -0700, Joel Brobecker wrote:
>
> > +moxie-*-elf)
> > + gdb_target_obs="moxie-tdep.o"
> > + gdb_sim=../sim/moxie/libsim.a
>
> The second line means that you won't be able to build for moxie-elf
> unless the simulator part is approved and checked in. If getting
> the sim parts in takes a bit of time, you may elect to keep that
> line out of the patch, and resubmit it later, after the sim patch
> is in.
The simulator is in now, so I'm committing the following obvious patch.
AG
2009-04-30 Anthony Green <green@moxielogic.com>
* configure.tgt: Link the moxie simulator in with gdb.
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.216
diff -u -r1.216 configure.tgt
--- configure.tgt 30 Apr 2009 03:04:28 -0000 1.216
+++ configure.tgt 1 May 2009 03:18:00 -0000
@@ -116,8 +116,7 @@
moxie-*-elf)
gdb_target_obs="moxie-tdep.o"
- # Add this once the moxie sim has been committed.
- # gdb_sim=../sim/moxie/libsim.a
+ gdb_sim=../sim/moxie/libsim.a
;;
h8300-*-*)
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-05-01 3:20 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-23 11:57 PATCH: new gdb port: moxie-elf green
2009-04-23 18:29 ` Joel Brobecker
2009-04-23 21:25 ` Anthony Green
2009-04-23 23:41 ` Anthony Green
2009-04-24 0:01 ` Joel Brobecker
2009-04-24 1:02 ` Anthony Green
2009-04-24 2:27 ` Anthony Green
2009-04-24 3:28 ` Joel Brobecker
2009-05-01 3:20 ` Anthony Green
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox