From e4dbd248df205219ec934f2b9d00f11f5a192913 Mon Sep 17 00:00:00 2001 From: Peter Schauer Date: Sat, 29 Jul 1995 08:50:00 +0000 Subject: [PATCH] * alpha-tdep.c: Move sigtramp handling of saved registers from read_next_frame_reg to alpha_find_saved_regs, handle saved floating point registers. * mips-tdep.c: Move sigtramp handling of saved registers from read_next_frame_reg to mips_find_saved_regs, handle saved floating point registers. * config/mips/tm-irix3.h, config/mips/tm-irix5.h, config/mips/tm-mipsv4.h (SIGFRAME_FPREGSAVE_OFF): Define. * sparc-tdep.c (sparc_pc_adjust): Fix check for `unimp' instruction to handle functions returning structures with large sizes properly. --- gdb/ChangeLog | 34 +++++++ gdb/alpha-tdep.c | 61 +++++++----- gdb/mips-tdep.c | 251 ++++++++++++++++++++++++++++++++++++----------- gdb/sparc-tdep.c | 8 +- 4 files changed, 271 insertions(+), 83 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f6475fe25d6..53f7bf835e5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,37 @@ +Sat Jul 29 01:45:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * alpha-tdep.c: Move sigtramp handling of saved registers from + read_next_frame_reg to alpha_find_saved_regs, handle saved + floating point registers. + * mips-tdep.c: Move sigtramp handling of saved registers from + read_next_frame_reg to mips_find_saved_regs, handle saved + floating point registers. + * config/mips/tm-irix3.h, config/mips/tm-irix5.h, + config/mips/tm-mipsv4.h (SIGFRAME_FPREGSAVE_OFF): Define. + + * sparc-tdep.c (sparc_pc_adjust): Fix check for `unimp' + instruction to handle functions returning structures with + large sizes properly. + +Fri Jul 28 11:50:17 1995 steve chamberlain + + * configure, configure.in (z8k-*-sim): deleted. + +Thu Jul 27 12:49:28 1995 Jeffrey A. Law + + * lynx-nat.c (child_wait): Handle threads exiting. + +Thu Jul 27 07:47:50 1995 Michael Meissner + + * rs6000-tdep.c (skip_prologue): Don't assume the update stack + instruction is the last in the prologue, since xlc stores the lr + after the stack update. Make sure offset is correct sign for + large frames. + (frame_saved_pc): Move test for signal before frameless. + + * config/rs6000/tm-rs6000.h (DEFAULT_LR_SAVE): Define. + * config/powerpc/tm-ppc-eabi.h (DEFAULT_LR_SAVE): Redefine. + Thu Jul 27 01:22:08 1995 Jeffrey A. Law * hppa-tdep.c (hppa_fix_call_dummy): Rewrite code for calling diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 10a8d53cfd8..fd752f64b20 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -149,6 +149,40 @@ alpha_find_saved_regs (frame) obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs)); memset (frame->saved_regs, 0, sizeof (struct frame_saved_regs)); + /* If it is the frame for __sigtramp, the saved registers are located + in a sigcontext structure somewhere on the stack. __sigtramp + passes a pointer to the sigcontext structure on the stack. + If the stack layout for __sigtramp changes, or if sigcontext offsets + change, we might have to update this code. */ +#ifndef SIGFRAME_PC_OFF +#define SIGFRAME_PC_OFF (2 * 8) +#define SIGFRAME_REGSAVE_OFF (4 * 8) +#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8) +#endif + if (frame->signal_handler_caller) + { + CORE_ADDR sigcontext_pointer_addr; + CORE_ADDR sigcontext_addr; + + if (frame->next) + sigcontext_pointer_addr = frame->next->frame; + else + sigcontext_pointer_addr = frame->frame; + sigcontext_addr = read_memory_integer(sigcontext_pointer_addr, 8); + for (ireg = 0; ireg < 32; ireg++) + { + reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8; + frame->saved_regs->regs[ireg] = reg_position; + } + for (ireg = 0; ireg < 32; ireg++) + { + reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8; + frame->saved_regs->regs[FP0_REGNUM + ireg] = reg_position; + } + frame->saved_regs->regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF; + return; + } + proc_desc = frame->proc_desc; if (proc_desc == NULL) /* I'm not sure how/whether this can happen. Normally when we can't @@ -164,7 +198,7 @@ alpha_find_saved_regs (frame) returnreg = PROC_PC_REG (proc_desc); - /* Note that RA is always saved first, regardless of it's actual + /* Note that RA is always saved first, regardless of its actual register number. */ if (mask & (1 << returnreg)) { @@ -202,30 +236,11 @@ read_next_frame_reg(fi, regno) struct frame_info *fi; int regno; { - /* If it is the frame for sigtramp we have a pointer to the sigcontext - on the stack. - If the stack layout for __sigtramp changes or if sigcontext offsets - change we might have to update this code. */ -#ifndef SIGFRAME_PC_OFF -#define SIGFRAME_PC_OFF (2 * 8) -#define SIGFRAME_REGSAVE_OFF (4 * 8) -#endif for (; fi; fi = fi->next) { - if (fi->signal_handler_caller) - { - int offset; - CORE_ADDR sigcontext_addr = read_memory_integer(fi->frame, 8); - - if (regno == PC_REGNUM) - offset = SIGFRAME_PC_OFF; - else if (regno < 32) - offset = SIGFRAME_REGSAVE_OFF + regno * 8; - else - return 0; - return read_memory_integer(sigcontext_addr + offset, 8); - } - else if (regno == SP_REGNUM) + /* We have to get the saved sp from the sigcontext + if it is a signal handler frame. */ + if (regno == SP_REGNUM && !fi->signal_handler_caller) return fi->frame; else { diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index d708b6acabc..c6ec5f9b46c 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -43,6 +43,12 @@ extern struct obstack frame_cache_obstack; static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR)); #endif +static void mips_set_fpu_command PARAMS ((char *, int, + struct cmd_list_element *)); + +static void mips_show_fpu_command PARAMS ((char *, int, + struct cmd_list_element *)); + void mips_set_processor_type_command PARAMS ((char *, int)); int mips_set_processor_type PARAMS ((char *)); @@ -62,7 +68,9 @@ 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; +enum mips_fpu_type mips_fpu; + +static char *mips_fpu_string; /* A set of original names, to be used when restoring back to generic registers from a specific set. */ @@ -120,6 +128,23 @@ char *mips_r3081_reg_names[] = { "", "", "ehi", "", "", "", "epc", "prid", }; +/* Names of LSI 33k registers. */ + +char *mips_lsi33k_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", + "epc", "hi", "lo", "sr", "cause","badvaddr", + "dcic", "bpc", "bda", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", +}; + struct { char *name; char **regnames; @@ -129,6 +154,7 @@ struct { { "r3051", mips_r3051_reg_names }, { "r3071", mips_r3081_reg_names }, { "r3081", mips_r3081_reg_names }, + { "lsi33k", mips_lsi33k_reg_names }, { NULL, NULL } }; @@ -178,6 +204,39 @@ mips_find_saved_regs (fci) obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs)); memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs)); + /* If it is the frame for sigtramp, the saved registers are located + in a sigcontext structure somewhere on the stack. + If the stack layout for sigtramp changes we might have to change these + constants and the companion fixup_sigtramp in mdebugread.c */ +#ifndef SIGFRAME_BASE +/* To satisfy alignment restrictions, sigcontext is located 4 bytes + above the sigtramp frame. */ +#define SIGFRAME_BASE 4 +#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * 4) +#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 3 * 4) +#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 4 + 3 * 4) +#endif +#ifndef SIGFRAME_REG_SIZE +#define SIGFRAME_REG_SIZE 4 +#endif + if (fci->signal_handler_caller) + { + for (ireg = 0; ireg < 32; ireg++) + { + reg_position = fci->frame + SIGFRAME_REGSAVE_OFF + + ireg * SIGFRAME_REG_SIZE; + fci->saved_regs->regs[ireg] = reg_position; + } + for (ireg = 0; ireg < 32; ireg++) + { + reg_position = fci->frame + SIGFRAME_FPREGSAVE_OFF + + ireg * SIGFRAME_REG_SIZE; + fci->saved_regs->regs[FP0_REGNUM + ireg] = reg_position; + } + fci->saved_regs->regs[PC_REGNUM] = fci->frame + SIGFRAME_PC_OFF; + return; + } + proc_desc = fci->proc_desc; if (proc_desc == NULL) /* I'm not sure how/whether this can happen. Normally when we can't @@ -291,32 +350,12 @@ read_next_frame_reg(fi, regno) struct frame_info *fi; int regno; { - /* If it is the frame for sigtramp we have a complete sigcontext - somewhere above the frame and we get the saved registers from there. - If the stack layout for sigtramp changes we might have to change these - constants and the companion fixup_sigtramp in mdebugread.c */ -#ifndef SIGFRAME_BASE -/* To satisfy alignment restrictions the sigcontext is located 4 bytes - above the sigtramp frame. */ -#define SIGFRAME_BASE 4 -#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * 4) -#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 3 * 4) -#endif -#ifndef SIGFRAME_REG_SIZE -#define SIGFRAME_REG_SIZE 4 -#endif for (; fi; fi = fi->next) { - if (fi->signal_handler_caller) - { - int offset; - if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF; - else if (regno < 32) offset = (SIGFRAME_REGSAVE_OFF - + regno * SIGFRAME_REG_SIZE); - else return 0; - return read_memory_integer(fi->frame + offset, MIPS_REGSIZE); - } - else if (regno == SP_REGNUM) return fi->frame; + /* We have to get the saved sp from the sigcontext + if it is a signal handler frame. */ + if (regno == SP_REGNUM && !fi->signal_handler_caller) + return fi->frame; else { if (fi->saved_regs == NULL) @@ -510,6 +549,11 @@ find_proc_desc (pc, next_frame) 0, NULL); } + /* If we never found a PDR for this function in symbol reading, then + examine prologues to find the information. */ + if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1) + sym = NULL; + if (sym) { /* IF this is the topmost frame AND @@ -681,7 +725,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr) int fake_args = 0; for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) { - value_ptr arg = value_arg_coerce (args[i]); + value_ptr arg = args[i]; m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg)); /* This entire mips-specific routine is because doubles must be aligned * on 8-byte boundaries. It still isn't quite right, because MIPS decided @@ -761,6 +805,9 @@ mips_push_dummy_frame() #define GEN_REG_SAVE_COUNT 22 #define FLOAT_REG_SAVE_MASK MASK(0,19) #define FLOAT_REG_SAVE_COUNT 20 +#define FLOAT_SINGLE_REG_SAVE_MASK \ + ((1<<18)|(1<<16)|(1<<14)|(1<<12)|(1<<10)|(1<<8)|(1<<6)|(1<<4)|(1<<2)|(1<<0)) +#define FLOAT_SINGLE_REG_SAVE_COUNT 10 #define SPECIAL_REG_SAVE_COUNT 4 /* * The registers we must save are all those not preserved across @@ -784,7 +831,18 @@ mips_push_dummy_frame() * (low memory) */ PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK; - PROC_FREG_MASK(proc_desc) = mips_fpu ? FLOAT_REG_SAVE_MASK : 0; + switch (mips_fpu) + { + case MIPS_FPU_DOUBLE: + PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK; + break; + case MIPS_FPU_SINGLE: + PROC_FREG_MASK(proc_desc) = FLOAT_SINGLE_REG_SAVE_MASK; + break; + case MIPS_FPU_NONE: + PROC_FREG_MASK(proc_desc) = 0; + break; + } PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */ -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT; PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */ @@ -828,14 +886,16 @@ mips_push_dummy_frame() write_memory (sp - 8, buffer, REGISTER_RAW_SIZE (HI_REGNUM)); read_register_gen (LO_REGNUM, buffer); write_memory (sp - 12, buffer, REGISTER_RAW_SIZE (LO_REGNUM)); - if (mips_fpu) + if (mips_fpu != MIPS_FPU_NONE) read_register_gen (FCRCS_REGNUM, buffer); else memset (buffer, 0, REGISTER_RAW_SIZE (FCRCS_REGNUM)); write_memory (sp - 16, buffer, REGISTER_RAW_SIZE (FCRCS_REGNUM)); - sp -= 4 * (GEN_REG_SAVE_COUNT - + (mips_fpu ? FLOAT_REG_SAVE_COUNT : 0) - + SPECIAL_REG_SAVE_COUNT); + sp -= 4 * (GEN_REG_SAVE_COUNT + SPECIAL_REG_SAVE_COUNT); + if (mips_fpu == MIPS_FPU_DOUBLE) + sp -= 4 * FLOAT_REG_SAVE_COUNT; + else if (mips_fpu == MIPS_FPU_SINGLE) + sp -= 4 * FLOAT_SINGLE_REG_SAVE_COUNT; write_register (SP_REGNUM, sp); PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE + CALL_DUMMY_START_OFFSET; PROC_HIGH_ADDR(proc_desc) = sp; @@ -894,7 +954,7 @@ mips_pop_frame() write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4)); write_register (LO_REGNUM, read_memory_integer(new_sp - 12, 4)); - if (mips_fpu) + if (mips_fpu != MIPS_FPU_NONE) write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4)); } } @@ -903,14 +963,7 @@ static void mips_print_register (regnum, all) int regnum, all; { - unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE]; - struct type *our_type = - init_type (TYPE_CODE_INT, - /* We will fill in the length for each register. */ - 0, - TYPE_FLAG_UNSIGNED, - NULL, - NULL); + char raw_buffer[MAX_REGISTER_RAW_SIZE]; /* Get the data in raw format. */ if (read_relative_register_raw_bytes (regnum, raw_buffer)) @@ -921,19 +974,20 @@ mips_print_register (regnum, all) /* If an even floating pointer register, also print as double. */ if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+32 - && !((regnum-FP0_REGNUM) & 1)) { - char dbuffer[MAX_REGISTER_RAW_SIZE]; + && !((regnum-FP0_REGNUM) & 1)) + { + char dbuffer[MAX_REGISTER_RAW_SIZE]; - read_relative_register_raw_bytes (regnum, dbuffer); - read_relative_register_raw_bytes (regnum+1, dbuffer+4); + read_relative_register_raw_bytes (regnum, dbuffer); + read_relative_register_raw_bytes (regnum+1, dbuffer+4); #ifdef REGISTER_CONVERT_TO_TYPE - REGISTER_CONVERT_TO_TYPE(regnum, builtin_type_double, dbuffer); + REGISTER_CONVERT_TO_TYPE(regnum, builtin_type_double, dbuffer); #endif - printf_filtered ("(d%d: ", regnum-FP0_REGNUM); - val_print (builtin_type_double, dbuffer, 0, - gdb_stdout, 0, 1, 0, Val_pretty_default); - printf_filtered ("); "); - } + printf_filtered ("(d%d: ", regnum-FP0_REGNUM); + val_print (builtin_type_double, dbuffer, 0, + gdb_stdout, 0, 1, 0, Val_pretty_default); + printf_filtered ("); "); + } fputs_filtered (reg_names[regnum], gdb_stdout); /* The problem with printing numeric register names (r26, etc.) is that @@ -1174,7 +1228,11 @@ mips_extract_return_value (valtype, regbuf, valbuf) { int regnum; - regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT && mips_fpu ? FP0_REGNUM : 2; + regnum = 2; + if (TYPE_CODE (valtype) == TYPE_CODE_FLT + && (mips_fpu == MIPS_FPU_DOUBLE + || (mips_fpu == MIPS_FPU_SINGLE && TYPE_LENGTH (valtype) <= 4))) + regnum = FP0_REGNUM; memcpy (valbuf, regbuf + REGISTER_BYTE (regnum), TYPE_LENGTH (valtype)); #ifdef REGISTER_CONVERT_TO_TYPE @@ -1192,7 +1250,12 @@ mips_store_return_value (valtype, valbuf) int regnum; char raw_buffer[MAX_REGISTER_RAW_SIZE]; - regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT && mips_fpu ? FP0_REGNUM : 2; + regnum = 2; + if (TYPE_CODE (valtype) == TYPE_CODE_FLT + && (mips_fpu == MIPS_FPU_DOUBLE + || (mips_fpu == MIPS_FPU_SINGLE && TYPE_LENGTH (valtype) <= 4))) + regnum = FP0_REGNUM; + memcpy(raw_buffer, valbuf, TYPE_LENGTH (valtype)); #ifdef REGISTER_CONVERT_FROM_TYPE @@ -1218,6 +1281,69 @@ in_sigtramp (pc, ignore) return (pc >= sigtramp_address && pc < sigtramp_end); } +/* Command to set FPU type. mips_fpu_string will have been set to the + user's argument. Set mips_fpu based on mips_fpu_string, and then + canonicalize mips_fpu_string. */ + +/*ARGSUSED*/ +static void +mips_set_fpu_command (args, from_tty, c) + char *args; + int from_tty; + struct cmd_list_element *c; +{ + char *err = NULL; + + if (mips_fpu_string == NULL || *mips_fpu_string == '\0') + mips_fpu = MIPS_FPU_DOUBLE; + else if (strcasecmp (mips_fpu_string, "double") == 0 + || strcasecmp (mips_fpu_string, "on") == 0 + || strcasecmp (mips_fpu_string, "1") == 0 + || strcasecmp (mips_fpu_string, "yes") == 0) + mips_fpu = MIPS_FPU_DOUBLE; + else if (strcasecmp (mips_fpu_string, "none") == 0 + || strcasecmp (mips_fpu_string, "off") == 0 + || strcasecmp (mips_fpu_string, "0") == 0 + || strcasecmp (mips_fpu_string, "no") == 0) + mips_fpu = MIPS_FPU_NONE; + else if (strcasecmp (mips_fpu_string, "single") == 0) + mips_fpu = MIPS_FPU_SINGLE; + else + err = strsave (mips_fpu_string); + + if (mips_fpu_string != NULL) + free (mips_fpu_string); + + switch (mips_fpu) + { + case MIPS_FPU_DOUBLE: + mips_fpu_string = strsave ("double"); + break; + case MIPS_FPU_SINGLE: + mips_fpu_string = strsave ("single"); + break; + case MIPS_FPU_NONE: + mips_fpu_string = strsave ("none"); + break; + } + + if (err != NULL) + { + struct cleanup *cleanups = make_cleanup (free, err); + error ("Unknown FPU type `%s'. Use `double', `none', or `single'.", + err); + do_cleanups (cleanups); + } +} + +static void +mips_show_fpu_command (args, from_tty, c) + char *args; + int from_tty; + struct cmd_list_element *c; +{ +} + /* Command to set the processor type. */ void @@ -1332,13 +1458,20 @@ _initialize_mips_tdep () /* Let the user turn off floating point and set the fence post for heuristic_proc_start. */ - add_show_from_set - (add_set_cmd ("mipsfpu", class_support, var_boolean, - (char *) &mips_fpu, - "Set use of floating point coprocessor.\n\ -Turn off to avoid using floating point instructions when calling functions\n\ -or dealing with return values.", &setlist), - &showlist); + c = add_set_cmd ("mipsfpu", class_support, var_string_noescape, + (char *) &mips_fpu_string, + "Set use of floating point coprocessor.\n\ +Set to `none' to avoid using floating point instructions when calling\n\ +functions or dealing with return values. Set to `single' to use only\n\ +single precision floating point as on the R4650. Set to `double' for\n\ +normal floating point support.", + &setlist); + c->function.sfunc = mips_set_fpu_command; + c = add_show_from_set (c, &showlist); + c->function.sfunc = mips_show_fpu_command; + + mips_fpu = MIPS_FPU_DOUBLE; + mips_fpu_string = strsave ("double"); c = add_set_cmd ("processor", class_support, var_string_noescape, (char *) &tmp_mips_processor_type, diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 172f98d1a5b..45031a2debc 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1043,7 +1043,7 @@ sparc_pc_adjust(pc) err = target_read_memory (pc + 8, buf, sizeof(long)); insn = extract_unsigned_integer (buf, 4); - if ((err == 0) && (insn & 0xfffffe00) == 0) + if ((err == 0) && (insn & 0xffc00000) == 0) return pc+12; else return pc+8; @@ -1139,6 +1139,7 @@ prgregset_t *gregsetp; { register int regi; register prgreg_t *regp = (prgreg_t *) gregsetp; + static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0}; /* GDB register numbers for Gn, On, Ln, In all match /proc reg numbers. */ for (regi = G0_REGNUM ; regi <= I7_REGNUM ; regi++) @@ -1151,6 +1152,11 @@ prgregset_t *gregsetp; supply_register (PC_REGNUM, (char *) (regp + R_PC)); supply_register (NPC_REGNUM,(char *) (regp + R_nPC)); supply_register (Y_REGNUM, (char *) (regp + R_Y)); + + /* Fill inaccessible registers with zero. */ + supply_register (WIM_REGNUM, zerobuf); + supply_register (TBR_REGNUM, zerobuf); + supply_register (CPS_REGNUM, zerobuf); } void -- 2.30.2