diff options
author | Stu Grossman <grossman@cygnus> | 1994-01-22 01:58:55 +0000 |
---|---|---|
committer | Stu Grossman <grossman@cygnus> | 1994-01-22 01:58:55 +0000 |
commit | d575ddc0ef874292672001dc58848befa5325115 (patch) | |
tree | 7dc4ccacf310f9df8813efffca814c2403449024 /gdb/lynx-nat.c | |
parent | 24845456a360df80c98ecbda5e5df485115e62d7 (diff) | |
download | gdb-d575ddc0ef874292672001dc58848befa5325115.zip gdb-d575ddc0ef874292672001dc58848befa5325115.tar.gz gdb-d575ddc0ef874292672001dc58848befa5325115.tar.bz2 |
* lynx-nat.c: Add Sparc support.
* sparcly-nat.c: Remove. It's useless.
* config/sparc/nm-sparclynx.h: Rewrite.
* config/sparc/sparclynx.mh (NATDEPFILES): Replace sparcly-nat.o
with lynx-nat.o
* config/sparc/tm-sparclynx.h: Rewrite.
Diffstat (limited to 'gdb/lynx-nat.c')
-rw-r--r-- | gdb/lynx-nat.c | 294 |
1 files changed, 291 insertions, 3 deletions
diff --git a/gdb/lynx-nat.c b/gdb/lynx-nat.c index 48e52d2..4510972 100644 --- a/gdb/lynx-nat.c +++ b/gdb/lynx-nat.c @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <sys/ptrace.h> #include <sys/wait.h> +#include <sys/fpp.h> static unsigned long registers_addr PARAMS ((int pid)); @@ -95,6 +96,287 @@ static int regmap[] = }; #endif +#ifdef SPARC +/* Mappings from tm-sparc.h */ + +#define FX(ENTRY)(offsetof(struct fcontext, ENTRY)) + +static int regmap[] = +{ + -1, /* g0 */ + X(g1), + X(g2), + X(g3), + X(g4), + -1, /* g5->g7 aren't saved by Lynx */ + -1, + -1, + + X(o[0]), + X(o[1]), + X(o[2]), + X(o[3]), + X(o[4]), + X(o[5]), + X(o[6]), /* sp */ + X(o[7]), /* ra */ + + -1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */ + + -1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */ + + FX(f.fregs[0]), /* f0 */ + FX(f.fregs[1]), + FX(f.fregs[2]), + FX(f.fregs[3]), + FX(f.fregs[4]), + FX(f.fregs[5]), + FX(f.fregs[6]), + FX(f.fregs[7]), + FX(f.fregs[8]), + FX(f.fregs[9]), + FX(f.fregs[10]), + FX(f.fregs[11]), + FX(f.fregs[12]), + FX(f.fregs[13]), + FX(f.fregs[14]), + FX(f.fregs[15]), + FX(f.fregs[16]), + FX(f.fregs[17]), + FX(f.fregs[18]), + FX(f.fregs[19]), + FX(f.fregs[20]), + FX(f.fregs[21]), + FX(f.fregs[22]), + FX(f.fregs[23]), + FX(f.fregs[24]), + FX(f.fregs[25]), + FX(f.fregs[26]), + FX(f.fregs[27]), + FX(f.fregs[28]), + FX(f.fregs[29]), + FX(f.fregs[30]), + FX(f.fregs[31]), + + X(y), + X(psr), + X(wim), + X(tbr), + X(pc), + X(npc), + FX(fsr), /* fpsr */ + -1, /* cpsr */ +}; +#endif + +#ifdef SPARC + +/* This routine handles some oddball cases for Sparc registers and LynxOS. + In partucular, it causes refs to G0, g5->7, and all fp regs to return zero. + It also handles knows where to find the I & L regs on the stack. */ + +void +fetch_inferior_registers (regno) + int regno; +{ + int whatregs = 0; + +#define WHATREGS_FLOAT 1 +#define WHATREGS_GEN 2 +#define WHATREGS_STACK 4 + + if (regno == -1) + whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK; + else if (regno >= L0_REGNUM && regno <= I7_REGNUM) + whatregs = WHATREGS_STACK; + else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32) + whatregs = WHATREGS_FLOAT; + else + whatregs = WHATREGS_GEN; + + if (whatregs & WHATREGS_GEN) + { + struct econtext ec; /* general regs */ + char buf[MAX_REGISTER_RAW_SIZE]; + int retval; + int i; + + errno = 0; + retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec, + 0); + if (errno) + perror_with_name ("Sparc fetch_inferior_registers(ptrace)"); + + memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM)); + supply_register (G0_REGNUM, buf); + supply_register (TBR_REGNUM, (char *)&ec.tbr); + + memcpy (®isters[REGISTER_BYTE (G1_REGNUM)], &ec.g1, + 4 * REGISTER_RAW_SIZE (G1_REGNUM)); + for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++) + register_valid[i] = 1; + + supply_register (PS_REGNUM, (char *)&ec.psr); + supply_register (Y_REGNUM, (char *)&ec.y); + supply_register (PC_REGNUM, (char *)&ec.pc); + supply_register (NPC_REGNUM, (char *)&ec.npc); + supply_register (WIM_REGNUM, (char *)&ec.wim); + + memcpy (®isters[REGISTER_BYTE (O0_REGNUM)], ec.o, + 8 * REGISTER_RAW_SIZE (O0_REGNUM)); + for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++) + register_valid[i] = 1; + } + + if (whatregs & WHATREGS_STACK) + { + CORE_ADDR sp; + int i; + + sp = read_register (SP_REGNUM); + + target_xfer_memory (sp, ®isters[REGISTER_BYTE(I0_REGNUM)], + 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0); + for (i = I0_REGNUM; i <= I7_REGNUM; i++) + register_valid[i] = 1; + + sp += 8 * REGISTER_RAW_SIZE (I0_REGNUM); + + target_xfer_memory (sp, ®isters[REGISTER_BYTE(L0_REGNUM)], + 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0); + for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++) + register_valid[i] = 1; + } + + if (whatregs & WHATREGS_FLOAT) + { + struct fcontext fc; /* fp regs */ + int retval; + int i; + + errno = 0; + retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc, + 0); + if (errno) + perror_with_name ("Sparc fetch_inferior_registers(ptrace)"); + + memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs, + 32 * REGISTER_RAW_SIZE (FP0_REGNUM)); + for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++) + register_valid[i] = 1; + + supply_register (FPS_REGNUM, (char *)&fc.fsr); + } +} + +/* This routine handles storing of the I & L regs for the Sparc. The trick + here is that they actually live on the stack. The really tricky part is + that when changing the stack pointer, the I & L regs must be written to + where the new SP points, otherwise the regs will be incorrect when the + process is started up again. We assume that the I & L regs are valid at + this point. */ + +void +store_inferior_registers (regno) + int regno; +{ + int whatregs = 0; + + if (regno == -1) + whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK; + else if (regno >= L0_REGNUM && regno <= I7_REGNUM) + whatregs = WHATREGS_STACK; + else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32) + whatregs = WHATREGS_FLOAT; + else if (regno == SP_REGNUM) + whatregs = WHATREGS_STACK | WHATREGS_GEN; + else + whatregs = WHATREGS_GEN; + + if (whatregs & WHATREGS_GEN) + { + struct econtext ec; /* general regs */ + int retval; + + ec.tbr = read_register (TBR_REGNUM); + memcpy (&ec.g1, ®isters[REGISTER_BYTE (G1_REGNUM)], + 4 * REGISTER_RAW_SIZE (G1_REGNUM)); + + ec.psr = read_register (PS_REGNUM); + ec.y = read_register (Y_REGNUM); + ec.pc = read_register (PC_REGNUM); + ec.npc = read_register (NPC_REGNUM); + ec.wim = read_register (WIM_REGNUM); + + memcpy (ec.o, ®isters[REGISTER_BYTE (O0_REGNUM)], + 8 * REGISTER_RAW_SIZE (O0_REGNUM)); + + errno = 0; + retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec, + 0); + if (errno) + perror_with_name ("Sparc fetch_inferior_registers(ptrace)"); + } + + if (whatregs & WHATREGS_STACK) + { + int regoffset; + CORE_ADDR sp; + + sp = read_register (SP_REGNUM); + + if (regno == -1 || regno == SP_REGNUM) + { + if (!register_valid[L0_REGNUM+5]) + abort(); + target_xfer_memory (sp, ®isters[REGISTER_BYTE (I0_REGNUM)], + 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1); + sp += 8 * REGISTER_RAW_SIZE (I0_REGNUM); + target_xfer_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)], + 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1); + } + else if (regno >= L0_REGNUM && regno <= I7_REGNUM) + { + if (!register_valid[regno]) + abort(); + if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7) + regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM) + + 8 * REGISTER_RAW_SIZE (I0_REGNUM); + else + regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM); + target_xfer_memory (sp + regoffset, ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (regno), 1); + } + } + + if (whatregs & WHATREGS_FLOAT) + { + struct fcontext fc; /* fp regs */ + int retval; + +/* We read fcontext first so that we can get good values for fq_t... */ + errno = 0; + retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc, + 0); + if (errno) + perror_with_name ("Sparc fetch_inferior_registers(ptrace)"); + + memcpy (fc.f.fregs, ®isters[REGISTER_BYTE (FP0_REGNUM)], + 32 * REGISTER_RAW_SIZE (FP0_REGNUM)); + + fc.fsr = read_register (FPS_REGNUM); + + errno = 0; + retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc, + 0); + if (errno) + perror_with_name ("Sparc fetch_inferior_registers(ptrace)"); + } +} +#endif + +#ifndef SPARC + /* Return the offset relative to the start of the per-thread data to the saved context block. */ @@ -142,7 +424,7 @@ fetch_inferior_registers (regno) ecp = registers_addr (inferior_pid); - for (regno = reglo; regno <= reghi; regno++) + for (regno = reglo; regno <= reghi && regmap[regno] != -1; regno++) { char buf[MAX_REGISTER_RAW_SIZE]; int ptrace_fun = PTRACE_PEEKTHREAD; @@ -189,7 +471,7 @@ store_inferior_registers (regno) ecp = registers_addr (inferior_pid); - for (regno = reglo; regno <= reghi; regno++) + for (regno = reglo; regno <= reghi && regmap[regno] != -1; regno++) { int ptrace_fun = PTRACE_POKEUSER; @@ -211,6 +493,7 @@ store_inferior_registers (regno) } } } +#endif /* ifndef SPARC */ /* Wait for child to do something. Return pid of child, or -1 in case of error; store status through argument pointer OURSTATUS. */ @@ -231,7 +514,12 @@ child_wait (pid, ourstatus) if (attach_flag) set_sigint_trap(); /* Causes SIGINT to be passed on to the attached process. */ - pid = wait (status); + pid = wait (&status); +#ifdef SPARC +/* Swap halves of status so that the rest of GDB can understand it */ + status = (status << 16) | ((unsigned)status >> 16); +#endif + save_errno = errno; if (attach_flag) |