diff options
author | Steve Chamberlain <sac@cygnus> | 1993-04-27 01:17:32 +0000 |
---|---|---|
committer | Steve Chamberlain <sac@cygnus> | 1993-04-27 01:17:32 +0000 |
commit | 9faacb925f0b526a5c79c886c711f2826e1ecbb7 (patch) | |
tree | 06caa461dc95129a7b0918846d05c7bfbba0278b /gdb | |
parent | ed173a7696deb9417b59db73e105bfae8a17ab7a (diff) | |
download | ppe42-binutils-9faacb925f0b526a5c79c886c711f2826e1ecbb7.tar.gz ppe42-binutils-9faacb925f0b526a5c79c886c711f2826e1ecbb7.zip |
Support for Hitachi SH
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/.Sanitize | 1 | ||||
-rw-r--r-- | gdb/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/config/.Sanitize | 1 | ||||
-rw-r--r-- | gdb/config/sh/.Sanitize | 29 | ||||
-rw-r--r-- | gdb/config/sh/sh.mt | 3 | ||||
-rw-r--r-- | gdb/config/sh/tm-sh.h | 239 | ||||
-rw-r--r-- | gdb/configure.in | 2 | ||||
-rw-r--r-- | gdb/sh-tdep.c | 242 |
8 files changed, 521 insertions, 0 deletions
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 <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 ())); +} |