aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephane Carrez <stcarrez@nerim.fr>2000-08-26 13:36:25 +0000
committerStephane Carrez <stcarrez@nerim.fr>2000-08-26 13:36:25 +0000
commit82c230c2d9da9859b8b9c3f2ce150e205403e4e5 (patch)
tree6550e2c01c6af2fd07a46a90d854b572d2a2756a
parent2dc4e391d462122aa3c97934b7dc3205e7d0e55d (diff)
downloadgdb-82c230c2d9da9859b8b9c3f2ce150e205403e4e5.zip
gdb-82c230c2d9da9859b8b9c3f2ce150e205403e4e5.tar.gz
gdb-82c230c2d9da9859b8b9c3f2ce150e205403e4e5.tar.bz2
Multi-arch support for 68hc11
-rw-r--r--gdb/ChangeLog27
-rw-r--r--gdb/m68hc11-tdep.c996
2 files changed, 668 insertions, 355 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 608fab0..1a87ccf 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,30 @@
+2000-08-26 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * m68hc11-tdep.c (m68hc11_register_names): Update name of registers.
+ (m68hc11_get_register_info): New function.
+ (m68hc11_initialize_register_info): New function to get addresses
+ of soft registers.
+ (m68hc11_which_soft_register): New function.
+ (m68hc11_fetch_pseudo_register, m68hc11_store_pseudo_register):
+ New functions to translate read/write of soft registers into a
+ memory read/write.
+ (m68hc11_guess_from_prologue): Initialize soft register addresses.
+ Use the soft register addresses to guess the prologue.
+ (m68hc11_gdbarch_init): Install the pseudo registers.
+
+ * m68hc11-tdep.c (m68hc11_register_name, m68hc11_breakpoint_from_pc,
+ m68hc11_saved_pc_after_call, m68hc11_frame_saved_pc,
+ m68hc11_frame_args_address, m68hc11_frame_locals_address,
+ m68hc11_guess_from_prologue, m68hc11_push_arguments,
+ m68hc11_call_dummy_address, m68hc11_call_dymmy_address,
+ m68hc11_register_virtual_type, m68hc11_store_struct_return,
+ m68hc11_store_return_value, m68hc11_extract_return_value,
+ m68hc11_use_struct_convention, m68hc11_return_value_on_stack,
+ m68hc11_extract_struct_value_address, m68hc11_push_return_address,
+ m68hc11_register_byte, m68hc11_register_raw_size,
+ m68hc11_gdbarch_init): New functions for multi-arch support.
+ (m68hc11_not_yet): Remove.
+
Fri Aug 25 16:57:05 2000 David Taylor <taylor@texas.cygnus.com>
* regcache.c (register_changed): New function.
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index 4c2d505..6f8db5f 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -18,51 +18,24 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#if 0
-/* FIXME: This is from tm-m68hc1.h */
-
-#define GDB_TARGET_IS_M6811
-
-/* Define the bit, byte, and word ordering of the machine. */
-
-#define TARGET_BYTE_ORDER BIG_ENDIAN
-
-/* Offset from address of function to start of its code.
- Zero on most machines. */
-
-#define FUNCTION_START_OFFSET 0
-
-#ifdef __STDC__ /* Forward decls for prototypes */
-struct frame_info;
-struct frame_saved_regs;
-struct type;
-struct value;
-#endif
-
-/* Advance PC across any function entry prologue instructions
- to reach some "real" code. */
-extern CORE_ADDR m68hc11_skip_prologue ();
-#define SKIP_PROLOGUE(ip) \
- m68hc11_skip_prologue (ip)
-
-
-/* Stack grows downward. */
-
-#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
-
-/* For a breakpoint, use "test". This is also the breakpoint
- instruction on the 68HC12. */
-#define BREAKPOINT {0x0}
-
-/* If your kernel resets the pc after the trap happens you may need to
- define this before including this file. */
-#define DECR_PC_AFTER_BREAK 0
-
-extern char *m68hc11_register_names[];
-#define REGISTER_NAME(i) m68hc11_register_names[i]
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "arch-utils.h"
-#define REGISTER_SIZE 2
+#include "target.h"
+#include "opcode/m68hc11.h"
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
@@ -71,261 +44,288 @@ extern char *m68hc11_register_names[];
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
-#define X_REGNUM 0
-#define D_REGNUM 1
-#define Y_REGNUM 2
-#define SP_REGNUM 3
-#define PC_REGNUM 4
-#define A_REGNUM 5
-#define B_REGNUM 6
-#define PSW_REGNUM 7
-#define Z_REGNUM 8
-#define FP_REGNUM 9
-#define TMP_REGNUM 10
-#define ZS_REGNUM 11
-#define XY_REGNUM 12
-#define ZD1_REGNUM 13
-#define ZD32_REGNUM (ZD1_REGNUM+31)
-
-#define NUM_REGS (ZD32_REGNUM+1)
-
-#include "opcode/m68hc11.h"
-
-/* Say how much memory is needed to store a copy of the register set */
-#define REGISTER_BYTES ((NUM_REGS)*2)
-
-/* Index within `registers' of the first byte of the space for
- register N. */
-
-#define REGISTER_BYTE(N) ((N) * 2)
-
-/* Number of bytes of storage in the actual machine representation
- for register N. */
-
-#define REGISTER_RAW_SIZE(N) (2)
-
-/* Number of bytes of storage in the program's representation
- for register N. */
-
-#define REGISTER_VIRTUAL_SIZE(N) (2)
-
-/* Largest value REGISTER_RAW_SIZE can have. */
-
-#define MAX_REGISTER_RAW_SIZE 8
-
-/* Largest value REGISTER_VIRTUAL_SIZE can have. */
-
-#define MAX_REGISTER_VIRTUAL_SIZE 8
-
-/* Return the GDB type object for the "standard" data type
- of data in register N. */
-
-#define REGISTER_VIRTUAL_TYPE(N) builtin_type_uint16
-
-/* Store the address of the place in which to copy the structure the
- subroutine will return. This is called from call_function.
-
- We store structs through a pointer passed in D */
-
-#define STORE_STRUCT_RETURN(ADDR, SP) \
- { write_register (D_REGNUM, (ADDR)); }
-
-
-/* Write into appropriate registers a function return value
- of type TYPE, given in virtual format.
-
- Things always get returned in D/X */
-
-#define STORE_RETURN_VALUE(TYPE,VALBUF) \
- write_register_bytes (REGISTER_BYTE (D_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
-
-
-/* Extract from an array REGBUF containing the (raw) register state
- the address in which a function should return its structure value,
- as a CORE_ADDR (or an expression that can be used as one). */
-
-#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(CORE_ADDR *)(REGBUF))
-
-
-/* Define other aspects of the stack frame.
- we keep a copy of the worked out return pc lying around, since it
- is a useful bit of info */
-
-#define EXTRA_FRAME_INFO \
- int frame_reg; \
- CORE_ADDR return_pc; \
- CORE_ADDR dummy; \
- int frameless; \
- int size;
-
-/* There's a mess in stack frame creation. See comments in blockframe.c
- near reference to INIT_FRAME_PC_FIRST. */
-
-#define INIT_FRAME_PC(fromleaf, prev) /* nada */
-
-#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
- (prev)->pc = ((fromleaf) ? SAVED_PC_AFTER_CALL ((prev)->next) : \
- (prev)->next ? FRAME_SAVED_PC ((prev)->next) : read_pc ());
-
-#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
- m68hc11_init_extra_frame_info (fromleaf, fi)
-
-extern void m68hc11_init_extra_frame_info (int fromleaf,
- struct frame_info * fi);
-
-/* A macro that tells us whether the function invocation represented
- by FI does not have a frame on the stack associated with it. If it
- does not, FRAMELESS is set to 1, else 0. */
-
-#define FRAMELESS_FUNCTION_INVOCATION(FI) \
- frameless_look_for_prologue (FI)
-
-#define FRAME_CHAIN(FRAME) m68hc11_frame_chain (FRAME)
-#define FRAME_CHAIN_VALID(chain,frame) \
- ((chain) != 0 && (frame) != 0)
-#define FRAME_SAVED_PC(FRAME) ((FRAME)->return_pc)
-#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
-#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
-
-#define SAVED_PC_AFTER_CALL(frame) m68hc11_saved_pc_after_call (frame)
-
-/* Set VAL to the number of args passed to frame described by FI.
- Can set VAL to -1, meaning no way to tell. */
-/* We can't tell how many args there are */
-
-#define FRAME_NUM_ARGS(fi) (-1)
-
-/* Return number of bytes at start of arglist that are not really args. */
-
-#define FRAME_ARGS_SKIP 0
-
-
-/* Put here the code to store, into a struct frame_saved_regs,
- the addresses of the saved registers of frame described by FRAME_INFO.
- This includes special registers such as pc and fp saved in special
- ways in the stack frame. sp is even more special:
- the address we return for it IS the sp for the next frame. */
+#define HARD_X_REGNUM 0
+#define HARD_D_REGNUM 1
+#define HARD_Y_REGNUM 2
+#define HARD_SP_REGNUM 3
+#define HARD_PC_REGNUM 4
+
+#define HARD_A_REGNUM 5
+#define HARD_B_REGNUM 6
+#define HARD_CCR_REGNUM 7
+#define M68HC11_LAST_HARD_REG (HARD_CCR_REGNUM)
+
+/* Z is replaced by X or Y by gcc during machine reorg.
+ ??? There is no way to get it and even know whether
+ it's in X or Y or in ZS. */
+#define SOFT_Z_REGNUM 8
+
+/* Soft registers. These registers are special. There are treated
+ like normal hard registers by gcc and gdb (ie, within dwarf2 info).
+ They are physically located in memory. */
+#define SOFT_FP_REGNUM 9
+#define SOFT_TMP_REGNUM 10
+#define SOFT_ZS_REGNUM 11
+#define SOFT_XY_REGNUM 12
+#define SOFT_D1_REGNUM 13
+#define SOFT_D32_REGNUM (SOFT_D1_REGNUM+31)
+#define M68HC11_MAX_SOFT_REGS 32
+
+#define M68HC11_NUM_REGS (8)
+#define M68HC11_NUM_PSEUDO_REGS (M68HC11_MAX_SOFT_REGS+5)
+#define M68HC11_ALL_REGS (M68HC11_NUM_REGS+M68HC11_NUM_PSEUDO_REGS)
+
+#define M68HC11_REG_SIZE (2)
+
+struct gdbarch_tdep
+ {
+ /* from the elf header */
+ int elf_flags;
+ };
+
+struct frame_extra_info
+{
+ int frame_reg;
+ CORE_ADDR return_pc;
+ CORE_ADDR dummy;
+ int frameless;
+ int size;
+};
-#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
- m68hc11_frame_find_saved_regs (frame_info, &(frame_saved_regs))
+/* Table of registers for 68HC11. This includes the hard registers
+ and the soft registers used by GCC. */
+static char *
+m68hc11_register_names[] =
+{
+ "x", "d", "y", "sp", "pc", "a", "b",
+ "ccr", "z", "frame","tmp", "zs", "xy",
+ "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "d10", "d11", "d12", "d13", "d14",
+ "d15", "d16", "d17", "d18", "d19", "d20", "d21",
+ "d22", "d23", "d24", "d25", "d26", "d27", "d28",
+ "d29", "d30", "d31", "d32"
+};
-extern void m68hc11_frame_find_saved_regs (struct frame_info *,
- struct frame_saved_regs *);
+struct m68hc11_soft_reg
+{
+ const char *name;
+ CORE_ADDR addr;
+};
-#define CALL_DUMMY { 0 }
-#define PUSH_DUMMY_FRAME
-#define CALL_DUMMY_START_OFFSET 0
-#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+static struct m68hc11_soft_reg soft_regs[M68HC11_ALL_REGS];
-extern CORE_ADDR m68hc11_call_dummy_address (void);
-#define CALL_DUMMY_ADDRESS() m68hc11_call_dummy_address ()
+#define M68HC11_FP_ADDR soft_regs[SOFT_FP_REGNUM].addr
-#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
-sp = m68hc11_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+static int soft_min_addr;
+static int soft_max_addr;
+static int soft_reg_initialized = 0;
-extern CORE_ADDR m68hc11_fix_call_dummy (char *, CORE_ADDR, CORE_ADDR,
- int, struct value **,
- struct type *, int);
-#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
- sp = m68hc11_push_arguments ((nargs), (args), (sp), \
- (struct_return), (struct_addr))
-extern CORE_ADDR m68hc11_push_arguments (int, struct value **,
- CORE_ADDR, int, CORE_ADDR);
+/* 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
+m68hc11_get_register_info (struct m68hc11_soft_reg *reg, const char *name)
+{
+ struct minimal_symbol *msymbol;
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol)
+ {
+ reg->addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ reg->name = xstrdup (name);
+
+ /* Keep track of the address range for soft registers. */
+ if (reg->addr < (CORE_ADDR) soft_min_addr)
+ soft_min_addr = reg->addr;
+ if (reg->addr > (CORE_ADDR) soft_max_addr)
+ soft_max_addr = reg->addr;
+ }
+ else
+ {
+ reg->name = 0;
+ reg->addr = 0;
+ }
+}
-/* Extract from an array REGBUF containing the (raw) register state
- a function return value of type TYPE, and copy that, in virtual format,
- into VALBUF. */
+/* Initialize the table of soft register addresses according
+ to the symbol table. */
+ static void
+m68hc11_initialize_register_info (void)
+{
+ int i;
-#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
-m68hc11_extract_return_value(TYPE, REGBUF, VALBUF)
-extern void m68hc11_extract_return_value (struct type *, char *, char *);
+ if (soft_reg_initialized)
+ return;
+
+ soft_min_addr = INT_MAX;
+ soft_max_addr = 0;
+ for (i = 0; i < M68HC11_ALL_REGS; i++)
+ {
+ soft_regs[i].name = 0;
+ }
+
+ m68hc11_get_register_info (&soft_regs[SOFT_FP_REGNUM], "_.frame");
+ m68hc11_get_register_info (&soft_regs[SOFT_TMP_REGNUM], "_.tmp");
+ m68hc11_get_register_info (&soft_regs[SOFT_ZS_REGNUM], "_.z");
+ soft_regs[SOFT_Z_REGNUM] = soft_regs[SOFT_ZS_REGNUM];
+ m68hc11_get_register_info (&soft_regs[SOFT_XY_REGNUM], "_.xy");
+ for (i = SOFT_D1_REGNUM; i < M68HC11_MAX_SOFT_REGS; i++)
+ {
+ char buf[10];
-/* Discard from the stack the innermost frame,
- restoring all saved registers. */
-#define POP_FRAME m68hc11_pop_frame();
-extern void m68hc11_pop_frame (void);
+ sprintf (buf, "_.d%d", i - SOFT_D1_REGNUM + 1);
+ m68hc11_get_register_info (&soft_regs[i], buf);
+ }
+ if (soft_regs[SOFT_FP_REGNUM].name == 0)
+ {
+ warning ("No frame soft register found in the symbol table.\n");
+ warning ("Stack backtrace will not work.\n");
+ }
+ soft_reg_initialized = 1;
+}
-/* Number of bits in the appropriate type. */
+/* Given an address in memory, return the soft register number if
+ that address corresponds to a soft register. Returns -1 if not. */
+static int
+m68hc11_which_soft_register (CORE_ADDR addr)
+{
+ int i;
+
+ if (addr < soft_min_addr || addr > soft_max_addr)
+ return -1;
+
+ for (i = SOFT_FP_REGNUM; i < M68HC11_ALL_REGS; i++)
+ {
+ if (soft_regs[i].name && soft_regs[i].addr == addr)
+ return i;
+ }
+ return -1;
+}
-#define TARGET_INT_BIT (2 * TARGET_CHAR_BIT)
-#define TARGET_PTR_BIT (2 * TARGET_CHAR_BIT)
-#define TARGET_DOUBLE_BIT (4 * TARGET_CHAR_BIT)
-#define TARGET_LONG_DOUBLE_BIT (8 * TARGET_CHAR_BIT)
+/* Fetch a pseudo register. The 68hc11 soft registers are treated like
+ pseudo registers. They are located in memory. Translate the register
+ fetch into a memory read. */
+void
+m68hc11_fetch_pseudo_register (int regno)
+{
+ char buf[MAX_REGISTER_RAW_SIZE];
-#endif
+ m68hc11_initialize_register_info ();
+
+ /* Fetch a soft register: translate into a memory read. */
+ if (soft_regs[regno].name)
+ {
+ target_read_memory (soft_regs[regno].addr, buf, 2);
+ }
+ else
+ {
+ memset (buf, 0, 2);
+ }
+ supply_register (regno, buf);
+}
-#include "defs.h"
-#include "frame.h"
-#include "obstack.h"
-#include "symtab.h"
-#include "gdbtypes.h"
-#include "gdbcmd.h"
-#include "gdbcore.h"
-#include "gdb_string.h"
-#include "value.h"
-#include "inferior.h"
-#include "dis-asm.h"
-#include "symfile.h"
-#include "objfiles.h"
+/* Store a pseudo register. Translate the register store
+ into a memory write. */
+static void
+m68hc11_store_pseudo_register (int regno)
+{
+ m68hc11_initialize_register_info ();
-/* NOTE: This port is not finished. Several operations are not implemented
- and will raise an error. Most of these functions concern the calling
- of a function by GDB itself (command 'call') and retrieving data pushed
- on the stack. */
+ /* Store a soft register: translate into a memory write. */
+ if (soft_regs[regno].name)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
-void m68hc11_frame_find_saved_regs (struct frame_info *fi,
- struct frame_saved_regs *fsr);
-static void m68hc11_pop_dummy_frame (struct frame_info *fi);
+ read_register_gen (regno, buf);
+ target_write_memory (soft_regs[regno].addr, buf, 2);
+ }
+}
-/* Table of registers for 68HC11. This includes the hard registers
- and the pseudo hard registers used by GCC. */
-char*
-m68hc11_register_names[] =
+static char *
+m68hc11_register_name (int reg_nr)
{
- "x", "d", "y", "sp", "pc", "a", "b",
- "ccr", "z", "frame","tmp", "zs", "xy",
- "ZD1", "ZD2", "ZD3", "ZD4", "ZD5", "ZD6", "ZD7",
- "ZD8", "ZD9", "ZD10", "ZD11", "ZD12", "ZD13", "ZD14",
- "ZD15", "ZD16", "ZD17", "ZD18", "ZD19", "ZD20", "ZD21",
- "ZD22", "ZD23", "ZD24", "ZD25", "ZD26", "ZD27", "ZD28",
- "ZD29", "ZD30", "ZD31", "ZD32"
-};
-
-static int reg_last = 32 * 2 + 6;
-static int frame_index = 6;
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= M68HC11_ALL_REGS)
+ return NULL;
+
+ /* If we don't know the address of a soft register, pretend it
+ does not exist. */
+ if (reg_nr > M68HC11_LAST_HARD_REG && soft_regs[reg_nr].name == 0)
+ return NULL;
+ return m68hc11_register_names[reg_nr];
+}
-/* Raise an error for operations which are not yet provided. */
-static void
-m68hc11_not_yet (const char *operation)
+static unsigned char *
+m68hc11_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
- error ("Operation '%s' is not yet implemented\n", operation);
+ static unsigned char breakpoint[] = {0x0};
+
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
}
/* Immediately after a function call, return the saved pc before the frame
- is setup. For sun3's, we check for the common case of being inside of a
- system call, and if so, we know that Sun pushes the call # on the stack
- prior to doing the trap. */
+ is setup. */
-CORE_ADDR
+static CORE_ADDR
m68hc11_saved_pc_after_call (struct frame_info *frame)
{
- unsigned addr = frame->frame + 1 + 2;
-
- addr = read_register (SP_REGNUM) + 1;
+ CORE_ADDR addr;
+
+ addr = read_register (HARD_SP_REGNUM) + 1;
addr &= 0x0ffff;
return read_memory_integer (addr, 2) & 0x0FFFF;
}
+static CORE_ADDR
+m68hc11_frame_saved_pc (struct frame_info *frame)
+{
+ return frame->extra_info->return_pc;
+}
+
+static CORE_ADDR
+m68hc11_frame_args_address (struct frame_info *frame)
+{
+ return frame->frame;
+}
+
+static CORE_ADDR
+m68hc11_frame_locals_address (struct frame_info *frame)
+{
+ return frame->frame;
+}
+
/* Discard from the stack the innermost frame, restoring all saved
registers. */
-void
+static void
m68hc11_pop_frame (void)
{
- m68hc11_not_yet ("m68hc11_pop_frame");
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp, sp;
+ register int regnum;
+
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ fp = FRAME_FP (frame);
+ FRAME_INIT_SAVED_REGS (frame);
+
+ /* Copy regs from where they were saved in the frame. */
+ for (regnum = 0; regnum < M68HC11_ALL_REGS; regnum++)
+ if (frame->saved_regs[regnum])
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs[regnum], 2));
+
+ write_register (HARD_PC_REGNUM, frame->extra_info->return_pc);
+ sp = fp + frame->extra_info->size;
+ write_register (HARD_SP_REGNUM, sp);
+ }
+ flush_cached_frames ();
}
/* Analyze the function prologue to find some information
@@ -334,26 +334,27 @@ m68hc11_pop_frame (void)
- the offset of the previous frame saved address (from current frame)
- the soft registers which are pushed. */
static void
-m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR* first_line,
- int* frame_offset, int* pushed_regs)
+m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR fp,
+ CORE_ADDR *first_line,
+ int *frame_offset, CORE_ADDR *pushed_regs)
{
+ CORE_ADDR save_addr;
CORE_ADDR func_end;
unsigned char op0, op1, op2;
int add_sp_mode;
- int sp_adjust;
+ int sp_adjust = 0;
int size;
int found_frame_point;
- int found_load;
+ int saved_reg;
CORE_ADDR first_pc;
- int reg_saved;
first_pc = get_pc_function_start (pc);
size = 0;
+ m68hc11_initialize_register_info ();
if (first_pc == 0)
{
*frame_offset = 0;
- *pushed_regs = 0;
*first_line = pc;
return;
}
@@ -424,13 +425,14 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR* first_line,
op2 = read_memory_unsigned_integer (pc + 2, 1);
/* ldx *frame */
- if (op0 == OP_LDX && op1 == frame_index)
+ if (op0 == OP_LDX && op1 == M68HC11_FP_ADDR)
{
pc += 2;
}
/* ldy *frame */
- else if (op0 == OP_PAGE2 && op1 == OP_LDY && op2 == frame_index)
+ else if (op0 == OP_PAGE2 && op1 == OP_LDY
+ && op2 == M68HC11_FP_ADDR)
{
pc += 3;
}
@@ -450,7 +452,7 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR* first_line,
}
/* sts *frame */
- else if (op0 == OP_STS && op1 == frame_index)
+ else if (op0 == OP_STS && op1 == M68HC11_FP_ADDR)
{
found_frame_point = 1;
pc += 2;
@@ -516,63 +518,75 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR* first_line,
/* Now, look forward to see how many registers are pushed on the stack.
We look only for soft registers so there must be a first LDX *REG
before a PSHX. */
- reg_saved = 0;
- found_load = 0;
+ saved_reg = -1;
+ save_addr = fp;
while (pc + 2 < func_end)
{
op0 = read_memory_unsigned_integer (pc, 1);
op1 = read_memory_unsigned_integer (pc + 1, 1);
op2 = read_memory_unsigned_integer (pc + 2, 1);
- if (op0 == OP_LDX && op1 > frame_index && op1 <= reg_last)
+ if (op0 == OP_LDX)
{
- found_load = 1;
+ saved_reg = m68hc11_which_soft_register (op1);
+ if (saved_reg < 0 || saved_reg == SOFT_FP_REGNUM)
+ break;
+
pc += 2;
}
- else if (op0 == OP_PAGE2 && op1 == OP_LDY
- && op2 > frame_index && op2 < reg_last)
+ else if (op0 == OP_PAGE2 && op1 == OP_LDY)
{
- found_load = 1;
+ saved_reg = m68hc11_which_soft_register (op2);
+ if (saved_reg < 0 || saved_reg == SOFT_FP_REGNUM)
+ break;
+
pc += 3;
}
else if (op0 == OP_PSHX)
{
/* If there was no load, this is a push for a function call. */
- if (found_load == 0)
+ if (saved_reg < 0 || saved_reg >= M68HC11_ALL_REGS)
break;
-
- reg_saved += 2;
+
+ /* Keep track of the address where that register is saved
+ on the stack. */
+ save_addr -= 2;
+ if (pushed_regs)
+ pushed_regs[saved_reg] = save_addr;
+
pc += 1;
- found_load = 0;
+ saved_reg = -1;
}
else if (op0 == OP_PAGE2 && op1 == OP_PSHY)
{
- if (found_load == 0)
+ if (saved_reg < 0 || saved_reg >= M68HC11_ALL_REGS)
break;
- reg_saved += 2;
+ /* Keep track of the address where that register is saved
+ on the stack. */
+ save_addr -= 2;
+ if (pushed_regs)
+ pushed_regs[saved_reg] = save_addr;
+
pc += 2;
- found_load = 0;
+ saved_reg = -1;
}
else
{
break;
}
}
- *pushed_regs = reg_saved;
*first_line = pc;
}
-
-CORE_ADDR
+static CORE_ADDR
m68hc11_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
int frame_offset;
- int pushed_args;
- /* If we have line debugging information, then the end of the. */
- /* prologue should be the first assembly instruction of the
+ /* If we have line debugging information, then the end of the
+ prologue should be the first assembly instruction of the
first source line. */
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
@@ -581,7 +595,7 @@ m68hc11_skip_prologue (CORE_ADDR pc)
return sal.end;
}
- m68hc11_guess_from_prologue (pc, &pc, &frame_offset, &pushed_args);
+ m68hc11_guess_from_prologue (pc, 0, &pc, &frame_offset, 0);
return pc;
}
@@ -590,24 +604,25 @@ m68hc11_skip_prologue (CORE_ADDR pc)
INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
*/
-CORE_ADDR
+static CORE_ADDR
m68hc11_frame_chain (struct frame_info *frame)
{
- unsigned addr;
+ CORE_ADDR addr;
- if (frame->return_pc == 0 || inside_entry_file(frame->return_pc))
- return (CORE_ADDR)0;
+ if (frame->extra_info->return_pc == 0
+ || inside_entry_file (frame->extra_info->return_pc))
+ return (CORE_ADDR) 0;
if (frame->frame == 0)
{
return (CORE_ADDR) 0;
}
- addr = frame->frame + frame->size + 1 - 2;
+ addr = frame->frame + frame->extra_info->size + 1 - 2;
addr = read_memory_unsigned_integer (addr, 2) & 0x0FFFF;
if (addr == 0)
{
- return (CORE_ADDR)0;
+ return (CORE_ADDR) 0;
}
return addr;
@@ -618,35 +633,47 @@ m68hc11_frame_chain (struct frame_info *frame)
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special: the address we
return for it IS the sp for the next frame. */
-void
-m68hc11_frame_find_saved_regs (struct frame_info *fi,
- struct frame_saved_regs *fsr)
+static void
+m68hc11_frame_init_saved_regs (struct frame_info *fi)
{
CORE_ADDR pc;
- int saved;
-
+
+ if (fi->saved_regs == NULL)
+ frame_saved_regs_zalloc (fi);
+ else
+ memset (fi->saved_regs, 0, sizeof (fi->saved_regs));
+
pc = fi->pc;
- memset (fsr, 0, sizeof (*fsr));
- m68hc11_guess_from_prologue (pc, &pc, &fi->size, &saved);
+ m68hc11_guess_from_prologue (pc, fi->frame, &pc, &fi->extra_info->size,
+ fi->saved_regs);
+
+ fi->saved_regs[SOFT_FP_REGNUM] = fi->frame + fi->extra_info->size + 1 - 2;
+ fi->saved_regs[HARD_SP_REGNUM] = fi->frame + fi->extra_info->size + 1;
+ fi->saved_regs[HARD_PC_REGNUM] = fi->saved_regs[HARD_SP_REGNUM];
}
-void
+static void
m68hc11_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
- unsigned addr;
- struct frame_saved_regs dummy;
+ CORE_ADDR addr;
- m68hc11_frame_find_saved_regs (fi, &dummy);
+ fi->extra_info = (struct frame_extra_info *)
+ frame_obstack_alloc (sizeof (struct frame_extra_info));
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ m68hc11_frame_init_saved_regs (fi);
if (fromleaf)
{
- fi->return_pc = m68hc11_saved_pc_after_call (fi);
+ fi->extra_info->return_pc = m68hc11_saved_pc_after_call (fi);
}
else
{
- addr = fi->frame + fi->size + 1;
- fi->return_pc = read_memory_unsigned_integer (addr, 2) & 0x0ffff;
-
+ addr = fi->frame + fi->extra_info->size + 1;
+ addr = read_memory_unsigned_integer (addr, 2) & 0x0ffff;
+ fi->extra_info->return_pc = addr;
#if 0
printf ("Pc@0x%04x, FR 0x%04x, size %d, read ret @0x%04x -> 0x%04x\n",
fi->pc,
@@ -661,13 +688,14 @@ m68hc11_init_extra_frame_info (int fromleaf, struct frame_info *fi)
static void
show_regs (char *args, int from_tty)
{
- int ccr = read_register (PSW_REGNUM);
+ int ccr = read_register (HARD_CCR_REGNUM);
int i;
-
+ int nr;
+
printf_filtered ("PC=%04x SP=%04x FP=%04x CCR=%02x %c%c%c%c%c%c%c%c\n",
- read_register (PC_REGNUM),
- read_register (SP_REGNUM),
- read_register (FP_REGNUM),
+ (int) read_register (HARD_PC_REGNUM),
+ (int) read_register (HARD_SP_REGNUM),
+ (int) read_register (SOFT_FP_REGNUM),
ccr,
ccr & M6811_S_BIT ? 'S' : '-',
ccr & M6811_X_BIT ? 'X' : '-',
@@ -679,75 +707,333 @@ show_regs (char *args, int from_tty)
ccr & M6811_C_BIT ? 'C' : '-');
printf_filtered ("D=%04x IX=%04x IY=%04x\n",
- read_register (D_REGNUM),
- read_register (X_REGNUM),
- read_register (Y_REGNUM));
- for (i = ZD1_REGNUM; i <= ZD32_REGNUM; i++)
+ (int) read_register (HARD_D_REGNUM),
+ (int) read_register (HARD_X_REGNUM),
+ (int) read_register (HARD_Y_REGNUM));
+
+ nr = 0;
+ for (i = SOFT_D1_REGNUM; i < M68HC11_ALL_REGS; i++)
{
- printf_filtered ("ZD%d=%04x",
- i - ZD1_REGNUM + 1,
- read_register (i));
- if (((i - ZD1_REGNUM) % 8) == 7)
+ /* Skip registers which are not defined in the symbol table. */
+ if (soft_regs[i].name == 0)
+ continue;
+
+ printf_filtered ("D%d=%04x",
+ i - SOFT_D1_REGNUM + 1,
+ (int) read_register (i));
+ nr++;
+ if ((nr % 8) == 7)
printf_filtered ("\n");
else
printf_filtered (" ");
}
+ if (nr && (nr % 8) != 7)
+ printf_filtered ("\n");
}
-CORE_ADDR
-m68hc11_fix_call_dummy (char *dummyname,
- CORE_ADDR start_sp,
- CORE_ADDR fun,
- int nargs,
- value_ptr *args,
- struct type *type,
- int gcc_p)
-{
- m68hc11_not_yet ("m68hc11_fix_call_dummy");
- return 0;
-}
-
-static void
-m68hc11_pop_dummy_frame (struct frame_info *fi)
-{
- m68hc11_not_yet ("m68hc11_pop_dummy_frame");
-}
-
-
-CORE_ADDR
+static CORE_ADDR
m68hc11_push_arguments (int nargs,
value_ptr *args,
CORE_ADDR sp,
int struct_return,
CORE_ADDR struct_addr)
{
- m68hc11_not_yet ("m68hc11_push_arguments");
- return 0;
+ int stack_alloc;
+ int argnum;
+ int first_stack_argnum;
+ int stack_offset;
+ struct type *type;
+ char *val;
+ int len;
+
+ stack_alloc = 0;
+ first_stack_argnum = 0;
+ if (struct_return)
+ {
+ write_register (HARD_D_REGNUM, struct_addr);
+ }
+ else if (nargs > 0)
+ {
+ type = VALUE_TYPE (args[0]);
+ len = TYPE_LENGTH (type);
+
+ /* First argument is passed in D and X registers. */
+ if (len <= 4)
+ {
+ LONGEST v = extract_unsigned_integer (VALUE_CONTENTS (args[0]), len);
+ first_stack_argnum = 1;
+ write_register (HARD_D_REGNUM, v);
+ if (len > 2)
+ {
+ v >>= 16;
+ write_register (HARD_X_REGNUM, v);
+ }
+ }
+ }
+ for (argnum = first_stack_argnum; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ stack_alloc += (TYPE_LENGTH (type) + 1) & ~2;
+ }
+ sp -= stack_alloc;
+
+ stack_offset = 1;
+ for (argnum = first_stack_argnum; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ len = TYPE_LENGTH (type);
+
+ val = (char*) VALUE_CONTENTS (args[argnum]);
+ write_memory (sp + stack_offset, val, len);
+ stack_offset += len;
+ }
+ return sp;
}
+/* Return a location where we can set a breakpoint that will be hit
+ when an inferior function call returns. */
CORE_ADDR
m68hc11_call_dummy_address (void)
{
- m68hc11_not_yet ("m68hc11_call_dummy_address");
- return 0;
+ return (CORE_ADDR) read_register (HARD_PC_REGNUM);
}
-/* Given a return value in `regbuf' with a type `valtype',
+static struct type *
+m68hc11_register_virtual_type (int reg_nr)
+{
+ return builtin_type_uint16;
+}
+
+static void
+m68hc11_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+ write_register (HARD_D_REGNUM, addr);
+}
+
+static void
+m68hc11_store_return_value (struct type *type, char *valbuf)
+{
+ write_register_bytes (REGISTER_BYTE (HARD_D_REGNUM),
+ valbuf, TYPE_LENGTH (type));
+}
+
+
+/* Given a return value in `regbuf' with a type `type',
extract and copy its value into `valbuf'. */
-void
-m68hc11_extract_return_value (struct type *valtype,
+static void
+m68hc11_extract_return_value (struct type *type,
char *regbuf,
char *valbuf)
{
- m68hc11_not_yet ("m68hc11_extract_return_value");
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 2)
+ {
+ memcpy (valbuf, &regbuf[2], len);
+ }
+ else if (len <= 4)
+ {
+ memcpy (valbuf, regbuf, len);
+ }
+ else
+ {
+ error ("bad size for return value");
+ }
+}
+
+/* Should call_function allocate stack space for a struct return? */
+static int
+m68hc11_use_struct_convention (int gcc_p, struct type *type)
+{
+ return (TYPE_LENGTH (type) > 4);
+}
+
+static int
+m68hc11_return_value_on_stack (struct type *type)
+{
+ return m68hc11_use_struct_convention (1, type);
+}
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+static CORE_ADDR
+m68hc11_extract_struct_value_address (char *regbuf)
+{
+ return extract_address (&regbuf[HARD_D_REGNUM * 2],
+ REGISTER_RAW_SIZE (HARD_D_REGNUM));
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+static CORE_ADDR
+m68hc11_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+{
+ char valbuf[2];
+
+ pc = read_register (HARD_PC_REGNUM);
+ sp -= 2;
+ store_unsigned_integer (valbuf, 2, pc);
+ write_memory (sp + 1, valbuf, 2);
+#if 0
+ write_register (HARD_PC_REGNUM, CALL_DUMMY_ADDRESS ());
+#endif
+ return sp;
+}
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+static int
+m68hc11_register_byte (int reg_nr)
+{
+ return (reg_nr * M68HC11_REG_SIZE);
+}
+
+static int
+m68hc11_register_raw_size (int reg_nr)
+{
+ return M68HC11_REG_SIZE;
+}
+
+static struct gdbarch *
+m68hc11_gdbarch_init (struct gdbarch_info info,
+ struct gdbarch_list *arches)
+{
+ static LONGEST m68hc11_call_dummy_words[] =
+ {0};
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+ int elf_flags;
+
+ /* Extract the elf_flags if available */
+ elf_flags = 0;
+
+ soft_reg_initialized = 0;
+
+ /* try to find a pre-existing architecture */
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
+ arches != NULL;
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
+ {
+ /* MIPS needs to be pedantic about which ABI the object is
+ using. */
+ if (gdbarch_tdep (current_gdbarch)->elf_flags != elf_flags)
+ continue;
+ return arches->gdbarch;
+ }
+
+ /* Need a new architecture. Fill in a target specific vector. */
+ tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+ gdbarch = gdbarch_alloc (&info, tdep);
+ tdep->elf_flags = elf_flags;
+
+ /* Initially set everything according to the ABI. */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, 32);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_ptr_bit (gdbarch, 16);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+
+ /* Set register info. */
+ set_gdbarch_fp0_regnum (gdbarch, -1);
+ set_gdbarch_max_register_raw_size (gdbarch, 2);
+ set_gdbarch_max_register_virtual_size (gdbarch, 2);
+ set_gdbarch_register_raw_size (gdbarch, m68hc11_register_raw_size);
+ set_gdbarch_register_virtual_size (gdbarch, m68hc11_register_raw_size);
+ set_gdbarch_register_byte (gdbarch, m68hc11_register_byte);
+ set_gdbarch_frame_init_saved_regs (gdbarch, m68hc11_frame_init_saved_regs);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+
+ set_gdbarch_read_pc (gdbarch, generic_target_read_pc);
+ set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
+ set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
+ set_gdbarch_write_fp (gdbarch, generic_target_write_fp);
+ set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
+ set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
+
+ set_gdbarch_num_regs (gdbarch, M68HC11_NUM_REGS);
+ set_gdbarch_num_pseudo_regs (gdbarch, M68HC11_NUM_PSEUDO_REGS);
+ set_gdbarch_sp_regnum (gdbarch, HARD_SP_REGNUM);
+ set_gdbarch_fp_regnum (gdbarch, SOFT_FP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, HARD_PC_REGNUM);
+ set_gdbarch_register_name (gdbarch, m68hc11_register_name);
+ set_gdbarch_register_size (gdbarch, 2);
+ set_gdbarch_register_bytes (gdbarch, M68HC11_ALL_REGS * 2);
+ set_gdbarch_register_virtual_type (gdbarch, m68hc11_register_virtual_type);
+ set_gdbarch_fetch_pseudo_register (gdbarch, m68hc11_fetch_pseudo_register);
+ set_gdbarch_store_pseudo_register (gdbarch, m68hc11_store_pseudo_register);
+
+ set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
+ set_gdbarch_call_dummy_length (gdbarch, 0);
+ set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+ set_gdbarch_call_dummy_address (gdbarch, m68hc11_call_dummy_address);
+ set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1); /*???*/
+ set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+ set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+ set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
+ set_gdbarch_call_dummy_words (gdbarch, m68hc11_call_dummy_words);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch,
+ sizeof (m68hc11_call_dummy_words));
+ set_gdbarch_call_dummy_p (gdbarch, 1);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+ set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+ set_gdbarch_extract_return_value (gdbarch, m68hc11_extract_return_value);
+ set_gdbarch_push_arguments (gdbarch, m68hc11_push_arguments);
+ set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+ set_gdbarch_push_return_address (gdbarch, m68hc11_push_return_address);
+ set_gdbarch_return_value_on_stack (gdbarch, m68hc11_return_value_on_stack);
+
+ set_gdbarch_store_struct_return (gdbarch, m68hc11_store_struct_return);
+ set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
+ set_gdbarch_extract_struct_value_address (gdbarch,
+ m68hc11_extract_struct_value_address);
+ set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
+
+
+ set_gdbarch_frame_chain (gdbarch, m68hc11_frame_chain);
+ set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid);
+ set_gdbarch_frame_saved_pc (gdbarch, m68hc11_frame_saved_pc);
+ set_gdbarch_frame_args_address (gdbarch, m68hc11_frame_args_address);
+ set_gdbarch_frame_locals_address (gdbarch, m68hc11_frame_locals_address);
+ set_gdbarch_saved_pc_after_call (gdbarch, m68hc11_saved_pc_after_call);
+ set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+
+ set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+ set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+
+ set_gdbarch_store_struct_return (gdbarch, m68hc11_store_struct_return);
+ set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
+ set_gdbarch_extract_struct_value_address
+ (gdbarch, m68hc11_extract_struct_value_address);
+ set_gdbarch_use_struct_convention (gdbarch, m68hc11_use_struct_convention);
+ set_gdbarch_init_extra_frame_info (gdbarch, m68hc11_init_extra_frame_info);
+ set_gdbarch_pop_frame (gdbarch, m68hc11_pop_frame);
+ set_gdbarch_skip_prologue (gdbarch, m68hc11_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ set_gdbarch_function_start_offset (gdbarch, 0);
+ set_gdbarch_breakpoint_from_pc (gdbarch, m68hc11_breakpoint_from_pc);
+
+ set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+ set_gdbarch_ieee_float (gdbarch, 1);
+
+ return gdbarch;
}
void
_initialize_m68hc11_tdep (void)
{
- tm_print_insn = print_insn_m68hc11;
+ register_gdbarch_init (bfd_arch_m68hc11, m68hc11_gdbarch_init);
+ if (!tm_print_insn) /* Someone may have already set it */
+ tm_print_insn = print_insn_m68hc11;
add_com ("regs", class_vars, show_regs, "Print all registers");
}