diff options
Diffstat (limited to 'gdb/v850-tdep.c')
-rw-r--r-- | gdb/v850-tdep.c | 204 |
1 files changed, 177 insertions, 27 deletions
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index 7363fc2..7e6b431 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -1,6 +1,5 @@ /* Target-dependent code for the NEC V850 for GDB, the GNU debugger. - Copyright 1986, 1996 - Free Software Foundation, Inc. + Copyright 1996, Free Software Foundation, Inc. This file is part of GDB. @@ -18,8 +17,6 @@ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* ??? Support for calling functions from gdb in sparc64 is unfinished. */ - #include "defs.h" #include "frame.h" #include "inferior.h" @@ -28,9 +25,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "value.h" #include "bfd.h" #include "gdb_string.h" - #include "gdbcore.h" +struct dummy_frame +{ + struct dummy_frame *next; + + CORE_ADDR fp; + CORE_ADDR sp; + CORE_ADDR rp; + CORE_ADDR pc; +}; + +static struct dummy_frame *dummy_frame_stack = NULL; /* This function actually figures out the frame address for a given pc and sp. This is tricky on the v850 because we only use an explicit frame @@ -49,7 +56,7 @@ v850_init_extra_frame_info (fi) int framereg; if (fi->next) - fi->pc = v850_find_callers_reg (fi->next, RP_REGNUM); + fi->pc = FRAME_SAVED_PC (fi->next); /* First, figure out the bounds of the prologue so that we can limit the search to something reasonable. */ @@ -58,7 +65,10 @@ v850_init_extra_frame_info (fi) { sal = find_pc_line (func_addr, 0); - prologue_end = sal.end; + if (sal.line == 0) + prologue_end = fi->pc; + else + prologue_end = sal.end; } else prologue_end = func_addr + 100; /* We're in the boondocks */ @@ -108,21 +118,10 @@ v850_init_extra_frame_info (fi) } } -#if 0 - if (!fi->next) - fi->frame = read_register (framereg); - else - if (framereg == SP_REGNUM) - fi->frame = fi->next->frame; - else - fi->frame = v850_find_callers_reg (fi, framereg); - - if (framereg == SP_REGNUM) - fi->frame -= frameoffset; -#else - if (!fi->next && framereg == SP_REGNUM) + if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL)) + fi->frame = dummy_frame_stack->sp; + else if (!fi->next && framereg == SP_REGNUM) fi->frame = read_register (framereg) - frameoffset; -#endif for (reg = 0; reg < NUM_REGS; reg++) if (fi->fsr.regs[reg] != 0) @@ -137,6 +136,24 @@ v850_find_callers_reg (fi, regnum) struct frame_info *fi; int regnum; { + /* XXX - Won't work if multiple dummy frames are active */ + if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL)) + switch (regnum) + { + case SP_REGNUM: + return dummy_frame_stack->sp; + break; + case FP_REGNUM: + return dummy_frame_stack->fp; + break; + case RP_REGNUM: + return dummy_frame_stack->pc; + break; + case PC_REGNUM: + return dummy_frame_stack->pc; + break; + } + for (; fi; fi = fi->next) if (fi->fsr.regs[regnum] != 0) return read_memory_integer (fi->fsr.regs[regnum], 4); @@ -149,13 +166,15 @@ v850_frame_chain (fi) struct frame_info *fi; { CORE_ADDR callers_pc, callers_sp; - struct frame_info temp_fi; CORE_ADDR func_addr, prologue_end, current_pc; int frameoffset; /* First, find out who called us */ - callers_pc = v850_find_callers_reg (fi, RP_REGNUM); + callers_pc = FRAME_SAVED_PC (fi); + + if (PC_IN_CALL_DUMMY (callers_pc, NULL, NULL)) + return dummy_frame_stack->sp; /* XXX Won't work if multiple dummy frames on stack! */ /* Next, figure out where his prologue is. */ @@ -163,9 +182,16 @@ v850_frame_chain (fi) { struct symtab_and_line sal; + /* Stop when the caller is the entry point function */ + if (func_addr == entry_point_address ()) + return 0; + sal = find_pc_line (func_addr, 0); - prologue_end = sal.end; + if (sal.line == 0) + prologue_end = callers_pc; + else + prologue_end = sal.end; } else prologue_end = func_addr + 100; /* We're in the boondocks */ @@ -217,11 +243,12 @@ v850_skip_prologue (pc) sal = find_pc_line (func_addr, 0); - if (sal.end < func_end) + if (sal.line != 0 && sal.end < func_end) return sal.end; else - /* The line after the prologue is after the end of the function. In - this case, there probably isn't a prologue. */ + /* Either there's no line info, or the line after the prologue is after + the end of the function. In this case, there probably isn't a + prologue. */ return pc; } @@ -229,12 +256,60 @@ v850_skip_prologue (pc) return pc; } +/* All we do here is record SP and FP on the call dummy stack */ + +void +v850_push_dummy_frame () +{ + struct dummy_frame *dummy_frame; + + dummy_frame = xmalloc (sizeof (struct dummy_frame)); + + dummy_frame->fp = read_register (FP_REGNUM); + dummy_frame->sp = read_register (SP_REGNUM); + dummy_frame->rp = read_register (RP_REGNUM); + dummy_frame->pc = read_register (PC_REGNUM); + dummy_frame->next = dummy_frame_stack; + dummy_frame_stack = dummy_frame; +} + +int +v850_pc_in_call_dummy (pc) + CORE_ADDR pc; +{ + return dummy_frame_stack + && pc >= CALL_DUMMY_ADDRESS () + && pc <= CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK; +} + struct frame_info * v850_pop_frame (frame) struct frame_info *frame; { int regnum; + if (PC_IN_CALL_DUMMY (frame->pc, NULL, NULL)) + { + struct dummy_frame *dummy_frame; + + dummy_frame = dummy_frame_stack; + if (!dummy_frame) + error ("Can't pop dummy frame!"); + + dummy_frame_stack = dummy_frame->next; + + write_register (FP_REGNUM, dummy_frame->fp); + write_register (SP_REGNUM, dummy_frame->sp); + write_register (RP_REGNUM, dummy_frame->rp); + write_register (PC_REGNUM, dummy_frame->pc); + + free (dummy_frame); + + flush_cached_frames (); + + return NULL; + } + write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); for (regnum = 0; regnum < NUM_REGS; regnum++) @@ -246,6 +321,81 @@ v850_pop_frame (frame) return NULL; } + +/* Put arguments in the right places, and setup return address register (RP) to + point at a convenient place to put a breakpoint. First four args go in + R6->R9, subsequent args go into sp + 16 -> sp + ... Structs are passed by + reference. 64 bit quantities (doubles and long longs) may be split between + the regs and the stack. When calling a function that returns a struct, a + pointer to the struct is passed in as a secret first argument (always in R6). + + By the time we get here, stack space has been allocated for the args, but + not for the struct return pointer. */ + +CORE_ADDR +v850_push_arguments (nargs, args, sp, struct_return, struct_addr) + int nargs; + value_ptr *args; + CORE_ADDR sp; + unsigned char struct_return; + CORE_ADDR struct_addr; +{ + int argreg; + int argnum; + + argreg = 6; + + if (struct_return) + { + write_register (argreg++, struct_addr); + sp -= 4; + } + + for (argnum = 0; argnum < nargs; argnum++) + { + int len; + char *val; + char valbuf[4]; + + if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT + && TYPE_LENGTH (VALUE_TYPE (*args)) > 8) + { + store_address (valbuf, 4, VALUE_ADDRESS (*args)); + len = 4; + val = valbuf; + } + else + { + len = TYPE_LENGTH (VALUE_TYPE (*args)); + val = (char *)VALUE_CONTENTS (*args); + } + + while (len > 0) + if (argreg <= 9) + { + CORE_ADDR regval; + + regval = extract_address (val, REGISTER_RAW_SIZE (argreg)); + write_register (argreg, regval); + + len -= REGISTER_RAW_SIZE (argreg); + val += REGISTER_RAW_SIZE (argreg); + argreg++; + } + else + { + write_memory (sp + argnum * 4, val, 4); + + len -= 4; + val += 4; + } + args++; + } + + write_register (RP_REGNUM, entry_point_address ()); + + return sp; +} void _initialize_sparc_tdep () |