/* 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 fp,a0
mov sp,fp
add <size>,sp
- Register saves for d2, d3, a3 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
+ Register saves for d2, d3, a1, a2 as needed. Saves start
+ 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, a3 as needed. Saves start
- at sp and work towards higher addresses.
+ Register saves for d2, d3, a1, a2 as needed. Saves start
+ 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;
}
status = target_read_memory (fi->pc, buf, 1);
if (status != 0)
{
- fi->frame = read_sp ();
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
return fi->pc;
}
if (buf[0] == 0xfe)
{
- fi->frame = read_sp ();
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
return fi->pc;
}
}
frame hasn't been allocated yet. */
if (fi && fi->pc == func_addr)
{
- fi->frame = read_sp ();
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
return fi->pc;
}
status = target_read_memory (addr, buf, 2);
if (status != 0)
{
- if (fi && fi->status & MY_FRAME_IN_SP)
+ if (fi && fi->next == NULL && fi->status & MY_FRAME_IN_SP)
fi->frame = read_sp ();
return addr;
}
}
/* 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;
{
/* We still haven't allocated our local stack. Handle this
as if we stopped on the first or last insn of a function. */
- if (fi)
+ if (fi && fi->next == NULL)
fi->frame = read_sp ();
return addr;
}
status = target_read_memory (addr, buf, 2);
if (status != 0)
{
- if (fi)
+ if (fi && fi->next == NULL)
fi->frame = read_sp ();
return addr;
}
}
else
{
- if (fi)
+ if (fi && fi->next == NULL)
fi->frame = read_sp ();
return addr;
}
}
/* 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. */
status = target_read_memory (addr, buf, 2);
if (status != 0)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
fi->frame = read_sp ();
return addr;
}
addr += 2;
if (addr >= stop)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
- fi->frame = read_sp () + stack_size;
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
return addr;
}
}
status = target_read_memory (addr + 2, buf, 2);
if (status != 0)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
fi->frame = read_sp ();
return addr;
}
addr += 4;
if (addr >= stop)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
- fi->frame = read_sp () + stack_size;
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
return addr;
}
}
status = target_read_memory (addr + 2, buf, 3);
if (status != 0)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
fi->frame = read_sp ();
return addr;
}
addr += 5;
if (addr >= stop)
{
- if (fi && (fi->status & MY_FRAME_IN_SP))
- fi->frame = read_sp () + stack_size;
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
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->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;
}
/* At this point fi->frame needs to be correct.
- If MY_FRAME_IN_SP is set, then we need to fix fi->frame so
- that backtracing, find_frame_saved_regs, etc work correctly. */
- if (fi && (fi->status & MY_FRAME_IN_SP) != 0)
+ If MY_FRAME_IN_SP is set and we're the innermost frame, then we
+ need to fix fi->frame so that backtracing, find_frame_saved_regs,
+ etc work correctly. */
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP) != 0)
fi->frame = read_sp () - fi->stack_size;
/* And last we have the register saves. These are relatively
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 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)
if (status != 0)
return addr;
}
+ if (buf[0] == 0x5d)
+ {
+ if (fi)
+ {
+ status = target_read_memory (addr + 1, buf, 1);
+ if (status != 0)
+ return addr;
+ fi->fsr.regs[5] = (fi->frame + stack_size
+ + extract_signed_integer (buf, 1));
+ }
+ addr += 2;
+ if (addr >= stop)
+ return addr;
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+ }
if (buf[0] == 0x5e || buf[0] == 0x5c)
{
if (fi)
}
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). */
- return fi->frame + dummy_frame.stack_size + 4;
+ 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 stack_offset = 0;
+ int regsused = struct_return ? 1 : 0;
/* This should be a nop, but align the stack just in case something
- went wrong. */
- sp &= ~3;
+ went wrong. Stacks are two byte aligned on the mn10200. */
+ sp &= ~1;
/* Now make space on the stack for the args.
XXX This doesn't appear to handle pass-by-invisible reference
arguments. */
for (argnum = 0; argnum < nargs; argnum++)
- len += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3);
+ {
+ int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1;
+
+ /* If we've used all argument registers, then this argument is
+ 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. */
+ else if (arg_length <= 2
+ || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR)
+ {
+ regsused++;
+ }
+ else if (regsused == 0)
+ {
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ len += arg_length;
+ }
+ }
/* Allocate stack space. */
sp -= len;
+ regsused = struct_return ? 1 : 0;
/* Push all arguments onto the stack. */
for (argnum = 0; argnum < nargs; argnum++)
{
int len;
char *val;
- /* XXX Check this. What about UNIONS? Size check looks
- wrong too. */
+ /* XXX Check this. What about UNIONS? */
if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
&& 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);
}
- while (len > 0)
+ if (regsused < 2
+ && (len <= 2
+ || TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_PTR))
{
- /* XXX This looks wrong; we can have one and two byte args. */
- write_memory (sp + stack_offset, val, 4);
+ write_register (regsused, extract_unsigned_integer (val, 4));
+ regsused++;
+ }
+ else if (regsused == 0 && len == 4)
+ {
+ write_register (regsused, extract_unsigned_integer (val, 2));
+ write_register (regsused + 1, extract_unsigned_integer (val + 2, 2));
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ while (len > 0)
+ {
+ write_memory (sp + stack_offset, val, 2);
- len -= 4;
- val += 4;
- stack_offset += 4;
+ len -= 2;
+ val += 2;
+ stack_offset += 2;
+ }
}
args++;
}
/* 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];
+
+ store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ());
+ write_memory (sp - 4, buf, 4);
+ return sp - 4;
+}
+
+/* Function: store_struct_return (addr,sp)
+ Store the structure value return address for an inferior function
+ call. */
+CORE_ADDR
+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;
}
-