Support for Hitachi SH
authorSteve Chamberlain <sac@cygnus>
Tue, 27 Apr 1993 01:17:32 +0000 (01:17 +0000)
committerSteve Chamberlain <sac@cygnus>
Tue, 27 Apr 1993 01:17:32 +0000 (01:17 +0000)
13 files changed:
bfd/.Sanitize
bfd/ChangeLog
bfd/Makefile.in
bfd/coffcode.h
bfd/configure.in
gdb/.Sanitize
gdb/ChangeLog
gdb/config/.Sanitize
gdb/config/sh/.Sanitize [new file with mode: 0644]
gdb/config/sh/sh.mt [new file with mode: 0644]
gdb/config/sh/tm-sh.h [new file with mode: 0644]
gdb/configure.in
gdb/sh-tdep.c [new file with mode: 0644]

index 6a1eb5c6a5ca66d36b06f78b0ee7f8161984fb91..2a5001b82c979250b25dc26bf4680555e35dfead 100644 (file)
@@ -55,6 +55,7 @@ coff-m88k.c
 coff-mips.c
 coff-msym.c
 coff-rs6000.c
+coff-sh.c
 coff-we32k.c
 coff-z8k.c
 coffcode.h
@@ -97,6 +98,7 @@ cpu-hppa.c
 cpu-i960.c
 cpu-m88k.c
 cpu-rs6000.c
+cpu-sh.c
 cpu-we32k.c
 cpu-z8k.c
 hp300bsd.c
index 0d9977b538b6521a239131ad14ee6bee9decb2fd..5cf6bf20c2a2e209e7b7dd07f679ce350f685645 100644 (file)
@@ -1,3 +1,8 @@
+Mon Apr 26 13:24:43 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * Makefile.in, archures.c, coffcode.h, targets.c: Support for
+       Hitachi SH.
+
 Mon Apr 26 13:55:42 1993  Jim Kingdon  (kingdon@cygnus.com)
 
        * trad-core.c (trad_unix_core_file_p): Check the file size.
index ab0bdaa38e93db98da5d21429dd57d76e88cdc09..809935ade2347c7bfbf21eead8959a96b36498b2 100644 (file)
@@ -75,7 +75,7 @@ BFD_LIBS = libbfd.o opncls.o bfd.o archive.o targets.o cache.o \
 
 BFD_MACHINES = cpu-h8300.o cpu-i960.o cpu-sparc.o cpu-m68k.o cpu-m88k.o \
        cpu-vax.o cpu-mips.o cpu-a29k.o cpu-i386.o cpu-rs6000.o cpu-hppa.o \
-       cpu-z8k.o cpu-we32k.o cpu-h8500.o
+       cpu-z8k.o cpu-we32k.o cpu-h8500.o cpu-alpha.o cpu-sh.o
 
 BFD_BACKENDS = aout32.o sunos.o newsos3.o mipsbsd.o aout-adobe.o \
        i386aout.o i386bsd.o i386linux.o \
@@ -85,7 +85,7 @@ BFD_BACKENDS = aout32.o sunos.o newsos3.o mipsbsd.o aout-adobe.o \
        coff-mips.o coff-msym.o \
        elf32.o elf32-sparc.o elf32-i386.o elf32-i860.o elf32-m68k.o \
        bout.o \
-       hppa.o oasys.o ieee.o srec.o stab-syms.o
+       hppa.o oasys.o ieee.o srec.o stab-syms.o coff-alpha.o coff-sh.o
 
 OPTIONAL_BACKENDS = trad-core.o
 
@@ -124,7 +124,8 @@ CFILES = libbfd.c opncls.c bfd.c archive.c targets.c cache.c \
         cpu-m88k.c cpu-vax.c cpu-mips.c cpu-a29k.c cpu-i386.c \
         cpu-rs6000.c coff-h8300.c hppa.c cpu-hppa.c cpu-we32k.c reloc16.c \
         mipsbsd.c \
-        elf32.c elf32-sparc.c elf32-i386.c elf32-i860.c elf32-m68k.c
+        elf32.c elf32-sparc.c elf32-i386.c elf32-i860.c elf32-m68k.c \
+        coff-alpha.c cpu-alpha.c
 
 STAGESTUFF = $(TARGETLIB) $(OFILES)
 
@@ -138,7 +139,7 @@ check:
 installcheck:
 
 info dvi : force
-       @$(MAKE) subdir_do DO=info "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+       @$(MAKE) subdir_do DO=$@ "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
 
 clean-info:
        @$(MAKE) subdir_do DO=clean-info "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
@@ -325,7 +326,8 @@ bfd.ps:
 
 libbfd.o : libbfd.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h 
 opncls.o : opncls.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h 
-bfd.o : bfd.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h 
+bfd.o : bfd.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h \
+  $(INCDIR)/coff/sym.h libecoff.h
 archive.o : archive.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h \
   $(INCDIR)/aout/ar.h $(INCDIR)/aout/ranlib.h 
 targets.o : targets.c $(INCDIR)/bfd.h $(INCDIR)/obstack.h libbfd.h 
index ad89efe44712ef36dd48f9eab2cd1cc7749c2e70..1913e3573efa0df10790e6fe92ba33fb7c7a2124 100644 (file)
@@ -342,7 +342,7 @@ DEFUN(sec_to_styp_flags, (sec_name, sec_flags),
   }
   else if (!strcmp (sec_name, _LIT))
   {
-    stype_flags = STYP_LIT;
+    styp_flags = STYP_LIT;
 #endif /* _LIT */
 
   }
@@ -921,6 +921,13 @@ DEFUN (coff_set_arch_mach_hook, (abfd, filehdr),
     break;
 #endif
 
+#ifdef SHMAGIC
+  case SHMAGIC:
+    arch = bfd_arch_sh;
+    machine = 0;
+    break;
+#endif
+
 #ifdef H8500MAGIC
   case H8500MAGIC:
     arch = bfd_arch_h8500;
@@ -1117,6 +1124,14 @@ DEFUN(coff_set_flags,(abfd, magicp, flagsp),
       return true;
       break;
 #endif
+
+#ifdef SHMAGIC
+  case bfd_arch_sh:
+      *magicp = SHMAGIC;
+      return true;
+      break;
+#endif
+
 #ifdef H8500MAGIC
     case bfd_arch_h8500:
       *magicp = H8500MAGIC;
index 88d66924088aae39fb050bd4823a524a1a9cd1eb..3270999293deb0f0b47dacf38dc4495c1df4c109 100644 (file)
@@ -34,12 +34,15 @@ fi
 #  convention, else the table becomes a real mess to understand and maintain.
 
 case "${target}" in
+  alpha-*-*)           bfd_target=alphaosf ;;
   a29k-*-ebmon)                bfd_target=a29k-coff ;;
   a29k-*-udi)          bfd_target=a29k-coff ;;
   a29k-*-aout)         bfd_target=a29k-aout ;;
   a29k-*-coff)         bfd_target=a29k-coff ;;
   a29k-*-sym1)         bfd_target=a29k-coff ;;
   h8300-*-*)           bfd_target=h8300-coff ;;
+  h8500-*-*)           bfd_target=h8500-coff ;;
+  sh-*-*)              bfd_target=sh-coff ;;
   hppa*-*-bsd)         bfd_target=hppabsd ;;
   hppa*-*-hpux)                bfd_target=hppahpux ;;
   i[34]86-*-sysv4*)    bfd_target=i386-elf ;;
@@ -63,10 +66,11 @@ case "${target}" in
   m68*-ericsson-*)     bfd_target=m68k-aout ;;
   m68*-netx-*)         bfd_target=m68k-aout ;;
   m88k-*-*)            bfd_target=m88k-coff ;;
-  mips-big-*)          bfd_target=irix3 ;;
+  mips-big-*)          bfd_target=bigmips ;;
   mips-dec-bsd*)        bfd_target=mipsdecbsd ;;
   mips-dec-*)          bfd_target=decstation ;;
-  mips-sgi-*)          bfd_target=irix3 ;;
+  mips-*-ecoff)                bfd_target=bigmips ;;
+  mips-sgi-*)          bfd_target=bigmips ;;
   rs6000-*-*)          bfd_target=rs6000 ;;
   sparc-*-solaris2*)   bfd_target=sparc-elf ;;
   sparc-*-sysv4*)      bfd_target=sparc-elf ;;
index 0a7bd4db260044a97c538149f7485e2b78d1f09d..e0e5d8269dbc92ea700e2a49f912bec62f8ca505 100644 (file)
@@ -192,6 +192,7 @@ ser-go32.c
 ser-unix.c
 serial.c
 serial.h
+sh-tdep.c
 signals.h
 solib.c
 solib.h
index adad3030d838c099fa271623e923592ad88486ef..72aaefebf1aef179a52757c087387964defe6cc6 100644 (file)
@@ -1,3 +1,7 @@
+Mon Apr 26 17:59:38 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * config/sh/sh.mt, config/sh/tm-sh.h, sh-tdep.c: New files.
+
 Mon Apr 26 07:13:32 1993  Jim Kingdon  (kingdon@cygnus.com)
 
        * rs6000-tdep.c (branch_dest): Deal with stepping through system call.
index e19895a5478e557e85f2e31acfd1b1bfffbca782..7ce85e8e9657ff8e01a866b3927bce64424ccc4d 100644 (file)
@@ -40,6 +40,7 @@ pa
 pyr
 romp
 rs6000
+sh
 sparc
 tahoe
 tm-sunos.h
diff --git a/gdb/config/sh/.Sanitize b/gdb/config/sh/.Sanitize
new file mode 100644 (file)
index 0000000..8cf9167
--- /dev/null
@@ -0,0 +1,29 @@
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+sh.mt
+tm-sh.h
+
+Do-last:
+
+# End of file.
diff --git a/gdb/config/sh/sh.mt b/gdb/config/sh/sh.mt
new file mode 100644 (file)
index 0000000..7851338
--- /dev/null
@@ -0,0 +1,3 @@
+# Target: Hitachi Super-H ICE and simulator
+TDEPFILES= exec.o sh-tdep.o remote-sim.o ../sim/sh/interp.o ../sim/sh/table.o
+TM_FILE= tm-sh.h
diff --git a/gdb/config/sh/tm-sh.h b/gdb/config/sh/tm-sh.h
new file mode 100644 (file)
index 0000000..af2a023
--- /dev/null
@@ -0,0 +1,239 @@
+/* Parameters for execution on a Hitachi Super-H machine.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Contributed by Steve Chamberlain sac@cygnus.com */
+
+#define GDB_TARGET_IS_SH
+
+#define IEEE_FLOAT 1
+
+/* 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
+
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+extern CORE_ADDR sh_skip_prologue ();
+#define SKIP_PROLOGUE(ip) \
+    {(ip) = sh_skip_prologue(ip);}
+
+
+/* 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. 
+
+   The return address is the value saved in the PR register + 4  */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+  (ADDR_BITS_REMOVE(read_register(PR_REGNUM))+4)
+
+/* Stack grows downward.  */
+
+#define INNER_THAN <
+
+/* Illegal instruction - used by the simulator for breakpoint
+   detection */
+
+#define BREAKPOINT {0xc3, 0xff}  /* 0xc3ff is trapa #ff */
+
+
+/* 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
+
+/* Nonzero if instruction at PC is a return instruction.  */
+#define ABOUT_TO_RETURN(pc) (read_memory_integer(pc,2) == 0x000b)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Say how long registers are.  */
+#define REGISTER_TYPE  long
+
+/* Say how much memory is needed to store a copy of the register set */
+#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.  */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* 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
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO)  \
+       { memcpy ((TO), (FROM), 4); }
+
+/* Convert data from virtual format for register REGNUM
+   to raw format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO)   \
+       { memcpy ((TO), (FROM), 4); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* 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", "r7", \
+   "r8", "r9", "r10","r11","r12","r13","r14","r15",\
+   "pc", "pr","gbr","vbr","mach","macl","sr","ticks","cycles","insts"     }
+
+#define NUM_REGS 25
+
+/* 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 FP_REGNUM      14
+#define SP_REGNUM      15
+#define PC_REGNUM      16
+#define PR_REGNUM      17
+#define GBR_REGNUM     18
+#define VBR_REGNUM     19
+#define MACH_REGNUM    20
+#define MACL_REGNUM    21
+#define CR_REGNUM      22
+
+/* 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 R4 */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+    { write_register (4, (ADDR));  }
+
+/* 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.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy ((char *)(REGBUF), VALBUF, TYPE_LENGTH(TYPE))
+
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  
+
+   Things always get returned in R4/R5 */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+  write_register_bytes (REGISTER_BYTE(4), 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 \
+    CORE_ADDR return_pc;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+    init_extra_frame_info(fromleaf, 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) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+CORE_ADDR h8500_frame_chain (/* FRAME thisframe */);
+
+#define FRAME_CHAIN(FRAME)       sh_frame_chain(FRAME)
+#define FRAME_SAVED_PC(FRAME)    ((FRAME)->return_pc)
+#define FRAME_ARGS_ADDRESS(fi)   (fi)->frame
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->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(val,fi) (val = -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)        \
+   frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+#define NAMES_HAVE_UNDERSCORE
+
+typedef unsigned short INSN_WORD;
+
+#define ADDR_BITS_REMOVE(addr) ((addr) & 0xfffff)
+#define ADDR_BITS_SET(addr)    (addr)
+
+#define CALL_DUMMY_LENGTH 10
+
+/* Discard from the stack the innermost frame,
+   restoring all saved registers.  */
+
+#define POP_FRAME pop_frame();
+
index db75a4f45c7cf1c7d4db7af9faf417e06aafb36f..831afcb020c456320d8265cad7d95079e11f0bbb 100644 (file)
@@ -152,6 +152,8 @@ c2-*-*)                     gdb_target=convex ;;
 h8300-*-*)             gdb_target=h8300hms ;;
 h8500-*-*)             gdb_target=h8500hms ;;
 
+sh-*-*)                        gdb_target=sh ;;
+
 hppa*-*-bsd)           gdb_target=hppabsd ;;
 hppa*-*-hpux)          gdb_target=hppahpux ;;
 
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
new file mode 100644 (file)
index 0000000..74e746d
--- /dev/null
@@ -0,0 +1,242 @@
+/* Target-machine dependent code for Hitachi Super-H, for GDB.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ Contributed by Steve Chamberlain
+                sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "dis-asm.h"
+#include "../opcodes/sh-opc.h"
+
+
+/* Prologue looks like
+   [mov.l      <regs>,@-r15]...
+   [sts.l      pr,@-r15]
+   [mov.l      r14,@-r15]
+   [mov                r15,r14]
+*/
+
+#define IS_STS(x)              ((x) == 0x4f22)
+#define IS_PUSH(x)             (((x) & 0xff0f) == 0x2f06)
+#define GET_PUSHED_REG(x)      (((x) >> 4) & 0xf)
+#define IS_MOV_SP_FP(x)        ((x) == 0x6ef3)
+#define IS_ADD_SP(x)           (((x) & 0xff00) == 0x7f00)
+
+
+/* Skip any prologue before the guts of a function */
+
+CORE_ADDR
+sh_skip_prologue (start_pc)
+     CORE_ADDR start_pc;
+
+{
+  int w;
+
+  w = read_memory_integer (start_pc, 2);
+  while (IS_STS (w)
+        || IS_PUSH (w)
+        || IS_MOV_SP_FP (w))
+    {
+      start_pc += 2;
+      w = read_memory_integer (start_pc, 2);
+    }
+
+  return start_pc;
+}
+
+/* Disassemble an instruction */
+
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  disassemble_info info;
+  GDB_INIT_DISASSEMBLE_INFO (info, stream);
+  return print_insn_sh (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.  */
+
+FRAME_ADDR
+sh_frame_chain (thisframe)
+     FRAME thisframe;
+{
+  if (!inside_entry_file (thisframe->pc))
+    return (read_memory_integer (FRAME_FP (thisframe), 4));
+  else
+    return 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. */
+
+
+void
+frame_find_saved_regs (fi, fsr)
+     struct frame_info *fi;
+     struct frame_saved_regs *fsr;
+{
+  int where[16];
+  int rn;
+  int have_fp = 0;
+  int depth;
+  int pc;
+  int opc;
+  int insn;
+
+  opc = pc = get_pc_function_start (fi->pc);
+
+  insn = read_memory_integer (pc, 2);
+
+  for (rn = 0; rn < NUM_REGS; rn++)
+    where[rn] = -1;
+
+  depth = 0;
+
+  /* Loop around examining the prologue insns, but give up
+     after 15 of them, since we're getting silly then */
+  while (pc < opc + 15 * 2)
+    {
+      /* See where the registers will be saved to */
+      if (IS_PUSH (insn))
+       {
+         pc += 2;
+         rn = GET_PUSHED_REG (insn);
+         where[rn] = depth;
+         insn = read_memory_integer (pc, 2);
+         depth += 4;
+       }
+      else if (IS_STS (insn))
+       {
+         pc += 2;
+         where[PR_REGNUM] = depth;
+         insn = read_memory_integer (pc, 2);
+         depth += 4;
+       }
+      else if (IS_ADD_SP (insn))
+       {
+         pc += 2;
+         depth += -((char) (insn & 0xff));
+         insn = read_memory_integer (pc, 2);
+       }
+      else break;
+    }
+
+  /* Now we know how deep things are, we can work out their addresses */
+
+  for (rn = 0; rn < NUM_REGS; rn++)
+    {
+      if (where[rn] >= 0)
+       {
+         if (rn == FP_REGNUM)
+           have_fp = 1;
+
+         fsr->regs[rn] = fi->frame - where[rn] + depth - 4;
+       }
+      else
+       {
+         fsr->regs[rn] = 0;
+       }
+    }
+
+  if (have_fp)
+    {
+
+      fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[FP_REGNUM], 4);
+    }
+  else
+    {
+      fsr->regs[SP_REGNUM] = fi->frame - 4;
+    }
+
+  /* Remember the address of the frame pointer */
+
+  /* Work out the return pc - either from the saved pr or the pr
+     value */
+
+  if (fsr->regs[PR_REGNUM])
+    {
+      fi->return_pc = read_memory_integer (fsr->regs[PR_REGNUM], 4) + 4;
+    }
+  else
+    {
+      fi->return_pc = read_register (PR_REGNUM) + 4;
+    }
+}
+
+/* initialize the extra info saved in a FRAME */
+
+void
+init_extra_frame_info (fromleaf, fi)
+     int fromleaf;
+     struct frame_info *fi;
+{
+  struct frame_saved_regs dummy;
+  frame_find_saved_regs (fi, &dummy);
+}
+
+
+/* Discard from the stack the innermost frame,
+   restoring all saved registers.  */
+
+void
+pop_frame ()
+{
+  register FRAME frame = get_current_frame ();
+  register CORE_ADDR fp;
+  register int regnum;
+  struct frame_saved_regs fsr;
+  struct frame_info *fi;
+
+  fi = get_frame_info (frame);
+  fp = fi->frame;
+  get_frame_saved_regs (fi, &fsr);
+
+  /* Copy regs from where they were saved in the frame */
+  for (regnum = 0; regnum < NUM_REGS; regnum++)
+    {
+      if (fsr.regs[regnum])
+       {
+         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+       }
+    }
+
+  write_register (PC_REGNUM, fi->return_pc);
+  write_register (SP_REGNUM, fp + 4);
+  flush_cached_frames ();
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),
+                                      read_pc ()));
+}