From 9faacb925f0b526a5c79c886c711f2826e1ecbb7 Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Tue, 27 Apr 1993 01:17:32 +0000 Subject: [PATCH] Support for Hitachi SH --- bfd/.Sanitize | 2 + bfd/ChangeLog | 5 + bfd/Makefile.in | 12 +- bfd/coffcode.h | 17 ++- bfd/configure.in | 8 +- gdb/.Sanitize | 1 + gdb/ChangeLog | 4 + gdb/config/.Sanitize | 1 + gdb/config/sh/.Sanitize | 29 +++++ gdb/config/sh/sh.mt | 3 + gdb/config/sh/tm-sh.h | 239 +++++++++++++++++++++++++++++++++++++++ gdb/configure.in | 2 + gdb/sh-tdep.c | 242 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 557 insertions(+), 8 deletions(-) create mode 100644 gdb/config/sh/.Sanitize create mode 100644 gdb/config/sh/sh.mt create mode 100644 gdb/config/sh/tm-sh.h create mode 100644 gdb/sh-tdep.c diff --git a/bfd/.Sanitize b/bfd/.Sanitize index 6a1eb5c6a5..2a5001b82c 100644 --- a/bfd/.Sanitize +++ b/bfd/.Sanitize @@ -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 diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0d9977b538..5cf6bf20c2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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. diff --git a/bfd/Makefile.in b/bfd/Makefile.in index ab0bdaa38e..809935ade2 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -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 diff --git a/bfd/coffcode.h b/bfd/coffcode.h index ad89efe447..1913e3573e 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -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; diff --git a/bfd/configure.in b/bfd/configure.in index 88d6692408..3270999293 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -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 ;; diff --git a/gdb/.Sanitize b/gdb/.Sanitize index 0a7bd4db26..e0e5d8269d 100644 --- a/gdb/.Sanitize +++ b/gdb/.Sanitize @@ -192,6 +192,7 @@ ser-go32.c ser-unix.c serial.c serial.h +sh-tdep.c signals.h solib.c solib.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index adad3030d8..72aaefebf1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. diff --git a/gdb/config/.Sanitize b/gdb/config/.Sanitize index e19895a547..7ce85e8e96 100644 --- a/gdb/config/.Sanitize +++ b/gdb/config/.Sanitize @@ -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 index 0000000000..8cf9167183 --- /dev/null +++ b/gdb/config/sh/.Sanitize @@ -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 index 0000000000..7851338f09 --- /dev/null +++ b/gdb/config/sh/sh.mt @@ -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 index 0000000000..af2a0236a2 --- /dev/null +++ b/gdb/config/sh/tm-sh.h @@ -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)) + + +/* 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(); + diff --git a/gdb/configure.in b/gdb/configure.in index db75a4f45c..831afcb020 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -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 index 0000000000..74e746d9e1 --- /dev/null +++ b/gdb/sh-tdep.c @@ -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 ,@-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 ())); +}