Support for different MIPS IDT processor models.

* mips-tdep.c (mips_processor_type, tmp_mips_processor_type,
	mips_generic_reg_names, mips_r3041_reg_names,
	mips_r3051_reg_names, mips_r3081_reg_names,
	mips_processor_type_table): New	globals.
	(mips_do_registers_info): Don't display register if name is empty.
	(mips_set_processor_type_command): New command.
	(mips_show_processor_type_command): New command.
	(mips_set_processor_type): New function.
	(mips_read_processor_type): New function.
	* config/mips/tm-idt.h (DEFAULT_MIPS_TYPE): New macro.
	* config/mips/tm-mips.h (DEFAULT_MIPS_TYPE): New macro.
	(NUM_REGS): Increase to account for all CP0 registers.
	(REGISTER_NAMES): Add empty names for CP0 registers.
	(FIRST_EMBED_REGNUM, LAST_EMBED_REGNUM): Adjust.
	(PRID_REGNUM): New macro.
This commit is contained in:
Stan Shebs 1994-11-18 02:18:09 +00:00
parent f618f758e9
commit 9f9f94aa09
4 changed files with 300 additions and 80 deletions

View File

@ -1,3 +1,22 @@
Thu Nov 17 17:51:12 1994 Stan Shebs (shebs@andros.cygnus.com)
Support for different MIPS IDT processor models.
* mips-tdep.c (mips_processor_type, tmp_mips_processor_type,
mips_generic_reg_names, mips_r3041_reg_names,
mips_r3051_reg_names, mips_r3081_reg_names,
mips_processor_type_table): New globals.
(mips_do_registers_info): Don't display register if name is empty.
(mips_set_processor_type_command): New command.
(mips_show_processor_type_command): New command.
(mips_set_processor_type): New function.
(mips_read_processor_type): New function.
* config/mips/tm-idt.h (DEFAULT_MIPS_TYPE): New macro.
* config/mips/tm-mips.h (DEFAULT_MIPS_TYPE): New macro.
(NUM_REGS): Increase to account for all CP0 registers.
(REGISTER_NAMES): Add empty names for CP0 registers.
(FIRST_EMBED_REGNUM, LAST_EMBED_REGNUM): Adjust.
(PRID_REGNUM): New macro.
Wed Nov 16 16:41:52 1994 Stan Shebs (shebs@andros.cygnus.com)
* README: Add warning about termcap in Ultrix and OSF/1.

View File

@ -19,3 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define TARGET_BYTE_ORDER_SELECTABLE
#include "mips/tm-bigmips.h"
#undef DEFAULT_MIPS_TYPE
#define DEFAULT_MIPS_TYPE "r3051"

View File

@ -34,13 +34,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Floating point is IEEE compliant */
#define IEEE_FLOAT
extern int mips_processor_id;
/* Some MIPS boards are provided both with and without a floating
point coprocessor; we provide a user settable variable to tell gdb
whether there is one or not. */
extern int mips_fpu;
/* The name of the usual type of MIPS processor that is in the target
system. */
#define DEFAULT_MIPS_TYPE "generic"
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -105,7 +108,7 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
/* Number of machine registers */
#define NUM_REGS 80
#define NUM_REGS 90
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
@ -120,8 +123,9 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
"fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
"epc", "prid"\
"fsr", "fir", "fp", "", \
"", "", "", "", "", "", "", "", \
"", "", "", "", "", "", "", "", \
}
/* Register numbers of various important registers.
@ -146,8 +150,9 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
#define FCRCS_REGNUM 70 /* FP control/status */
#define FCRIR_REGNUM 71 /* FP implementation/revision */
#define FP_REGNUM 72 /* Pseudo register that contains true address of executing stack frame */
#define FIRST_EMBED_REGNUM 73 /* First supervisor register for embedded use */
#define LAST_EMBED_REGNUM 79 /* Last one */
#define FIRST_EMBED_REGNUM 74 /* First CP0 register for embedded use */
#define PRID_REGNUM 89 /* Processor ID */
#define LAST_EMBED_REGNUM 89 /* Last one */
/* Define DO_REGISTERS_INFO() to do machine-specific formatting
of register dumps. */
@ -156,6 +161,7 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS*MIPS_REGSIZE)
/* Index within `registers' of the first byte of the space for

View File

@ -43,13 +43,95 @@ extern struct obstack frame_cache_obstack;
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
#endif
void mips_set_processor_type_command PARAMS ((char *, int));
static void reinit_frame_cache_sfunc PARAMS ((char *, int,
struct cmd_list_element *));
/* This value is the model of MIPS in use. It is derived from the value
of the PrID register. */
char *mips_processor_type;
char *tmp_mips_processor_type;
/* Some MIPS boards don't support floating point, so we permit the
user to turn it off. */
int mips_fpu = 1;
/* A set of original names, to be used when restoring back to generic
registers from a specific set. */
char *mips_generic_reg_names[] = REGISTER_NAMES;
/* Names of IDT R3041 registers. */
char *mips_r3041_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"", "", "bus", "ccfg", "", "", "", "",
"", "", "port", "cmp", "", "", "epc", "prid",
};
/* Names of IDT R3051 registers. */
char *mips_r3051_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"inx", "rand", "elo", "", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
/* Names of IDT R3081 registers. */
char *mips_r3081_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"inx", "rand", "elo", "cfg", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
struct {
char *name;
char **regnames;
} mips_processor_type_table[] = {
{ "generic", mips_generic_reg_names },
{ "r3041", mips_r3041_reg_names },
{ "r3051", mips_r3051_reg_names },
{ "r3071", mips_r3081_reg_names },
{ "r3081", mips_r3081_reg_names },
{ NULL, NULL }
};
/* Heuristic_proc_start may hunt through the text section for a long
time across a 2400 baud serial line. Allows the user to limit this
search. */
static unsigned int heuristic_fence_post = 0;
#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
@ -78,7 +160,7 @@ struct linked_proc_info
void
mips_find_saved_regs (fci)
FRAME fci;
struct frame_info *fci;
{
int ireg;
CORE_ADDR reg_position;
@ -202,7 +284,7 @@ mips_find_saved_regs (fci)
static int
read_next_frame_reg(fi, regno)
FRAME fi;
struct frame_info *fi;
int regno;
{
/* If it is the frame for sigtramp we have a complete sigcontext
@ -244,7 +326,7 @@ read_next_frame_reg(fi, regno)
int
mips_frame_saved_pc(frame)
FRAME frame;
struct frame_info *frame;
{
mips_extra_func_info_t proc_desc = frame->proc_desc;
/* We have to get the saved pc from the sigcontext
@ -326,7 +408,7 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
static mips_extra_func_info_t
heuristic_proc_desc(start_pc, limit_pc, next_frame)
CORE_ADDR start_pc, limit_pc;
FRAME next_frame;
struct frame_info *next_frame;
{
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
CORE_ADDR cur_pc;
@ -336,11 +418,12 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
unsigned long reg_mask = 0;
if (start_pc == 0) return NULL;
memset(&temp_proc_desc, '\0', sizeof(temp_proc_desc));
memset(&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
PROC_LOW_ADDR(&temp_proc_desc) = start_pc;
memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
if (start_pc + 200 < limit_pc)
limit_pc = start_pc + 200;
restart:
frame_size = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
@ -399,9 +482,9 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
}
static mips_extra_func_info_t
find_proc_desc(pc, next_frame)
CORE_ADDR pc;
FRAME next_frame;
find_proc_desc (pc, next_frame)
CORE_ADDR pc;
struct frame_info *next_frame;
{
mips_extra_func_info_t proc_desc;
struct block *b = block_for_pc(pc);
@ -431,7 +514,7 @@ find_proc_desc(pc, next_frame)
* THEN create a "heuristic" proc_desc (by analyzing
* the actual code) to replace the "official" proc_desc.
*/
proc_desc = (mips_extra_func_info_t)SYMBOL_VALUE(sym);
proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
if (next_frame == NULL) {
struct symtab_and_line val;
struct symbol *proc_symbol =
@ -445,9 +528,10 @@ find_proc_desc(pc, next_frame)
}
if (!proc_symbol || pc < val.pc) {
mips_extra_func_info_t found_heuristic =
heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),
pc, next_frame);
if (found_heuristic) proc_desc = found_heuristic;
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
pc, next_frame);
if (found_heuristic)
proc_desc = found_heuristic;
}
}
}
@ -459,10 +543,11 @@ find_proc_desc(pc, next_frame)
heuristic_proc_desc knows how to create them! */
register struct linked_proc_info *link;
for (link = linked_proc_desc_table; link; link = link->next)
if (PROC_LOW_ADDR(&link->info) <= pc
&& PROC_HIGH_ADDR(&link->info) > pc)
return &link->info;
if (PROC_LOW_ADDR(&link->info) <= pc
&& PROC_HIGH_ADDR(&link->info) > pc)
return &link->info;
if (startaddr == 0)
startaddr = heuristic_proc_start (pc);
@ -475,9 +560,9 @@ find_proc_desc(pc, next_frame)
mips_extra_func_info_t cached_proc_desc;
FRAME_ADDR
CORE_ADDR
mips_frame_chain(frame)
FRAME frame;
struct frame_info *frame;
{
mips_extra_func_info_t proc_desc;
CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
@ -563,10 +648,10 @@ init_extra_frame_info(fci)
cache. This allows the rest of info frame to extract the important
arguments without difficulty. */
FRAME
struct frame_info *
setup_arbitrary_frame (argc, argv)
int argc;
FRAME_ADDR *argv;
CORE_ADDR *argv;
{
if (argc != 2)
error ("MIPS frame specifications require two arguments: sp and pc");
@ -608,34 +693,33 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
accumulate_size = (accumulate_size + 7) & -8;
m_arg->offset = accumulate_size;
m_arg->contents = VALUE_CONTENTS(arg);
#ifndef GDB_TARGET_IS_MIPS64
accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
#else
if (accumulate_size >= 4 * MIPS_REGSIZE)
accumulate_size = (accumulate_size + m_arg->len + 3) &~ 4;
if (! GDB_TARGET_IS_MIPS64)
accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
else
{
static char zeroes[8] = { 0 };
int len = m_arg->len;
if (len < 8)
if (accumulate_size >= 4 * MIPS_REGSIZE)
accumulate_size = (accumulate_size + m_arg->len + 3) &~ 4;
else
{
#if TARGET_BYTE_ORDER == BIG_ENDIAN
m_arg->offset += 8 - len;
#endif
++m_arg;
m_arg->len = 8 - len;
m_arg->contents = zeroes;
#if TARGET_BYTE_ORDER == BIG_ENDIAN
m_arg->offset = accumulate_size;
#else
m_arg->offset = accumulate_size + len;
#endif
++fake_args;
static char zeroes[8] = { 0 };
int len = m_arg->len;
if (len < 8)
{
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
m_arg->offset += 8 - len;
++m_arg;
m_arg->len = 8 - len;
m_arg->contents = zeroes;
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
m_arg->offset = accumulate_size;
else
m_arg->offset = accumulate_size + len;
++fake_args;
}
accumulate_size = (accumulate_size + len + 7) & ~8;
}
accumulate_size = (accumulate_size + len + 7) & ~8;
}
#endif
}
accumulate_size = (accumulate_size + 7) & (-8);
if (accumulate_size < 4 * MIPS_REGSIZE)
@ -759,8 +843,8 @@ void
mips_pop_frame()
{
register int regnum;
FRAME frame = get_current_frame ();
CORE_ADDR new_sp = frame->frame;
struct frame_info *frame = get_current_frame ();
CORE_ADDR new_sp = FRAME_FP (frame);
mips_extra_func_info_t proc_desc = frame->proc_desc;
@ -781,8 +865,6 @@ mips_pop_frame()
}
write_register (SP_REGNUM, new_sp);
flush_cached_frames ();
/* We let mips_init_extra_frame_info figure out the frame pointer */
set_current_frame (create_new_frame (0, read_pc ()));
if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
{
@ -870,48 +952,66 @@ mips_print_register (regnum, all)
}
/* Replacement for generic do_registers_info. */
void
mips_do_registers_info (regnum, fpregs)
int regnum;
int fpregs;
{
if (regnum != -1) {
if (regnum != -1)
{
if (*(reg_names[regnum]) == '\0')
error ("Not a valid register for the current processor type");
mips_print_register (regnum, 0);
printf_filtered ("\n");
}
else {
for (regnum = 0; regnum < NUM_REGS; ) {
if ((!fpregs) && regnum >= FP0_REGNUM && regnum <= FCRIR_REGNUM) {
regnum++;
continue;
}
}
else
{
int did_newline;
for (regnum = 0; regnum < NUM_REGS; )
{
if (((!fpregs) && regnum >= FP0_REGNUM && regnum <= FCRIR_REGNUM)
|| *(reg_names[regnum]) == '\0')
{
regnum++;
continue;
}
mips_print_register (regnum, 1);
regnum++;
if ((regnum & 3) == 0 || regnum == NUM_REGS)
printf_filtered (";\n");
else
printf_filtered ("; ");
}
}
printf_filtered ("; ");
did_newline = 0;
if ((regnum & 3) == 0)
{
printf_filtered ("\n");
did_newline = 1;
}
}
if (!did_newline)
printf_filtered ("\n");
}
}
/* Return number of args passed to a frame. described by FIP.
Can return -1, meaning no way to tell. */
int
mips_frame_num_args(fip)
FRAME fip;
mips_frame_num_args (frame)
struct frame_info *frame;
{
#if 0
struct chain_info_t *p;
#if 0 /* FIXME Use or lose this! */
struct chain_info_t *p;
p = mips_find_cached_frame(FRAME_FP(fip));
if (p->valid)
return p->the_info.numargs;
p = mips_find_cached_frame (FRAME_FP (frame));
if (p->valid)
return p->the_info.numargs;
#endif
return -1;
return -1;
}
/* Is this a branch with a delay slot? */
static int is_delayed PARAMS ((unsigned long));
static int
@ -1110,11 +1210,90 @@ in_sigtramp (pc, ignore)
return (pc >= sigtramp_address && pc < sigtramp_end);
}
static void reinit_frame_cache_sfunc PARAMS ((char *, int,
struct cmd_list_element *));
/* Command to set the processor type. */
void
mips_set_processor_type_command (args, from_tty)
char *args;
int from_tty;
{
int i;
if (tmp_mips_processor_type == NULL || *tmp_mips_processor_type == '\0')
{
printf_unfiltered ("The known MIPS processor types are as follows:\n\n");
for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
printf_unfiltered ("%s\n", mips_processor_type_table[i].name);
/* Restore the value. */
tmp_mips_processor_type = strsave (mips_processor_type);
return;
}
if (!mips_set_processor_type (tmp_mips_processor_type))
{
error ("Unknown processor type `%s'.", tmp_mips_processor_type);
/* Restore its value. */
tmp_mips_processor_type = strsave (mips_processor_type);
}
}
static void
mips_show_processor_type_command (args, from_tty)
char *args;
int from_tty;
{
}
/* Modify the actual processor type. */
int
mips_set_processor_type (str)
char *str;
{
int i, j;
if (str == NULL)
return;
for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
{
if (strcasecmp (str, mips_processor_type_table[i].name) == 0)
{
mips_processor_type = str;
for (j = 0; j < NUM_REGS; ++j)
reg_names[j] = mips_processor_type_table[i].regnames[j];
return 1;
/* FIXME tweak fpu flag too */
}
}
return 0;
}
/* Attempt to identify the particular processor model by reading the
processor id. */
char *
mips_read_processor_type ()
{
int prid;
prid = read_register (PRID_REGNUM);
if (prid & ~0xf == 0x700)
return savestring ("r3041", strlen("r3041"));
return NULL;
}
/* Just like reinit_frame_cache, but with the right arguments to be
callable as an sfunc. */
static void
reinit_frame_cache_sfunc (args, from_tty, c)
char *args;
@ -1140,6 +1319,19 @@ Turn off to avoid using floating point instructions when calling functions\n\
or dealing with return values.", &setlist),
&showlist);
c = add_set_cmd ("processor", class_support, var_string_noescape,
(char *) &tmp_mips_processor_type,
"Set the type of MIPS processor in use.\n\
Set this to be able to access processor-type-specific registers.\n\
",
&setlist);
c->function.cfunc = mips_set_processor_type_command;
c = add_show_from_set (c, &showlist);
c->function.cfunc = mips_show_processor_type_command;
tmp_mips_processor_type = strsave (DEFAULT_MIPS_TYPE);
mips_set_processor_type_command (strsave (DEFAULT_MIPS_TYPE), 0);
/* We really would like to have both "0" and "unlimited" work, but
command.c doesn't deal with that. So make it a var_zinteger
because the user can always use "999999" or some such for unlimited. */