diff options
Diffstat (limited to 'gdb/sparc-xdep.c')
-rw-r--r-- | gdb/sparc-xdep.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/gdb/sparc-xdep.c b/gdb/sparc-xdep.c new file mode 100644 index 0000000..89fcb8d --- /dev/null +++ b/gdb/sparc-xdep.c @@ -0,0 +1,298 @@ +/* Machine-dependent code which would otherwise be in inflow.c and core.c, + for GDB, the GNU debugger, for SPARC host systems. + + Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc. + +This file is part of GDB. + +GDB 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 1, or (at your option) +any later version. + +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include "defs.h" +#include "tm-sparc.h" +#include "param-no-tm.h" +#include "inferior.h" +#include "target.h" + +#include <sys/param.h> +#include <sys/file.h> /* For L_SET */ + +#include <sys/ptrace.h> +#include <machine/reg.h> + +#include "gdbcore.h" +#include <sys/core.h> + +extern char register_valid[]; + +/* Fetch one or more registers from the inferior. REGNO == -1 to get + them all. We actually fetch more than requested, when convenient, + marking them as valid so we won't fetch them again. */ +void +fetch_inferior_registers (regno) + int regno; +{ + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + int i; + + /* We should never be called with deferred stores, because a prerequisite + for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh. */ + if (deferred_stores) abort(); + + DO_DEFERRED_STORES; + + /* Global and Out regs are fetched directly, as well as the control + registers. If we're getting one of the in or local regs, + and the stack pointer has not yet been fetched, + we have to do that first, since they're found in memory relative + to the stack pointer. */ + if (regno < O7_REGNUM /* including -1 */ + || regno >= Y_REGNUM + || (!register_valid[SP_REGNUM] && regno < I7_REGNUM)) + { + if (0 != ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers)) + perror("ptrace_getregs"); + + registers[REGISTER_BYTE (0)] = 0; + bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * REGISTER_RAW_SIZE (G0_REGNUM)); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc; + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y; + + for (i = G0_REGNUM; i <= O7_REGNUM; i++) + register_valid[i] = 1; + register_valid[Y_REGNUM] = 1; + register_valid[PS_REGNUM] = 1; + register_valid[PC_REGNUM] = 1; + register_valid[NPC_REGNUM] = 1; + /* If we don't set these valid, read_register_bytes() rereads + all the regs every time it is called! FIXME. */ + register_valid[WIM_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[TBR_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[FPS_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[CPS_REGNUM] = 1; /* Not true yet, FIXME */ + } + + /* Floating point registers */ + if (regno == -1 || (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31)) + { + if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers)) + perror("ptrace_getfpregs"); + bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof inferior_fp_registers.fpu_fr); + /* bcopy (&inferior_fp_registers.Fpu_fsr, + ®isters[REGISTER_BYTE (FPS_REGNUM)], + sizeof (FPU_FSR_TYPE)); FIXME??? -- gnu@cyg */ + for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++) + register_valid[i] = 1; + register_valid[FPS_REGNUM] = 1; + } + + /* These regs are saved on the stack by the kernel. Only read them + all (16 ptrace calls!) if we really need them. */ + if (regno == -1) + { + target_xfer_memory (*(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)], + ®isters[REGISTER_BYTE (L0_REGNUM)], + 16*REGISTER_RAW_SIZE (L0_REGNUM), 0); + for (i = L0_REGNUM; i <= I7_REGNUM; i++) + register_valid[i] = 1; + } + else if (regno >= L0_REGNUM && regno <= I7_REGNUM) + { + CORE_ADDR sp = *(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)]; + i = REGISTER_BYTE (regno); + if (register_valid[regno]) + printf("register %d valid and read\n", regno); + target_xfer_memory (sp + i - REGISTER_BYTE (L0_REGNUM), + ®isters[i], REGISTER_RAW_SIZE (regno), 0); + register_valid[regno] = 1; + } +} + +/* Store our register values back into the inferior. + If REGNO is -1, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +#define INT_REGS 1 +#define STACK_REGS 2 +#define FP_REGS 4 +int deferred_stores = 0; /* Cumulates stores we want to do eventually. */ + +int +store_inferior_registers (regno) + int regno; +{ + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + int wanna_store = INT_REGS + STACK_REGS + FP_REGS; + + /* First decide which pieces of machine-state we need to modify. + Default for regno == -1 case is all pieces. */ + if (regno >= 0) + if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32) + { + wanna_store = FP_REGS; + } + else + { + if (regno == SP_REGNUM) + wanna_store = INT_REGS + STACK_REGS; + else if (regno < L0_REGNUM || regno > I7_REGNUM) + wanna_store = INT_REGS; + else + wanna_store = STACK_REGS; + } + + /* See if we're forcing the stores to happen now, or deferring. */ + if (regno == -2) + { + wanna_store = deferred_stores; + deferred_stores = 0; + } + else + { + if (wanna_store == STACK_REGS) + { + /* Fall through and just store one stack reg. If we deferred + it, we'd have to store them all, or remember more info. */ + } + else + { + deferred_stores |= wanna_store; + return 0; + } + } + + if (wanna_store & STACK_REGS) + { + CORE_ADDR sp = *(CORE_ADDR *)®isters[REGISTER_BYTE (SP_REGNUM)]; + + if (regno < 0 || regno == SP_REGNUM) + { + if (!register_valid[L0_REGNUM+5]) abort(); + target_xfer_memory (sp, + ®isters[REGISTER_BYTE (L0_REGNUM)], + 16*REGISTER_RAW_SIZE (L0_REGNUM), 1); + } + else + { + if (!register_valid[regno]) abort(); + target_xfer_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM), + ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (regno), 1); + } + + } + + if (wanna_store & INT_REGS) + { + if (!register_valid[G1_REGNUM]) abort(); + + bcopy (®isters[REGISTER_BYTE (G1_REGNUM)], + &inferior_registers.r_g1, 15 * REGISTER_RAW_SIZE (G1_REGNUM)); + + inferior_registers.r_ps = + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; + inferior_registers.r_pc = + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; + inferior_registers.r_npc = + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)]; + inferior_registers.r_y = + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)]; + + if (0 != ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers)) + perror("ptrace_setregs"); + } + + if (wanna_store & FP_REGS) + { + if (!register_valid[FP0_REGNUM+9]) abort(); + bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], + &inferior_fp_registers, + sizeof inferior_fp_registers.fpu_fr); + +/* bcopy (®isters[REGISTER_BYTE (FPS_REGNUM)], + &inferior_fp_registers.Fpu_fsr, + sizeof (FPU_FSR_TYPE)); +****/ + if (0 != + ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers)) + perror("ptrace_setfpregs"); + } + return 0; +} + +void +fetch_core_registers (core_reg_sect, core_reg_size, which) + char *core_reg_sect; + unsigned core_reg_size; + int which; +{ + + if (which == 0) { + + /* Integer registers */ + +#define gregs ((struct regs *)core_reg_sect) + /* G0 *always* holds 0. */ + *(int *)®isters[REGISTER_BYTE (0)] = 0; + + /* The globals and output registers. */ + bcopy (&gregs->r_g1, + ®isters[REGISTER_BYTE (G1_REGNUM)], + 15 * REGISTER_RAW_SIZE (G1_REGNUM)); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc; + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc; + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y; + + /* My best guess at where to get the locals and input + registers is exactly where they usually are, right above + the stack pointer. If the core dump was caused by a bus error + from blowing away the stack pointer (as is possible) then this + won't work, but it's worth the try. */ + { + int sp; + + sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)]; + if (0 != target_read_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)], + 16 * REGISTER_RAW_SIZE (L0_REGNUM))) + { + /* fprintf so user can still use gdb */ + fprintf (stderr, + "Couldn't read input and local registers from core file\n"); + } + } + } else if (which == 2) { + + /* Floating point registers */ + +#define fpuregs ((struct fpu *) core_reg_sect) + if (core_reg_size >= sizeof (struct fpu)) + { + bcopy (fpuregs->fpu_regs, + ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof (fpuregs->fpu_regs)); + bcopy (&fpuregs->fpu_fsr, + ®isters[REGISTER_BYTE (FPS_REGNUM)], + sizeof (FPU_FSR_TYPE)); + } + else + fprintf (stderr, "Couldn't read float regs from core file\n"); + } +} |