mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
Modified Files:
ChangeLog configure.in defs.h mips-tdep.c * configure.in: add mips64-*-elf, mips64-*-ecoff, mips64el-*-elf, mips64el-*-ecoff and mips64-big-*. * defs.h: get rid of FORCE_LONG_LONG. * mips-tdep.c (mips_find_saved_regs): add sd and sdc1 instruction parsing. Change register size to be MIPS_REGSIZE.
This commit is contained in:
parent
4fbce2fdd2
commit
70126bf94e
@ -1,3 +1,11 @@
|
||||
Thu Feb 17 17:25:47 1994 Kung Hsu (kung@mexican.cygnus.com)
|
||||
|
||||
* configure.in: add mips64-*-elf, mips64-*-ecoff, mips64el-*-elf,
|
||||
mips64el-*-ecoff and mips64-big-*.
|
||||
* defs.h: get rid of FORCE_LONG_LONG.
|
||||
* mips-tdep.c (mips_find_saved_regs): add sd and sdc1 instruction
|
||||
parsing. Change register size to be MIPS_REGSIZE.
|
||||
|
||||
Thu Feb 17 09:30:22 1994 David J. Mackenzie (djm@thepub.cygnus.com)
|
||||
|
||||
* corelow.c, exec.c, irix5-nat.c, mipsread.c, objfiles.c,
|
||||
|
@ -256,8 +256,13 @@ m88*-motorola-sysv4*) gdb_target=delta88v4 ;;
|
||||
m88*-motorola-*) gdb_target=delta88 ;;
|
||||
m88*-*-*) gdb_target=m88k ;;
|
||||
|
||||
mips64*-big-*) gdb_target=bigmips64 ;;
|
||||
mips*-big-*) gdb_target=bigmips ;;
|
||||
mips*-dec-*) gdb_target=decstation ;;
|
||||
mips64*el-*-ecoff*) gdb_target=idtl64 ;;
|
||||
mips64*-idt-ecoff*) gdb_target=idt64 ;;
|
||||
mips64*el-*-elf*) gdb_target=idtl64 ;;
|
||||
mips64*-*-elf*) gdb_target=idt64 ;;
|
||||
mips*el-*-ecoff*) gdb_target=idtl ;;
|
||||
mips*-idt-ecoff*) gdb_target=idt ;;
|
||||
mips*el-*-elf*) gdb_target=idtl ;;
|
||||
|
@ -516,7 +516,7 @@ enum val_prettyprint
|
||||
|
||||
/* This is to make sure that LONGEST is at least as big as CORE_ADDR. */
|
||||
|
||||
#define LONGEST BFD_HOST_64_TYPE
|
||||
#define LONGEST BFD_HOST_64_BIT
|
||||
|
||||
#else /* No BFD64 */
|
||||
|
||||
@ -533,7 +533,7 @@ enum val_prettyprint
|
||||
will select "long long" use for testing purposes. -fnf */
|
||||
|
||||
#ifndef CC_HAS_LONG_LONG
|
||||
# if defined (__GNUC__) && defined (FORCE_LONG_LONG) /* See FIXME above */
|
||||
# if defined (__GNUC__) /*&& defined (FORCE_LONG_LONG)*/ /* See FIXME above */
|
||||
# define CC_HAS_LONG_LONG 1
|
||||
# endif
|
||||
#endif
|
||||
|
319
gdb/mips-tdep.c
319
gdb/mips-tdep.c
@ -34,6 +34,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "opcode/mips.h"
|
||||
|
||||
#define VM_MIN_ADDRESS (unsigned)0x400000
|
||||
|
||||
/* FIXME: Put this declaration in frame.h. */
|
||||
extern struct obstack frame_cache_obstack;
|
||||
|
||||
#if 0
|
||||
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
||||
@ -69,7 +72,132 @@ struct linked_proc_info
|
||||
} *linked_proc_desc_table = NULL;
|
||||
|
||||
|
||||
#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno)
|
||||
/* Guaranteed to set fci->saved_regs to some values (it never leaves it
|
||||
NULL). */
|
||||
|
||||
void
|
||||
mips_find_saved_regs (fci)
|
||||
FRAME fci;
|
||||
{
|
||||
int ireg;
|
||||
CORE_ADDR reg_position;
|
||||
/* r0 bit means kernel trap */
|
||||
int kernel_trap;
|
||||
/* What registers have been saved? Bitmasks. */
|
||||
unsigned long gen_mask, float_mask;
|
||||
mips_extra_func_info_t proc_desc;
|
||||
|
||||
fci->saved_regs = (struct frame_saved_regs *)
|
||||
obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
|
||||
memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
|
||||
|
||||
proc_desc = fci->proc_desc;
|
||||
if (proc_desc == NULL)
|
||||
/* I'm not sure how/whether this can happen. Normally when we can't
|
||||
find a proc_desc, we "synthesize" one using heuristic_proc_desc
|
||||
and set the saved_regs right away. */
|
||||
return;
|
||||
|
||||
kernel_trap = PROC_REG_MASK(proc_desc) & 1;
|
||||
gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
|
||||
float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
|
||||
|
||||
if (/* In any frame other than the innermost, we assume that all
|
||||
registers have been saved. This assumes that all register
|
||||
saves in a function happen before the first function
|
||||
call. */
|
||||
fci->next == NULL
|
||||
|
||||
/* In a dummy frame we know exactly where things are saved. */
|
||||
&& !PROC_DESC_IS_DUMMY (proc_desc)
|
||||
|
||||
/* Not sure exactly what kernel_trap means, but if it means
|
||||
the kernel saves the registers without a prologue doing it,
|
||||
we better not examine the prologue to see whether registers
|
||||
have been saved yet. */
|
||||
&& !kernel_trap)
|
||||
{
|
||||
/* We need to figure out whether the registers that the proc_desc
|
||||
claims are saved have been saved yet. */
|
||||
|
||||
CORE_ADDR addr;
|
||||
int status;
|
||||
char buf[4];
|
||||
unsigned long inst;
|
||||
|
||||
/* Bitmasks; set if we have found a save for the register. */
|
||||
unsigned long gen_save_found = 0;
|
||||
unsigned long float_save_found = 0;
|
||||
|
||||
for (addr = PROC_LOW_ADDR (proc_desc);
|
||||
addr < fci->pc /*&& (gen_mask != gen_save_found
|
||||
|| float_mask != float_save_found)*/;
|
||||
addr += 4)
|
||||
{
|
||||
status = read_memory_nobpt (addr, buf, 4);
|
||||
if (status)
|
||||
memory_error (status, addr);
|
||||
inst = extract_unsigned_integer (buf, 4);
|
||||
if (/* sw reg,n($sp) */
|
||||
(inst & 0xffe00000) == 0xafa00000
|
||||
|
||||
/* sw reg,n($r30) */
|
||||
|| (inst & 0xffe00000) == 0xafc00000
|
||||
|
||||
/* sd reg,n($sp) */
|
||||
|| (inst & 0xffe00000) == 0xffa00000)
|
||||
{
|
||||
/* It might be possible to use the instruction to
|
||||
find the offset, rather than the code below which
|
||||
is based on things being in a certain order in the
|
||||
frame, but figuring out what the instruction's offset
|
||||
is relative to might be a little tricky. */
|
||||
int reg = (inst & 0x001f0000) >> 16;
|
||||
gen_save_found |= (1 << reg);
|
||||
}
|
||||
else if (/* swc1 freg,n($sp) */
|
||||
(inst & 0xffe00000) == 0xe7a00000
|
||||
|
||||
/* swc1 freg,n($r30) */
|
||||
|| (inst & 0xffe00000) == 0xe7c00000
|
||||
|
||||
/* sdc1 freg,n($sp) */
|
||||
|| (inst & 0xffe00000) == 0xf7a00000)
|
||||
|
||||
{
|
||||
int reg = ((inst & 0x001f0000) >> 16);
|
||||
float_save_found |= (1 << reg);
|
||||
}
|
||||
}
|
||||
gen_mask = gen_save_found;
|
||||
float_mask = float_save_found;
|
||||
}
|
||||
|
||||
/* Fill in the offsets for the registers which gen_mask says
|
||||
were saved. */
|
||||
reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
|
||||
for (ireg= 31; gen_mask; --ireg, gen_mask <<= 1)
|
||||
if (gen_mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[ireg] = reg_position;
|
||||
reg_position -= MIPS_REGSIZE;
|
||||
}
|
||||
/* Fill in the offsets for the registers which float_mask says
|
||||
were saved. */
|
||||
reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
|
||||
|
||||
/* The freg_offset points to where the first *double* register
|
||||
is saved. So skip to the high-order word. */
|
||||
reg_position += 4;
|
||||
for (ireg = 31; float_mask; --ireg, float_mask <<= 1)
|
||||
if (float_mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
|
||||
reg_position -= MIPS_REGSIZE;
|
||||
}
|
||||
|
||||
fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
|
||||
}
|
||||
|
||||
static int
|
||||
read_next_frame_reg(fi, regno)
|
||||
@ -91,18 +219,26 @@ read_next_frame_reg(fi, regno)
|
||||
#define SIGFRAME_REG_SIZE 4
|
||||
#endif
|
||||
for (; fi; fi = fi->next)
|
||||
if (fi->signal_handler_caller) {
|
||||
{
|
||||
if (fi->signal_handler_caller)
|
||||
{
|
||||
int offset;
|
||||
if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;
|
||||
else if (regno < 32) offset = (SIGFRAME_REGSAVE_OFF
|
||||
+ regno * SIGFRAME_REG_SIZE);
|
||||
else return 0;
|
||||
return read_memory_integer(fi->frame + offset, 4);
|
||||
}
|
||||
return read_memory_integer(fi->frame + offset, MIPS_REGSIZE);
|
||||
}
|
||||
else if (regno == SP_REGNUM) return fi->frame;
|
||||
else if (fi->saved_regs->regs[regno])
|
||||
return read_memory_integer(fi->saved_regs->regs[regno], 4);
|
||||
return read_register(regno);
|
||||
else
|
||||
{
|
||||
if (fi->saved_regs == NULL)
|
||||
mips_find_saved_regs (fi);
|
||||
if (fi->saved_regs->regs[regno])
|
||||
return read_memory_integer(fi->saved_regs->regs[regno], MIPS_REGSIZE);
|
||||
}
|
||||
}
|
||||
return read_register (regno);
|
||||
}
|
||||
|
||||
int
|
||||
@ -372,129 +508,34 @@ void
|
||||
init_extra_frame_info(fci)
|
||||
struct frame_info *fci;
|
||||
{
|
||||
extern struct obstack frame_cache_obstack;
|
||||
/* Use proc_desc calculated in frame_chain */
|
||||
mips_extra_func_info_t proc_desc =
|
||||
fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
|
||||
|
||||
fci->saved_regs = (struct frame_saved_regs*)
|
||||
obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
|
||||
memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
|
||||
fci->saved_regs = NULL;
|
||||
fci->proc_desc =
|
||||
proc_desc == &temp_proc_desc ? 0 : proc_desc;
|
||||
if (proc_desc)
|
||||
{
|
||||
int ireg;
|
||||
CORE_ADDR reg_position;
|
||||
/* r0 bit means kernel trap */
|
||||
int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
|
||||
|
||||
/* Fixup frame-pointer - only needed for top frame */
|
||||
/* This may not be quite right, if proc has a real frame register.
|
||||
Get the value of the frame relative sp, procedure might have been
|
||||
interrupted by a signal at it's very start. */
|
||||
if (fci->pc == PROC_LOW_ADDR(proc_desc) && !PROC_DESC_IS_DUMMY(proc_desc))
|
||||
fci->frame = READ_FRAME_REG(fci, SP_REGNUM);
|
||||
if (fci->pc == PROC_LOW_ADDR (proc_desc)
|
||||
&& !PROC_DESC_IS_DUMMY (proc_desc))
|
||||
fci->frame = read_next_frame_reg (fci->next, SP_REGNUM);
|
||||
else
|
||||
fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
|
||||
+ PROC_FRAME_OFFSET(proc_desc);
|
||||
fci->frame =
|
||||
read_next_frame_reg (fci->next, PROC_FRAME_REG (proc_desc))
|
||||
+ PROC_FRAME_OFFSET (proc_desc);
|
||||
|
||||
if (proc_desc == &temp_proc_desc)
|
||||
*fci->saved_regs = temp_saved_regs;
|
||||
else
|
||||
{
|
||||
/* What registers have been saved? Bitmasks. */
|
||||
unsigned long gen_mask, float_mask;
|
||||
|
||||
gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
|
||||
float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
|
||||
|
||||
if (/* In any frame other than the innermost, we assume that all
|
||||
registers have been saved. This assumes that all register
|
||||
saves in a function happen before the first function
|
||||
call. */
|
||||
fci->next == NULL
|
||||
|
||||
/* In a dummy frame we know exactly where things are saved. */
|
||||
&& !PROC_DESC_IS_DUMMY (proc_desc)
|
||||
|
||||
/* Not sure exactly what kernel_trap means, but if it means
|
||||
the kernel saves the registers without a prologue doing it,
|
||||
we better not examine the prologue to see whether registers
|
||||
have been saved yet. */
|
||||
&& !kernel_trap)
|
||||
{
|
||||
/* We need to figure out whether the registers that the proc_desc
|
||||
claims are saved have been saved yet. */
|
||||
|
||||
CORE_ADDR addr;
|
||||
int status;
|
||||
char buf[4];
|
||||
unsigned long inst;
|
||||
|
||||
/* Bitmasks; set if we have found a save for the register. */
|
||||
unsigned long gen_save_found = 0;
|
||||
unsigned long float_save_found = 0;
|
||||
|
||||
for (addr = PROC_LOW_ADDR (proc_desc);
|
||||
addr < fci->pc && (gen_mask != gen_save_found
|
||||
|| float_mask != float_save_found);
|
||||
addr += 4)
|
||||
{
|
||||
status = read_memory_nobpt (addr, buf, 4);
|
||||
if (status)
|
||||
memory_error (status, addr);
|
||||
inst = extract_unsigned_integer (buf, 4);
|
||||
if (/* sw reg,n($sp) */
|
||||
(inst & 0xffe00000) == 0xafa00000
|
||||
|
||||
/* sw reg,n($r30) */
|
||||
|| (inst & 0xffe00000) == 0xafc00000)
|
||||
{
|
||||
/* It might be possible to use the instruction to
|
||||
find the offset, rather than the code below which
|
||||
is based on things being in a certain order in the
|
||||
frame, but figuring out what the instruction's offset
|
||||
is relative to might be a little tricky. */
|
||||
int reg = (inst & 0x001f0000) >> 16;
|
||||
gen_save_found |= (1 << reg);
|
||||
}
|
||||
else if (/* swc1 freg,n($sp) */
|
||||
(inst & 0xffe00000) == 0xe7a00000
|
||||
|
||||
/* swc1 freg,n($r30) */
|
||||
|| (inst & 0xffe00000) == 0xe7c00000)
|
||||
{
|
||||
int reg = ((inst & 0x001f0000) >> 16);
|
||||
float_save_found |= (1 << reg);
|
||||
}
|
||||
}
|
||||
gen_mask = gen_save_found;
|
||||
float_mask = float_save_found;
|
||||
}
|
||||
|
||||
/* Fill in the offsets for the registers which gen_mask says
|
||||
were saved. */
|
||||
reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
|
||||
for (ireg= 31; gen_mask; --ireg, gen_mask <<= 1)
|
||||
if (gen_mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
}
|
||||
/* Fill in the offsets for the registers which float_mask says
|
||||
were saved. */
|
||||
reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
|
||||
|
||||
/* The freg_offset points to where the first *double* register
|
||||
is saved. So skip to the high-order word. */
|
||||
reg_position += 4;
|
||||
for (ireg = 31; float_mask; --ireg, float_mask <<= 1)
|
||||
if (float_mask & 0x80000000)
|
||||
{
|
||||
fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
|
||||
reg_position -= 4;
|
||||
}
|
||||
fci->saved_regs = (struct frame_saved_regs*)
|
||||
obstack_alloc (&frame_cache_obstack,
|
||||
sizeof (struct frame_saved_regs));
|
||||
*fci->saved_regs = temp_saved_regs;
|
||||
fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
|
||||
}
|
||||
|
||||
/* hack: if argument regs are saved, guess these contain args */
|
||||
@ -503,8 +544,6 @@ init_extra_frame_info(fci)
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args = 3;
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args = 2;
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args = 1;
|
||||
|
||||
fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
|
||||
}
|
||||
}
|
||||
|
||||
@ -544,11 +583,13 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
|
||||
CORE_ADDR struct_addr;
|
||||
{
|
||||
register i;
|
||||
int accumulate_size = struct_return ? 4 : 0;
|
||||
int accumulate_size = struct_return ? MIPS_REGSIZE : 0;
|
||||
struct mips_arg { char *contents; int len; int offset; };
|
||||
struct mips_arg *mips_args =
|
||||
(struct mips_arg*)alloca(nargs * sizeof(struct mips_arg));
|
||||
(struct mips_arg*)alloca((nargs + 4) * sizeof(struct mips_arg));
|
||||
register struct mips_arg *m_arg;
|
||||
int fake_args = 0;
|
||||
|
||||
for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {
|
||||
extern value value_arg_coerce();
|
||||
value arg = value_arg_coerce (args[i]);
|
||||
@ -559,16 +600,48 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
|
||||
* breaks their varargs implementation...). A correct solution
|
||||
* requires an simulation of gcc's 'alignof' (and use of 'alignof'
|
||||
* in stdarg.h/varargs.h).
|
||||
* On the 64 bit r4000 we always pass the first four arguments
|
||||
* using eight bytes each, so that we can load them up correctly
|
||||
* in CALL_DUMMY.
|
||||
*/
|
||||
if (m_arg->len > 4) accumulate_size = (accumulate_size + 7) & -8;
|
||||
if (m_arg->len > 4)
|
||||
accumulate_size = (accumulate_size + 7) & -8;
|
||||
m_arg->offset = accumulate_size;
|
||||
accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
|
||||
m_arg->contents = VALUE_CONTENTS(arg);
|
||||
#ifndef GDB_TARGET_IS_MIPS64
|
||||
accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
|
||||
#else
|
||||
if (accumulate_size >= 4 * MIPS_REGSIZE)
|
||||
accumulate_size = (accumulate_size + m_arg->len + 3) &~ 4;
|
||||
else
|
||||
{
|
||||
static char zeroes[8] = { 0 };
|
||||
int len = m_arg->len;
|
||||
|
||||
if (len < 8)
|
||||
{
|
||||
#if TARGET_BYTE_ORDER == BIG_ENDIAN
|
||||
m_arg->offset += 8 - len;
|
||||
#endif
|
||||
++m_arg;
|
||||
m_arg->len = 8 - len;
|
||||
m_arg->contents = zeroes;
|
||||
#if TARGET_BYTE_ORDER == BIG_ENDIAN
|
||||
m_arg->offset = accumulate_size;
|
||||
#else
|
||||
m_arg->offset = accumulate_size + len;
|
||||
#endif
|
||||
++fake_args;
|
||||
}
|
||||
accumulate_size = (accumulate_size + len + 7) & ~8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
accumulate_size = (accumulate_size + 7) & (-8);
|
||||
if (accumulate_size < 16) accumulate_size = 16;
|
||||
if (accumulate_size < 4 * MIPS_REGSIZE)
|
||||
accumulate_size = 4 * MIPS_REGSIZE;
|
||||
sp -= accumulate_size;
|
||||
for (i = nargs; m_arg--, --i >= 0; )
|
||||
for (i = nargs + fake_args; m_arg--, --i >= 0; )
|
||||
write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
|
||||
if (struct_return)
|
||||
{
|
||||
@ -684,6 +757,8 @@ mips_pop_frame()
|
||||
mips_extra_func_info_t proc_desc = frame->proc_desc;
|
||||
|
||||
write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
|
||||
if (frame->saved_regs == NULL)
|
||||
mips_find_saved_regs (frame);
|
||||
if (proc_desc)
|
||||
{
|
||||
for (regnum = 32; --regnum >= 0; )
|
||||
|
Loading…
Reference in New Issue
Block a user