/* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
- Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007,
+ 2008, 2009, 2010, 2011 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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
#include "linux-low.h"
#include "gdb_proc_service.h"
+/* Defined in auto-generated file mips-linux.c. */
+void init_registers_mips_linux (void);
+/* Defined in auto-generated file mips64-linux.c. */
+void init_registers_mips64_linux (void);
+
#ifndef PTRACE_GET_THREAD_AREA
#define PTRACE_GET_THREAD_AREA 25
#endif
#include <sys/reg.h>
#endif
-#define mips_num_regs 90
+#define mips_num_regs 73
#include <asm/ptrace.h>
/* Return the ptrace ``address'' of register REGNO. */
-/* Matches mips_generic32_regs */
static int mips_regmap[] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
+ -1, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31,
FPC_CSR, FPC_EIR,
- -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
+ 0
};
/* From mips-linux-nat.c. */
if (mips_regmap[regno] == -1)
return 1;
- if (find_regno ("zero") == regno)
+ if (find_regno ("r0") == regno)
return 1;
return 0;
if (mips_regmap[regno] == -1)
return 1;
- if (find_regno ("zero") == regno)
+ if (find_regno ("r0") == regno)
return 1;
if (find_regno ("cause") == regno)
return 1;
- if (find_regno ("bad") == regno)
+ if (find_regno ("badvaddr") == regno)
return 1;
if (find_regno ("fir") == regno)
}
static CORE_ADDR
-mips_get_pc ()
+mips_get_pc (struct regcache *regcache)
{
union mips_register pc;
- collect_register_by_name ("pc", pc.buf);
+ collect_register_by_name (regcache, "pc", pc.buf);
return register_size (0) == 4 ? pc.reg32 : pc.reg64;
}
static void
-mips_set_pc (CORE_ADDR pc)
+mips_set_pc (struct regcache *regcache, CORE_ADDR pc)
{
union mips_register newpc;
if (register_size (0) == 4)
else
newpc.reg64 = pc;
- supply_register_by_name ("pc", newpc.buf);
+ supply_register_by_name (regcache, "pc", newpc.buf);
}
/* Correct in either endianness. */
is outside of the function. So rather than importing software single-step,
we can just run until exit. */
static CORE_ADDR
-mips_reinsert_addr ()
+mips_reinsert_addr (void)
{
+ struct regcache *regcache = get_thread_regcache (current_inferior, 1);
union mips_register ra;
- collect_register_by_name ("ra", ra.buf);
+ collect_register_by_name (regcache, "r31", ra.buf);
return register_size (0) == 4 ? ra.reg32 : ra.reg64;
}
ps_err_e
ps_get_thread_area (const struct ps_prochandle *ph,
- lwpid_t lwpid, int idx, void **base)
+ lwpid_t lwpid, int idx, void **base)
{
if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
return PS_ERR;
#ifdef HAVE_PTRACE_GETREGS
static void
-mips_collect_register (int use_64bit, int regno, union mips_register *reg)
+mips_collect_register (struct regcache *regcache,
+ int use_64bit, int regno, union mips_register *reg)
{
union mips_register tmp_reg;
if (use_64bit)
{
- collect_register (regno, &tmp_reg.reg64);
+ collect_register (regcache, regno, &tmp_reg.reg64);
*reg = tmp_reg;
}
else
{
- collect_register (regno, &tmp_reg.reg32);
+ collect_register (regcache, regno, &tmp_reg.reg32);
reg->reg64 = tmp_reg.reg32;
}
}
static void
-mips_supply_register (int use_64bit, int regno, const union mips_register *reg)
+mips_supply_register (struct regcache *regcache,
+ int use_64bit, int regno, const union mips_register *reg)
{
int offset = 0;
if (__BYTE_ORDER == __BIG_ENDIAN && !use_64bit)
offset = 4;
- supply_register (regno, reg->buf + offset);
+ supply_register (regcache, regno, reg->buf + offset);
}
static void
-mips_collect_register_32bit (int use_64bit, int regno, unsigned char *buf)
+mips_collect_register_32bit (struct regcache *regcache,
+ int use_64bit, int regno, unsigned char *buf)
{
union mips_register tmp_reg;
int reg32;
- mips_collect_register (use_64bit, regno, &tmp_reg);
+ mips_collect_register (regcache, use_64bit, regno, &tmp_reg);
reg32 = tmp_reg.reg64;
memcpy (buf, ®32, 4);
}
static void
-mips_supply_register_32bit (int use_64bit, int regno, const unsigned char *buf)
+mips_supply_register_32bit (struct regcache *regcache,
+ int use_64bit, int regno, const unsigned char *buf)
{
union mips_register tmp_reg;
int reg32;
memcpy (®32, buf, 4);
tmp_reg.reg64 = reg32;
- mips_supply_register (use_64bit, regno, &tmp_reg);
+ mips_supply_register (regcache, use_64bit, regno, &tmp_reg);
}
static void
-mips_fill_gregset (void *buf)
+mips_fill_gregset (struct regcache *regcache, void *buf)
{
union mips_register *regset = buf;
int i, use_64bit;
use_64bit = (register_size (0) == 8);
- for (i = 0; i < 32; i++)
- mips_collect_register (use_64bit, i, regset + i);
-
- mips_collect_register (use_64bit, find_regno ("lo"), regset + 32);
- mips_collect_register (use_64bit, find_regno ("hi"), regset + 33);
- mips_collect_register (use_64bit, find_regno ("pc"), regset + 34);
- mips_collect_register (use_64bit, find_regno ("bad"), regset + 35);
- mips_collect_register (use_64bit, find_regno ("sr"), regset + 36);
- mips_collect_register (use_64bit, find_regno ("cause"), regset + 37);
+ for (i = 1; i < 32; i++)
+ mips_collect_register (regcache, use_64bit, i, regset + i);
+
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("lo"), regset + 32);
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("hi"), regset + 33);
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("pc"), regset + 34);
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("badvaddr"), regset + 35);
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("status"), regset + 36);
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("cause"), regset + 37);
+
+ mips_collect_register (regcache, use_64bit,
+ find_regno ("restart"), regset + 0);
}
static void
-mips_store_gregset (const void *buf)
+mips_store_gregset (struct regcache *regcache, const void *buf)
{
const union mips_register *regset = buf;
int i, use_64bit;
use_64bit = (register_size (0) == 8);
for (i = 0; i < 32; i++)
- mips_supply_register (use_64bit, i, regset + i);
-
- mips_supply_register (use_64bit, find_regno ("lo"), regset + 32);
- mips_supply_register (use_64bit, find_regno ("hi"), regset + 33);
- mips_supply_register (use_64bit, find_regno ("pc"), regset + 34);
- mips_supply_register (use_64bit, find_regno ("bad"), regset + 35);
- mips_supply_register (use_64bit, find_regno ("sr"), regset + 36);
- mips_supply_register (use_64bit, find_regno ("cause"), regset + 37);
+ mips_supply_register (regcache, use_64bit, i, regset + i);
+
+ mips_supply_register (regcache, use_64bit, find_regno ("lo"), regset + 32);
+ mips_supply_register (regcache, use_64bit, find_regno ("hi"), regset + 33);
+ mips_supply_register (regcache, use_64bit, find_regno ("pc"), regset + 34);
+ mips_supply_register (regcache, use_64bit,
+ find_regno ("badvaddr"), regset + 35);
+ mips_supply_register (regcache, use_64bit,
+ find_regno ("status"), regset + 36);
+ mips_supply_register (regcache, use_64bit,
+ find_regno ("cause"), regset + 37);
+
+ mips_supply_register (regcache, use_64bit,
+ find_regno ("restart"), regset + 0);
}
static void
-mips_fill_fpregset (void *buf)
+mips_fill_fpregset (struct regcache *regcache, void *buf)
{
union mips_register *regset = buf;
int i, use_64bit, first_fp, big_endian;
/* See GDB for a discussion of this peculiar layout. */
for (i = 0; i < 32; i++)
if (use_64bit)
- collect_register (first_fp + i, regset[i].buf);
+ collect_register (regcache, first_fp + i, regset[i].buf);
else
- collect_register (first_fp + i,
+ collect_register (regcache, first_fp + i,
regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
- mips_collect_register_32bit (use_64bit, find_regno ("fsr"), regset[32].buf);
- mips_collect_register_32bit (use_64bit, find_regno ("fir"),
+ mips_collect_register_32bit (regcache, use_64bit,
+ find_regno ("fcsr"), regset[32].buf);
+ mips_collect_register_32bit (regcache, use_64bit, find_regno ("fir"),
regset[32].buf + 4);
}
static void
-mips_store_fpregset (const void *buf)
+mips_store_fpregset (struct regcache *regcache, const void *buf)
{
const union mips_register *regset = buf;
int i, use_64bit, first_fp, big_endian;
/* See GDB for a discussion of this peculiar layout. */
for (i = 0; i < 32; i++)
if (use_64bit)
- supply_register (first_fp + i, regset[i].buf);
+ supply_register (regcache, first_fp + i, regset[i].buf);
else
- supply_register (first_fp + i,
+ supply_register (regcache, first_fp + i,
regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
- mips_supply_register_32bit (use_64bit, find_regno ("fsr"), regset[32].buf);
- mips_supply_register_32bit (use_64bit, find_regno ("fir"),
+ mips_supply_register_32bit (regcache, use_64bit,
+ find_regno ("fcsr"), regset[32].buf);
+ mips_supply_register_32bit (regcache, use_64bit, find_regno ("fir"),
regset[32].buf + 4);
}
#endif /* HAVE_PTRACE_GETREGS */
struct regset_info target_regsets[] = {
#ifdef HAVE_PTRACE_GETREGS
- { PTRACE_GETREGS, PTRACE_SETREGS, 38 * 8, GENERAL_REGS,
+ { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
mips_fill_gregset, mips_store_gregset },
- { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 33 * 8, FP_REGS,
+ { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
mips_fill_fpregset, mips_store_fpregset },
#endif /* HAVE_PTRACE_GETREGS */
- { 0, 0, -1, -1, NULL, NULL }
+ { 0, 0, 0, -1, -1, NULL, NULL }
};
struct linux_target_ops the_low_target = {
+#ifdef __mips64
+ init_registers_mips64_linux,
+#else
+ init_registers_mips_linux,
+#endif
mips_num_regs,
mips_regmap,
mips_cannot_fetch_register,