/* Target-machine dependent code for the AMD 29000
- Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Jim Kingdon.
This file is part of GDB.
static CORE_ADDR rstack_high_address = UINT_MAX;
/* Structure to hold cached info about function prologues. */
+
struct prologue_info
{
CORE_ADDR pc; /* First addr after fn prologue */
If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
frame pointer is being used. */
+
CORE_ADDR
examine_prologue (pc, rsize, msize, mfp_used)
CORE_ADDR pc;
skip_prologue (pc)
CORE_ADDR pc;
{
- return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL,
- (int *)NULL);
+ return examine_prologue (pc, NULL, NULL, NULL);
}
+
/*
* Examine the one or two word tag at the beginning of a function.
* The tag word is expect to be at 'p', if it is not there, we fail
* convention today (1/15/92).
* msize is return in bytes.
*/
+
static int /* 0/1 - failure/success of finding the tag word */
-examine_tag(p, is_trans, argcount, msize, mfp_used)
+examine_tag (p, is_trans, argcount, msize, mfp_used)
CORE_ADDR p;
int *is_trans;
- int *argcount;
+ int *argcount;
unsigned *msize;
int *mfp_used;
{
return 0;
if (tag1 & (1<<23)) /* A two word tag */
{
- tag2 = read_memory_integer (p+4, 4);
+ tag2 = read_memory_integer (p-4, 4);
if (msize)
- *msize = tag2;
+ *msize = tag2 * 2;
}
else /* A one word tag */
{
*msize = tag1 & 0x7ff;
}
if (is_trans)
- *is_trans = ((tag1 & (1<<21)) ? 1 : 0);
+ *is_trans = ((tag1 & (1<<21)) ? 1 : 0);
+ /* Note that this includes the frame pointer and the return address
+ register, so the actual number of registers of arguments is two less.
+ argcount can be zero, however, sometimes, for strange assembler
+ routines. */
if (argcount)
*argcount = (tag1 >> 16) & 0x1f;
if (mfp_used)
*mfp_used = ((tag1 & (1<<22)) ? 1 : 0);
- return(1);
+ return 1;
}
/* Initialize the frame. In addition to setting "extra" frame info,
we also set ->frame because we use it in a nonstandard way, and ->pc
because we need to know it to get the other stuff. See the diagram
of stacks and the frame cache in tm-a29k.h for more detail. */
+
static void
-init_frame_info (innermost_frame, fci)
+init_frame_info (innermost_frame, frame)
int innermost_frame;
- struct frame_info *fci;
+ struct frame_info *frame;
{
CORE_ADDR p;
long insn;
int mfp_used, trans;
struct symbol *func;
- p = fci->pc;
+ p = frame->pc;
if (innermost_frame)
- fci->frame = read_register (GR1_REGNUM);
+ frame->frame = read_register (GR1_REGNUM);
else
- fci->frame = fci->next->frame + fci->next->rsize;
+ frame->frame = frame->next->frame + frame->next->rsize;
-#if CALL_DUMMY_LOCATION == ON_STACK
+#if 0 /* CALL_DUMMY_LOCATION == ON_STACK */
This wont work;
#else
if (PC_IN_CALL_DUMMY (p, 0, 0))
#endif
{
- fci->rsize = DUMMY_FRAME_RSIZE;
+ frame->rsize = DUMMY_FRAME_RSIZE;
/* This doesn't matter since we never try to get locals or args
from a dummy frame. */
- fci->msize = 0;
+ frame->msize = 0;
/* Dummy frames always use a memory frame pointer. */
- fci->saved_msp =
- read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4);
- fci->flags |= (TRANSPARENT|MFP_USED);
+ frame->saved_msp =
+ read_register_stack_integer (frame->frame + DUMMY_FRAME_RSIZE - 4, 4);
+ frame->flags |= (TRANSPARENT|MFP_USED);
return;
}
/* Search backward to find the trace-back tag. However,
do not trace back beyond the start of the text segment
(just as a sanity check to avoid going into never-never land). */
+#if 1
while (p >= text_start
&& ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0)
p -= 4;
-
+#else /* 0 */
+ char pat[4] = {0, 0, 0, 0};
+ char mask[4];
+ char insn_raw[4];
+ store_unsigned_integer (mask, 4, TAGWORD_ZERO_MASK);
+ /* Enable this once target_search is enabled and tested. */
+ target_search (4, pat, mask, p, -4, text_start, p+1, &p, &insn_raw);
+ insn = extract_unsigned_integer (insn_raw, 4);
+#endif /* 0 */
+
if (p < text_start)
{
/* Couldn't find the trace-back tag.
Something strange is going on. */
- fci->saved_msp = 0;
- fci->rsize = 0;
- fci->msize = 0;
- fci->flags = TRANSPARENT;
+ frame->saved_msp = 0;
+ frame->rsize = 0;
+ frame->msize = 0;
+ frame->flags = TRANSPARENT;
return;
}
else
else /* No tag try prologue */
examine_prologue (p, &rsize, &msize, &mfp_used);
- fci->rsize = rsize;
- fci->msize = msize;
- fci->flags = 0;
+ frame->rsize = rsize;
+ frame->msize = msize;
+ frame->flags = 0;
if (mfp_used)
- fci->flags |= MFP_USED;
+ frame->flags |= MFP_USED;
if (trans)
- fci->flags |= TRANSPARENT;
+ frame->flags |= TRANSPARENT;
if (innermost_frame)
{
- fci->saved_msp = read_register (MSP_REGNUM) + msize;
+ frame->saved_msp = read_register (MSP_REGNUM) + msize;
}
else
{
if (mfp_used)
- fci->saved_msp =
- read_register_stack_integer (fci->frame + rsize - 4, 4);
+ frame->saved_msp =
+ read_register_stack_integer (frame->frame + rsize - 4, 4);
else
- fci->saved_msp = fci->next->saved_msp + msize;
+ frame->saved_msp = frame->next->saved_msp + msize;
}
}
void
-init_extra_frame_info (fci)
- struct frame_info *fci;
+init_extra_frame_info (frame)
+ struct frame_info *frame;
{
- if (fci->next == 0)
+ if (frame->next == 0)
/* Assume innermost frame. May produce strange results for "info frame"
but there isn't any way to tell the difference. */
- init_frame_info (1, fci);
+ init_frame_info (1, frame);
else {
/* We're in get_prev_frame_info.
Take care of everything in init_frame_pc. */
}
void
-init_frame_pc (fromleaf, fci)
+init_frame_pc (fromleaf, frame)
int fromleaf;
- struct frame_info *fci;
+ struct frame_info *frame;
{
- fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) :
- fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ());
- init_frame_info (fromleaf, fci);
+ frame->pc = (fromleaf ? SAVED_PC_AFTER_CALL (frame->next) :
+ frame->next ? FRAME_SAVED_PC (frame->next) : read_pc ());
+ init_frame_info (fromleaf, frame);
}
\f
/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
otherwise it was fetched from a register.
The argument RAW_BUFFER must point to aligned memory. */
+
void
get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
char *raw_buffer;
int *optimized;
CORE_ADDR *addrp;
- FRAME frame;
+ struct frame_info *frame;
int regnum;
enum lval_type *lvalp;
{
CORE_ADDR addr;
enum lval_type lval;
+ if (!target_has_registers)
+ error ("No registers.");
+
+ /* Probably now redundant with the target_has_registers check. */
if (frame == 0)
return;
- fi = get_frame_info (frame);
-
/* Once something has a register number, it doesn't get optimized out. */
if (optimized != NULL)
*optimized = 0;
{
if (raw_buffer != NULL)
{
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), fi->frame);
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->frame);
}
if (lvalp != NULL)
*lvalp = not_lval;
{
if (raw_buffer != NULL)
{
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), fi->pc);
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
}
/* Not sure we have to do this. */
{
if (raw_buffer != NULL)
{
- if (fi->next != NULL)
+ if (frame->next != NULL)
{
store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
- fi->next->saved_msp);
+ frame->next->saved_msp);
}
else
read_register_gen (MSP_REGNUM, raw_buffer);
return;
}
- addr = fi->frame + (regnum - LR0_REGNUM) * 4;
+ addr = frame->frame + (regnum - LR0_REGNUM) * 4;
if (raw_buffer != NULL)
read_register_stack (addr, raw_buffer, &addr, &lval);
if (lvalp != NULL)
void
pop_frame ()
{
- FRAME frame = get_current_frame ();
- struct frame_info *fi = get_frame_info (frame);
- CORE_ADDR rfb = read_register (RFB_REGNUM);
- CORE_ADDR gr1 = fi->frame + fi->rsize;
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR rfb = read_register (RFB_REGNUM);
+ CORE_ADDR gr1 = frame->frame + frame->rsize;
CORE_ADDR lr1;
CORE_ADDR original_lr0;
int must_fix_lr0 = 0;
/* If popping a dummy frame, need to restore registers. */
if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
read_register (SP_REGNUM),
- FRAME_FP (fi)))
+ FRAME_FP (frame)))
{
int lrnum = LR0_REGNUM + DUMMY_ARG/4;
for (i = 0; i < DUMMY_SAVE_SR128; ++i)
}
/* Restore the memory stack pointer. */
- write_register (MSP_REGNUM, fi->saved_msp);
+ write_register (MSP_REGNUM, frame->saved_msp);
/* Restore the register stack pointer. */
write_register (GR1_REGNUM, gr1);
/* Fill. */
int num_bytes = lr1 - rfb;
int i;
- long word;
+ long word;
+
write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);
write_register (RFB_REGNUM, lr1);
for (i = 0; i < num_bytes; i += 4)
}
}
flush_cached_frames ();
- set_current_frame (create_new_frame (0, read_pc()));
}
/* Push an empty stack frame, to record the current PC, etc. */
gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
write_register (GR1_REGNUM, gr1);
+#ifdef VXWORKS_TARGET
+ /* We force re-reading all registers to get the new local registers set
+ after gr1 has been modified. This fix is due to the lack of single
+ register read/write operation in the RPC interface between VxGDB and
+ VxWorks. This really must be changed ! */
+
+ vx_read_register (-1);
+
+#endif /* VXWORK_TARGET */
+
rab = read_register (RAB_REGNUM);
if (gr1 < rab)
{
write_register (lrnum++, read_register (PC_REGNUM));
write_register (lrnum++, read_register (NPC_REGNUM));
write_register (lrnum++, read_register (PC2_REGNUM));
+
+ /* Why are we saving LR0? What would clobber it? (the dummy frame should
+ be below it on the register stack, no?). */
write_register (lrnum++, original_lr0);
}
three values (FP, PC, and MSP), we really need all three to do a
good job. */
-FRAME
+struct frame_info *
setup_arbitrary_frame (argc, argv)
int argc;
- FRAME_ADDR *argv;
+ CORE_ADDR *argv;
{
- FRAME fid;
+ struct frame_info *frame;
if (argc != 3)
error ("AMD 29k frame specifications require three arguments: rsp pc msp");
- fid = create_new_frame (argv[0], argv[1]);
+ frame = create_new_frame (argv[0], argv[1]);
- if (!fid)
+ if (!frame)
fatal ("internal: create_new_frame returned invalid frame id");
/* Creating a new frame munges the `frame' value from the current
GR1, so we restore it again here. FIXME, untangle all this
29K frame stuff... */
- fid->frame = argv[0];
+ frame->frame = argv[0];
/* Our MSP is in argv[2]. It'd be intelligent if we could just
save this value in the FRAME. But the way it's set up (FIXME),
we must save our caller's MSP. We compute that by adding our
memory stack frame size to our MSP. */
- fid->saved_msp = argv[2] + fid->msize;
+ frame->saved_msp = argv[2] + frame->msize;
- return fid;
+ return frame;
}
-
+int
+gdb_print_insn_a29k (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_big_a29k (memaddr, info);
+ else
+ return print_insn_little_a29k (memaddr, info);
+}
enum a29k_processor_types processor_type = a29k_unknown;
fprintf_filtered (gdb_stderr, " revision %c\n", 'A' + ((cfg_reg >> 24) & 0x0f));
}
+#ifdef GET_LONGJMP_TARGET
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+int
+get_longjmp_target(pc)
+ CORE_ADDR *pc;
+{
+ CORE_ADDR jb_addr;
+ char buf[sizeof(CORE_ADDR)];
+
+ jb_addr = read_register(LR2_REGNUM);
+
+ if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, (char *) buf,
+ sizeof(CORE_ADDR)))
+ return 0;
+
+ *pc = extract_address ((PTR) buf, sizeof(CORE_ADDR));
+ return 1;
+}
+#endif /* GET_LONGJMP_TARGET */
+
void
-_initialize_29k()
+_initialize_a29k_tdep ()
{
extern CORE_ADDR text_end;
+ tm_print_insn = gdb_print_insn_a29k;
+
/* FIXME, there should be a way to make a CORE_ADDR variable settable. */
add_show_from_set
(add_set_cmd ("rstack_high_address", class_support, var_uinteger,