From 9f9f94aa0930f4981532e953b54cd028c0a556c6 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Fri, 18 Nov 1994 02:18:09 +0000 Subject: [PATCH] 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. --- gdb/ChangeLog | 19 +++ gdb/config/mips/tm-idt.h | 3 + gdb/config/mips/tm-mips.h | 20 ++- gdb/mips-tdep.c | 338 ++++++++++++++++++++++++++++++++++++---------- 4 files changed, 300 insertions(+), 80 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cbcd77c..1ebf3c4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. diff --git a/gdb/config/mips/tm-idt.h b/gdb/config/mips/tm-idt.h index e53e5e7..ab9d28b 100644 --- a/gdb/config/mips/tm-idt.h +++ b/gdb/config/mips/tm-idt.h @@ -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" diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h index 2184aab..cb20c68 100644 --- a/gdb/config/mips/tm-mips.h +++ b/gdb/config/mips/tm-mips.h @@ -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 diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index f2cc19a..7e623c3 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -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. */ -- 2.7.4