* h8300-tdep.c: Multiarch. Drop `set machine' command in favor of
authorCorinna Vinschen <corinna@vinschen.de>
Mon, 16 Sep 2002 15:03:17 +0000 (15:03 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Mon, 16 Sep 2002 15:03:17 +0000 (15:03 +0000)
`set architecture'.  Unify naming convention of functions.
(h8300_skip_prologue): Improve prologue analysis.
(h8300_push_arguments): Rewritten to more closely match GCC's
bizarre argument-passing behavior, along with the comment describing
said behavior.
* remote-hms.c (hms_regnames): Don't use NUM_REGS in definition.
* config/h8300/tm-h8300.h: Multiarch.  Just keep stuff needed by
sim, remote-e7000.c, remote-hms.c and remote.c

gdb/ChangeLog
gdb/config/h8300/tm-h8300.h
gdb/h8300-tdep.c
gdb/remote-hms.c

index d35dd412fe97b8d252aea8ed7cf241c9a1cba5bc..a41708aa62f460921b9faeca558d87977a4ffe51 100644 (file)
@@ -1,3 +1,15 @@
+2002-09-16  Corinna Vinschen  <vinschen@redhat.com>
+
+       * h8300-tdep.c: Multiarch.  Drop `set machine' command in favor of
+       `set architecture'.  Unify naming convention of functions.
+       (h8300_skip_prologue): Improve prologue analysis.
+       (h8300_push_arguments): Rewritten to more closely match GCC's
+       bizarre argument-passing behavior, along with the comment describing
+       said behavior.
+       * remote-hms.c (hms_regnames): Don't use NUM_REGS in definition.
+       * config/h8300/tm-h8300.h: Multiarch.  Just keep stuff needed by
+       sim, remote-e7000.c, remote-hms.c and remote.c
+
 2002-09-15  Mark Kettenis  <kettenis@gnu.org>
 
        * i386-tdep.c (gdb_print_insn_i386): Removed.
index 3020e4d27c8417c7a35c491783d0cbfacd7af0ec..4e6005750457245476ba0c4218e7c054f6e754b8 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
-
-#include "regcache.h"
-
 /* Contributed by Steve Chamberlain sac@cygnus.com */
 
-struct frame_info;
-struct frame_saved_regs;
-struct value;
-struct type;
-
-/* 1 if debugging H8/300H application */ 
+#define GDB_MULTI_ARCH GDB_MULTI_ARCH_PARTIAL
 
 /* NOTE: ezannoni 2000-07-18: these variables are part of sim, defined
    in sim/h8300/compile.c.  They really should not be used this
@@ -36,279 +28,12 @@ struct type;
    GDB_TARGET_IS_H8300 in remote-e7000.c */
 extern int h8300hmode;
 extern int h8300smode;
-
-/* Number of bytes in a word */
-
-#define BINWORD (h8300hmode?4:2)
-
-#define EXTRA_FRAME_INFO       \
-       struct frame_saved_regs *fsr;   \
-       CORE_ADDR from_pc; \
-       CORE_ADDR args_pointer;\
-        CORE_ADDR locals_pointer ;
-
-/* Zero the frame_saved_regs pointer when the frame is initialized,
-   so that FRAME_FIND_SAVED_REGS () will know to allocate and
-   initialize a frame_saved_regs struct the first time it is called.
-   Set the arg_pointer to -1, which is not valid; 0 and other values
-   indicate real, cached values.  */
-
-#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
-       h8300_init_extra_frame_info (fromleaf, fi)
-
-extern void h8300_init_extra_frame_info ();
-
-#undef TARGET_INT_BIT
-#define TARGET_INT_BIT  16
-#undef TARGET_LONG_BIT
-#define TARGET_LONG_BIT  32
-#undef TARGET_PTR_BIT
-#define TARGET_PTR_BIT  (h8300hmode ? 32:16)
-
-/* Offset from address of function to start of its code.
-   Zero on most machines.  */
-
-#define FUNCTION_START_OFFSET 0
-
-/* Advance PC across any function entry prologue instructions
-   to reach some "real" code.  */
-
-#define SKIP_PROLOGUE(ip)   (h8300_skip_prologue(ip))
-extern CORE_ADDR h8300_skip_prologue ();
-
-/* Immediately after a function call, return the saved pc.
-   Can't always go through the frames for this because on some machines
-   the new frame is not set up until the new function executes
-   some instructions.  */
-
-#define SAVED_PC_AFTER_CALL(frame) \
-  read_memory_unsigned_integer (read_register (SP_REGNUM), BINWORD)
-
-/* Stack grows downward.  */
-
-#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
-
-/*#define BREAKPOINT {0x7A, 0xFF} */
-#define BREAKPOINT {0x01, 0x80}        /* Sleep */
-#define REMOTE_BREAKPOINT { 0x57, 0x30}                /* trapa #3 */
-/* 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
-
-/* Say how long registers are.  */
-
-#define REGISTER_SIZE 4
-
-#define NUM_REGS 14
-
-#define REGISTER_BYTES (NUM_REGS * 4)
-
-/* Index within `registers' of the first byte of the space for
-   register N.  */
-
-#define REGISTER_BYTE(N)  ((N) * 4)
-
-/* Number of bytes of storage in the actual machine representation
-   for register N.  On the H8/300, all regs are 2 bytes.  */
-
-#define REGISTER_RAW_SIZE(N) (h8300hmode ? 4 : 2)
-
-/* Number of bytes of storage in the program's representation
-   for register N.  */
-
-#define REGISTER_VIRTUAL_SIZE(N) (h8300hmode ? 4 : 2)
-
-/* Largest value REGISTER_RAW_SIZE can have.  */
-
-#define MAX_REGISTER_RAW_SIZE 4
-
-/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
-
-#define MAX_REGISTER_VIRTUAL_SIZE 4
-
-/* Return the GDB type object for the "standard" data type
-   of data in register N.  */
-
-#define REGISTER_VIRTUAL_TYPE(N) \
-(h8300hmode ? builtin_type_unsigned_long : builtin_type_unsigned_short)
-
-/* Initializer for an array of names of registers.
-   Entries beyond the first NUM_REGS are ignored.  */
-
-#define REGISTER_NAMES \
-  {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "ccr","pc","cycles","tick","inst",""}
-
-/* An array of names of registers. */
-
-extern char **h8300_register_names;
-#define REGISTER_NAME(i) h8300_register_names[i]
-
-/* Register numbers of various important registers.
-   Note that some of these values are "real" register numbers,
-   and correspond to the general registers of the machine,
-   and some are "phony" register numbers which are too large
-   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 ARG0_REGNUM    0       /* first reg in which an arg may be passed */
-#define ARGLAST_REGNUM 2       /* last  reg in which an arg may be passed */
-#define FP_REGNUM      6       /* Contain saddress of executing stack frame */
-#define SP_REGNUM      7       /* Contains address of top of stack */
-#define CCR_REGNUM     8       /* Contains processor status */
-#define PC_REGNUM      9       /* Contains program counter */
-#define EXR_REGNUM     11      /* Contains processor status */
-
-/* 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.  */
-
-/* FIXME: Won't work with both h8/300's.  */
-
-extern void h8300_extract_return_value (struct type *, char *, char *);
-#define DEPRECATED_EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
-    h8300_extract_return_value (TYPE, (char *)(REGBUF), (char *)(VALBUF))
-
-/* Write into appropriate registers a function return value
-   of type TYPE, given in virtual format.  Assumes floats are passed
-   in d0/d1.  */
-/* FIXME: Won't work with both h8/300's.  */
-
-extern void h8300_store_return_value (struct type *, char *);
-#define DEPRECATED_STORE_RETURN_VALUE(TYPE,VALBUF) \
-    h8300_store_return_value(TYPE, (char *) (VALBUF))
-
-/* struct passing and returning stuff */
-#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP)   \
-       write_register (0, STRUCT_ADDR)
-
-#define USE_STRUCT_CONVENTION(gcc_p, type)     (1)
-
-/* 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 DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
-     extract_address (REGBUF + REGISTER_BYTE (0), \
-                     REGISTER_RAW_SIZE (0))
-
-/* Describe the pointer in each stack frame to the previous stack frame
-   (its caller).  */
-
-/* FRAME_CHAIN takes a frame's nominal address
-   and produces the frame's chain-pointer.
-
-   However, if FRAME_CHAIN_VALID returns zero,
-   it means the given frame is the outermost one and has no caller.  */
-
-#define FRAME_CHAIN(FRAME) h8300_frame_chain(FRAME)
-CORE_ADDR h8300_frame_chain (struct frame_info *);
-
-/* In the case of the H8/300, the frame's nominal address
-   is the address of a 2-byte word containing the calling frame's address.  */
-
-/* Use the alternate method of avoiding running up off the end of
-   the frame chain or following frames back into the startup code.
-   See the comments in objfile.h */
-
-#define FRAME_CHAIN_VALID(fp,fi) func_frame_chain_valid (fp, fi)
-
-/* Define other aspects of the stack frame.  */
-
-/* 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))
-
-/* Any function with a frame looks like this
-   SECOND ARG
-   FIRST ARG
-   RET PC
-   SAVED R2
-   SAVED R3
-   SAVED FP   <-FP POINTS HERE
-   LOCALS0
-   LOCALS1    <-SP POINTS HERE
- */
-
-#define FRAME_SAVED_PC(FRAME) h8300_frame_saved_pc(FRAME)
-extern CORE_ADDR h8300_frame_saved_pc (struct frame_info *);
-
-#define FRAME_ARGS_ADDRESS(fi) h8300_frame_args_address(fi)
-extern CORE_ADDR h8300_frame_args_address (struct frame_info *);
-
-#define FRAME_LOCALS_ADDRESS(fi) h8300_frame_locals_address(fi)
-extern CORE_ADDR h8300_frame_locals_address (struct frame_info *);
-
-/* 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
-   now that the C compiler delays popping them.  */
-
-#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 FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)        \
-   h8300_frame_find_saved_regs(frame_info, &(frame_saved_regs))
-extern void h8300_frame_find_saved_regs (struct frame_info *,
-                                        struct frame_saved_regs *);
-\f
-
-typedef unsigned short INSN_WORD;
-
-
-#define        PRINT_REGISTER_HOOK(regno) h8300_print_register_hook(regno)
-extern void h8300_print_register_hook (int);
-
 #define GDB_TARGET_IS_H8300
 
+/* Needed for remote.c */
+#define REMOTE_BREAKPOINT { 0x57, 0x30}                /* trapa #3 */
+/* Needed for remote-hms.c */
+#define CCR_REGNUM 8
+/* Needed for remote-e7000.c */
 #define NUM_REALREGS (h8300smode?11:10)
-#define NOP { 0x01, 0x80}      /* A sleep insn */
-
-#define BELIEVE_PCC_PROMOTION 1
-
-/*
- * CALL_DUMMY stuff:
- */
-
-#define USE_GENERIC_DUMMY_FRAMES 1
-#define CALL_DUMMY                     {0}
-#define CALL_DUMMY_LENGTH              (0)
-#define CALL_DUMMY_ADDRESS()           entry_point_address ()
-#define CALL_DUMMY_LOCATION            AT_ENTRY_POINT
-#define CALL_DUMMY_START_OFFSET                (0)
-#define CALL_DUMMY_BREAKPOINT_OFFSET   (0)
-
-extern CORE_ADDR h8300_push_arguments (int nargs,
-                                      struct value **args,
-                                      CORE_ADDR sp,
-                                      unsigned char struct_return,
-                                      CORE_ADDR struct_addr);
-extern CORE_ADDR h8300_push_return_address (CORE_ADDR, CORE_ADDR);
-extern void h8300_pop_frame (void);
-
-#define PC_IN_CALL_DUMMY(PC, SP, FP)   generic_pc_in_call_dummy (PC, SP, FP)
-#define FIX_CALL_DUMMY(DUMMY, START_SP, FUNADDR, NARGS, ARGS, TYPE, GCCP)
-#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
-  (h8300_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR))
-/* Push an empty stack frame, to record the current PC, etc.  */
-#define PUSH_DUMMY_FRAME       generic_push_dummy_frame ()
-/* Discard from the stack the innermost frame, restoring all registers.  */
-#define POP_FRAME              h8300_pop_frame ()
-#define PUSH_RETURN_ADDRESS(PC, SP)    h8300_push_return_address (PC, SP)
 
-/* override the standard get_saved_register function with 
-   one that takes account of generic CALL_DUMMY frames */
-#define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \
-     generic_unwind_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
index f992d4bd6b9f8a92baac957875bfb90c79c551d3..cd627993ec700e16579ab6a23ac74f6885d2d4f7 100644 (file)
  */
 
 #include "defs.h"
-#include "frame.h"
-#include "symtab.h"
-#include "dis-asm.h"
-#include "gdbcmd.h"
-#include "gdbtypes.h"
-#include "gdbcore.h"
-#include "gdb_string.h"
 #include "value.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "arch-utils.h"
 #include "regcache.h"
+#include "gdbcore.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
 
-extern int h8300hmode, h8300smode;
+/* Extra info which is saved in each frame_info. */
+struct frame_extra_info
+{
+  CORE_ADDR from_pc;
+  CORE_ADDR args_pointer;
+  CORE_ADDR locals_pointer;
+};
 
-#undef  NUM_REGS
-#define NUM_REGS (h8300smode?12:11)
+#define E_NUM_REGS (h8300smode ? 14 : 13)
+
+enum
+{
+  h8300_reg_size = 2,
+  h8300h_reg_size = 4,
+  h8300_max_reg_size = 4,
+};
+#define BINWORD (h8300hmode ? h8300h_reg_size : h8300_reg_size)
+
+enum gdb_regnum
+{
+  E_R0_REGNUM, E_ER0_REGNUM = E_R0_REGNUM, E_ARG0_REGNUM = E_R0_REGNUM,
+  E_R1_REGNUM, E_ER1_REGNUM = E_R1_REGNUM,
+  E_R2_REGNUM, E_ER2_REGNUM = E_R2_REGNUM, E_ARGLAST_REGNUM = E_R2_REGNUM,
+  E_R3_REGNUM, E_ER3_REGNUM = E_R3_REGNUM,
+  E_R4_REGNUM, E_ER4_REGNUM = E_R4_REGNUM,
+  E_R5_REGNUM, E_ER5_REGNUM = E_R5_REGNUM,
+  E_R6_REGNUM, E_ER6_REGNUM = E_R6_REGNUM, E_FP_REGNUM = E_R6_REGNUM,
+  E_SP_REGNUM,
+  E_CCR_REGNUM,
+  E_PC_REGNUM,
+  E_CYCLES_REGNUM,
+  E_TICK_REGNUM, E_EXR_REGNUM = E_TICK_REGNUM,
+  E_INST_REGNUM, E_TICKS_REGNUM = E_INST_REGNUM,
+  E_INSTS_REGNUM
+};
 
 #define UNSIGNED_SHORT(X) ((X) & 0xffff)
 
@@ -53,24 +83,95 @@ extern int h8300hmode, h8300smode;
 #define IS_MOVK_R5(x) (x==0x7905)
 #define IS_SUB_R5SP(x) (x==0x1957)
 
-/* The register names change depending on whether the h8300h processor
-   type is selected. */
+/* If the instruction at PC is an argument register spill, return its
+   length.  Otherwise, return zero.
 
-static char *original_register_names[] = REGISTER_NAMES;
+   An argument register spill is an instruction that moves an argument
+   from the register in which it was passed to the stack slot in which
+   it really lives.  It is a byte, word, or longword move from an
+   argument register to a negative offset from the frame pointer.  */
 
-static char *h8300h_register_names[] = {
-  "er0", "er1", "er2", "er3", "er4", "er5", "er6",
-  "sp", "ccr", "pc", "cycles", "exr", "tick", "inst"
-};
+static int
+h8300_is_argument_spill (CORE_ADDR pc)
+{
+  int w = read_memory_unsigned_integer (pc, 2);
+
+  if ((w & 0xfff0) == 0x6ee0                  /* mov.b Rs,@(d:16,er6) */
+      && 8 <= (w & 0xf) && (w & 0xf) <= 10)   /* Rs is R0L, R1L, or R2L  */
+    {
+      int w2 = read_memory_integer (pc + 2, 2);
+
+      /* ... and d:16 is negative.  */
+      if (w2 < 0)
+        return 4;
+    }
+  else if (w == 0x7860)
+    {
+      int w2 = read_memory_integer (pc + 2, 2);
 
-char **h8300_register_names = original_register_names;
+      if ((w2 & 0xfff0) == 0x6aa0)              /* mov.b Rs, @(d:24,er6) */
+        {
+          LONGEST disp = read_memory_integer (pc + 4, 4);
 
-/* Local function declarations.  */
+          /* ... and d:24 is negative.  */
+          if (disp < 0 && disp > 0xffffff)
+            return 8;
+        }
+    }
+  else if ((w & 0xfff0) == 0x6fe0             /* mov.w Rs,@(d:16,er6) */
+           && (w & 0xf) <= 2)                 /* Rs is R0, R1, or R2 */
+    {
+      int w2 = read_memory_integer (pc + 2, 2);
 
-static CORE_ADDR examine_prologue ();
-static void set_machine_hook (char *filename);
+      /* ... and d:16 is negative.  */
+      if (w2 < 0)
+        return 4;
+    }
+  else if (w == 0x78e0)
+    {
+      int w2 = read_memory_integer (pc + 2, 2);
 
-CORE_ADDR
+      if ((w2 & 0xfff0) == 0x6ba0)              /* mov.b Rs, @(d:24,er6) */
+        {
+          LONGEST disp = read_memory_integer (pc + 4, 4);
+
+          /* ... and d:24 is negative.  */
+          if (disp < 0 && disp > 0xffffff)
+            return 8;
+        }
+    }
+  else if (w == 0x0100)
+    {
+      int w2 = read_memory_integer (pc + 2, 2);
+
+      if ((w2 & 0xfff0) == 0x6fe0             /* mov.l Rs,@(d:16,er6) */
+          && (w2 & 0xf) <= 2)                /* Rs is ER0, ER1, or ER2 */
+        {
+          int w3 = read_memory_integer (pc + 4, 2);
+
+          /* ... and d:16 is negative.  */
+          if (w3 < 0)
+            return 6;
+        }
+      else if (w2 == 0x78e0)
+        {
+          int w3 = read_memory_integer (pc + 4, 2);
+
+          if ((w3 & 0xfff0) == 0x6ba0)          /* mov.l Rs, @(d:24,er6) */
+            {
+              LONGEST disp = read_memory_integer (pc + 6, 4);
+
+              /* ... and d:24 is negative.  */
+              if (disp < 0 && disp > 0xffffff)
+                return 10;
+            }
+        }
+    }
+
+  return 0;
+}
+
+static CORE_ADDR
 h8300_skip_prologue (CORE_ADDR start_pc)
 {
   short int w;
@@ -137,10 +238,21 @@ h8300_skip_prologue (CORE_ADDR start_pc)
   if (IS_SUBL_SP (w))
     start_pc += 6 + adjust;
 
+  /* Check for spilling an argument register to the stack frame.
+     This could also be an initializing store from non-prologue code,
+     but I don't think there's any harm in skipping that.  */
+  for (;;)
+    {
+      int spill_size = h8300_is_argument_spill (start_pc);
+      if (spill_size == 0)
+        break;
+      start_pc += spill_size;
+    }
+
   return start_pc;
 }
 
-int
+static int
 gdb_print_insn_h8300 (bfd_vma memaddr, disassemble_info * info)
 {
   if (h8300smode)
@@ -151,82 +263,13 @@ gdb_print_insn_h8300 (bfd_vma memaddr, disassemble_info * info)
     return print_insn_h8300 (memaddr, info);
 }
 
-/* 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.
-
-   For us, the frame address is its stack pointer value, so we look up
-   the function prologue to determine the caller's sp value, and return it.  */
-
-CORE_ADDR
-h8300_frame_chain (struct frame_info *thisframe)
-{
-  if (PC_IN_CALL_DUMMY (thisframe->pc, thisframe->frame, thisframe->frame))
-    {                          /* initialize the from_pc now */
-      thisframe->from_pc = generic_read_register_dummy (thisframe->pc,
-                                                       thisframe->frame,
-                                                       PC_REGNUM);
-      return thisframe->frame;
-    }
-  h8300_frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
-  return thisframe->fsr->regs[SP_REGNUM];
-}
-
-/* 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.
-
-   We cache the result of doing this in the frame_obstack, since it is
-   fairly expensive.  */
-
-void
-h8300_frame_find_saved_regs (struct frame_info *fi,
-                            struct frame_saved_regs *fsr)
-{
-  register struct frame_saved_regs *cache_fsr;
-  CORE_ADDR ip;
-  struct symtab_and_line sal;
-  CORE_ADDR limit;
-
-  if (!fi->fsr)
-    {
-      cache_fsr = (struct frame_saved_regs *)
-       frame_obstack_alloc (sizeof (struct frame_saved_regs));
-      memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
-
-      fi->fsr = cache_fsr;
-
-      if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
-       {                       /* no more to do. */
-         if (fsr)
-           *fsr = *fi->fsr;
-         return;
-       }
-      /* Find the start and end of the function prologue.  If the PC
-         is in the function prologue, we only consider the part that
-         has executed already.  */
-
-      ip = get_pc_function_start (fi->pc);
-      sal = find_pc_line (ip, 0);
-      limit = (sal.end && sal.end < fi->pc) ? sal.end : fi->pc;
-
-      /* This will fill in fields in *fi as well as in cache_fsr.  */
-      examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
-    }
-
-  if (fsr)
-    *fsr = *fi->fsr;
-}
-
 /* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
    is not the address of a valid instruction, the address of the next
    instruction beyond ADDR otherwise.  *PWORD1 receives the first word
    of the instruction. */
 
-CORE_ADDR
-NEXT_PROLOGUE_INSN (CORE_ADDR addr, CORE_ADDR lim, INSN_WORD * pword1)
+static CORE_ADDR
+NEXT_PROLOGUE_INSN (CORE_ADDR addr, CORE_ADDR lim, unsigned short* pword1)
 {
   char buf[2];
   if (addr < lim + 8)
@@ -248,18 +291,29 @@ NEXT_PROLOGUE_INSN (CORE_ADDR addr, CORE_ADDR lim, INSN_WORD * pword1)
    `fi' is a struct frame_info pointer; we fill in various fields in it
    to reflect the offsets of the arg pointer and the locals pointer.  */
 
+/* Any function with a frame looks like this
+   SECOND ARG
+   FIRST ARG
+   RET PC
+   SAVED R2
+   SAVED R3
+   SAVED FP   <-FP POINTS HERE
+   LOCALS0
+   LOCALS1    <-SP POINTS HERE
+ */
+
 static CORE_ADDR
-examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
-                 CORE_ADDR after_prolog_fp, struct frame_saved_regs *fsr,
-                 struct frame_info *fi)
+h8300_examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
+                       CORE_ADDR after_prolog_fp, CORE_ADDR *fsr,
+                       struct frame_info *fi)
 {
   register CORE_ADDR next_ip;
   int r;
   int have_fp = 0;
-  INSN_WORD insn_word;
+  unsigned short insn_word;
   /* Number of things pushed onto stack, starts at 2/4, 'cause the
      PC is already there */
-  unsigned int reg_save_depth = h8300hmode ? 4 : 2;
+  unsigned int reg_save_depth = BINWORD;
 
   unsigned int auto_depth = 0; /* Number of bytes of autos */
 
@@ -270,11 +324,11 @@ examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
   memset (in_frame, 1, 11);
   for (r = 0; r < 8; r++)
     {
-      fsr->regs[r] = 0;
+      fsr[r] = 0;
     }
   if (after_prolog_fp == 0)
     {
-      after_prolog_fp = read_register (SP_REGNUM);
+      after_prolog_fp = read_register (E_SP_REGNUM);
     }
 
   /* If the PC isn't valid, quit now.  */
@@ -290,7 +344,7 @@ examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
     }
 
   /* Skip over any fp push instructions */
-  fsr->regs[6] = after_prolog_fp;
+  fsr[E_FP_REGNUM] = after_prolog_fp;
   while (next_ip && IS_PUSH_FP (insn_word))
     {
       ip = next_ip + adjust;
@@ -360,7 +414,7 @@ examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
        {
          ip = next_ip;
          next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
-         fsr->regs[r] = after_prolog_fp + auto_depth;
+         fsr[r] = after_prolog_fp + auto_depth;
          auto_depth += 2 + adjust;
          continue;
        }
@@ -377,7 +431,7 @@ examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
 
          for (i = start; i <= start + count; i++)
            {
-             fsr->regs[i] = after_prolog_fp + auto_depth;
+             fsr[i] = after_prolog_fp + auto_depth;
              auto_depth += 4;
            }
        }
@@ -385,37 +439,67 @@ examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
     }
 
   /* The args are always reffed based from the stack pointer */
-  fi->args_pointer = after_prolog_fp;
+  fi->extra_info->args_pointer = after_prolog_fp;
   /* Locals are always reffed based from the fp */
-  fi->locals_pointer = after_prolog_fp;
+  fi->extra_info->locals_pointer = after_prolog_fp;
   /* The PC is at a known place */
-  fi->from_pc =
+  fi->extra_info->from_pc =
     read_memory_unsigned_integer (after_prolog_fp + BINWORD, BINWORD);
 
   /* Rememeber any others too */
-  in_frame[PC_REGNUM] = 0;
+  in_frame[E_PC_REGNUM] = 0;
 
   if (have_fp)
     /* We keep the old FP in the SP spot */
-    fsr->regs[SP_REGNUM] =
-      read_memory_unsigned_integer (fsr->regs[6], BINWORD);
+    fsr[E_SP_REGNUM] = read_memory_unsigned_integer (fsr[E_FP_REGNUM], BINWORD);
   else
-    fsr->regs[SP_REGNUM] = after_prolog_fp + auto_depth;
+    fsr[E_SP_REGNUM] = after_prolog_fp + auto_depth;
 
   return (ip);
 }
 
-void
-h8300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+static void
+h8300_frame_init_saved_regs (struct frame_info *fi)
 {
-  fi->fsr = 0;                 /* Not yet allocated */
-  fi->args_pointer = 0;                /* Unknown */
-  fi->locals_pointer = 0;      /* Unknown */
-  fi->from_pc = 0;
-  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
-    {                          /* anything special to do? */
-      return;
+  CORE_ADDR func_addr, func_end;
+
+  if (!fi->saved_regs)
+    {
+      frame_saved_regs_zalloc (fi);
+
+      /* Find the beginning of this function, so we can analyze its
+        prologue. */
+      if (find_pc_partial_function (fi->pc, NULL, &func_addr, &func_end))
+        {
+         struct symtab_and_line sal = find_pc_line (func_addr, 0);
+         CORE_ADDR limit = (sal.end && sal.end < fi->pc) ? sal.end : fi->pc;
+         /* This will fill in fields in fi. */
+         h8300_examine_prologue (func_addr, limit, fi->frame, fi->saved_regs, fi);
+       }
+      /* Else we're out of luck (can't debug completely stripped code). 
+        FIXME. */
+    }
+}
+
+/* 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.
+
+   For us, the frame address is its stack pointer value, so we look up
+   the function prologue to determine the caller's sp value, and return it.  */
+
+static CORE_ADDR
+h8300_frame_chain (struct frame_info *thisframe)
+{
+  if (PC_IN_CALL_DUMMY (thisframe->pc, thisframe->frame, thisframe->frame))
+    {                          /* initialize the from_pc now */
+      thisframe->extra_info->from_pc = generic_read_register_dummy (
+                                                       thisframe->pc,
+                                                       thisframe->frame,
+                                                       E_PC_REGNUM);
+      return thisframe->frame;
     }
+  return thisframe->saved_regs[E_SP_REGNUM];
 }
 
 /* Return the saved PC from this frame.
@@ -423,168 +507,212 @@ h8300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
    If the frame has a memory copy of SRP_REGNUM, use that.  If not,
    just use the register SRP_REGNUM itself.  */
 
-CORE_ADDR
+static CORE_ADDR
 h8300_frame_saved_pc (struct frame_info *frame)
 {
   if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
-    return generic_read_register_dummy (frame->pc, frame->frame, PC_REGNUM);
+    return generic_read_register_dummy (frame->pc, frame->frame, E_PC_REGNUM);
   else
-    return frame->from_pc;
+    return frame->extra_info->from_pc;
 }
 
-CORE_ADDR
+static void
+h8300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+{
+  if (!fi->extra_info)
+    {
+      fi->extra_info = (struct frame_extra_info *)
+        frame_obstack_alloc (sizeof (struct frame_extra_info));
+      fi->extra_info->from_pc = 0;
+      fi->extra_info->args_pointer = 0;                /* Unknown */
+      fi->extra_info->locals_pointer = 0;      /* Unknown */
+      
+      if (!fi->pc)
+        {
+         if (fi->next)
+           fi->pc = h8300_frame_saved_pc (fi->next);
+       }
+      h8300_frame_init_saved_regs (fi);
+    }
+}
+
+static CORE_ADDR
 h8300_frame_locals_address (struct frame_info *fi)
 {
   if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
     return (CORE_ADDR) 0;      /* Not sure what else to do... */
-  if (!fi->locals_pointer)
-    {
-      struct frame_saved_regs ignore;
-
-      get_frame_saved_regs (fi, &ignore);
-
-    }
-  return fi->locals_pointer;
+  return fi->extra_info->locals_pointer;
 }
 
 /* Return the address of the argument block for the frame
    described by FI.  Returns 0 if the address is unknown.  */
 
-CORE_ADDR
+static CORE_ADDR
 h8300_frame_args_address (struct frame_info *fi)
 {
   if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
     return (CORE_ADDR) 0;      /* Not sure what else to do... */
-  if (!fi->args_pointer)
-    {
-      struct frame_saved_regs ignore;
-
-      get_frame_saved_regs (fi, &ignore);
-
-    }
-
-  return fi->args_pointer;
+  return fi->extra_info->args_pointer;
 }
 
+/* Round N up or down to the nearest multiple of UNIT.
+   Evaluate N only once, UNIT several times.
+   UNIT must be a power of two.  */
+#define round_up(n, unit)   (((n) + (unit) - 1) & -(unit))
+#define round_down(n, unit) ((n) & -(unit))
+
 /* Function: push_arguments
    Setup the function arguments for calling a function in the inferior.
+   In this discussion, a `word' is 16 bits on the H8/300s, and 32 bits
+   on the H8/300H.
+
+   There are actually two ABI's here: -mquickcall (the default) and
+   -mno-quickcall.  With -mno-quickcall, all arguments are passed on
+   the stack after the return address, word-aligned.  With
+   -mquickcall, GCC tries to use r0 -- r2 to pass registers.  Since
+   GCC doesn't indicate in the object file which ABI was used to
+   compile it, GDB only supports the default --- -mquickcall.
+
+   Here are the rules for -mquickcall, in detail:
+
+   Each argument, whether scalar or aggregate, is padded to occupy a
+   whole number of words.  Arguments smaller than a word are padded at
+   the most significant end; those larger than a word are padded at
+   the least significant end.
+
+   The initial arguments are passed in r0 -- r2.  Earlier arguments go in
+   lower-numbered registers.  Multi-word arguments are passed in
+   consecutive registers, with the most significant end in the
+   lower-numbered register.
+
+   If an argument doesn't fit entirely in the remaining registers, it
+   is passed entirely on the stack.  Stack arguments begin just after
+   the return address.  Once an argument has overflowed onto the stack
+   this way, all subsequent arguments are passed on the stack.
+
+   The above rule has odd consequences.  For example, on the h8/300s,
+   if a function takes two longs and an int as arguments:
+   - the first long will be passed in r0/r1,
+   - the second long will be passed entirely on the stack, since it
+     doesn't fit in r2,
+   - and the int will be passed on the stack, even though it could fit
+     in r2.
+
+   A weird exception: if an argument is larger than a word, but not a
+   whole number of words in length (before padding), it is passed on
+   the stack following the rules for stack arguments above, even if
+   there are sufficient registers available to hold it.  Stranger
+   still, the argument registers are still `used up' --- even though
+   there's nothing in them.
+
+   So, for example, on the h8/300s, if a function expects a three-byte
+   structure and an int, the structure will go on the stack, and the
+   int will go in r2, not r0.
+  
+   If the function returns an aggregate type (struct, union, or class)
+   by value, the caller must allocate space to hold the return value,
+   and pass the callee a pointer to this space as an invisible first
+   argument, in R0.
+
+   For varargs functions, the last fixed argument and all the variable
+   arguments are always passed on the stack.  This means that calls to
+   varargs functions don't work properly unless there is a prototype
+   in scope.
+
+   Basically, this ABI is not good, for the following reasons:
+   - You can't call vararg functions properly unless a prototype is in scope.
+   - Structure passing is inconsistent, to no purpose I can see.
+   - It often wastes argument registers, of which there are only three
+     to begin with.  */
 
-   On the Hitachi H8/300 architecture, there are three registers (R0 to R2)
-   which are dedicated for passing function arguments.  Up to the first
-   three arguments (depending on size) may go into these registers.
-   The rest go on the stack.
-
-   Arguments that are smaller than WORDSIZE bytes will still take up a
-   whole register or a whole WORDSIZE word on the stack, and will be
-   right-justified in the register or the stack word.  This includes
-   chars and small aggregate types.  Note that WORDSIZE depends on the 
-   cpu type.
-
-   Arguments that are larger than WORDSIZE bytes will be split between
-   two or more registers as available, but will NOT be split between a
-   register and the stack.
-
-   An exceptional case exists for struct arguments (and possibly other
-   aggregates such as arrays) -- if the size is larger than WORDSIZE
-   bytes but not a multiple of WORDSIZE bytes.  In this case the
-   argument is never split between the registers and the stack, but
-   instead is copied in its entirety onto the stack, AND also copied
-   into as many registers as there is room for.  In other words, space
-   in registers permitting, two copies of the same argument are passed
-   in.  As far as I can tell, only the one on the stack is used,
-   although that may be a function of the level of compiler
-   optimization.  I suspect this is a compiler bug.  Arguments of
-   these odd sizes are left-justified within the word (as opposed to
-   arguments smaller than WORDSIZE bytes, which are right-justified).
-
-   If the function is to return an aggregate type such as a struct,
-   the caller must allocate space into which the callee will copy the
-   return value.  In this case, a pointer to the return value location
-   is passed into the callee in register R0, which displaces one of
-   the other arguments passed in via registers R0 to R2.  */
-
-CORE_ADDR
+static CORE_ADDR
 h8300_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
-                     unsigned char struct_return, CORE_ADDR struct_addr)
+                     int struct_return, CORE_ADDR struct_addr)
 {
   int stack_align, stack_alloc, stack_offset;
-  int wordsize;
-  int argreg;
-  int argnum;
-  struct type *type;
-  CORE_ADDR regval;
-  char *val;
-  char valbuf[4];
-  int len;
-
-  if (h8300hmode || h8300smode)
+  int wordsize = BINWORD;
+  int reg;
+  int argument;
+
+  /* First, make sure the stack is properly aligned.  */
+  sp = round_down (sp, wordsize);
+
+  /* Now make sure there's space on the stack for the arguments.  We
+     may over-allocate a little here, but that won't hurt anything.  */
+  stack_alloc = 0;
+  for (argument = 0; argument < nargs; argument++)
+    stack_alloc += round_up (TYPE_LENGTH (VALUE_TYPE (args[argument])),
+                             wordsize);
+  sp -= stack_alloc;
+
+  /* Now load as many arguments as possible into registers, and push
+     the rest onto the stack.  */
+  reg = E_ARG0_REGNUM;
+  stack_offset = 0;
+
+  /* If we're returning a structure by value, then we must pass a
+     pointer to the buffer for the return value as an invisible first
+     argument.  */
+  if (struct_return)
+    write_register (reg++, struct_addr);
+
+  for (argument = 0; argument < nargs; argument++)
     {
-      stack_align = 3;
-      wordsize = 4;
-    }
-  else
-    {
-      stack_align = 1;
-      wordsize = 2;
-    }
-
-  /* first force sp to a n-byte alignment */
-  sp = sp & ~stack_align;
-
-  /* Now make sure there's space on the stack */
-  for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
-    stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + stack_align)
-                   & ~stack_align);
-  sp -= stack_alloc;           /* make room on stack for args */
-  /* we may over-allocate a little here, but that won't hurt anything */
-
-  argreg = ARG0_REGNUM;
-  if (struct_return)           /* "struct return" pointer takes up one argreg */
-    {
-      write_register (argreg++, struct_addr);
-    }
-
-  /* Now load as many as possible of the first arguments into
-     registers, and push the rest onto the stack.  There are 3N bytes
-     in three registers available.  Loop thru args from first to last.  */
-
-  for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
-    {
-      type = VALUE_TYPE (args[argnum]);
-      len = TYPE_LENGTH (type);
-      memset (valbuf, 0, sizeof (valbuf));
-      if (len < wordsize)
-       {
-         /* the purpose of this is to right-justify the value within the word */
-         memcpy (valbuf + (wordsize - len),
-                 (char *) VALUE_CONTENTS (args[argnum]), len);
-         val = valbuf;
-       }
+      struct type *type = VALUE_TYPE (args[argument]);
+      int len = TYPE_LENGTH (type);
+      char *contents = (char *) VALUE_CONTENTS (args[argument]);
+
+      /* Pad the argument appropriately.  */
+      int padded_len = round_up (len, wordsize);
+      char *padded = alloca (padded_len);
+
+      memset (padded, 0, padded_len);
+      memcpy (len < wordsize ? padded + padded_len - len : padded,
+              contents, len);
+
+      /* Could the argument fit in the remaining registers?  */
+      if (padded_len <= (E_ARGLAST_REGNUM - reg + 1) * wordsize)
+        {
+          /* Are we going to pass it on the stack anyway, for no good
+             reason?  */
+          if (len > wordsize && len % wordsize)
+            {
+              /* I feel so unclean.  */
+              write_memory (sp + stack_offset, padded, padded_len);
+              stack_offset += padded_len;
+
+              /* That's right --- even though we passed the argument
+                 on the stack, we consume the registers anyway!  Love
+                 me, love my dog.  */
+              reg += padded_len / wordsize;
+            }
+          else
+            {
+              /* Heavens to Betsy --- it's really going in registers!
+                 It would be nice if we could use write_register_bytes
+                 here, but on the h8/300s, there are gaps between
+                 the registers in the register file.  */
+              int offset;
+
+              for (offset = 0; offset < padded_len; offset += wordsize)
+                {
+                  ULONGEST word = extract_address (padded + offset, wordsize);
+                  write_register (reg++, word);
+                }
+            }
+        }
       else
-       val = (char *) VALUE_CONTENTS (args[argnum]);
-
-      if (len >
-         (ARGLAST_REGNUM + 1 - argreg) * REGISTER_RAW_SIZE (ARG0_REGNUM)
-         || (len > wordsize && (len & stack_align) != 0))
-       {                       /* passed on the stack */
-         write_memory (sp + stack_offset, val,
-                       len < wordsize ? wordsize : len);
-         stack_offset += (len + stack_align) & ~stack_align;
-       }
-      /* NOTE WELL!!!!!  This is not an "else if" clause!!!
-         That's because some *&^%$ things get passed on the stack
-         AND in the registers!   */
-      if (len <=
-         (ARGLAST_REGNUM + 1 - argreg) * REGISTER_RAW_SIZE (ARG0_REGNUM))
-       while (len > 0)
-         {                     /* there's room in registers */
-           regval = extract_address (val, wordsize);
-           write_register (argreg, regval);
-           len -= wordsize;
-           val += wordsize;
-           argreg++;
-         }
+        {
+          /* It doesn't fit in registers!  Onto the stack it goes.  */
+          write_memory (sp + stack_offset, padded, padded_len);
+          stack_offset += padded_len;
+
+          /* Once one argument has spilled onto the stack, all
+             subsequent arguments go on the stack.  */
+          reg = E_ARGLAST_REGNUM + 1;
+        }
     }
+
   return sp;
 }
 
@@ -594,16 +722,11 @@ h8300_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
    empty CALL_DUMMY, ie. the target will not actually be executing
    a JSR/BSR instruction.  */
 
-CORE_ADDR
+static CORE_ADDR
 h8300_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
 {
   unsigned char buf[4];
-  int wordsize;
-
-  if (h8300hmode || h8300smode)
-    wordsize = 4;
-  else
-    wordsize = 2;
+  int wordsize = BINWORD;
 
   sp -= wordsize;
   store_unsigned_integer (buf, wordsize, CALL_DUMMY_ADDRESS ());
@@ -616,11 +739,10 @@ h8300_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
    was created.  Usually used either by the "RETURN" command, or by
    call_function_by_hand after the dummy_frame is finished. */
 
-void
+static void
 h8300_pop_frame (void)
 {
-  unsigned regnum;
-  struct frame_saved_regs fsr;
+  unsigned regno;
   struct frame_info *frame = get_current_frame ();
 
   if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
@@ -629,21 +751,20 @@ h8300_pop_frame (void)
     }
   else
     {
-      get_frame_saved_regs (frame, &fsr);
-
-      for (regnum = 0; regnum < 8; regnum++)
+      for (regno = 0; regno < 8; regno++)
        {
-         /* Don't forget SP_REGNUM is a frame_saved_regs struct is the
+         /* Don't forget E_SP_REGNUM is a frame_saved_regs struct is the
             actual value we want, not the address of the value we want.  */
-         if (fsr.regs[regnum] && regnum != SP_REGNUM)
-           write_register (regnum,
-                           read_memory_integer (fsr.regs[regnum], BINWORD));
-         else if (fsr.regs[regnum] && regnum == SP_REGNUM)
-           write_register (regnum, frame->frame + 2 * BINWORD);
+         if (frame->saved_regs[regno] && regno != E_SP_REGNUM)
+           write_register (regno,
+                           read_memory_integer (frame->saved_regs[regno],
+                                                BINWORD));
+         else if (frame->saved_regs[regno] && regno == E_SP_REGNUM)
+           write_register (regno, frame->frame + 2 * BINWORD);
        }
 
-      /* Don't forget the update the PC too!  */
-      write_pc (frame->from_pc);
+      /* Don't forget to update the PC too!  */
+      write_register (E_PC_REGNUM, frame->extra_info->from_pc);
     }
   flush_cached_frames ();
 }
@@ -652,17 +773,11 @@ h8300_pop_frame (void)
    Figure out where in REGBUF the called function has left its return value.
    Copy that into VALBUF.  Be sure to account for CPU type.   */
 
-void
+static void
 h8300_extract_return_value (struct type *type, char *regbuf, char *valbuf)
 {
-  int wordsize, len;
-
-  if (h8300smode || h8300hmode)
-    wordsize = 4;
-  else
-    wordsize = 2;
-
-  len = TYPE_LENGTH (type);
+  int wordsize = BINWORD;
+  int len = TYPE_LENGTH (type);
 
   switch (len)
     {
@@ -671,7 +786,7 @@ h8300_extract_return_value (struct type *type, char *regbuf, char *valbuf)
       memcpy (valbuf, regbuf + REGISTER_BYTE (0) + (wordsize - len), len);
       break;
     case 4:                    /* (long), (float) */
-      if (h8300smode || h8300hmode)
+      if (wordsize == 4)
        {
          memcpy (valbuf, regbuf + REGISTER_BYTE (0), 4);
        }
@@ -692,17 +807,13 @@ h8300_extract_return_value (struct type *type, char *regbuf, char *valbuf)
    Place the appropriate value in the appropriate registers.
    Primarily used by the RETURN command.  */
 
-void
+static void
 h8300_store_return_value (struct type *type, char *valbuf)
 {
-  int wordsize, len, regval;
-
-  if (h8300hmode || h8300smode)
-    wordsize = 4;
-  else
-    wordsize = 2;
+  int regval;
+  int wordsize = BINWORD;
+  int len = TYPE_LENGTH (type);
 
-  len = TYPE_LENGTH (type);
   switch (len)
     {
     case 1:                    /* char */
@@ -712,7 +823,7 @@ h8300_store_return_value (struct type *type, char *valbuf)
       break;
     case 4:                    /* long, float */
       regval = extract_address (valbuf, len);
-      if (h8300smode || h8300hmode)
+      if (wordsize == 4)
        {
          write_register (0, regval);
        }
@@ -728,112 +839,62 @@ h8300_store_return_value (struct type *type, char *valbuf)
     }
 }
 
-struct cmd_list_element *setmemorylist;
+static struct cmd_list_element *setmachinelist;
 
-static void
-set_register_names (void)
+static const char *
+h8300_register_name (int regno)
 {
-  if (h8300hmode != 0)
-    h8300_register_names = h8300h_register_names;
+  /* The register names change depending on whether the h8300h processor
+     type is selected. */
+  static char *h8300_register_names[] = {
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6",
+    "sp", "ccr","pc","cycles", "tick", "inst", ""
+  };
+  static char *h8300s_register_names[] = {
+    "er0", "er1", "er2", "er3", "er4", "er5", "er6",
+    "sp", "ccr", "pc", "cycles", "exr", "tick", "inst"
+  };
+  char **register_names =
+               h8300smode ? h8300s_register_names : h8300_register_names;
+  if (regno < 0 || regno >= E_NUM_REGS)
+    internal_error (__FILE__, __LINE__,
+                   "h8300_register_name: illegal register number %d", regno);
   else
-    h8300_register_names = original_register_names;
-}
-
-static void
-h8300_command (char *args, int from_tty)
-{
-  extern int h8300hmode;
-  h8300hmode = 0;
-  h8300smode = 0;
-  set_register_names ();
+    return register_names[regno];
 }
 
 static void
-h8300h_command (char *args, int from_tty)
+h8300_print_register (int regno)
 {
-  extern int h8300hmode;
-  h8300hmode = 1;
-  h8300smode = 0;
-  set_register_names ();
-}
-
-static void
-h8300s_command (char *args, int from_tty)
-{
-  extern int h8300smode;
-  extern int h8300hmode;
-  h8300smode = 1;
-  h8300hmode = 1;
-  set_register_names ();
-}
-
-static void
-set_machine (char *args, int from_tty)
-{
-  printf_unfiltered ("\"set machine\" must be followed by h8300, h8300h");
-  printf_unfiltered ("or h8300s");
-  help_list (setmemorylist, "set memory ", -1, gdb_stdout);
-}
+  long val = read_register (regno);
+  const char *name = h8300_register_name (regno);
 
-/* set_machine_hook is called as the exec file is being opened, but
-   before the symbol file is opened.  This allows us to set the
-   h8300hmode flag based on the machine type specified in the exec
-   file.  This in turn will cause subsequently defined pointer types
-   to be 16 or 32 bits as appropriate for the machine.  */
+  if (!name || !*name)
+    return;
 
-static void
-set_machine_hook (char *filename)
-{
-  if (bfd_get_mach (exec_bfd) == bfd_mach_h8300s)
-    {
-      h8300smode = 1;
-      h8300hmode = 1;
-    }
-  else if (bfd_get_mach (exec_bfd) == bfd_mach_h8300h)
+  printf_filtered ("%-14s ", name);
+  if (h8300hmode)
     {
-      h8300smode = 0;
-      h8300hmode = 1;
+      if (val)
+       printf_filtered ("0x%08lx   %-8ld", val, val);
+      else
+       printf_filtered ("0x%-8lx   %-8ld", val, val);
     }
   else
     {
-      h8300smode = 0;
-      h8300hmode = 0;
+      if (val)
+       printf_filtered ("0x%04lx   %-4ld", val, val);
+      else
+       printf_filtered ("0x%-4lx   %-4ld", val, val);
     }
-  set_register_names ();
-}
-
-void
-_initialize_h8300m (void)
-{
-  add_prefix_cmd ("machine", no_class, set_machine,
-                 "set the machine type",
-                 &setmemorylist, "set machine ", 0, &setlist);
-
-  add_cmd ("h8300", class_support, h8300_command,
-          "Set machine to be H8/300.", &setmemorylist);
-
-  add_cmd ("h8300h", class_support, h8300h_command,
-          "Set machine to be H8/300H.", &setmemorylist);
-
-  add_cmd ("h8300s", class_support, h8300s_command,
-          "Set machine to be H8/300S.", &setmemorylist);
-
-  /* Add a hook to set the machine type when we're loading a file. */
-
-  specify_exec_file_hook (set_machine_hook);
-}
-
-void
-h8300_print_register_hook (int regno)
-{
-  if (regno == CCR_REGNUM)
+  if (regno == E_CCR_REGNUM)
     {
       /* CCR register */
       int C, Z, N, V;
-      unsigned char b[REGISTER_SIZE];
+      unsigned char b[h8300h_reg_size];
       unsigned char l;
       frame_register_read (selected_frame, regno, b);
-      l = b[REGISTER_VIRTUAL_SIZE (CCR_REGNUM) - 1];
+      l = b[REGISTER_VIRTUAL_SIZE (E_CCR_REGNUM) - 1];
       printf_unfiltered ("\t");
       printf_unfiltered ("I-%d ", (l & 0x80) != 0);
       printf_unfiltered ("UI-%d ", (l & 0x40) != 0);
@@ -868,24 +929,243 @@ h8300_print_register_hook (int regno)
       if ((Z | (N ^ V)) == 1)
        printf_unfiltered ("<= ");
     }
-
-  if (regno == EXR_REGNUM && h8300smode)
+  else if (regno == E_EXR_REGNUM && h8300smode)
     {
       /* EXR register */
-      unsigned char b[REGISTER_SIZE];
+      unsigned char b[h8300h_reg_size];
       unsigned char l;
       frame_register_read (selected_frame, regno, b);
-      l = b[REGISTER_VIRTUAL_SIZE (EXR_REGNUM) - 1];
+      l = b[REGISTER_VIRTUAL_SIZE (E_EXR_REGNUM) - 1];
       printf_unfiltered ("\t");
       printf_unfiltered ("T-%d - - - ", (l & 0x80) != 0);
       printf_unfiltered ("I2-%d ", (l & 4) != 0);
       printf_unfiltered ("I1-%d ", (l & 2) != 0);
       printf_unfiltered ("I0-%d", (l & 1) != 0);
     }
+  printf_filtered ("\n");
+}
+
+static void
+h8300_do_registers_info (int regno, int cpregs)
+{
+  if (regno < 0)
+    for (regno = 0; regno < E_NUM_REGS; ++regno)
+      h8300_print_register (regno);
+  else
+    h8300_print_register (regno);
+}
+
+static CORE_ADDR
+h8300_saved_pc_after_call (struct frame_info *ignore)
+{
+  return read_memory_unsigned_integer (read_register (E_SP_REGNUM), BINWORD);
+}
+
+static int
+h8300_register_byte (int regno)
+{
+  if (regno < 0 || regno >= E_NUM_REGS)
+    internal_error (__FILE__, __LINE__,
+                   "h8300_register_byte: illegal register number %d", regno);
+  else
+    return regno * BINWORD;
+}
+
+static int
+h8300_register_raw_size (int regno)
+{
+  if (regno < 0 || regno >= E_NUM_REGS)
+    internal_error (__FILE__, __LINE__,
+                   "h8300_register_raw_size: illegal register number %d",
+                   regno);
+  else
+    return BINWORD;
+}
+
+static struct type *
+h8300_register_virtual_type (int regno)
+{
+  if (regno < 0 || regno >= E_NUM_REGS)
+    internal_error (__FILE__, __LINE__,
+                   "h8300_register_virtual_type: illegal register number %d",
+                   regno);
+  else
+    return h8300hmode ?
+          builtin_type_unsigned_long : builtin_type_unsigned_short;
+}
+
+static void
+h8300_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{ 
+  write_register (0, addr);
+}
+
+static int
+h8300_use_struct_convention (int gcc_p, struct type *type)
+{
+  return 1;
+}
+
+static CORE_ADDR
+h8300_extract_struct_value_address (char *regbuf)
+{
+  return extract_address (regbuf + h8300_register_byte (E_ARG0_REGNUM),
+                         h8300_register_raw_size (E_ARG0_REGNUM));
+}
+
+const static unsigned char *
+h8300_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+  /*static unsigned char breakpoint[] = { 0x7A, 0xFF };*/      /* ??? */
+  static unsigned char breakpoint[] = { 0x01, 0x80 };          /* Sleep */
+
+  *lenptr = sizeof (breakpoint);
+  return breakpoint;
+}
+
+static void
+h8300_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+                       struct frame_info *frame, const char *args)
+{
+  fprintf_filtered (file, "\
+No floating-point info available for this processor.\n");
+}
+
+static struct gdbarch *
+h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  static LONGEST call_dummy_words[1] = { 0 };
+  struct gdbarch_tdep *tdep = NULL;
+  struct gdbarch *gdbarch;
+
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
+
+#if 0
+  tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+#endif
+
+  if (info.bfd_arch_info->arch != bfd_arch_h8300)
+    return NULL;
+
+  switch (info.bfd_arch_info->mach)
+    {
+      case bfd_mach_h8300:
+       h8300smode = 0;
+       h8300hmode = 0;
+       break;
+      case bfd_mach_h8300h:
+       h8300smode = 0;
+       h8300hmode = 1;
+       break;
+      case bfd_mach_h8300s:
+       h8300smode = 1;
+       h8300hmode = 1;
+       break;
+    }
+
+  gdbarch = gdbarch_alloc (&info, 0);
+
+  /*
+   * Basic register fields and methods.
+   */
+
+  set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
+  set_gdbarch_num_pseudo_regs (gdbarch, 0);
+  set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
+  set_gdbarch_fp_regnum (gdbarch, E_FP_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
+  set_gdbarch_register_name (gdbarch, h8300_register_name);
+  set_gdbarch_register_size (gdbarch, BINWORD);
+  set_gdbarch_register_bytes (gdbarch, E_NUM_REGS * BINWORD);
+  set_gdbarch_register_byte (gdbarch, h8300_register_byte);
+  set_gdbarch_register_raw_size (gdbarch, h8300_register_raw_size);
+  set_gdbarch_max_register_raw_size (gdbarch, h8300h_reg_size);
+  set_gdbarch_register_virtual_size (gdbarch, h8300_register_raw_size);
+  set_gdbarch_max_register_virtual_size (gdbarch, h8300h_reg_size);
+  set_gdbarch_register_virtual_type (gdbarch, h8300_register_virtual_type);
+  set_gdbarch_do_registers_info (gdbarch, h8300_do_registers_info);
+  set_gdbarch_print_float_info (gdbarch, h8300_print_float_info);
+
+  /*
+   * Frame Info
+   */
+  set_gdbarch_init_extra_frame_info (gdbarch, h8300_init_extra_frame_info);
+  set_gdbarch_frame_init_saved_regs (gdbarch, h8300_frame_init_saved_regs);
+  set_gdbarch_frame_chain (gdbarch, h8300_frame_chain);
+  set_gdbarch_get_saved_register (gdbarch, generic_unwind_get_saved_register);
+  set_gdbarch_saved_pc_after_call (gdbarch, h8300_saved_pc_after_call);
+  set_gdbarch_frame_saved_pc (gdbarch, h8300_frame_saved_pc);
+  set_gdbarch_skip_prologue (gdbarch, h8300_skip_prologue);
+  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+  set_gdbarch_frame_args_address (gdbarch, h8300_frame_args_address);
+  set_gdbarch_frame_locals_address (gdbarch, h8300_frame_locals_address);
+
+  /* 
+   * Miscelany
+   */
+  /* Stack grows up. */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  /* PC stops zero byte after a trap instruction
+     (which means: exactly on trap instruction). */
+  set_gdbarch_decr_pc_after_break (gdbarch, 0);
+  /* This value is almost never non-zero... */
+  set_gdbarch_function_start_offset (gdbarch, 0);
+  /* This value is almost never non-zero... */
+  set_gdbarch_frame_args_skip (gdbarch, 0);
+  /* OK to default this value to 'unknown'. */
+  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+  set_gdbarch_frameless_function_invocation (gdbarch,
+                                            frameless_look_for_prologue);
+
+  /* W/o prototype, coerce float args to double. */
+  //set_gdbarch_coerce_float_to_double (gdbarch, standard_coerce_float_to_double);
+
+  /*
+   * Call Dummies
+   * 
+   * These values and methods are used when gdb calls a target function.  */
+  set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
+  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+  set_gdbarch_push_return_address (gdbarch, h8300_push_return_address);
+  set_gdbarch_deprecated_extract_return_value (gdbarch, h8300_extract_return_value);
+  set_gdbarch_push_arguments (gdbarch, h8300_push_arguments);
+  set_gdbarch_pop_frame (gdbarch, h8300_pop_frame);
+  set_gdbarch_store_struct_return (gdbarch, h8300_store_struct_return);
+  set_gdbarch_deprecated_store_return_value (gdbarch, h8300_store_return_value);
+  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, h8300_extract_struct_value_address);
+  set_gdbarch_use_struct_convention (gdbarch, h8300_use_struct_convention);
+  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+  set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
+  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+  set_gdbarch_call_dummy_length (gdbarch, 0);
+  set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
+  set_gdbarch_call_dummy_p (gdbarch, 1);
+  set_gdbarch_call_dummy_words (gdbarch, call_dummy_words);
+  set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  /* set_gdbarch_call_dummy_stack_adjust */
+  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+  set_gdbarch_breakpoint_from_pc (gdbarch, h8300_breakpoint_from_pc);
+
+  set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+  set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_ptr_bit (gdbarch, BINWORD * TARGET_CHAR_BIT);
+  set_gdbarch_addr_bit (gdbarch, BINWORD * TARGET_CHAR_BIT);
+
+  //set_gdbarch_stack_align (gdbarch, SOME_stack_align);
+  set_gdbarch_extra_stack_alignment_needed (gdbarch, 0);
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+  return gdbarch;
 }
 
 void
 _initialize_h8300_tdep (void)
 {
   tm_print_insn = gdb_print_insn_h8300;
+  register_gdbarch_init (bfd_arch_h8300, h8300_gdbarch_init);
 }
index 4a2b088c508637a411a5477a89a6c2b0bbf645ef..438d6c6d6c7d97435576573f1770141d8b14bd08 100644 (file)
@@ -64,9 +64,9 @@ hms_supply_register (char *regname, int regnamelen, char *val, int vallen)
  * registers either. So, typing "info reg sp" becomes a "r30".
  */
 
-static char *hms_regnames[NUM_REGS] =
+static char *hms_regnames[] =
 {
-  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC"
+  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC", "", "", "", ""
 };
 
 /*