From d7d35f004c9c506c0b3f7002d96bad37bb492411 Mon Sep 17 00:00:00 2001 From: Fred Fish Date: Mon, 29 Mar 1993 23:38:30 +0000 Subject: * config/a29k/tm-a29k.h: Renamed from config/a29k/tm-29k.h. * a29k-pinsn.c: Renamed from am29k-pinsn.c. * a29k-tdep.c: Renamed from am29k-tdep.c. * remote-eb.c, config/a29k/tm-ultra3.h: Include renamed tm-a29k.h. * remote-monitor.c, remote-st2000.c, config/a29k/{nm-ultra3.h, tm-a29k.h, xm-ultra3.h}, config/romp/rtbsd.mh, doc/gdbinv-s.texi, testsuite/gdb.t15/funcargs.exp, testsuite/gdb.t17/callfuncs.exp: Map '29k' to 'a29k'. * config/a29k/{a29k-kern.mt, a29k-udi.mt, a29k.mt, ultra3.mt} (TDEPFILES): Use renamed a29k-pinsn.o and a29k-tdep.o. * config/a29k/{a29k-udi.mt, a29k.mt} (TM_FILE): Use renamed tm-a29k.h. * config/a29k/a29k-udi.mt (MT_CFLAGS): Remove TARGET_AM29K define that does not appear anywhere else in the gdb source tree. * doc/gdbinit.texinfo: Document renaming of tm-29k.h to tm-a29k.h. --- gdb/ChangeLog | 25 +- gdb/a29k-pinsn.c | 300 ++++++++++++++++ gdb/a29k-tdep.c | 831 +++++++++++++++++++++++++++++++++++++++++++ gdb/am29k-pinsn.c | 300 ---------------- gdb/am29k-tdep.c | 831 ------------------------------------------- gdb/config/a29k/a29k-kern.mt | 2 +- gdb/config/a29k/a29k-udi.mt | 6 +- gdb/config/a29k/a29k.mt | 4 +- gdb/config/a29k/nm-ultra3.h | 2 +- gdb/config/a29k/tm-a29k.h | 26 +- gdb/config/a29k/tm-ultra3.h | 8 +- gdb/config/a29k/ultra3.mt | 2 +- gdb/config/a29k/xm-ultra3.h | 4 +- gdb/doc/gdbint.texinfo | 34 +- gdb/doc/gdbinv-s.texi | 8 +- gdb/remote-eb.c | 4 +- gdb/remote-monitor.c | 2 +- gdb/remote-st2000.c | 2 +- 18 files changed, 1201 insertions(+), 1190 deletions(-) create mode 100644 gdb/a29k-pinsn.c create mode 100644 gdb/a29k-tdep.c delete mode 100644 gdb/am29k-pinsn.c delete mode 100644 gdb/am29k-tdep.c (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b5aadf8..b45fd61 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +Mon Mar 29 15:03:25 1993 Fred Fish (fnf@cygnus.com) + + * config/a29k/tm-a29k.h: Renamed from config/a29k/tm-29k.h. + * a29k-pinsn.c: Renamed from am29k-pinsn.c. + * a29k-tdep.c: Renamed from am29k-tdep.c. + * remote-eb.c, config/a29k/tm-ultra3.h: Include renamed tm-a29k.h. + * remote-monitor.c, remote-st2000.c, config/a29k/{nm-ultra3.h, + tm-a29k.h, xm-ultra3.h}, config/romp/rtbsd.mh, doc/gdbinv-s.texi, + testsuite/gdb.t15/funcargs.exp, testsuite/gdb.t17/callfuncs.exp: + Map '29k' to 'a29k'. + * config/a29k/{a29k-kern.mt, a29k-udi.mt, a29k.mt, ultra3.mt} + (TDEPFILES): Use renamed a29k-pinsn.o and a29k-tdep.o. + * config/a29k/{a29k-udi.mt, a29k.mt} (TM_FILE): Use renamed + tm-a29k.h. + * config/a29k/a29k-udi.mt (MT_CFLAGS): Remove TARGET_AM29K + define that does not appear anywhere else in the gdb source tree. + * doc/gdbinit.texinfo: Document renaming of tm-29k.h to tm-a29k.h. + Mon Mar 29 13:55:29 1993 Jim Kingdon (kingdon@cygnus.com) * xcoffread.c (sort_syms, compare_symbols): Remove. @@ -6,11 +24,6 @@ Mon Mar 29 13:55:29 1993 Jim Kingdon (kingdon@cygnus.com) * xcoffread.c: Nuke NAMES_HAVE_DOT define (not used). -Fri Mar 26 11:29:30 1993 Jim Kingdon (kingdon@cygnus.com) - - * breakpoint.{c,h}: Add exp_string to struct breakpoint and use - it in breakpoint_re_set. - Sun Mar 28 11:24:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) * breakpoint.c (breakpoint_re_set_one): Fix storage leak. @@ -33,6 +46,8 @@ Fri Mar 26 15:25:05 1993 John Gilmore (gnu@cygnus.com) Fri Mar 26 11:29:30 1993 Jim Kingdon (kingdon@cygnus.com) + * breakpoint.{c,h}: Add exp_string to struct breakpoint and use + it in breakpoint_re_set. * breakpoint.c (watch_command, enable_breakpoint): Fetch lazy values. * rs6000-tdep.c (single_step): Misc cleanups (CORE_ADDR not int, diff --git a/gdb/a29k-pinsn.c b/gdb/a29k-pinsn.c new file mode 100644 index 0000000..bd95aef --- /dev/null +++ b/gdb/a29k-pinsn.c @@ -0,0 +1,300 @@ +/* Instruction printing code for the AMD 29000 + Copyright (C) 1990 Free Software Foundation, Inc. + Contributed by Cygnus Support. Written by Jim Kingdon. + +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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "target.h" +#include "opcode/a29k.h" + +/* Print a symbolic representation of a general-purpose + register number NUM on STREAM. + NUM is a number as found in the instruction, not as found in + debugging symbols; it must be in the range 0-255. */ +static void +print_general (num, stream) + int num; + FILE *stream; +{ + if (num < 128) + fprintf_filtered (stream, "gr%d", num); + else + fprintf_filtered (stream, "lr%d", num - 128); +} + +/* Like print_general but a special-purpose register. + + The mnemonics used by the AMD assembler are not quite the same + as the ones in the User's Manual. We use the ones that the + assembler uses. */ +static void +print_special (num, stream) + int num; + FILE *stream; +{ + /* Register names of registers 0-SPEC0_NUM-1. */ + static char *spec0_names[] = { + "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", + "pc0", "pc1", "pc2", "mmu", "lru" + }; +#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0])) + + /* Register names of registers 128-128+SPEC128_NUM-1. */ + static char *spec128_names[] = { + "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr" + }; +#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0])) + + /* Register names of registers 160-160+SPEC160_NUM-1. */ + static char *spec160_names[] = { + "fpe", "inte", "fps", "sr163", "exop" + }; +#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0])) + + if (num < SPEC0_NUM) + fprintf_filtered (stream, spec0_names[num]); + else if (num >= 128 && num < 128 + SPEC128_NUM) + fprintf_filtered (stream, spec128_names[num-128]); + else if (num >= 160 && num < 160 + SPEC160_NUM) + fprintf_filtered (stream, spec160_names[num-160]); + else + fprintf_filtered (stream, "sr%d", num); +} + +/* Is an instruction with OPCODE a delayed branch? */ +static int +is_delayed_branch (opcode) + int opcode; +{ + return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1 + || opcode == 0xa4 || opcode == 0xa5 + || opcode == 0xb4 || opcode == 0xb5 + || opcode == 0xc4 || opcode == 0xc0 + || opcode == 0xac || opcode == 0xad + || opcode == 0xcc); +} + +/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}. + Note that the amd can be set up as either + big or little-endian (the tm file says which) and we can't assume + the host machine is the same. */ +static void +find_bytes (insn, insn0, insn8, insn16, insn24) + char *insn; + unsigned char *insn0; + unsigned char *insn8; + unsigned char *insn16; + unsigned char *insn24; +{ +#if TARGET_BYTE_ORDER == BIG_ENDIAN + *insn24 = insn[0]; + *insn16 = insn[1]; + *insn8 = insn[2]; + *insn0 = insn[3]; +#else /* Little-endian. */ + *insn24 = insn[3]; + *insn16 = insn[2]; + *insn8 = insn[1]; + *insn0 = insn[0]; +#endif /* Little-endian. */ +} + +/* Print one instruction from MEMADDR on STREAM. + Return the size of the instruction (always 4 on a29k). */ +int +print_insn (memaddr, stream) + CORE_ADDR memaddr; + FILE *stream; +{ + /* The raw instruction. */ + char insn[4]; + + /* The four bytes of the instruction. */ + unsigned char insn24, insn16, insn8, insn0; + + struct a29k_opcode const * opcode; + + read_memory (memaddr, &insn[0], 4); + + find_bytes (insn, &insn0, &insn8, &insn16, &insn24); + + /* Handle the nop (aseq 0x40,gr1,gr1) specially */ + if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) { + fprintf_filtered (stream,"nop"); + return 4; + } + + /* The opcode is always in insn24. */ + for (opcode = &a29k_opcodes[0]; + opcode < &a29k_opcodes[num_opcodes]; + ++opcode) + { + if ((insn24<<24) == opcode->opcode) + { + char *s; + + fprintf_filtered (stream, "%s ", opcode->name); + for (s = opcode->args; *s != '\0'; ++s) + { + switch (*s) + { + case 'a': + print_general (insn8, stream); + break; + + case 'b': + print_general (insn0, stream); + break; + + case 'c': + print_general (insn16, stream); + break; + + case 'i': + fprintf_filtered (stream, "%d", insn0); + break; + + case 'x': + fprintf_filtered (stream, "%d", (insn16 << 8) + insn0); + break; + + case 'h': + fprintf_filtered (stream, "0x%x", + (insn16 << 24) + (insn0 << 16)); + break; + + case 'X': + fprintf_filtered (stream, "%d", + ((insn16 << 8) + insn0) | 0xffff0000); + break; + + case 'P': + /* This output looks just like absolute addressing, but + maybe that's OK (it's what the GDB 68k and EBMON + 29k disassemblers do). */ + /* All the shifting is to sign-extend it. p*/ + print_address + (memaddr + + (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14), + stream); + break; + + case 'A': + print_address ((insn16 << 10) + (insn0 << 2), stream); + break; + + case 'e': + fprintf_filtered (stream, "%d", insn16 >> 7); + break; + + case 'n': + fprintf_filtered (stream, "0x%x", insn16 & 0x7f); + break; + + case 'v': + fprintf_filtered (stream, "0x%x", insn16); + break; + + case 's': + print_special (insn8, stream); + break; + + case 'u': + fprintf_filtered (stream, "%d", insn0 >> 7); + break; + + case 'r': + fprintf_filtered (stream, "%d", (insn0 >> 4) & 7); + break; + + case 'd': + fprintf_filtered (stream, "%d", (insn0 >> 2) & 3); + break; + + case 'f': + fprintf_filtered (stream, "%d", insn0 & 3); + break; + + case 'F': + fprintf_filtered (stream, "%d", (insn16 >> 2) & 15); + break; + + case 'C': + fprintf_filtered (stream, "%d", insn16 & 3); + break; + + default: + fprintf_filtered (stream, "%c", *s); + } + } + + /* Now we look for a const,consth pair of instructions, + in which case we try to print the symbolic address. */ + if (insn24 == 2) /* consth */ + { + int errcode; + char prev_insn[4]; + unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24; + + errcode = target_read_memory (memaddr - 4, + &prev_insn[0], + 4); + if (errcode == 0) + { + /* If it is a delayed branch, we need to look at the + instruction before the delayed brach to handle + things like + + const _foo + call _printf + consth _foo + */ + find_bytes (prev_insn, &prev_insn0, &prev_insn8, + &prev_insn16, &prev_insn24); + if (is_delayed_branch (prev_insn24)) + { + errcode = target_read_memory + (memaddr - 8, &prev_insn[0], 4); + find_bytes (prev_insn, &prev_insn0, &prev_insn8, + &prev_insn16, &prev_insn24); + } + } + + /* If there was a problem reading memory, then assume + the previous instruction was not const. */ + if (errcode == 0) + { + /* Is it const to the same register? */ + if (prev_insn24 == 3 + && prev_insn8 == insn8) + { + fprintf_filtered (stream, "\t; "); + print_address (((insn16 << 24) + (insn0 << 16) + + (prev_insn16 << 8) + (prev_insn0)), + stream); + } + } + } + + return 4; + } + } + fprintf_filtered (stream, ".word 0x%8x", + (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0); + return 4; +} diff --git a/gdb/a29k-tdep.c b/gdb/a29k-tdep.c new file mode 100644 index 0000000..dfb8398 --- /dev/null +++ b/gdb/a29k-tdep.c @@ -0,0 +1,831 @@ +/* Target-machine dependent code for the AMD 29000 + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Contributed by Cygnus Support. Written by Jim Kingdon. + +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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "frame.h" +#include "value.h" +#include "symtab.h" +#include "inferior.h" +#include "gdbcmd.h" + +/* If all these bits in an instruction word are zero, it is a "tag word" + which precedes a function entry point and gives stack traceback info. + This used to be defined as 0xff000000, but that treated 0x00000deb as + a tag word, while it is really used as a breakpoint. */ +#define TAGWORD_ZERO_MASK 0xff00f800 + +extern CORE_ADDR text_start; /* FIXME, kludge... */ + +/* The user-settable top of the register stack in virtual memory. We + won't attempt to access any stored registers above this address, if set + nonzero. */ + +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 */ + unsigned rsize, msize; /* register stack frame size, mem stack ditto */ + unsigned mfp_used : 1; /* memory frame pointer used */ + unsigned rsize_valid : 1; /* Validity bits for the above */ + unsigned msize_valid : 1; + unsigned mfp_valid : 1; +}; + +/* Examine the prologue of a function which starts at PC. Return + the first addess past the prologue. If MSIZE is non-NULL, then + set *MSIZE to the memory stack frame size. If RSIZE is non-NULL, + then set *RSIZE to the register stack frame size (not including + incoming arguments and the return address & frame pointer stored + with them). If no prologue is found, *RSIZE is set to zero. + If no prologue is found, or a prologue which doesn't involve + allocating a memory stack frame, then set *MSIZE to zero. + + Note that both msize and rsize are in bytes. This is not consistent + with the _User's Manual_ with respect to rsize, but it is much more + convenient. + + 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; + unsigned *msize; + unsigned *rsize; + int *mfp_used; +{ + long insn; + CORE_ADDR p = pc; + struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc); + struct prologue_info *mi = 0; + + if (msymbol != NULL) + mi = (struct prologue_info *) msymbol -> info; + + if (mi != 0) + { + int valid = 1; + if (rsize != NULL) + { + *rsize = mi->rsize; + valid &= mi->rsize_valid; + } + if (msize != NULL) + { + *msize = mi->msize; + valid &= mi->msize_valid; + } + if (mfp_used != NULL) + { + *mfp_used = mi->mfp_used; + valid &= mi->mfp_valid; + } + if (valid) + return mi->pc; + } + + if (rsize != NULL) + *rsize = 0; + if (msize != NULL) + *msize = 0; + if (mfp_used != NULL) + *mfp_used = 0; + + /* Prologue must start with subtracting a constant from gr1. + Normally this is sub gr1,gr1,. */ + insn = read_memory_integer (p, 4); + if ((insn & 0xffffff00) != 0x25010100) + { + /* If the frame is large, instead of a single instruction it + might be a pair of instructions: + const , + sub gr1,gr1, + */ + int reg; + /* Possible value for rsize. */ + unsigned int rsize0; + + if ((insn & 0xff000000) != 0x03000000) + { + p = pc; + goto done; + } + reg = (insn >> 8) & 0xff; + rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff)); + p += 4; + insn = read_memory_integer (p, 4); + if ((insn & 0xffffff00) != 0x24010100 + || (insn & 0xff) != reg) + { + p = pc; + goto done; + } + if (rsize != NULL) + *rsize = rsize0; + } + else + { + if (rsize != NULL) + *rsize = (insn & 0xff); + } + p += 4; + + /* Next instruction must be asgeu V_SPILL,gr1,rab. + * We don't check the vector number to allow for kernel debugging. The + * kernel will use a different trap number. + */ + insn = read_memory_integer (p, 4); + if ((insn & 0xff00ffff) != (0x5e000100|RAB_HW_REGNUM)) + { + p = pc; + goto done; + } + p += 4; + + /* Next instruction usually sets the frame pointer (lr1) by adding + from gr1. However, this can (and high C does) be + deferred until anytime before the first function call. So it is + OK if we don't see anything which sets lr1. + To allow for alternate register sets (gcc -mkernel-registers) the msp + register number is a compile time constant. */ + + /* Normally this is just add lr1,gr1,. */ + insn = read_memory_integer (p, 4); + if ((insn & 0xffffff00) == 0x15810100) + p += 4; + else + { + /* However, for large frames it can be + const , + add lr1,gr1, + */ + int reg; + CORE_ADDR q; + + if ((insn & 0xff000000) == 0x03000000) + { + reg = (insn >> 8) & 0xff; + q = p + 4; + insn = read_memory_integer (q, 4); + if ((insn & 0xffffff00) == 0x14810100 + && (insn & 0xff) == reg) + p = q; + } + } + + /* Next comes "add lr{},msp,0", but only if a memory + frame pointer is in use. We just check for add lr,msp,0; + we don't check this rsize against the first instruction, and + we don't check that the trace-back tag indicates a memory frame pointer + is in use. + To allow for alternate register sets (gcc -mkernel-registers) the msp + register number is a compile time constant. + + The recommended instruction is actually "sll lr,msp,0". + We check for that, too. Originally Jim Kingdon's code seemed + to be looking for a "sub" instruction here, but the mask was set + up to lose all the time. */ + insn = read_memory_integer (p, 4); + if (((insn & 0xff80ffff) == (0x15800000|(MSP_HW_REGNUM<<8))) /* add */ + || ((insn & 0xff80ffff) == (0x81800000|(MSP_HW_REGNUM<<8)))) /* sll */ + { + p += 4; + if (mfp_used != NULL) + *mfp_used = 1; + } + + /* Next comes a subtraction from msp to allocate a memory frame, + but only if a memory frame is + being used. We don't check msize against the trace-back tag. + + To allow for alternate register sets (gcc -mkernel-registers) the msp + register number is a compile time constant. + + Normally this is just + sub msp,msp, + */ + insn = read_memory_integer (p, 4); + if ((insn & 0xffffff00) == + (0x25000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8))) + { + p += 4; + if (msize != NULL) + *msize = insn & 0xff; + } + else + { + /* For large frames, instead of a single instruction it might + be + + const , + consth , ; optional + sub msp,msp, + */ + int reg; + unsigned msize0; + CORE_ADDR q = p; + + if ((insn & 0xff000000) == 0x03000000) + { + reg = (insn >> 8) & 0xff; + msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff); + q += 4; + insn = read_memory_integer (q, 4); + /* Check for consth. */ + if ((insn & 0xff000000) == 0x02000000 + && (insn & 0x0000ff00) == reg) + { + msize0 |= (insn << 8) & 0xff000000; + msize0 |= (insn << 16) & 0x00ff0000; + q += 4; + insn = read_memory_integer (q, 4); + } + /* Check for sub msp,msp,. */ + if ((insn & 0xffffff00) == + (0x24000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8)) + && (insn & 0xff) == reg) + { + p = q + 4; + if (msize != NULL) + *msize = msize0; + } + } + } + + done: + if (msymbol != NULL) + { + if (mi == 0) + { + /* Add a new cache entry. */ + mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info)); + msymbol -> info = (char *)mi; + mi->rsize_valid = 0; + mi->msize_valid = 0; + mi->mfp_valid = 0; + } + /* else, cache entry exists, but info is incomplete. */ + mi->pc = p; + if (rsize != NULL) + { + mi->rsize = *rsize; + mi->rsize_valid = 1; + } + if (msize != NULL) + { + mi->msize = *msize; + mi->msize_valid = 1; + } + if (mfp_used != NULL) + { + mi->mfp_used = *mfp_used; + mi->mfp_valid = 1; + } + } + return p; +} + +/* Advance PC across any function entry prologue instructions + to reach some "real" code. */ + +CORE_ADDR +skip_prologue (pc) + CORE_ADDR pc; +{ + return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL, + (int *)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 + * by returning 0. The documentation for the tag word was taken from + * page 7-15 of the 29050 User's Manual. We are assuming that the + * m bit is in bit 22 of the tag word, which seems to be the agreed upon + * 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) + CORE_ADDR p; + int *is_trans; + int *argcount; + unsigned *msize; + int *mfp_used; +{ + unsigned int tag1, tag2; + + tag1 = read_memory_integer (p, 4); + if ((tag1 & TAGWORD_ZERO_MASK) != 0) /* Not a tag word */ + return 0; + if (tag1 & (1<<23)) /* A two word tag */ + { + tag2 = read_memory_integer (p+4, 4); + if (msize) + *msize = tag2; + } + else /* A one word tag */ + { + if (msize) + *msize = tag1 & 0x7ff; + } + if (is_trans) + *is_trans = ((tag1 & (1<<21)) ? 1 : 0); + if (argcount) + *argcount = (tag1 >> 16) & 0x1f; + if (mfp_used) + *mfp_used = ((tag1 & (1<<22)) ? 1 : 0); + 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) + int innermost_frame; + struct frame_info *fci; +{ + CORE_ADDR p; + long insn; + unsigned rsize; + unsigned msize; + int mfp_used, trans; + struct symbol *func; + + p = fci->pc; + + if (innermost_frame) + fci->frame = read_register (GR1_REGNUM); + else + fci->frame = fci->next_frame + fci->next->rsize; + +#if CALL_DUMMY_LOCATION == ON_STACK + This wont work; +#else + if (PC_IN_CALL_DUMMY (p, 0, 0)) +#endif + { + fci->rsize = DUMMY_FRAME_RSIZE; + /* This doesn't matter since we never try to get locals or args + from a dummy frame. */ + fci->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); + return; + } + + func = find_pc_function (p); + if (func != NULL) + p = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); + else + { + /* 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). */ + while (p >= text_start + && ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0) + p -= 4; + + 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; + return; + } + else + /* Advance to the first word of the function, i.e. the word + after the trace-back tag. */ + p += 4; + } + /* We've found the start of the function. + * Try looking for a tag word that indicates whether there is a + * memory frame pointer and what the memory stack allocation is. + * If one doesn't exist, try using a more exhaustive search of + * the prologue. For now we don't care about the argcount or + * whether or not the routine is transparent. + */ + if (examine_tag(p-4,&trans,NULL,&msize,&mfp_used)) /* Found a good tag */ + examine_prologue (p, &rsize, 0, 0); + else /* No tag try prologue */ + examine_prologue (p, &rsize, &msize, &mfp_used); + + fci->rsize = rsize; + fci->msize = msize; + fci->flags = 0; + if (mfp_used) + fci->flags |= MFP_USED; + if (trans) + fci->flags |= TRANSPARENT; + if (innermost_frame) + { + fci->saved_msp = read_register (MSP_REGNUM) + msize; + } + else + { + if (mfp_used) + fci->saved_msp = + read_register_stack_integer (fci->frame + rsize - 4, 4); + else + fci->saved_msp = fci->next->saved_msp + msize; + } +} + +void +init_extra_frame_info (fci) + struct frame_info *fci; +{ + if (fci->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); + else { + /* We're in get_prev_frame_info. + Take care of everything in init_frame_pc. */ + ; + } +} + +void +init_frame_pc (fromleaf, fci) + int fromleaf; + struct frame_info *fci; +{ + fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) : + fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ()); + init_frame_info (fromleaf, fci); +} + +/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their + offsets being relative to the memory stack pointer (high C) or + saved_msp (gcc). */ + +CORE_ADDR +frame_locals_address (fi) + struct frame_info *fi; +{ + if (fi->flags & MFP_USED) + return fi->saved_msp; + else + return fi->saved_msp - fi->msize; +} + +/* Routines for reading the register stack. The caller gets to treat + the register stack as a uniform stack in memory, from address $gr1 + straight through $rfb and beyond. */ + +/* Analogous to read_memory except the length is understood to be 4. + Also, myaddr can be NULL (meaning don't bother to read), and + if actual_mem_addr is non-NULL, store there the address that it + was fetched from (or if from a register the offset within + registers). Set *LVAL to lval_memory or lval_register, depending + on where it came from. */ +void +read_register_stack (memaddr, myaddr, actual_mem_addr, lval) + CORE_ADDR memaddr; + char *myaddr; + CORE_ADDR *actual_mem_addr; + enum lval_type *lval; +{ + long rfb = read_register (RFB_REGNUM); + long rsp = read_register (RSP_REGNUM); + + /* If we don't do this 'info register' stops in the middle. */ + if (memaddr >= rstack_high_address) + { + int val = -1; /* a bogus value */ + /* It's in a local register, but off the end of the stack. */ + int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; + if (myaddr != NULL) + *(int*)myaddr = val; /* Provide bogusness */ + supply_register(regnum, (char *)&val); /* More bogusness */ + if (lval != NULL) + *lval = lval_register; + if (actual_mem_addr != NULL) + *actual_mem_addr = REGISTER_BYTE (regnum); + } + /* If it's in the part of the register stack that's in real registers, + get the value from the registers. If it's anywhere else in memory + (e.g. in another thread's saved stack), skip this part and get + it from real live memory. */ + else if (memaddr < rfb && memaddr >= rsp) + { + /* It's in a register. */ + int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; + if (regnum > LR0_REGNUM + 127) + error ("Attempt to read register stack out of range."); + if (myaddr != NULL) + read_register_gen (regnum, myaddr); + if (lval != NULL) + *lval = lval_register; + if (actual_mem_addr != NULL) + *actual_mem_addr = REGISTER_BYTE (regnum); + } + else + { + /* It's in the memory portion of the register stack. */ + if (myaddr != NULL) + read_memory (memaddr, myaddr, 4); + if (lval != NULL) + *lval = lval_memory; + if (actual_mem_addr != NULL) + *actual_mem_addr = memaddr; + } +} + +/* Analogous to read_memory_integer + except the length is understood to be 4. */ +long +read_register_stack_integer (memaddr, len) + CORE_ADDR memaddr; + int len; +{ + long buf; + read_register_stack (memaddr, &buf, NULL, NULL); + SWAP_TARGET_AND_HOST (&buf, 4); + return buf; +} + +/* Copy 4 bytes from GDB memory at MYADDR into inferior memory + at MEMADDR and put the actual address written into in + *ACTUAL_MEM_ADDR. */ +static void +write_register_stack (memaddr, myaddr, actual_mem_addr) + CORE_ADDR memaddr; + char *myaddr; + CORE_ADDR *actual_mem_addr; +{ + long rfb = read_register (RFB_REGNUM); + long rsp = read_register (RSP_REGNUM); + /* If we don't do this 'info register' stops in the middle. */ + if (memaddr >= rstack_high_address) + { + /* It's in a register, but off the end of the stack. */ + if (actual_mem_addr != NULL) + *actual_mem_addr = 0; + } + else if (memaddr < rfb) + { + /* It's in a register. */ + int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; + if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127) + error ("Attempt to read register stack out of range."); + if (myaddr != NULL) + write_register (regnum, *(long *)myaddr); + if (actual_mem_addr != NULL) + *actual_mem_addr = 0; + } + else + { + /* It's in the memory portion of the register stack. */ + if (myaddr != NULL) + write_memory (memaddr, myaddr, 4); + if (actual_mem_addr != NULL) + *actual_mem_addr = memaddr; + } +} + +/* Find register number REGNUM relative to FRAME and put its + (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable + was optimized out (and thus can't be fetched). If the variable + was fetched from memory, set *ADDRP to where it was fetched from, + 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; + int regnum; + enum lval_type *lvalp; +{ + struct frame_info *fi; + CORE_ADDR addr; + enum lval_type lval; + + 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 (regnum == RSP_REGNUM) + { + if (raw_buffer != NULL) + *(CORE_ADDR *)raw_buffer = fi->frame; + if (lvalp != NULL) + *lvalp = not_lval; + return; + } + else if (regnum == PC_REGNUM) + { + if (raw_buffer != NULL) + *(CORE_ADDR *)raw_buffer = fi->pc; + + /* Not sure we have to do this. */ + if (lvalp != NULL) + *lvalp = not_lval; + + return; + } + else if (regnum == MSP_REGNUM) + { + if (raw_buffer != NULL) + { + if (fi->next != NULL) + *(CORE_ADDR *)raw_buffer = fi->next->saved_msp; + else + *(CORE_ADDR *)raw_buffer = read_register (MSP_REGNUM); + } + /* The value may have been computed, not fetched. */ + if (lvalp != NULL) + *lvalp = not_lval; + return; + } + else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128) + { + /* These registers are not saved over procedure calls, + so just print out the current values. */ + if (raw_buffer != NULL) + *(CORE_ADDR *)raw_buffer = read_register (regnum); + if (lvalp != NULL) + *lvalp = lval_register; + if (addrp != NULL) + *addrp = REGISTER_BYTE (regnum); + return; + } + + addr = fi->frame + (regnum - LR0_REGNUM) * 4; + if (raw_buffer != NULL) + read_register_stack (addr, raw_buffer, &addr, &lval); + if (lvalp != NULL) + *lvalp = lval; + if (addrp != NULL) + *addrp = addr; +} + + +/* Discard from the stack the innermost frame, + restoring all saved registers. */ + +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; + CORE_ADDR lr1; + int i; + + /* 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))) + { + int lrnum = LR0_REGNUM + DUMMY_ARG/4; + for (i = 0; i < DUMMY_SAVE_SR128; ++i) + write_register (SR_REGNUM (i + 128),read_register (lrnum++)); + for (i = 0; i < DUMMY_SAVE_SR160; ++i) + write_register (SR_REGNUM(i+160), read_register (lrnum++)); + for (i = 0; i < DUMMY_SAVE_GREGS; ++i) + write_register (RETURN_REGNUM + i, read_register (lrnum++)); + /* Restore the PCs. */ + write_register(PC_REGNUM, read_register (lrnum++)); + write_register(NPC_REGNUM, read_register (lrnum)); + } + + /* Restore the memory stack pointer. */ + write_register (MSP_REGNUM, fi->saved_msp); + /* Restore the register stack pointer. */ + write_register (GR1_REGNUM, gr1); + /* Check whether we need to fill registers. */ + lr1 = read_register (LR0_REGNUM + 1); + if (lr1 > rfb) + { + /* Fill. */ + int num_bytes = lr1 - rfb; + int i; + 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) + { + /* Note: word is in host byte order. */ + word = read_memory_integer (rfb + i, 4); + write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word); + } + } + flush_cached_frames (); + set_current_frame (create_new_frame (0, read_pc())); +} + +/* Push an empty stack frame, to record the current PC, etc. */ + +void +push_dummy_frame () +{ + long w; + CORE_ADDR rab, gr1; + CORE_ADDR msp = read_register (MSP_REGNUM); + int lrnum, i, saved_lr0; + + + /* Allocate the new frame. */ + gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE; + write_register (GR1_REGNUM, gr1); + + rab = read_register (RAB_REGNUM); + if (gr1 < rab) + { + /* We need to spill registers. */ + int num_bytes = rab - gr1; + CORE_ADDR rfb = read_register (RFB_REGNUM); + int i; + long word; + + write_register (RFB_REGNUM, rfb - num_bytes); + write_register (RAB_REGNUM, gr1); + for (i = 0; i < num_bytes; i += 4) + { + /* Note: word is in target byte order. */ + read_register_gen (LR0_REGNUM + i / 4, (char *) &word); + write_memory (rfb - num_bytes + i, (char *) &word, 4); + } + } + + /* There are no arguments in to the dummy frame, so we don't need + more than rsize plus the return address and lr1. */ + write_register (LR0_REGNUM + 1, gr1 + DUMMY_FRAME_RSIZE + 2 * 4); + + /* Set the memory frame pointer. */ + write_register (LR0_REGNUM + DUMMY_FRAME_RSIZE / 4 - 1, msp); + + /* Allocate arg_slop. */ + write_register (MSP_REGNUM, msp - 16 * 4); + + /* Save registers. */ + lrnum = LR0_REGNUM + DUMMY_ARG/4; + for (i = 0; i < DUMMY_SAVE_SR128; ++i) + write_register (lrnum++, read_register (SR_REGNUM (i + 128))); + for (i = 0; i < DUMMY_SAVE_SR160; ++i) + write_register (lrnum++, read_register (SR_REGNUM (i + 160))); + for (i = 0; i < DUMMY_SAVE_GREGS; ++i) + write_register (lrnum++, read_register (RETURN_REGNUM + i)); + /* Save the PCs. */ + write_register (lrnum++, read_register (PC_REGNUM)); + write_register (lrnum, read_register (NPC_REGNUM)); +} + + +void +_initialize_29k() +{ + extern CORE_ADDR text_end; + + /* 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, + (char *)&rstack_high_address, + "Set top address in memory of the register stack.\n\ +Attempts to access registers saved above this address will be ignored\n\ +or will produce the value -1.", &setlist), + &showlist); + + /* FIXME, there should be a way to make a CORE_ADDR variable settable. */ + add_show_from_set + (add_set_cmd ("call_scratch_address", class_support, var_uinteger, + (char *)&text_end, +"Set address in memory where small amounts of RAM can be used\n\ +when making function calls into the inferior.", &setlist), + &showlist); +} diff --git a/gdb/am29k-pinsn.c b/gdb/am29k-pinsn.c deleted file mode 100644 index 36b7344..0000000 --- a/gdb/am29k-pinsn.c +++ /dev/null @@ -1,300 +0,0 @@ -/* Instruction printing code for the AMD 29000 - Copyright (C) 1990 Free Software Foundation, Inc. - Contributed by Cygnus Support. Written by Jim Kingdon. - -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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "defs.h" -#include "target.h" -#include "opcode/a29k.h" - -/* Print a symbolic representation of a general-purpose - register number NUM on STREAM. - NUM is a number as found in the instruction, not as found in - debugging symbols; it must be in the range 0-255. */ -static void -print_general (num, stream) - int num; - FILE *stream; -{ - if (num < 128) - fprintf_filtered (stream, "gr%d", num); - else - fprintf_filtered (stream, "lr%d", num - 128); -} - -/* Like print_general but a special-purpose register. - - The mnemonics used by the AMD assembler are not quite the same - as the ones in the User's Manual. We use the ones that the - assembler uses. */ -static void -print_special (num, stream) - int num; - FILE *stream; -{ - /* Register names of registers 0-SPEC0_NUM-1. */ - static char *spec0_names[] = { - "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", - "pc0", "pc1", "pc2", "mmu", "lru" - }; -#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0])) - - /* Register names of registers 128-128+SPEC128_NUM-1. */ - static char *spec128_names[] = { - "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr" - }; -#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0])) - - /* Register names of registers 160-160+SPEC160_NUM-1. */ - static char *spec160_names[] = { - "fpe", "inte", "fps", "sr163", "exop" - }; -#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0])) - - if (num < SPEC0_NUM) - fprintf_filtered (stream, spec0_names[num]); - else if (num >= 128 && num < 128 + SPEC128_NUM) - fprintf_filtered (stream, spec128_names[num-128]); - else if (num >= 160 && num < 160 + SPEC160_NUM) - fprintf_filtered (stream, spec160_names[num-160]); - else - fprintf_filtered (stream, "sr%d", num); -} - -/* Is an instruction with OPCODE a delayed branch? */ -static int -is_delayed_branch (opcode) - int opcode; -{ - return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1 - || opcode == 0xa4 || opcode == 0xa5 - || opcode == 0xb4 || opcode == 0xb5 - || opcode == 0xc4 || opcode == 0xc0 - || opcode == 0xac || opcode == 0xad - || opcode == 0xcc); -} - -/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}. - Note that the amd can be set up as either - big or little-endian (the tm file says which) and we can't assume - the host machine is the same. */ -static void -find_bytes (insn, insn0, insn8, insn16, insn24) - char *insn; - unsigned char *insn0; - unsigned char *insn8; - unsigned char *insn16; - unsigned char *insn24; -{ -#if TARGET_BYTE_ORDER == BIG_ENDIAN - *insn24 = insn[0]; - *insn16 = insn[1]; - *insn8 = insn[2]; - *insn0 = insn[3]; -#else /* Little-endian. */ - *insn24 = insn[3]; - *insn16 = insn[2]; - *insn8 = insn[1]; - *insn0 = insn[0]; -#endif /* Little-endian. */ -} - -/* Print one instruction from MEMADDR on STREAM. - Return the size of the instruction (always 4 on am29k). */ -int -print_insn (memaddr, stream) - CORE_ADDR memaddr; - FILE *stream; -{ - /* The raw instruction. */ - char insn[4]; - - /* The four bytes of the instruction. */ - unsigned char insn24, insn16, insn8, insn0; - - struct a29k_opcode const * opcode; - - read_memory (memaddr, &insn[0], 4); - - find_bytes (insn, &insn0, &insn8, &insn16, &insn24); - - /* Handle the nop (aseq 0x40,gr1,gr1) specially */ - if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) { - fprintf_filtered (stream,"nop"); - return 4; - } - - /* The opcode is always in insn24. */ - for (opcode = &a29k_opcodes[0]; - opcode < &a29k_opcodes[num_opcodes]; - ++opcode) - { - if ((insn24<<24) == opcode->opcode) - { - char *s; - - fprintf_filtered (stream, "%s ", opcode->name); - for (s = opcode->args; *s != '\0'; ++s) - { - switch (*s) - { - case 'a': - print_general (insn8, stream); - break; - - case 'b': - print_general (insn0, stream); - break; - - case 'c': - print_general (insn16, stream); - break; - - case 'i': - fprintf_filtered (stream, "%d", insn0); - break; - - case 'x': - fprintf_filtered (stream, "%d", (insn16 << 8) + insn0); - break; - - case 'h': - fprintf_filtered (stream, "0x%x", - (insn16 << 24) + (insn0 << 16)); - break; - - case 'X': - fprintf_filtered (stream, "%d", - ((insn16 << 8) + insn0) | 0xffff0000); - break; - - case 'P': - /* This output looks just like absolute addressing, but - maybe that's OK (it's what the GDB 68k and EBMON - 29k disassemblers do). */ - /* All the shifting is to sign-extend it. p*/ - print_address - (memaddr + - (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14), - stream); - break; - - case 'A': - print_address ((insn16 << 10) + (insn0 << 2), stream); - break; - - case 'e': - fprintf_filtered (stream, "%d", insn16 >> 7); - break; - - case 'n': - fprintf_filtered (stream, "0x%x", insn16 & 0x7f); - break; - - case 'v': - fprintf_filtered (stream, "0x%x", insn16); - break; - - case 's': - print_special (insn8, stream); - break; - - case 'u': - fprintf_filtered (stream, "%d", insn0 >> 7); - break; - - case 'r': - fprintf_filtered (stream, "%d", (insn0 >> 4) & 7); - break; - - case 'd': - fprintf_filtered (stream, "%d", (insn0 >> 2) & 3); - break; - - case 'f': - fprintf_filtered (stream, "%d", insn0 & 3); - break; - - case 'F': - fprintf_filtered (stream, "%d", (insn16 >> 2) & 15); - break; - - case 'C': - fprintf_filtered (stream, "%d", insn16 & 3); - break; - - default: - fprintf_filtered (stream, "%c", *s); - } - } - - /* Now we look for a const,consth pair of instructions, - in which case we try to print the symbolic address. */ - if (insn24 == 2) /* consth */ - { - int errcode; - char prev_insn[4]; - unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24; - - errcode = target_read_memory (memaddr - 4, - &prev_insn[0], - 4); - if (errcode == 0) - { - /* If it is a delayed branch, we need to look at the - instruction before the delayed brach to handle - things like - - const _foo - call _printf - consth _foo - */ - find_bytes (prev_insn, &prev_insn0, &prev_insn8, - &prev_insn16, &prev_insn24); - if (is_delayed_branch (prev_insn24)) - { - errcode = target_read_memory - (memaddr - 8, &prev_insn[0], 4); - find_bytes (prev_insn, &prev_insn0, &prev_insn8, - &prev_insn16, &prev_insn24); - } - } - - /* If there was a problem reading memory, then assume - the previous instruction was not const. */ - if (errcode == 0) - { - /* Is it const to the same register? */ - if (prev_insn24 == 3 - && prev_insn8 == insn8) - { - fprintf_filtered (stream, "\t; "); - print_address (((insn16 << 24) + (insn0 << 16) - + (prev_insn16 << 8) + (prev_insn0)), - stream); - } - } - } - - return 4; - } - } - fprintf_filtered (stream, ".word 0x%8x", - (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0); - return 4; -} diff --git a/gdb/am29k-tdep.c b/gdb/am29k-tdep.c deleted file mode 100644 index e009026..0000000 --- a/gdb/am29k-tdep.c +++ /dev/null @@ -1,831 +0,0 @@ -/* Target-machine dependent code for the AMD 29000 - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. - Contributed by Cygnus Support. Written by Jim Kingdon. - -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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "defs.h" -#include "gdbcore.h" -#include "frame.h" -#include "value.h" -#include "symtab.h" -#include "inferior.h" -#include "gdbcmd.h" - -/* If all these bits in an instruction word are zero, it is a "tag word" - which precedes a function entry point and gives stack traceback info. - This used to be defined as 0xff000000, but that treated 0x00000deb as - a tag word, while it is really used as a breakpoint. */ -#define TAGWORD_ZERO_MASK 0xff00f800 - -extern CORE_ADDR text_start; /* FIXME, kludge... */ - -/* The user-settable top of the register stack in virtual memory. We - won't attempt to access any stored registers above this address, if set - nonzero. */ - -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 */ - unsigned rsize, msize; /* register stack frame size, mem stack ditto */ - unsigned mfp_used : 1; /* memory frame pointer used */ - unsigned rsize_valid : 1; /* Validity bits for the above */ - unsigned msize_valid : 1; - unsigned mfp_valid : 1; -}; - -/* Examine the prologue of a function which starts at PC. Return - the first addess past the prologue. If MSIZE is non-NULL, then - set *MSIZE to the memory stack frame size. If RSIZE is non-NULL, - then set *RSIZE to the register stack frame size (not including - incoming arguments and the return address & frame pointer stored - with them). If no prologue is found, *RSIZE is set to zero. - If no prologue is found, or a prologue which doesn't involve - allocating a memory stack frame, then set *MSIZE to zero. - - Note that both msize and rsize are in bytes. This is not consistent - with the _User's Manual_ with respect to rsize, but it is much more - convenient. - - 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; - unsigned *msize; - unsigned *rsize; - int *mfp_used; -{ - long insn; - CORE_ADDR p = pc; - struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc); - struct prologue_info *mi = 0; - - if (msymbol != NULL) - mi = (struct prologue_info *) msymbol -> info; - - if (mi != 0) - { - int valid = 1; - if (rsize != NULL) - { - *rsize = mi->rsize; - valid &= mi->rsize_valid; - } - if (msize != NULL) - { - *msize = mi->msize; - valid &= mi->msize_valid; - } - if (mfp_used != NULL) - { - *mfp_used = mi->mfp_used; - valid &= mi->mfp_valid; - } - if (valid) - return mi->pc; - } - - if (rsize != NULL) - *rsize = 0; - if (msize != NULL) - *msize = 0; - if (mfp_used != NULL) - *mfp_used = 0; - - /* Prologue must start with subtracting a constant from gr1. - Normally this is sub gr1,gr1,. */ - insn = read_memory_integer (p, 4); - if ((insn & 0xffffff00) != 0x25010100) - { - /* If the frame is large, instead of a single instruction it - might be a pair of instructions: - const , - sub gr1,gr1, - */ - int reg; - /* Possible value for rsize. */ - unsigned int rsize0; - - if ((insn & 0xff000000) != 0x03000000) - { - p = pc; - goto done; - } - reg = (insn >> 8) & 0xff; - rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff)); - p += 4; - insn = read_memory_integer (p, 4); - if ((insn & 0xffffff00) != 0x24010100 - || (insn & 0xff) != reg) - { - p = pc; - goto done; - } - if (rsize != NULL) - *rsize = rsize0; - } - else - { - if (rsize != NULL) - *rsize = (insn & 0xff); - } - p += 4; - - /* Next instruction must be asgeu V_SPILL,gr1,rab. - * We don't check the vector number to allow for kernel debugging. The - * kernel will use a different trap number. - */ - insn = read_memory_integer (p, 4); - if ((insn & 0xff00ffff) != (0x5e000100|RAB_HW_REGNUM)) - { - p = pc; - goto done; - } - p += 4; - - /* Next instruction usually sets the frame pointer (lr1) by adding - from gr1. However, this can (and high C does) be - deferred until anytime before the first function call. So it is - OK if we don't see anything which sets lr1. - To allow for alternate register sets (gcc -mkernel-registers) the msp - register number is a compile time constant. */ - - /* Normally this is just add lr1,gr1,. */ - insn = read_memory_integer (p, 4); - if ((insn & 0xffffff00) == 0x15810100) - p += 4; - else - { - /* However, for large frames it can be - const , - add lr1,gr1, - */ - int reg; - CORE_ADDR q; - - if ((insn & 0xff000000) == 0x03000000) - { - reg = (insn >> 8) & 0xff; - q = p + 4; - insn = read_memory_integer (q, 4); - if ((insn & 0xffffff00) == 0x14810100 - && (insn & 0xff) == reg) - p = q; - } - } - - /* Next comes "add lr{},msp,0", but only if a memory - frame pointer is in use. We just check for add lr,msp,0; - we don't check this rsize against the first instruction, and - we don't check that the trace-back tag indicates a memory frame pointer - is in use. - To allow for alternate register sets (gcc -mkernel-registers) the msp - register number is a compile time constant. - - The recommended instruction is actually "sll lr,msp,0". - We check for that, too. Originally Jim Kingdon's code seemed - to be looking for a "sub" instruction here, but the mask was set - up to lose all the time. */ - insn = read_memory_integer (p, 4); - if (((insn & 0xff80ffff) == (0x15800000|(MSP_HW_REGNUM<<8))) /* add */ - || ((insn & 0xff80ffff) == (0x81800000|(MSP_HW_REGNUM<<8)))) /* sll */ - { - p += 4; - if (mfp_used != NULL) - *mfp_used = 1; - } - - /* Next comes a subtraction from msp to allocate a memory frame, - but only if a memory frame is - being used. We don't check msize against the trace-back tag. - - To allow for alternate register sets (gcc -mkernel-registers) the msp - register number is a compile time constant. - - Normally this is just - sub msp,msp, - */ - insn = read_memory_integer (p, 4); - if ((insn & 0xffffff00) == - (0x25000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8))) - { - p += 4; - if (msize != NULL) - *msize = insn & 0xff; - } - else - { - /* For large frames, instead of a single instruction it might - be - - const , - consth , ; optional - sub msp,msp, - */ - int reg; - unsigned msize0; - CORE_ADDR q = p; - - if ((insn & 0xff000000) == 0x03000000) - { - reg = (insn >> 8) & 0xff; - msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff); - q += 4; - insn = read_memory_integer (q, 4); - /* Check for consth. */ - if ((insn & 0xff000000) == 0x02000000 - && (insn & 0x0000ff00) == reg) - { - msize0 |= (insn << 8) & 0xff000000; - msize0 |= (insn << 16) & 0x00ff0000; - q += 4; - insn = read_memory_integer (q, 4); - } - /* Check for sub msp,msp,. */ - if ((insn & 0xffffff00) == - (0x24000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8)) - && (insn & 0xff) == reg) - { - p = q + 4; - if (msize != NULL) - *msize = msize0; - } - } - } - - done: - if (msymbol != NULL) - { - if (mi == 0) - { - /* Add a new cache entry. */ - mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info)); - msymbol -> info = (char *)mi; - mi->rsize_valid = 0; - mi->msize_valid = 0; - mi->mfp_valid = 0; - } - /* else, cache entry exists, but info is incomplete. */ - mi->pc = p; - if (rsize != NULL) - { - mi->rsize = *rsize; - mi->rsize_valid = 1; - } - if (msize != NULL) - { - mi->msize = *msize; - mi->msize_valid = 1; - } - if (mfp_used != NULL) - { - mi->mfp_used = *mfp_used; - mi->mfp_valid = 1; - } - } - return p; -} - -/* Advance PC across any function entry prologue instructions - to reach some "real" code. */ - -CORE_ADDR -skip_prologue (pc) - CORE_ADDR pc; -{ - return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL, - (int *)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 - * by returning 0. The documentation for the tag word was taken from - * page 7-15 of the 29050 User's Manual. We are assuming that the - * m bit is in bit 22 of the tag word, which seems to be the agreed upon - * 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) - CORE_ADDR p; - int *is_trans; - int *argcount; - unsigned *msize; - int *mfp_used; -{ - unsigned int tag1, tag2; - - tag1 = read_memory_integer (p, 4); - if ((tag1 & TAGWORD_ZERO_MASK) != 0) /* Not a tag word */ - return 0; - if (tag1 & (1<<23)) /* A two word tag */ - { - tag2 = read_memory_integer (p+4, 4); - if (msize) - *msize = tag2; - } - else /* A one word tag */ - { - if (msize) - *msize = tag1 & 0x7ff; - } - if (is_trans) - *is_trans = ((tag1 & (1<<21)) ? 1 : 0); - if (argcount) - *argcount = (tag1 >> 16) & 0x1f; - if (mfp_used) - *mfp_used = ((tag1 & (1<<22)) ? 1 : 0); - 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-29k.h for more detail. */ -static void -init_frame_info (innermost_frame, fci) - int innermost_frame; - struct frame_info *fci; -{ - CORE_ADDR p; - long insn; - unsigned rsize; - unsigned msize; - int mfp_used, trans; - struct symbol *func; - - p = fci->pc; - - if (innermost_frame) - fci->frame = read_register (GR1_REGNUM); - else - fci->frame = fci->next_frame + fci->next->rsize; - -#if CALL_DUMMY_LOCATION == ON_STACK - This wont work; -#else - if (PC_IN_CALL_DUMMY (p, 0, 0)) -#endif - { - fci->rsize = DUMMY_FRAME_RSIZE; - /* This doesn't matter since we never try to get locals or args - from a dummy frame. */ - fci->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); - return; - } - - func = find_pc_function (p); - if (func != NULL) - p = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); - else - { - /* 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). */ - while (p >= text_start - && ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0) - p -= 4; - - 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; - return; - } - else - /* Advance to the first word of the function, i.e. the word - after the trace-back tag. */ - p += 4; - } - /* We've found the start of the function. - * Try looking for a tag word that indicates whether there is a - * memory frame pointer and what the memory stack allocation is. - * If one doesn't exist, try using a more exhaustive search of - * the prologue. For now we don't care about the argcount or - * whether or not the routine is transparent. - */ - if (examine_tag(p-4,&trans,NULL,&msize,&mfp_used)) /* Found a good tag */ - examine_prologue (p, &rsize, 0, 0); - else /* No tag try prologue */ - examine_prologue (p, &rsize, &msize, &mfp_used); - - fci->rsize = rsize; - fci->msize = msize; - fci->flags = 0; - if (mfp_used) - fci->flags |= MFP_USED; - if (trans) - fci->flags |= TRANSPARENT; - if (innermost_frame) - { - fci->saved_msp = read_register (MSP_REGNUM) + msize; - } - else - { - if (mfp_used) - fci->saved_msp = - read_register_stack_integer (fci->frame + rsize - 4, 4); - else - fci->saved_msp = fci->next->saved_msp + msize; - } -} - -void -init_extra_frame_info (fci) - struct frame_info *fci; -{ - if (fci->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); - else { - /* We're in get_prev_frame_info. - Take care of everything in init_frame_pc. */ - ; - } -} - -void -init_frame_pc (fromleaf, fci) - int fromleaf; - struct frame_info *fci; -{ - fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) : - fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ()); - init_frame_info (fromleaf, fci); -} - -/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their - offsets being relative to the memory stack pointer (high C) or - saved_msp (gcc). */ - -CORE_ADDR -frame_locals_address (fi) - struct frame_info *fi; -{ - if (fi->flags & MFP_USED) - return fi->saved_msp; - else - return fi->saved_msp - fi->msize; -} - -/* Routines for reading the register stack. The caller gets to treat - the register stack as a uniform stack in memory, from address $gr1 - straight through $rfb and beyond. */ - -/* Analogous to read_memory except the length is understood to be 4. - Also, myaddr can be NULL (meaning don't bother to read), and - if actual_mem_addr is non-NULL, store there the address that it - was fetched from (or if from a register the offset within - registers). Set *LVAL to lval_memory or lval_register, depending - on where it came from. */ -void -read_register_stack (memaddr, myaddr, actual_mem_addr, lval) - CORE_ADDR memaddr; - char *myaddr; - CORE_ADDR *actual_mem_addr; - enum lval_type *lval; -{ - long rfb = read_register (RFB_REGNUM); - long rsp = read_register (RSP_REGNUM); - - /* If we don't do this 'info register' stops in the middle. */ - if (memaddr >= rstack_high_address) - { - int val = -1; /* a bogus value */ - /* It's in a local register, but off the end of the stack. */ - int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; - if (myaddr != NULL) - *(int*)myaddr = val; /* Provide bogusness */ - supply_register(regnum, (char *)&val); /* More bogusness */ - if (lval != NULL) - *lval = lval_register; - if (actual_mem_addr != NULL) - *actual_mem_addr = REGISTER_BYTE (regnum); - } - /* If it's in the part of the register stack that's in real registers, - get the value from the registers. If it's anywhere else in memory - (e.g. in another thread's saved stack), skip this part and get - it from real live memory. */ - else if (memaddr < rfb && memaddr >= rsp) - { - /* It's in a register. */ - int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; - if (regnum > LR0_REGNUM + 127) - error ("Attempt to read register stack out of range."); - if (myaddr != NULL) - read_register_gen (regnum, myaddr); - if (lval != NULL) - *lval = lval_register; - if (actual_mem_addr != NULL) - *actual_mem_addr = REGISTER_BYTE (regnum); - } - else - { - /* It's in the memory portion of the register stack. */ - if (myaddr != NULL) - read_memory (memaddr, myaddr, 4); - if (lval != NULL) - *lval = lval_memory; - if (actual_mem_addr != NULL) - *actual_mem_addr = memaddr; - } -} - -/* Analogous to read_memory_integer - except the length is understood to be 4. */ -long -read_register_stack_integer (memaddr, len) - CORE_ADDR memaddr; - int len; -{ - long buf; - read_register_stack (memaddr, &buf, NULL, NULL); - SWAP_TARGET_AND_HOST (&buf, 4); - return buf; -} - -/* Copy 4 bytes from GDB memory at MYADDR into inferior memory - at MEMADDR and put the actual address written into in - *ACTUAL_MEM_ADDR. */ -static void -write_register_stack (memaddr, myaddr, actual_mem_addr) - CORE_ADDR memaddr; - char *myaddr; - CORE_ADDR *actual_mem_addr; -{ - long rfb = read_register (RFB_REGNUM); - long rsp = read_register (RSP_REGNUM); - /* If we don't do this 'info register' stops in the middle. */ - if (memaddr >= rstack_high_address) - { - /* It's in a register, but off the end of the stack. */ - if (actual_mem_addr != NULL) - *actual_mem_addr = 0; - } - else if (memaddr < rfb) - { - /* It's in a register. */ - int regnum = (memaddr - rsp) / 4 + LR0_REGNUM; - if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127) - error ("Attempt to read register stack out of range."); - if (myaddr != NULL) - write_register (regnum, *(long *)myaddr); - if (actual_mem_addr != NULL) - *actual_mem_addr = 0; - } - else - { - /* It's in the memory portion of the register stack. */ - if (myaddr != NULL) - write_memory (memaddr, myaddr, 4); - if (actual_mem_addr != NULL) - *actual_mem_addr = memaddr; - } -} - -/* Find register number REGNUM relative to FRAME and put its - (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable - was optimized out (and thus can't be fetched). If the variable - was fetched from memory, set *ADDRP to where it was fetched from, - 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; - int regnum; - enum lval_type *lvalp; -{ - struct frame_info *fi; - CORE_ADDR addr; - enum lval_type lval; - - 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 (regnum == RSP_REGNUM) - { - if (raw_buffer != NULL) - *(CORE_ADDR *)raw_buffer = fi->frame; - if (lvalp != NULL) - *lvalp = not_lval; - return; - } - else if (regnum == PC_REGNUM) - { - if (raw_buffer != NULL) - *(CORE_ADDR *)raw_buffer = fi->pc; - - /* Not sure we have to do this. */ - if (lvalp != NULL) - *lvalp = not_lval; - - return; - } - else if (regnum == MSP_REGNUM) - { - if (raw_buffer != NULL) - { - if (fi->next != NULL) - *(CORE_ADDR *)raw_buffer = fi->next->saved_msp; - else - *(CORE_ADDR *)raw_buffer = read_register (MSP_REGNUM); - } - /* The value may have been computed, not fetched. */ - if (lvalp != NULL) - *lvalp = not_lval; - return; - } - else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128) - { - /* These registers are not saved over procedure calls, - so just print out the current values. */ - if (raw_buffer != NULL) - *(CORE_ADDR *)raw_buffer = read_register (regnum); - if (lvalp != NULL) - *lvalp = lval_register; - if (addrp != NULL) - *addrp = REGISTER_BYTE (regnum); - return; - } - - addr = fi->frame + (regnum - LR0_REGNUM) * 4; - if (raw_buffer != NULL) - read_register_stack (addr, raw_buffer, &addr, &lval); - if (lvalp != NULL) - *lvalp = lval; - if (addrp != NULL) - *addrp = addr; -} - - -/* Discard from the stack the innermost frame, - restoring all saved registers. */ - -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; - CORE_ADDR lr1; - int i; - - /* 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))) - { - int lrnum = LR0_REGNUM + DUMMY_ARG/4; - for (i = 0; i < DUMMY_SAVE_SR128; ++i) - write_register (SR_REGNUM (i + 128),read_register (lrnum++)); - for (i = 0; i < DUMMY_SAVE_SR160; ++i) - write_register (SR_REGNUM(i+160), read_register (lrnum++)); - for (i = 0; i < DUMMY_SAVE_GREGS; ++i) - write_register (RETURN_REGNUM + i, read_register (lrnum++)); - /* Restore the PCs. */ - write_register(PC_REGNUM, read_register (lrnum++)); - write_register(NPC_REGNUM, read_register (lrnum)); - } - - /* Restore the memory stack pointer. */ - write_register (MSP_REGNUM, fi->saved_msp); - /* Restore the register stack pointer. */ - write_register (GR1_REGNUM, gr1); - /* Check whether we need to fill registers. */ - lr1 = read_register (LR0_REGNUM + 1); - if (lr1 > rfb) - { - /* Fill. */ - int num_bytes = lr1 - rfb; - int i; - 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) - { - /* Note: word is in host byte order. */ - word = read_memory_integer (rfb + i, 4); - write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word); - } - } - flush_cached_frames (); - set_current_frame (create_new_frame (0, read_pc())); -} - -/* Push an empty stack frame, to record the current PC, etc. */ - -void -push_dummy_frame () -{ - long w; - CORE_ADDR rab, gr1; - CORE_ADDR msp = read_register (MSP_REGNUM); - int lrnum, i, saved_lr0; - - - /* Allocate the new frame. */ - gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE; - write_register (GR1_REGNUM, gr1); - - rab = read_register (RAB_REGNUM); - if (gr1 < rab) - { - /* We need to spill registers. */ - int num_bytes = rab - gr1; - CORE_ADDR rfb = read_register (RFB_REGNUM); - int i; - long word; - - write_register (RFB_REGNUM, rfb - num_bytes); - write_register (RAB_REGNUM, gr1); - for (i = 0; i < num_bytes; i += 4) - { - /* Note: word is in target byte order. */ - read_register_gen (LR0_REGNUM + i / 4, (char *) &word); - write_memory (rfb - num_bytes + i, (char *) &word, 4); - } - } - - /* There are no arguments in to the dummy frame, so we don't need - more than rsize plus the return address and lr1. */ - write_register (LR0_REGNUM + 1, gr1 + DUMMY_FRAME_RSIZE + 2 * 4); - - /* Set the memory frame pointer. */ - write_register (LR0_REGNUM + DUMMY_FRAME_RSIZE / 4 - 1, msp); - - /* Allocate arg_slop. */ - write_register (MSP_REGNUM, msp - 16 * 4); - - /* Save registers. */ - lrnum = LR0_REGNUM + DUMMY_ARG/4; - for (i = 0; i < DUMMY_SAVE_SR128; ++i) - write_register (lrnum++, read_register (SR_REGNUM (i + 128))); - for (i = 0; i < DUMMY_SAVE_SR160; ++i) - write_register (lrnum++, read_register (SR_REGNUM (i + 160))); - for (i = 0; i < DUMMY_SAVE_GREGS; ++i) - write_register (lrnum++, read_register (RETURN_REGNUM + i)); - /* Save the PCs. */ - write_register (lrnum++, read_register (PC_REGNUM)); - write_register (lrnum, read_register (NPC_REGNUM)); -} - - -void -_initialize_29k() -{ - extern CORE_ADDR text_end; - - /* 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, - (char *)&rstack_high_address, - "Set top address in memory of the register stack.\n\ -Attempts to access registers saved above this address will be ignored\n\ -or will produce the value -1.", &setlist), - &showlist); - - /* FIXME, there should be a way to make a CORE_ADDR variable settable. */ - add_show_from_set - (add_set_cmd ("call_scratch_address", class_support, var_uinteger, - (char *)&text_end, -"Set address in memory where small amounts of RAM can be used\n\ -when making function calls into the inferior.", &setlist), - &showlist); -} diff --git a/gdb/config/a29k/a29k-kern.mt b/gdb/config/a29k/a29k-kern.mt index 0ecf14f..cb06f80 100644 --- a/gdb/config/a29k/a29k-kern.mt +++ b/gdb/config/a29k/a29k-kern.mt @@ -5,6 +5,6 @@ # As compared to ordinary remote 29K debugging, this changes the register # numbering a bit, to hold kernel regs, and adds support for looking at # the upage. -TDEPFILES= exec.o am29k-pinsn.o am29k-tdep.o remote-mm.o remote-adapt.o +TDEPFILES= exec.o a29k-pinsn.o a29k-tdep.o remote-mm.o remote-adapt.o TM_FILE= tm-ultra3.h MT_CFLAGS = -DKERNEL_DEBUGGING -DNO_HIF_SUPPORT diff --git a/gdb/config/a29k/a29k-udi.mt b/gdb/config/a29k/a29k-udi.mt index dba0705..3ed65d2 100644 --- a/gdb/config/a29k/a29k-udi.mt +++ b/gdb/config/a29k/a29k-udi.mt @@ -1,5 +1,5 @@ # Target: AMD 29000 on EB29K board over a serial line. -TDEPFILES= exec.o am29k-pinsn.o remote-udi.o am29k-tdep.o udip2soc.o udr.o -TM_FILE= tm-29k.h +TDEPFILES= exec.o a29k-pinsn.o remote-udi.o a29k-tdep.o udip2soc.o udr.o +TM_FILE= tm-a29k.h # The following is for ../include/a.out.encap.h -MT_CFLAGS = -Da29k -DREMOTE -DTARGET=TARGET_AM29K -DAMD_COFF +MT_CFLAGS = -Da29k -DREMOTE -DAMD_COFF diff --git a/gdb/config/a29k/a29k.mt b/gdb/config/a29k/a29k.mt index 29ae63b..cd947dc 100644 --- a/gdb/config/a29k/a29k.mt +++ b/gdb/config/a29k/a29k.mt @@ -5,6 +5,6 @@ # Adapt (remote-adapt.c), # or a MiniMon debugger (remote-mm.c). # Or run native on an Ultracomputer. -TDEPFILES= exec.o am29k-pinsn.o am29k-tdep.o remote-eb.o remote-mm.o remote-adapt.o -TM_FILE= tm-29k.h +TDEPFILES= exec.o a29k-pinsn.o a29k-tdep.o remote-eb.o remote-mm.o remote-adapt.o +TM_FILE= tm-a29k.h MT_CFLAGS = -DNO_HIF_SUPPORT diff --git a/gdb/config/a29k/nm-ultra3.h b/gdb/config/a29k/nm-ultra3.h index e593729..c9fd7f2 100644 --- a/gdb/config/a29k/nm-ultra3.h +++ b/gdb/config/a29k/nm-ultra3.h @@ -1,4 +1,4 @@ -/* Host definitions for GDB running on a 29k NYU Ultracomputer +/* Host definitions for GDB running on an a29k NYU Ultracomputer Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. Contributed by David Wood (wood@lab.ultra.nyu.edu). diff --git a/gdb/config/a29k/tm-a29k.h b/gdb/config/a29k/tm-a29k.h index 206f9d4..56d6a86 100644 --- a/gdb/config/a29k/tm-a29k.h +++ b/gdb/config/a29k/tm-a29k.h @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ accessed through EBMON software running on the PC, which we use as we'd use a remote stub (see remote-eb.c). - If gdb is ported to other 29k machines/systems, the + If gdb is ported to other a29k machines/systems, the machine/system-specific parts should be removed from this file (a la tm-68k.h). */ @@ -93,7 +93,7 @@ CORE_ADDR skip_prologue (); #define DECR_PC_AFTER_BREAK 0 /* Nonzero if instruction at PC is a return instruction. - On the 29k, this is a "jmpi l0" instruction. */ + On the a29k, this is a "jmpi l0" instruction. */ #define ABOUT_TO_RETURN(pc) \ ((read_memory_integer (pc, 4) & 0xff0000ff) == 0xc0000080) @@ -291,13 +291,13 @@ CORE_ADDR skip_prologue (); /* Store the address of the place in which to copy the structure the subroutine will return. This is called from call_function. */ -/* On the 29k the LRP points to the part of the structure beyond the first +/* On the a29k the LRP points to the part of the structure beyond the first 16 words. */ #define STORE_STRUCT_RETURN(ADDR, SP) \ write_register (LRP_REGNUM, (ADDR) + 16 * 4); /* Should call_function allocate stack space for a struct return? */ -/* On the 29k objects over 16 words require the caller to allocate space. */ +/* On the a29k objects over 16 words require the caller to allocate space. */ #define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16 * 4) /* Extract from an array REGBUF containing the (raw) register state @@ -333,7 +333,7 @@ CORE_ADDR skip_prologue (); TYPE_LENGTH (TYPE)); \ } -/* The am29k user's guide documents well what the stacks look like. +/* The a29k user's guide documents well what the stacks look like. But what isn't so clear there is how this interracts with the symbols, or with GDB. In the following saved_msp, saved memory stack pointer (which functions @@ -355,7 +355,7 @@ CORE_ADDR skip_prologue (); before trying to print arguments or anything. The following diagram attempts to depict what is going on in memory - (see also the _am29k user's guide_) and also how that interacts with + (see also the _a29k user's guide_) and also how that interacts with GDB frames. We arbitrarily pick fci->frame to point the same place as the register stack pointer; since we set it ourself in INIT_EXTRA_FRAME_INFO, and access it only through the FRAME_* @@ -364,7 +364,7 @@ CORE_ADDR skip_prologue (); (1) as a "magic cookie" which uniquely identifies frames (even over calls to the inferior), (2) (in PC_IN_CALL_DUMMY [ON_STACK]) as the value of SP_REGNUM before the dummy frame was pushed. These - two meanings would be incompatible for the 29k if we defined + two meanings would be incompatible for the a29k if we defined CALL_DUMMY_LOCATION == ON_STACK (but we don't, so don't worry about it). Also note that "lr1" below, while called a frame pointer in the user's guide, has only one function: To determine whether @@ -463,7 +463,7 @@ void init_frame_pc (); However, if FRAME_CHAIN_VALID returns zero, it means the given frame is the outermost one and has no caller. */ -/* On the 29k, the nominal address of a frame is the address on the +/* On the a29k, the nominal address of a frame is the address on the register stack of the return address (the one next to the incoming arguments, not down at the bottom so nominal address == stack pointer). @@ -472,7 +472,7 @@ void init_frame_pc (); However, that doesn't work for us, so when creating the innermost frame we set ->frame ourselves in INIT_EXTRA_FRAME_INFO. */ -/* These are mostly dummies for the 29k because INIT_FRAME_PC +/* These are mostly dummies for the a29k because INIT_FRAME_PC sets prev->frame instead. */ #define FRAME_CHAIN(thisframe) ((thisframe)->frame + (thisframe)->rsize) @@ -524,7 +524,7 @@ extern CORE_ADDR frame_locals_address (); #define FRAME_ARGS_SKIP 0 /* Provide our own get_saved_register. HAVE_REGISTER_WINDOWS is insufficient - because registers get renumbered on the 29k without getting saved. */ + because registers get renumbered on the a29k without getting saved. */ #define GET_SAVED_REGISTER @@ -572,7 +572,7 @@ extern CORE_ADDR frame_locals_address (); the msp, it won't end up larger than mfp_dummy (it is needed in the case where margs and struct_ret do not add up to at least 16 words). struct ret: This area is allocated by GDB if the return value is more - than 16 words. struct ret_16 is not used on the 29k. + than 16 words. struct ret_16 is not used on the a29k. margs: Pushed by GDB. The call dummy copies the first 16 words to args_out_dummy. retaddr_sproc: Contains the PC at the time we call the function. @@ -671,7 +671,7 @@ extern void pop_frame (); into a call sequence of the above form stored at DUMMYNAME. */ /* Currently this stuffs in the address of the function that we are calling. - Since different 29k systems use different breakpoint instructions, it + Since different a29k systems use different breakpoint instructions, it also stuffs BREAKPOINT in the right place (to avoid having to duplicate CALL_DUMMY in each tm-*.h file). */ @@ -682,7 +682,7 @@ extern void pop_frame (); /* FIXME memcpy ((char *)(dummyname) + BREAKPT_INSN, break_insn, 4); */ \ } -/* 29k architecture has separate data & instruction memories -- wired to +/* a29k architecture has separate data & instruction memories -- wired to different pins on the chip -- and can't execute the data memory. Also, there should be space after text_end; we won't get a SIGSEGV or scribble on data space. */ diff --git a/gdb/config/a29k/tm-ultra3.h b/gdb/config/a29k/tm-ultra3.h index 1603d8b..e17407c 100644 --- a/gdb/config/a29k/tm-ultra3.h +++ b/gdb/config/a29k/tm-ultra3.h @@ -18,8 +18,8 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* This file includes tm-29k.h, but predefines REGISTER_NAMES and - related macros. The file supports a 29k running our flavor of +/* This file includes tm-a29k.h, but predefines REGISTER_NAMES and + related macros. The file supports a a29k running our flavor of Unix on our Ultra3 PE Boards. */ /* Byte order is configurable, but this machine runs big-endian. */ @@ -183,9 +183,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif #endif /* !KERNEL_DEBUGGING */ -#include "a29k/tm-29k.h" +#include "a29k/tm-a29k.h" -/**** The following are definitions that override those in tm-29k.h ****/ +/**** The following are definitions that override those in tm-a29k.h ****/ /* This sequence of words is the instructions mtsrim cr, 15 diff --git a/gdb/config/a29k/ultra3.mt b/gdb/config/a29k/ultra3.mt index 840b79d..a6f8cbe 100644 --- a/gdb/config/a29k/ultra3.mt +++ b/gdb/config/a29k/ultra3.mt @@ -1,5 +1,5 @@ # Target: AMD 29000 running Unix on New York Univerisity processor board. -TDEPFILES= am29k-pinsn.o am29k-tdep.o +TDEPFILES= a29k-pinsn.o a29k-tdep.o TM_FILE= tm-ultra3.h # SYM1 is some OS they have. MT_CFLAGS = -DSYM1 diff --git a/gdb/config/a29k/xm-ultra3.h b/gdb/config/a29k/xm-ultra3.h index 0abf68d..74ff6d3 100644 --- a/gdb/config/a29k/xm-ultra3.h +++ b/gdb/config/a29k/xm-ultra3.h @@ -1,4 +1,4 @@ -/* Host definitions for GDB running on a 29k NYU Ultracomputer +/* Host definitions for GDB running on an a29k NYU Ultracomputer Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc. Contributed by David Wood (wood@lab.ultra.nyu.edu). @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Here at NYU we have what we call an ULTRA3 PE board. So ifdefs for ULTRA3 are my doing. At this point in time, - I don't know of any other Unixi running on the 29k. */ + I don't know of any other Unixi running on the a29k. */ #define HOST_BYTE_ORDER BIG_ENDIAN diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 725e948..3578ef1 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -1643,14 +1643,20 @@ xcoffread.c remote-mm.c @item NO_JOB_CONTROL signals.h -@item NO_MALLOC_CHECK -utils.c -@item NO_MMALLOC -utils.c -@item NO_MMALLOC -objfiles.c @item NO_MMALLOC -utils.c +GDB will use the @code{mmalloc} library for memory allocation for symbol +reading, unless this symbol is defined. Define it on systems +on which @code{mmalloc} does not +work for some reason. One example is the DECstation, where its RPC +library can't cope with our redefinition of @code{malloc} to call +@code{mmalloc}. When defining @code{NO_MMALLOC}, you will also have +to override the setting of @code{MMALLOC_LIB} to empty, in the Makefile. +Therefore, this define is usually set on the command line by overriding +@code{MMALLOC_DISABLE} in @file{config/*.mh}, rather than by defining +it in @file{xm-*.h}. +@item NO_MMALLOC_CHECK +Define this if you are using @code{mmalloc}, but don't want the overhead +of checking the heap with @code{mmcheck}. @item NO_SIGINTERRUPT remote-adapt.c @item NO_SINGLE_STEP @@ -1712,7 +1718,7 @@ pyr-xdep.c @item REGISTER_BYTES remote.c @item REGISTER_NAMES -tm-29k.h +tm-a29k.h @item REG_STACK_SEGMENT exec.c @item REG_STRUCT_HAS_ADDR @@ -2226,16 +2232,6 @@ infrun.c xcoffread.c @item NO_HIF_SUPPORT remote-mm.c -@item NO_JOB_CONTROL -signals.h -@item NO_MALLOC_CHECK -utils.c -@item NO_MMALLOC -utils.c -@item NO_MMALLOC -objfiles.c -@item NO_MMALLOC -utils.c @item NO_SIGINTERRUPT remote-adapt.c @item NO_SINGLE_STEP @@ -2287,7 +2283,7 @@ valops.c @item REGISTER_BYTES remote.c @item REGISTER_NAMES -tm-29k.h +tm-a29k.h @item REG_STACK_SEGMENT exec.c @item REG_STRUCT_HAS_ADDR diff --git a/gdb/doc/gdbinv-s.texi b/gdb/doc/gdbinv-s.texi index e3c625a..a94fa24 100644 --- a/gdb/doc/gdbinv-s.texi +++ b/gdb/doc/gdbinv-s.texi @@ -451,19 +451,19 @@ a break is detected. @cindex UDI @cindex AMD29K via UDI @value{GDBN} supports AMD's UDI (``Universal Debugger Interface'') -protocol for debugging the 29k processor family. To use this +protocol for debugging the a29k processor family. To use this configuration with AMD targets running the MiniMON monitor, you need the program @code{MONTIP}, available from AMD at no charge. You can also -use @value{GDBN} with the UDI conformant 29k simulator program +use @value{GDBN} with the UDI conformant a29k simulator program @code{ISSTIP}, also available from AMD. @table @code @item target udi @var{keyword} @kindex udi -Select the UDI interface to a remote 29K board or simulator, where +Select the UDI interface to a remote a29k board or simulator, where @var{keyword} is an entry in the AMD configuration file @file{udi_soc}. This file contains keyword entries which specify parameters used to -connect to 29k targets. If the @file{udi_soc} file is not in your +connect to a29k targets. If the @file{udi_soc} file is not in your working directory, you must set the environment variable @samp{UDICONF} to its pathname. @end table diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c index 7c5b686..605945c 100644 --- a/gdb/remote-eb.c +++ b/gdb/remote-eb.c @@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This is like remote.c but is for an esoteric situation-- - having a 29k board in a PC hooked up to a unix machine with + having a a29k board in a PC hooked up to a unix machine with a serial line, and running ctty com1 on the PC, through which the unix machine can run ebmon. Not to mention that the PC has PC/NFS, so it can access the same executables that gdb can, @@ -28,7 +28,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TM_FILE_OVERRIDE #include "defs.h" #include -#include "a29k/tm-29k.h" +#include "a29k/tm-a29k.h" #include "inferior.h" #include "wait.h" diff --git a/gdb/remote-monitor.c b/gdb/remote-monitor.c index 7eac458..7736fe8 100644 --- a/gdb/remote-monitor.c +++ b/gdb/remote-monitor.c @@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ as mentioned in the following comment (left in for comic relief): "This is like remote.c but is for an esoteric situation-- - having a 29k board in a PC hooked up to a unix machine with + having an a29k board in a PC hooked up to a unix machine with a serial line, and running ctty com1 on the PC, through which the unix machine can run ebmon. Not to mention that the PC has PC/NFS, so it can access the same executables that gdb can, diff --git a/gdb/remote-st2000.c b/gdb/remote-st2000.c index 02a5a63..67ed256 100644 --- a/gdb/remote-st2000.c +++ b/gdb/remote-st2000.c @@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ as mentioned in the following comment (left in for comic relief): "This is like remote.c but is for an esoteric situation-- - having a 29k board in a PC hooked up to a unix machine with + having an a29k board in a PC hooked up to a unix machine with a serial line, and running ctty com1 on the PC, through which the unix machine can run ebmon. Not to mention that the PC has PC/NFS, so it can access the same executables that gdb can, -- cgit v1.1