diff options
Diffstat (limited to 'gdb/m32r-linux-nat.c')
-rw-r--r-- | gdb/m32r-linux-nat.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/gdb/m32r-linux-nat.c b/gdb/m32r-linux-nat.c new file mode 100644 index 0000000..7b35087 --- /dev/null +++ b/gdb/m32r-linux-nat.c @@ -0,0 +1,235 @@ +/* Native-dependent code for GNU/Linux m32r. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "gdbcore.h" +#include "regcache.h" +#include "linux-nat.h" + +#include "gdb_assert.h" +#include "gdb_string.h" +#include <sys/ptrace.h> +#include <sys/user.h> +#include <sys/procfs.h> + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" + +#include "m32r-tdep.h" + + + + +/* Since EVB register is not available for native debug, we reduce + the number of registers. */ +#define M32R_LINUX_NUM_REGS (M32R_NUM_REGS - 1) + +/* Mapping between the general-purpose registers in `struct user' + format and GDB's register array layout. */ +static int regmap[] = { + 4, 5, 6, 7, 0, 1, 2, 8, + 9, 10, 11, 12, 13, 24, 25, 23, + 19, 19, 26, 23, 22, 20, 16, 15 +}; + +#define PSW_REGMAP 19 +#define BBPSW_REGMAP 21 +#define SPU_REGMAP 23 +#define SPI_REGMAP 26 + +/* Doee apply to the corresponding SET requests as well. */ +#define GETREGS_SUPPLIES(regno) (0 <= (regno) && (regno) <= M32R_LINUX_NUM_REGS) + + + +/* Transfering the general-purpose registers between GDB, inferiors + and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (elf_gregset_t * gregsetp) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + switch (i) + { + case PSW_REGNUM: + *(regp + regmap[i]) = + ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8); + break; + case CBR_REGNUM: + *(regp + regmap[i]) = ((psw >> 8) & 1); + break; + } + + if (i != M32R_SP_REGNUM) + regcache_raw_supply (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_supply (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_supply (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register array. */ + +static void +fetch_regs (int tid) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + supply_gregset (®s); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_gregset (elf_gregset_t * gregsetp, int regno) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw, tmp; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + if (regno != -1 && regno != i) + continue; + + if (i == CBR_REGNUM || i == PSW_REGNUM) + continue; + + if (i == SPU_REGNUM || i == SPI_REGNUM) + continue; + + if (i != M32R_SP_REGNUM) + regcache_raw_collect (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_collect (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_collect (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Store all valid general-purpose registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_regs (int tid, int regno) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + fill_gregset (®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't write registers"); +} + + + +/* Transfering floating-point registers between GDB, inferiors and cores. + Since M32R has no floating-point registers, these functions do nothing. */ + +void +supply_fpregset (gdb_fpregset_t *fpregs) +{ +} + +void +fill_fpregset (gdb_fpregset_t *fpregs, int regno) +{ +} + + + +/* Transferring arbitrary registers between GDB and inferior. */ + +/* Fetch register REGNO from the child process. If REGNO is -1, do + this for all registers (including the floating point and SSE + registers). */ + +void +fetch_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_GETREGS request whenever possible, since it + transfers more registers in one system call, and we'll cache the + results. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + fetch_regs (tid); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request for bad register number %d.", regno); +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers (including the floating point and SSE + registers). */ +void +store_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_SETREGS request whenever possible, since it + transfers more registers in one system call. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + store_regs (tid, regno); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request to store bad register number %d.", regno); +} |