/* Target-dependent code for the Matsushita MN10200 for GDB, the GNU debugger.
Copyright 1997 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
#include "symfile.h"
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mn10200_use_struct_convention (int gcc_p, struct type *type)
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8);
+}
+/* *INDENT-OFF* */
/* The main purpose of this file is dealing with prologues to extract
information about stack frames and saved registers.
mov sp,fp
add <size>,sp
Register saves for d2, d3, a1, a2 as needed. Saves start
- at fp - <size> and work towards higher addresses. Note
- that the saves are actually done off the stack pointer
- in the prologue! This makes for smaller code and easier
- prologue scanning as the displacement fields will never
+ at fp - <size> + <outgoing_args_size> and work towards higher
+ addresses. Note that the saves are actually done off the stack
+ pointer in the prologue! This makes for smaller code and easier
+ prologue scanning as the displacement fields will unlikely
be more than 8 bits!
Without frame pointer:
add <size>,sp
Register saves for d2, d3, a1, a2 as needed. Saves start
- at sp and work towards higher addresses.
+ at sp + <outgoing_args_size> and work towards higher addresses.
+
+ Out of line prologue:
+ add <local size>,sp -- optional
+ jsr __prologue
+ add <outgoing_size>,sp -- optional
+ The stack pointer remains constant throughout the life of most
+ functions. As a result the compiler will usually omit the
+ frame pointer, so we must handle frame pointerless functions. */
- One day we might keep the stack pointer constant, that won't
- change the code for prologues, but it will make the frame
- pointerless case much more common. */
-
/* Analyze the prologue to determine where registers are saved,
the end of the prologue, etc etc. Return the end of the prologue
scanned.
NO_MORE_FRAMES: Set this if the current frame is "start" or
if the first instruction looks like mov <imm>,sp. This tells
frame chain to not bother trying to unwind past this frame. */
+/* *INDENT-ON* */
+
+
+
#define MY_FRAME_IN_SP 0x1
#define MY_FRAME_IN_FP 0x2
#define CALLER_A2_IN_A0 0x4
#define NO_MORE_FRAMES 0x8
-
+
static CORE_ADDR
-mn10200_analyze_prologue (fi, pc)
- struct frame_info *fi;
- CORE_ADDR pc;
+mn10200_analyze_prologue (struct frame_info *fi, CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end, addr, stop;
CORE_ADDR stack_size;
unsigned char buf[4];
int status;
char *name;
+ int out_of_line_prologue = 0;
/* Use the PC in the frame if it's provided to look up the
start of this function. */
/* If we're in start, then give up. */
if (strcmp (name, "start") == 0)
{
- fi->status = NO_MORE_FRAMES;
+ if (fi)
+ fi->status = NO_MORE_FRAMES;
return pc;
}
}
/* Now see if we have a frame pointer.
-
+
Search for mov a2,a0 (0xf278)
- then mov a3,a2 (0xf27e). */
+ then mov a3,a2 (0xf27e). */
if (buf[0] == 0xf2 && buf[1] == 0x78)
{
/* Our caller's $a2 will be found in $a0 now. Note it for
- our callers. */
+ our callers. */
if (fi)
fi->status |= CALLER_A2_IN_A0;
addr += 2;
}
/* Next we should allocate the local frame.
-
+
Search for add imm8,a3 (0xd3XX)
- or add imm16,a3 (0xf70bXXXX)
- or add imm24,a3 (0xf467XXXXXX).
-
+ or add imm16,a3 (0xf70bXXXX)
+ or add imm24,a3 (0xf467XXXXXX).
+
If none of the above was found, then this prologue has
no stack, and therefore can't have any register saves,
so quit now. */
return addr;
}
}
- else
+
+ /* Now see if we have a call to __prologue for an out of line
+ prologue. */
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+
+ /* First check for 16bit pc-relative call to __prologue. */
+ if (buf[0] == 0xfd)
{
- if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
- fi->frame = read_sp ();
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 1, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 2) + addr + 3) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 3 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 3;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+ /* Now check for the 24bit pc-relative call to __prologue. */
+ else if (buf[0] == 0xf4 && buf[1] == 0xe1)
+ {
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 3) + addr + 5) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 5 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 5;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+
+ /* Now actually handle the out of line prologue. */
+ if (out_of_line_prologue)
+ {
+ int outgoing_args_size = 0;
+
+ /* First adjust the stack size for this function. The out of
+ line prologue saves 4 registers (16bytes of data). */
+ if (fi)
+ fi->stack_size -= 16;
+
+ /* Update fi->frame if necessary. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp () - fi->stack_size;
+
+ /* After the out of line prologue, there may be another
+ stack adjustment for the outgoing arguments.
+
+ Search for add imm8,a3 (0xd3XX)
+ or add imm16,a3 (0xf70bXXXX)
+ or add imm24,a3 (0xf467XXXXXX). */
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+
+ if (buf[0] == 0xd3)
+ {
+ outgoing_args_size = extract_signed_integer (&buf[1], 1);
+ addr += 2;
+ }
+ else if (buf[0] == 0xf7 && buf[1] == 0x0b)
+ {
+ status = target_read_memory (addr + 2, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 2);
+ addr += 4;
+ }
+ else if (buf[0] == 0xf4 && buf[1] == 0x67)
+ {
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 3);
+ addr += 5;
+ }
+ else
+ outgoing_args_size = 0;
+
+ /* Now that we know the size of the outgoing arguments, fix
+ fi->frame again if this is the innermost frame. */
+ if (fi && fi->next == NULL)
+ fi->frame -= outgoing_args_size;
+
+ /* Note the register save information and update the stack
+ size for this frame too. */
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ fi->stack_size += outgoing_args_size;
+ }
+ /* There can be no more prologue insns, so return now. */
return addr;
}
and thus the number of different instructions we need to
check is greatly reduced because we know the displacements
will be small.
-
+
Search for movx d2,(X,a3) (0xf55eXX)
- then movx d3,(X,a3) (0xf55fXX)
- then mov a1,(X,a3) (0x5dXX) No frame pointer case
- then mov a2,(X,a3) (0x5eXX) No frame pointer case
- or mov a0,(X,a3) (0x5cXX) Frame pointer case. */
+ then movx d3,(X,a3) (0xf55fXX)
+ then mov a1,(X,a3) (0x5dXX) No frame pointer case
+ then mov a2,(X,a3) (0x5eXX) No frame pointer case
+ or mov a0,(X,a3) (0x5cXX) Frame pointer case. */
status = target_read_memory (addr, buf, 2);
if (status != 0)
}
return addr;
}
-
+
/* Function: frame_chain
Figure out and return the caller's frame pointer given current
frame_info struct.
stack pointer that was in use at the time the function call was made? */
CORE_ADDR
-mn10200_frame_chain (fi)
- struct frame_info *fi;
+mn10200_frame_chain (struct frame_info *fi)
{
struct frame_info dummy_frame;
/* Walk through the prologue to determine the stack size,
location of saved registers, end of the prologue, etc. */
if (fi->status == 0)
- mn10200_analyze_prologue (fi, (CORE_ADDR)0);
+ mn10200_analyze_prologue (fi, (CORE_ADDR) 0);
/* Quit now if mn10200_analyze_prologue set NO_MORE_FRAMES. */
if (fi->status & NO_MORE_FRAMES)
/* Now that we've analyzed our prologue, determine the frame
pointer for our caller.
- If our caller has a frame pointer, then we need to
- find the entry value of $a2 to our function.
+ If our caller has a frame pointer, then we need to
+ find the entry value of $a2 to our function.
- If CALLER_A2_IN_A0, then the chain is in $a0.
+ If CALLER_A2_IN_A0, then the chain is in $a0.
- If fsr.regs[6] is nonzero, then it's at the memory
- location pointed to by fsr.regs[6].
+ If fsr.regs[6] is nonzero, then it's at the memory
+ location pointed to by fsr.regs[6].
- Else it's still in $a2.
+ Else it's still in $a2.
+
+ If our caller does not have a frame pointer, then his
+ frame base is fi->frame + -caller's stack size + 4. */
- If our caller does not have a frame pointer, then his
- frame base is fi->frame + -caller's stack size + 4. */
-
/* The easiest way to get that info is to analyze our caller's frame.
So we set up a dummy frame and call mn10200_analyze_prologue to
if (dummy_frame.status & MY_FRAME_IN_FP)
{
/* Our caller has a frame pointer. So find the frame in $a2, $a0,
- or in the stack. */
+ or in the stack. */
if (fi->fsr.regs[6])
return (read_memory_integer (fi->fsr.regs[FP_REGNUM], REGISTER_SIZE)
& 0xffffff);
else
{
/* Our caller does not have a frame pointer. So his frame starts
- at the base of our frame (fi->frame) + <his size> + 4 (saved pc). */
+ at the base of our frame (fi->frame) + <his size> + 4 (saved pc). */
return fi->frame + -dummy_frame.stack_size + 4;
}
}
Return the address of the first inst past the prologue of the function. */
CORE_ADDR
-mn10200_skip_prologue (pc)
- CORE_ADDR pc;
+mn10200_skip_prologue (CORE_ADDR pc)
{
- CORE_ADDR func_addr, func_end;
-
- /* First check the symbol table. That'll be faster than scanning
- the prologue instructions if we have debug sybmols. */
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
- {
- struct symtab_and_line sal;
-
- sal = find_pc_line (func_addr, 0);
-
- if (sal.line != 0 && sal.end < func_end)
- return sal.end;
-
- return mn10200_analyze_prologue (NULL, pc);
- }
-
- /* We couldn't find the start of this function, do nothing. */
- return pc;
+ /* We used to check the debug symbols, but that can lose if
+ we have a null prologue. */
+ return mn10200_analyze_prologue (NULL, pc);
}
/* Function: pop_frame
command, or the call dummy breakpoint gets hit. */
void
-mn10200_pop_frame (frame)
- struct frame_info *frame;
+mn10200_pop_frame (struct frame_info *frame)
{
int regnum;
- if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
{
ULONGEST value;
value = read_memory_unsigned_integer (frame->fsr.regs[regnum],
- REGISTER_RAW_SIZE (regnum));
+ REGISTER_RAW_SIZE (regnum));
write_register (regnum, value);
}
order on the stack. */
CORE_ADDR
-mn10200_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;
+mn10200_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+ unsigned char struct_return, CORE_ADDR struct_addr)
{
int argnum = 0;
int len = 0;
int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1;
/* If we've used all argument registers, then this argument is
- pushed. */
+ pushed. */
if (regsused >= 2 || arg_length > 4)
{
regsused = 2;
len += arg_length;
}
/* We know we've got some arg register space left. If this argument
- will fit entirely in regs, then put it there. */
+ will fit entirely in regs, then put it there. */
else if (arg_length <= 2
- || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR)
+ || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR)
{
regsused++;
}
&& TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
{
/* XXX Wrong, we want a pointer to this argument. */
- len = TYPE_LENGTH (VALUE_TYPE (*args));
- val = (char *)VALUE_CONTENTS (*args);
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *) VALUE_CONTENTS (*args);
}
else
{
len = TYPE_LENGTH (VALUE_TYPE (*args));
- val = (char *)VALUE_CONTENTS (*args);
+ val = (char *) VALUE_CONTENTS (*args);
}
if (regsused < 2
/* Function: push_return_address (pc)
Set up the return address for the inferior function call.
Needed for targets where we don't actually execute a JSR/BSR instruction */
-
+
CORE_ADDR
-mn10200_push_return_address (pc, sp)
- CORE_ADDR pc;
- CORE_ADDR sp;
+mn10200_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
unsigned char buf[4];
/* Function: store_struct_return (addr,sp)
Store the structure value return address for an inferior function
call. */
-
+
CORE_ADDR
-mn10200_store_struct_return (addr, sp)
- CORE_ADDR addr;
- CORE_ADDR sp;
+mn10200_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
/* The structure return address is passed as the first argument. */
write_register (0, addr);
return sp;
}
-
+
/* Function: frame_saved_pc
Find the caller of this frame. We do this by seeing if RP_REGNUM
is saved in the stack anywhere, otherwise we get it from the
will be found. */
CORE_ADDR
-mn10200_frame_saved_pc (fi)
- struct frame_info *fi;
+mn10200_frame_saved_pc (struct frame_info *fi)
{
/* The saved PC will always be at the base of the current frame. */
return (read_memory_integer (fi->frame, REGISTER_SIZE) & 0xffffff);
}
-void
-get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
- char *raw_buffer;
- int *optimized;
- CORE_ADDR *addrp;
- struct frame_info *frame;
- int regnum;
- enum lval_type *lval;
-{
- generic_get_saved_register (raw_buffer, optimized, addrp,
- frame, regnum, lval);
-}
-
/* Function: init_extra_frame_info
Setup the frame's frame pointer, pc, and frame addresses for saved
registers. Most of the work is done in mn10200_analyze_prologue().
pointer just prior to calling the target function (see run_stack_dummy). */
void
-mn10200_init_extra_frame_info (fi)
- struct frame_info *fi;
+mn10200_init_extra_frame_info (struct frame_info *fi)
{
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
}
void
-_initialize_mn10200_tdep ()
+_initialize_mn10200_tdep (void)
{
tm_print_insn = print_insn_mn10200;
}
-