2003-07-22 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / m68hc11-tdep.c
index 0ad7c9dcde12ccecd6b6822b00de47c4eed305af..0b12de2d37191397572fdefc6b0c525c9f303b2e 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for Motorola 68HC11 & 68HC12
-   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Stephane Carrez, stcarrez@nerim.fr
 
 This file is part of GDB.
@@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "objfiles.h"
 #include "arch-utils.h"
 #include "regcache.h"
+#include "reggroups.h"
 
 #include "target.h"
 #include "opcode/m68hc11.h"
@@ -128,6 +129,10 @@ enum insn_return_kind {
 
 #define M68HC11_REG_SIZE    (2)
 
+#define M68HC12_NUM_REGS        (9)
+#define M68HC12_NUM_PSEUDO_REGS ((M68HC11_MAX_SOFT_REGS+5)+1-1)
+#define M68HC12_HARD_PC_REGNUM  (SOFT_D32_REGNUM+1)
+
 struct insn_sequence;
 struct gdbarch_tdep
   {
@@ -280,6 +285,27 @@ m68hc11_pseudo_register_read (struct gdbarch *gdbarch,
                              struct regcache *regcache,
                              int regno, void *buf)
 {
+  /* The PC is a pseudo reg only for 68HC12 with the memory bank
+     addressing mode.  */
+  if (regno == M68HC12_HARD_PC_REGNUM)
+    {
+      ULONGEST pc;
+      const int regsize = TYPE_LENGTH (builtin_type_uint32);
+
+      regcache_cooked_read_unsigned (regcache, HARD_PC_REGNUM, &pc);
+      if (pc >= 0x8000 && pc < 0xc000)
+        {
+          ULONGEST page;
+
+          regcache_cooked_read_unsigned (regcache, HARD_PAGE_REGNUM, &page);
+          pc -= 0x8000;
+          pc += (page << 14);
+          pc += 0x1000000;
+        }
+      store_unsigned_integer (buf, regsize, pc);
+      return;
+    }
+
   m68hc11_initialize_register_info ();
   
   /* Fetch a soft register: translate into a memory read.  */
@@ -300,6 +326,30 @@ m68hc11_pseudo_register_write (struct gdbarch *gdbarch,
                               struct regcache *regcache,
                               int regno, const void *buf)
 {
+  /* The PC is a pseudo reg only for 68HC12 with the memory bank
+     addressing mode.  */
+  if (regno == M68HC12_HARD_PC_REGNUM)
+    {
+      const int regsize = TYPE_LENGTH (builtin_type_uint32);
+      char *tmp = alloca (regsize);
+      CORE_ADDR pc;
+
+      memcpy (tmp, buf, regsize);
+      pc = extract_unsigned_integer (tmp, regsize);
+      if (pc >= 0x1000000)
+        {
+          pc -= 0x1000000;
+          regcache_cooked_write_unsigned (regcache, HARD_PAGE_REGNUM,
+                                          (pc >> 14) & 0x0ff);
+          pc &= 0x03fff;
+          regcache_cooked_write_unsigned (regcache, HARD_PC_REGNUM,
+                                          pc + 0x8000);
+        }
+      else
+        regcache_cooked_write_unsigned (regcache, HARD_PC_REGNUM, pc);
+      return;
+    }
+  
   m68hc11_initialize_register_info ();
 
   /* Store a soft register: translate into a memory write.  */
@@ -315,6 +365,11 @@ m68hc11_pseudo_register_write (struct gdbarch *gdbarch,
 static const char *
 m68hc11_register_name (int reg_nr)
 {
+  if (reg_nr == M68HC12_HARD_PC_REGNUM && USE_PAGE_REGISTER)
+    return "pc";
+  if (reg_nr == HARD_PC_REGNUM && USE_PAGE_REGISTER)
+    return "ppc";
+  
   if (reg_nr < 0)
     return NULL;
   if (reg_nr >= M68HC11_ALL_REGS)
@@ -343,16 +398,18 @@ static CORE_ADDR
 m68hc11_saved_pc_after_call (struct frame_info *frame)
 {
   CORE_ADDR addr;
-  
-  addr = read_register (HARD_SP_REGNUM) + STACK_CORRECTION;
-  addr &= 0x0ffff;
+  ULONGEST sp;
+
+  regcache_cooked_read_unsigned (current_regcache, HARD_SP_REGNUM, &sp);
+  sp += STACK_CORRECTION;
+  addr = sp & 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;
+  return get_frame_extra_info (frame)->return_pc;
 }
 
 static CORE_ADDR
@@ -360,21 +417,15 @@ m68hc11_frame_args_address (struct frame_info *frame)
 {
   CORE_ADDR addr;
 
-  addr = frame->frame + frame->extra_info->size + STACK_CORRECTION + 2;
-  if (frame->extra_info->return_kind == RETURN_RTC)
+  addr = get_frame_base (frame) + get_frame_extra_info (frame)->size + STACK_CORRECTION + 2;
+  if (get_frame_extra_info (frame)->return_kind == RETURN_RTC)
     addr += 1;
-  else if (frame->extra_info->return_kind == RETURN_RTI)
+  else if (get_frame_extra_info (frame)->return_kind == RETURN_RTI)
     addr += 7;
 
   return addr;
 }
 
-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.  */
 
@@ -385,21 +436,23 @@ m68hc11_pop_frame (void)
   register CORE_ADDR fp, sp;
   register int regnum;
 
-  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
+                                  get_frame_base (frame),
+                                  get_frame_base (frame)))
     generic_pop_dummy_frame ();
   else
     {
-      fp = FRAME_FP (frame);
-      FRAME_INIT_SAVED_REGS (frame);
+      fp = get_frame_base (frame);
+      DEPRECATED_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])
+       if (get_frame_saved_regs (frame)[regnum])
          write_register (regnum,
-                          read_memory_integer (frame->saved_regs[regnum], 2));
+                          read_memory_integer (get_frame_saved_regs (frame)[regnum], 2));
 
-      write_register (HARD_PC_REGNUM, frame->extra_info->return_pc);
-      sp = (fp + frame->extra_info->size + 2) & 0x0ffff;
+      write_register (HARD_PC_REGNUM, get_frame_extra_info (frame)->return_pc);
+      sp = (fp + get_frame_extra_info (frame)->size + 2) & 0x0ffff;
       write_register (HARD_SP_REGNUM, sp);
     }
   flush_cached_frames ();
@@ -413,24 +466,27 @@ m68hc11_pop_frame (void)
 
 /* 68HC11 opcodes.  */
 #undef M6811_OP_PAGE2
-#define M6811_OP_PAGE2 (0x18)
-#define M6811_OP_LDX   (0xde)
-#define M6811_OP_PSHX  (0x3c)
-#define M6811_OP_STS   (0x9f)
-#define M6811_OP_TSX   (0x30)
-#define M6811_OP_XGDX  (0x8f)
-#define M6811_OP_ADDD  (0xc3)
-#define M6811_OP_TXS   (0x35)
-#define M6811_OP_DES   (0x34)
+#define M6811_OP_PAGE2   (0x18)
+#define M6811_OP_LDX     (0xde)
+#define M6811_OP_LDX_EXT (0xfe)
+#define M6811_OP_PSHX    (0x3c)
+#define M6811_OP_STS     (0x9f)
+#define M6811_OP_STS_EXT (0xbf)
+#define M6811_OP_TSX     (0x30)
+#define M6811_OP_XGDX    (0x8f)
+#define M6811_OP_ADDD    (0xc3)
+#define M6811_OP_TXS     (0x35)
+#define M6811_OP_DES     (0x34)
 
 /* 68HC12 opcodes.  */
-#define M6812_OP_PAGE2 (0x18)
-#define M6812_OP_MOVW  (0x01)
-#define M6812_PB_PSHW  (0xae)
-#define M6812_OP_STS   (0x7f)
-#define M6812_OP_LEAS  (0x1b)
-#define M6812_OP_PSHX  (0x34)
-#define M6812_OP_PSHY  (0x35)
+#define M6812_OP_PAGE2   (0x18)
+#define M6812_OP_MOVW    (0x01)
+#define M6812_PB_PSHW    (0xae)
+#define M6812_OP_STS     (0x5f)
+#define M6812_OP_STS_EXT (0x7f)
+#define M6812_OP_LEAS    (0x1b)
+#define M6812_OP_PSHX    (0x34)
+#define M6812_OP_PSHY    (0x35)
 
 /* Operand extraction.  */
 #define OP_DIRECT      (0x100) /* 8-byte direct addressing.  */
@@ -462,6 +518,10 @@ static struct insn_sequence m6811_prologue[] = {
                      M6811_OP_PSHX } },
   { P_SAVE_REG, 5, { M6811_OP_PAGE2, M6811_OP_LDX, OP_DIRECT,
                      M6811_OP_PAGE2, M6811_OP_PSHX } },
+  { P_SAVE_REG, 4, { M6811_OP_LDX_EXT, OP_IMM_HIGH, OP_IMM_LOW,
+                     M6811_OP_PSHX } },
+  { P_SAVE_REG, 6, { M6811_OP_PAGE2, M6811_OP_LDX_EXT, OP_IMM_HIGH, OP_IMM_LOW,
+                     M6811_OP_PAGE2, M6811_OP_PSHX } },
 
   /* Sequences to allocate local variables.  */
   { P_LOCAL_N,  7, { M6811_OP_TSX,
@@ -480,6 +540,7 @@ static struct insn_sequence m6811_prologue[] = {
 
   /* Initialize the frame pointer.  */
   { P_SET_FRAME, 2, { M6811_OP_STS, OP_DIRECT } },
+  { P_SET_FRAME, 3, { M6811_OP_STS_EXT, OP_IMM_HIGH, OP_IMM_LOW } },
   { P_LAST, 0, { 0 } }
 };
 
@@ -488,7 +549,8 @@ static struct insn_sequence m6811_prologue[] = {
 static struct insn_sequence m6812_prologue[] = {  
   { P_SAVE_REG,  5, { M6812_OP_PAGE2, M6812_OP_MOVW, M6812_PB_PSHW,
                       OP_IMM_HIGH, OP_IMM_LOW } },
-  { P_SET_FRAME, 3, { M6812_OP_STS, OP_IMM_HIGH, OP_IMM_LOW } },
+  { P_SET_FRAME, 2, { M6812_OP_STS, OP_DIRECT } },
+  { P_SET_FRAME, 3, { M6812_OP_STS_EXT, OP_IMM_HIGH, OP_IMM_LOW } },
   { P_LOCAL_N,   2, { M6812_OP_LEAS, OP_PBYTE } },
   { P_LOCAL_2,   1, { M6812_OP_PSHX } },
   { P_LOCAL_2,   1, { M6812_OP_PSHY } },
@@ -753,29 +815,31 @@ m68hc11_skip_prologue (CORE_ADDR pc)
   return pc;
 }
 
-/* Given a GDB frame, determine the address of the calling function's frame.
-   This will be used to create a new GDB frame struct, and then
-   INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
-*/
+/* Given a GDB frame, determine the address of the calling function's
+   frame.  This will be used to create a new GDB frame struct, and
+   then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
+   will be called for the new frame.  */
 
 static CORE_ADDR
 m68hc11_frame_chain (struct frame_info *frame)
 {
   CORE_ADDR addr;
 
-  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
-    return frame->frame;       /* dummy frame same as caller's frame */
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
+                                  get_frame_base (frame),
+                                  get_frame_base (frame)))
+    return get_frame_base (frame);     /* dummy frame same as caller's frame */
 
-  if (frame->extra_info->return_pc == 0
-      || inside_entry_file (frame->extra_info->return_pc))
+  if (get_frame_extra_info (frame)->return_pc == 0
+      || inside_entry_file (get_frame_extra_info (frame)->return_pc))
     return (CORE_ADDR) 0;
 
-  if (frame->frame == 0)
+  if (get_frame_base (frame) == 0)
     {
       return (CORE_ADDR) 0;
     }
 
-  addr = frame->frame + frame->extra_info->size + STACK_CORRECTION - 2;
+  addr = get_frame_base (frame) + get_frame_extra_info (frame)->size + STACK_CORRECTION - 2;
   addr = read_memory_unsigned_integer (addr, 2) & 0x0FFFF;
   return addr;
 }  
@@ -791,36 +855,37 @@ m68hc11_frame_init_saved_regs (struct frame_info *fi)
   CORE_ADDR pc;
   CORE_ADDR addr;
 
-  if (fi->saved_regs == NULL)
+  if (get_frame_saved_regs (fi) == NULL)
     frame_saved_regs_zalloc (fi);
   else
-    memset (fi->saved_regs, 0, sizeof (fi->saved_regs));
+    memset (get_frame_saved_regs (fi), 0, SIZEOF_FRAME_SAVED_REGS);
 
-  pc = fi->pc;
-  fi->extra_info->return_kind = m68hc11_get_return_insn (pc);
-  m68hc11_guess_from_prologue (pc, fi->frame, &pc, &fi->extra_info->size,
-                               fi->saved_regs);
+  pc = get_frame_pc (fi);
+  get_frame_extra_info (fi)->return_kind = m68hc11_get_return_insn (pc);
+  m68hc11_guess_from_prologue (pc, get_frame_base (fi), &pc,
+                              &get_frame_extra_info (fi)->size,
+                               get_frame_saved_regs (fi));
 
-  addr = fi->frame + fi->extra_info->size + STACK_CORRECTION;
+  addr = get_frame_base (fi) + get_frame_extra_info (fi)->size + STACK_CORRECTION;
   if (soft_regs[SOFT_FP_REGNUM].name)
-    fi->saved_regs[SOFT_FP_REGNUM] = addr - 2;
+    get_frame_saved_regs (fi)[SOFT_FP_REGNUM] = addr - 2;
 
   /* Take into account how the function was called/returns.  */
-  if (fi->extra_info->return_kind == RETURN_RTC)
+  if (get_frame_extra_info (fi)->return_kind == RETURN_RTC)
     {
-      fi->saved_regs[HARD_PAGE_REGNUM] = addr;
+      get_frame_saved_regs (fi)[HARD_PAGE_REGNUM] = addr;
       addr++;
     }
-  else if (fi->extra_info->return_kind == RETURN_RTI)
+  else if (get_frame_extra_info (fi)->return_kind == RETURN_RTI)
     {
-      fi->saved_regs[HARD_CCR_REGNUM] = addr;
-      fi->saved_regs[HARD_D_REGNUM] = addr + 1;
-      fi->saved_regs[HARD_X_REGNUM] = addr + 3;
-      fi->saved_regs[HARD_Y_REGNUM] = addr + 5;
+      get_frame_saved_regs (fi)[HARD_CCR_REGNUM] = addr;
+      get_frame_saved_regs (fi)[HARD_D_REGNUM] = addr + 1;
+      get_frame_saved_regs (fi)[HARD_X_REGNUM] = addr + 3;
+      get_frame_saved_regs (fi)[HARD_Y_REGNUM] = addr + 5;
       addr += 7;
     }
-  fi->saved_regs[HARD_SP_REGNUM] = addr;
-  fi->saved_regs[HARD_PC_REGNUM] = fi->saved_regs[HARD_SP_REGNUM];
+  get_frame_saved_regs (fi)[HARD_SP_REGNUM] = addr;
+  get_frame_saved_regs (fi)[HARD_PC_REGNUM] = get_frame_saved_regs (fi)[HARD_SP_REGNUM];
 }
 
 static void
@@ -828,37 +893,36 @@ m68hc11_init_extra_frame_info (int fromleaf, struct frame_info *fi)
 {
   CORE_ADDR addr;
 
-  fi->extra_info = (struct frame_extra_info *)
-    frame_obstack_alloc (sizeof (struct frame_extra_info));
+  frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
   
-  if (fi->next)
-    fi->pc = FRAME_SAVED_PC (fi->next);
+  if (get_next_frame (fi))
+    deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
   
   m68hc11_frame_init_saved_regs (fi);
 
   if (fromleaf)
     {
-      fi->extra_info->return_kind = m68hc11_get_return_insn (fi->pc);
-      fi->extra_info->return_pc = m68hc11_saved_pc_after_call (fi);
+      get_frame_extra_info (fi)->return_kind = m68hc11_get_return_insn (get_frame_pc (fi));
+      get_frame_extra_info (fi)->return_pc = m68hc11_saved_pc_after_call (fi);
     }
   else
     {
-      addr = fi->saved_regs[HARD_PC_REGNUM];
+      addr = get_frame_saved_regs (fi)[HARD_PC_REGNUM];
       addr = read_memory_unsigned_integer (addr, 2) & 0x0ffff;
 
       /* Take into account the 68HC12 specific call (PC + page).  */
-      if (fi->extra_info->return_kind == RETURN_RTC
+      if (get_frame_extra_info (fi)->return_kind == RETURN_RTC
           && addr >= 0x08000 && addr < 0x0c000
           && USE_PAGE_REGISTER)
         {
-          CORE_ADDR page_addr = fi->saved_regs[HARD_PAGE_REGNUM];
+          CORE_ADDR page_addr = get_frame_saved_regs (fi)[HARD_PAGE_REGNUM];
 
           unsigned page = read_memory_unsigned_integer (page_addr, 1);
           addr -= 0x08000;
           addr += ((page & 0x0ff) << 14);
           addr += 0x1000000;
         }
-      fi->extra_info->return_pc = addr;
+      get_frame_extra_info (fi)->return_pc = addr;
     }
 }
 
@@ -992,16 +1056,11 @@ m68hc11_push_arguments (int nargs,
 }
 
 
-/* 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)
-{
-  return entry_point_address ();
-}
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
 
 static struct type *
-m68hc11_register_virtual_type (int reg_nr)
+m68hc11_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
   switch (reg_nr)
     {
@@ -1011,6 +1070,9 @@ m68hc11_register_virtual_type (int reg_nr)
     case HARD_CCR_REGNUM:
       return builtin_type_uint8;
 
+    case M68HC12_HARD_PC_REGNUM:
+      return builtin_type_uint32;
+
     default:
       return builtin_type_uint16;
     }
@@ -1026,57 +1088,58 @@ m68hc11_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
 }
 
 static void
-m68hc11_store_return_value (struct type *type, char *valbuf)
+m68hc11_store_return_value (struct type *type, struct regcache *regcache,
+                            const void *valbuf)
 {
   int len;
 
   len = TYPE_LENGTH (type);
 
   /* First argument is passed in D and X registers.  */
-  if (len <= 4)
+  if (len <= 2)
+    regcache_raw_write_part (regcache, HARD_D_REGNUM, 2 - len, len, valbuf);
+  else if (len <= 4)
     {
-      LONGEST v = extract_unsigned_integer (valbuf, len);
-
-      write_register (HARD_D_REGNUM, v);
-      if (len > 2)
-        {
-          v >>= 16;
-          write_register (HARD_X_REGNUM, v);
-        }
+      regcache_raw_write_part (regcache, HARD_X_REGNUM, 4 - len,
+                               len - 2, valbuf);
+      regcache_raw_write (regcache, HARD_D_REGNUM, (char*) valbuf + (len - 2));
     }
   else
     error ("return of value > 4 is not supported.");
 }
 
 
-/* Given a return value in `regbuf' with a type `type', 
+/* Given a return value in `regcache' with a type `type', 
    extract and copy its value into `valbuf'.  */
 
 static void
-m68hc11_extract_return_value (struct type *type,
-                              char *regbuf,
-                              char *valbuf)
+m68hc11_extract_return_value (struct type *type, struct regcache *regcache,
+                              void *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  
+  char buf[M68HC11_REG_SIZE];
+
+  regcache_raw_read (regcache, HARD_D_REGNUM, buf);
   switch (len)
     {
     case 1:
-      memcpy (valbuf, &regbuf[HARD_D_REGNUM * 2 + 1], len);
+      memcpy (valbuf, buf + 1, 1);
       break;
-  
+
     case 2:
-      memcpy (valbuf, &regbuf[HARD_D_REGNUM * 2], len);
+      memcpy (valbuf, buf, 2);
       break;
-      
+
     case 3:
-      memcpy (&valbuf[0], &regbuf[HARD_X_REGNUM * 2 + 1], 1);
-      memcpy (&valbuf[1], &regbuf[HARD_D_REGNUM * 2], 2);
+      memcpy ((char*) valbuf + 1, buf, 2);
+      regcache_raw_read (regcache, HARD_X_REGNUM, buf);
+      memcpy (valbuf, buf + 1, 1);
       break;
-      
+
     case 4:
-      memcpy (&valbuf[0], &regbuf[HARD_X_REGNUM * 2], 2);
-      memcpy (&valbuf[2], &regbuf[HARD_D_REGNUM * 2], 2);
+      memcpy ((char*) valbuf + 2, buf, 2);
+      regcache_raw_read (regcache, HARD_X_REGNUM, buf);
+      memcpy (valbuf, buf, 2);
       break;
 
     default:
@@ -1103,10 +1166,12 @@ m68hc11_return_value_on_stack (struct type *type)
    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)
+m68hc11_extract_struct_value_address (struct regcache *regcache)
 {
-  return extract_address (&regbuf[HARD_D_REGNUM * 2],
-                          REGISTER_RAW_SIZE (HARD_D_REGNUM));
+  char buf[M68HC11_REG_SIZE];
+
+  regcache_cooked_read (regcache, HARD_D_REGNUM, buf);
+  return extract_unsigned_integer (buf, M68HC11_REG_SIZE);
 }
 
 /* Function: push_return_address (pc)
@@ -1125,30 +1190,6 @@ m68hc11_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
   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)
-{
-  switch (reg_nr)
-    {
-    case HARD_PAGE_REGNUM:
-    case HARD_A_REGNUM:
-    case HARD_B_REGNUM:
-    case HARD_CCR_REGNUM:
-      return 1;
-
-    default:
-      return M68HC11_REG_SIZE;
-    }
-}
-
 /* Test whether the ELF symbol corresponds to a function using rtc or
    rti to return.  */
    
@@ -1173,6 +1214,66 @@ gdb_print_insn_m68hc11 (bfd_vma memaddr, disassemble_info *info)
     return print_insn_m68hc12 (memaddr, info);
 }
 
+\f
+
+/* 68HC11/68HC12 register groups.
+   Identify real hard registers and soft registers used by gcc.  */
+
+static struct reggroup *m68hc11_soft_reggroup;
+static struct reggroup *m68hc11_hard_reggroup;
+
+static void
+m68hc11_init_reggroups (void)
+{
+  m68hc11_hard_reggroup = reggroup_new ("hard", USER_REGGROUP);
+  m68hc11_soft_reggroup = reggroup_new ("soft", USER_REGGROUP);
+}
+
+static void
+m68hc11_add_reggroups (struct gdbarch *gdbarch)
+{
+  reggroup_add (gdbarch, m68hc11_hard_reggroup);
+  reggroup_add (gdbarch, m68hc11_soft_reggroup);
+  reggroup_add (gdbarch, general_reggroup);
+  reggroup_add (gdbarch, float_reggroup);
+  reggroup_add (gdbarch, all_reggroup);
+  reggroup_add (gdbarch, save_reggroup);
+  reggroup_add (gdbarch, restore_reggroup);
+  reggroup_add (gdbarch, vector_reggroup);
+  reggroup_add (gdbarch, system_reggroup);
+}
+
+static int
+m68hc11_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                             struct reggroup *group)
+{
+  /* We must save the real hard register as well as gcc
+     soft registers including the frame pointer.  */
+  if (group == save_reggroup || group == restore_reggroup)
+    {
+      return (regnum <= gdbarch_num_regs (gdbarch)
+              || ((regnum == SOFT_FP_REGNUM
+                   || regnum == SOFT_TMP_REGNUM
+                   || regnum == SOFT_ZS_REGNUM
+                   || regnum == SOFT_XY_REGNUM)
+                  && m68hc11_register_name (regnum)));
+    }
+
+  /* Group to identify gcc soft registers (d1..dN).  */
+  if (group == m68hc11_soft_reggroup)
+    {
+      return regnum >= SOFT_D1_REGNUM && m68hc11_register_name (regnum);
+    }
+
+  if (group == m68hc11_hard_reggroup)
+    {
+      return regnum == HARD_PC_REGNUM || regnum == HARD_SP_REGNUM
+        || regnum == HARD_X_REGNUM || regnum == HARD_D_REGNUM
+        || regnum == HARD_Y_REGNUM || regnum == HARD_CCR_REGNUM;
+    }
+  return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
 static struct gdbarch *
 m68hc11_gdbarch_init (struct gdbarch_info info,
                       struct gdbarch_list *arches)
@@ -1208,18 +1309,35 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
   gdbarch = gdbarch_alloc (&info, tdep);
   tdep->elf_flags = elf_flags;
 
+  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
+     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
+  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
+
   switch (info.bfd_arch_info->arch)
     {
     case bfd_arch_m68hc11:
       tdep->stack_correction = 1;
       tdep->use_page_register = 0;
       tdep->prologue = m6811_prologue;
+      set_gdbarch_addr_bit (gdbarch, 16);
+      set_gdbarch_num_pseudo_regs (gdbarch, M68HC11_NUM_PSEUDO_REGS);
+      set_gdbarch_pc_regnum (gdbarch, HARD_PC_REGNUM);
+      set_gdbarch_num_regs (gdbarch, M68HC11_NUM_REGS);
       break;
 
     case bfd_arch_m68hc12:
       tdep->stack_correction = 0;
       tdep->use_page_register = elf_flags & E_M68HC12_BANKS;
       tdep->prologue = m6812_prologue;
+      set_gdbarch_addr_bit (gdbarch, elf_flags & E_M68HC12_BANKS ? 32 : 16);
+      set_gdbarch_num_pseudo_regs (gdbarch,
+                                   elf_flags & E_M68HC12_BANKS
+                                   ? M68HC12_NUM_PSEUDO_REGS
+                                   : M68HC11_NUM_PSEUDO_REGS);
+      set_gdbarch_pc_regnum (gdbarch, elf_flags & E_M68HC12_BANKS
+                             ? M68HC12_HARD_PC_REGNUM : HARD_PC_REGNUM);
+      set_gdbarch_num_regs (gdbarch, elf_flags & E_M68HC12_BANKS
+                            ? M68HC12_NUM_REGS : M68HC11_NUM_REGS);
       break;
 
     default:
@@ -1234,92 +1352,67 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_int_bit (gdbarch, elf_flags & E_M68HC11_I32 ? 32 : 16);
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_double_bit (gdbarch, elf_flags & E_M68HC11_F64 ? 64 : 32);
-  set_gdbarch_long_double_bit (gdbarch, elf_flags & E_M68HC11_F64 ? 64 : 32);
+  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);
 
+  /* Characters are unsigned.  */
+  set_gdbarch_char_signed (gdbarch, 0);
+
   /* 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_deprecated_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_read_sp (gdbarch, generic_target_read_sp);
-  set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
+  set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_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_deprecated_fp_regnum (gdbarch, SOFT_FP_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_register_type (gdbarch, m68hc11_register_type);
   set_gdbarch_pseudo_register_read (gdbarch, m68hc11_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, m68hc11_pseudo_register_write);
 
-  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_deprecated_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_deprecated_call_dummy_words (gdbarch, m68hc11_call_dummy_words);
+  set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, sizeof (m68hc11_call_dummy_words));
+  set_gdbarch_deprecated_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
+  set_gdbarch_extract_return_value (gdbarch, m68hc11_extract_return_value);
+  set_gdbarch_deprecated_push_arguments (gdbarch, m68hc11_push_arguments);
+  set_gdbarch_deprecated_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_deprecated_store_struct_return (gdbarch, m68hc11_store_struct_return);
   set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
-  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
-  set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
-
+  set_gdbarch_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
 
-  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_deprecated_frame_chain (gdbarch, m68hc11_frame_chain);
+  set_gdbarch_deprecated_frame_saved_pc (gdbarch, m68hc11_frame_saved_pc);
+  set_gdbarch_deprecated_frame_args_address (gdbarch, m68hc11_frame_args_address);
+  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, m68hc11_saved_pc_after_call);
 
-  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
-  set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+  set_gdbarch_deprecated_get_saved_register (gdbarch, deprecated_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_deprecated_store_struct_return (gdbarch, m68hc11_store_struct_return);
+  set_gdbarch_deprecated_store_return_value (gdbarch, m68hc11_store_return_value);
   set_gdbarch_deprecated_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_deprecated_init_extra_frame_info (gdbarch, m68hc11_init_extra_frame_info);
+  set_gdbarch_deprecated_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_stack_align (gdbarch, m68hc11_stack_align);
+  set_gdbarch_deprecated_extra_stack_alignment_needed (gdbarch, 1);
   set_gdbarch_print_insn (gdbarch, gdb_print_insn_m68hc11);
 
+  m68hc11_add_reggroups (gdbarch);
+  set_gdbarch_register_reggroup_p (gdbarch, m68hc11_register_reggroup_p);
+
   /* Minsymbol frobbing.  */
   set_gdbarch_elf_make_msymbol_special (gdbarch,
                                         m68hc11_elf_make_msymbol_special);
@@ -1329,11 +1422,14 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
   return gdbarch;
 }
 
+extern initialize_file_ftype _initialize_m68hc11_tdep; /* -Wmissing-prototypes */
+
 void
 _initialize_m68hc11_tdep (void)
 {
   register_gdbarch_init (bfd_arch_m68hc11, m68hc11_gdbarch_init);
   register_gdbarch_init (bfd_arch_m68hc12, m68hc11_gdbarch_init);
+  m68hc11_init_reggroups ();
 
   add_com ("regs", class_vars, show_regs, "Print all registers");
 } 
This page took 0.034513 seconds and 4 git commands to generate.