diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2002-09-16 15:03:17 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2002-09-16 15:03:17 +0000 |
commit | 928e48af4f1074d16dcbb8b8f8d4a6800813ca02 (patch) | |
tree | 44e6c18ecefc5ce1059150df0448f901a348e2ce | |
parent | 4d1310b4a5c5a9a63b8bcf46dfe5ec34c933b340 (diff) | |
download | gdb-928e48af4f1074d16dcbb8b8f8d4a6800813ca02.zip gdb-928e48af4f1074d16dcbb8b8f8d4a6800813ca02.tar.gz gdb-928e48af4f1074d16dcbb8b8f8d4a6800813ca02.tar.bz2 |
* 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
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/config/h8300/tm-h8300.h | 287 | ||||
-rw-r--r-- | gdb/h8300-tdep.c | 1046 | ||||
-rw-r--r-- | gdb/remote-hms.c | 4 |
4 files changed, 683 insertions, 666 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d35dd41..a41708a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. diff --git a/gdb/config/h8300/tm-h8300.h b/gdb/config/h8300/tm-h8300.h index 3020e4d..4e60057 100644 --- a/gdb/config/h8300/tm-h8300.h +++ b/gdb/config/h8300/tm-h8300.h @@ -18,17 +18,9 @@ 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 *); - - -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) diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c index f992d4b..cd62799 100644 --- a/gdb/h8300-tdep.c +++ b/gdb/h8300-tdep.c @@ -26,20 +26,50 @@ */ #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); } diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c index 4a2b088..438d6c6 100644 --- a/gdb/remote-hms.c +++ b/gdb/remote-hms.c @@ -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", "", "", "", "" }; /* |