]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Multi-arch support for 68hc11
authorStephane Carrez <stcarrez@nerim.fr>
Sat, 26 Aug 2000 13:36:25 +0000 (13:36 +0000)
committerStephane Carrez <stcarrez@nerim.fr>
Sat, 26 Aug 2000 13:36:25 +0000 (13:36 +0000)
gdb/ChangeLog
gdb/m68hc11-tdep.c

index 608fab0047f2192ece4feba62694200a7f86d8ab..1a87ccfe7778d54fedc69e64c86c6528adb1c157 100644 (file)
@@ -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.
index 4c2d50511fd44a15d2da0c081448ff7e388d61e5..6f8db5faff08c953b9d7d9f961b921b48c4519fa 100644 (file)
@@ -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))
-\f
-
-/* 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");
 }