mips: Add MIPS64 support
The patch adds support for processors implementing MIPS64 instruction set. Change-Id: I79a983dfdead81553457a0f3e9e739a9785afaac Signed-off-by: Konstantin Kostyukhin <kost@niisi.msk.ru> Signed-off-by: Andrey Sidorov <anysidorov@gmail.com> Signed-off-by: Aleksey Kuleshov <rndfax@yandex.ru> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Peter Mamonov <pmamonov@gmail.com> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> CC: Dongxue Zhang <elta.era@gmail.com> CC: Paul Fertser <fercerpav@gmail.com> CC: Salvador Arroyo <sarroyofdez@yahoo.es> CC: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/2321 Tested-by: jenkins Reviewed-by: Paul Fertser <fercerpav@gmail.com>
This commit is contained in:
parent
20a310deb7
commit
1fbe8450a9
|
@ -32,6 +32,7 @@ noinst_LTLIBRARIES += %D%/libtarget.la
|
|||
|
||||
if TARGET64
|
||||
%C%_libtarget_la_SOURCES +=$(ARMV8_SRC)
|
||||
%C%_libtarget_la_SOURCES +=$(MIPS64_SRC)
|
||||
endif
|
||||
|
||||
TARGET_CORE_SRC = \
|
||||
|
@ -120,6 +121,13 @@ MIPS32_SRC = \
|
|||
%D%/mips32_dmaacc.c \
|
||||
%D%/mips_ejtag.c
|
||||
|
||||
MIPS64_SRC = \
|
||||
%D%/mips64.c \
|
||||
%D%/mips32_pracc.c \
|
||||
%D%/mips64_pracc.c \
|
||||
%D%/trace.c \
|
||||
%D%/mips_ejtag.c
|
||||
|
||||
NDS32_SRC = \
|
||||
%D%/nds32.c \
|
||||
%D%/nds32_reg.c \
|
||||
|
@ -193,10 +201,12 @@ ESIRISC_SRC = \
|
|||
%D%/etm_dummy.h \
|
||||
%D%/image.h \
|
||||
%D%/mips32.h \
|
||||
%D%/mips64.h \
|
||||
%D%/mips_m4k.h \
|
||||
%D%/mips_ejtag.h \
|
||||
%D%/mips32_pracc.h \
|
||||
%D%/mips32_dmaacc.h \
|
||||
%D%/mips64_pracc.h \
|
||||
%D%/oocd_trace.h \
|
||||
%D%/register.h \
|
||||
%D%/target.h \
|
||||
|
|
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
* Support for processors implementing MIPS64 instruction set
|
||||
*
|
||||
* Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
|
||||
* Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
|
||||
* Copyright (C) 2014 by Antony Pavlov <antonynpavlov@gmail.com>
|
||||
* Copyright (C) 2014 by Peter Mamonov <pmamonov@gmail.com>
|
||||
*
|
||||
* Based on the work of:
|
||||
* Copyright (C) 2008 by Spencer Oliver
|
||||
* Copyright (C) 2008 by David T.L. Wong
|
||||
* Copyright (C) 2010 by Konstantin Kostyukhin, Nikolay Shmyrev
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if BUILD_TARGET64 == 1
|
||||
|
||||
#include "mips64.h"
|
||||
|
||||
static const struct {
|
||||
unsigned id;
|
||||
const char *name;
|
||||
enum reg_type type;
|
||||
const char *group;
|
||||
const char *feature;
|
||||
int flag;
|
||||
} mips64_regs[] = {
|
||||
{ 0, "r0", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 1, "r1", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 2, "r2", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 3, "r3", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 4, "r4", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 5, "r5", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 6, "r6", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 7, "r7", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 8, "r8", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 9, "r9", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 10, "r10", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 11, "r11", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 12, "r12", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 13, "r13", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 14, "r14", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 15, "r15", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 16, "r16", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 17, "r17", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 18, "r18", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 19, "r19", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 20, "r20", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 21, "r21", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 22, "r22", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 23, "r23", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 24, "r24", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 25, "r25", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 26, "r26", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 27, "r27", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 28, "r28", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 29, "r29", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 30, "r30", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 31, "r31", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 32, "lo", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ 33, "hi", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 0, "pc", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cpu", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 1, "Random", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 2, "Entrylo_0", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 3, "Entrylo_1", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 4, "Context", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 5, "Pagemask", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 6, "Wired", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 7, "badvaddr", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 8, "Count", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 9, "EntryHi", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 10, "Compare", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 11, "status", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 12, "cause", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 13, "EPC", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 14, "PrID", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 15, "Config", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 16, "LLA", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 17, "WatchLo0", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 18, "WatchLo1", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 19, "WatchHi0", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 20, "WatchHi1", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 21, "Xcontext", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 22, "ChipMemCtrl", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 23, "Debug", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 24, "Perfcount, sel=0", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 25, "Perfcount, sel=1", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 26, "Perfcount, sel=2", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 27, "Perfcount, sel=3", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 28, "ECC", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 29, "CacheErr", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 30, "TagLo", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 31, "TagHi", REG_TYPE_UINT32, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 32, "DataHi", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_REGS + 33, "EEPC", REG_TYPE_UINT64, NULL,
|
||||
"org.gnu.gdb.mips.cp0", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 32, "fcsr", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 33, "fir", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 34, "fconfig", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 35, "fccr", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 36, "fexr", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
{ MIPS64_NUM_CORE_C0_REGS + 37, "fenr", REG_TYPE_INT, "float",
|
||||
"org.gnu.gdb.mips.fpu", 0 },
|
||||
};
|
||||
|
||||
static int reg_type2size(enum reg_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case REG_TYPE_UINT32:
|
||||
case REG_TYPE_INT:
|
||||
return 32;
|
||||
case REG_TYPE_UINT64:
|
||||
case REG_TYPE_IEEE_DOUBLE:
|
||||
return 64;
|
||||
default:
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
static int mips64_get_core_reg(struct reg *reg)
|
||||
{
|
||||
int retval;
|
||||
struct mips64_core_reg *mips64_reg = reg->arch_info;
|
||||
struct target *target = mips64_reg->target;
|
||||
struct mips64_common *mips64_target = target->arch_info;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
||||
retval = mips64_target->read_core_reg(target, mips64_reg->num);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int mips64_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||
{
|
||||
struct mips64_core_reg *mips64_reg = reg->arch_info;
|
||||
struct target *target = mips64_reg->target;
|
||||
uint64_t value = buf_get_u64(buf, 0, 64);
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
||||
buf_set_u64(reg->value, 0, 64, value);
|
||||
reg->dirty = 1;
|
||||
reg->valid = 1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int mips64_read_core_reg(struct target *target, int num)
|
||||
{
|
||||
uint64_t reg_value;
|
||||
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
|
||||
if ((num < 0) || (num >= MIPS64_NUM_REGS))
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
|
||||
reg_value = mips64->core_regs[num];
|
||||
buf_set_u64(mips64->core_cache->reg_list[num].value, 0, 64, reg_value);
|
||||
mips64->core_cache->reg_list[num].valid = 1;
|
||||
mips64->core_cache->reg_list[num].dirty = 0;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int mips64_write_core_reg(struct target *target, int num)
|
||||
{
|
||||
uint64_t reg_value;
|
||||
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
|
||||
if ((num < 0) || (num >= MIPS64_NUM_REGS))
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
|
||||
reg_value = buf_get_u64(mips64->core_cache->reg_list[num].value, 0, 64);
|
||||
mips64->core_regs[num] = reg_value;
|
||||
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num , reg_value);
|
||||
mips64->core_cache->reg_list[num].valid = 1;
|
||||
mips64->core_cache->reg_list[num].dirty = 0;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_invalidate_core_regs(struct target *target)
|
||||
{
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < mips64->core_cache->num_regs; i++) {
|
||||
mips64->core_cache->reg_list[i].valid = 0;
|
||||
mips64->core_cache->reg_list[i].dirty = 0;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int mips64_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
|
||||
int *reg_list_size, enum target_register_class reg_class)
|
||||
{
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
register int i;
|
||||
|
||||
/* include floating point registers */
|
||||
*reg_list_size = MIPS64_NUM_REGS;
|
||||
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
|
||||
|
||||
for (i = 0; i < MIPS64_NUM_REGS; i++)
|
||||
(*reg_list)[i] = &mips64->core_cache->reg_list[i];
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_save_context(struct target *target)
|
||||
{
|
||||
int retval;
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
|
||||
|
||||
retval = mips64_pracc_read_regs(ejtag_info, mips64->core_regs);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
for (unsigned i = 0; i < MIPS64_NUM_REGS; i++)
|
||||
retval = mips64->read_core_reg(target, i);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int mips64_restore_context(struct target *target)
|
||||
{
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
|
||||
|
||||
for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) {
|
||||
if (mips64->core_cache->reg_list[i].dirty)
|
||||
mips64->write_core_reg(target, i);
|
||||
}
|
||||
|
||||
return mips64_pracc_write_regs(ejtag_info, mips64->core_regs);
|
||||
}
|
||||
|
||||
int mips64_arch_state(struct target *target)
|
||||
{
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct reg *pc = &mips64->core_cache->reg_list[MIPS64_PC];
|
||||
|
||||
if (mips64->common_magic != MIPS64_COMMON_MAGIC) {
|
||||
LOG_ERROR("BUG: called for a non-MIPS64 target");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
LOG_USER("target halted due to %s, pc: 0x%" PRIx64 "",
|
||||
debug_reason_name(target), buf_get_u64(pc->value, 0, 64));
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct reg_arch_type mips64_reg_type = {
|
||||
.get = mips64_get_core_reg,
|
||||
.set = mips64_set_core_reg,
|
||||
};
|
||||
|
||||
int mips64_build_reg_cache(struct target *target)
|
||||
{
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct reg_cache **cache_p, *cache;
|
||||
struct mips64_core_reg *arch_info = NULL;
|
||||
struct reg *reg_list = NULL;
|
||||
unsigned i;
|
||||
|
||||
cache = calloc(1, sizeof(*cache));
|
||||
if (!cache) {
|
||||
LOG_ERROR("unable to allocate cache");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
reg_list = calloc(MIPS64_NUM_REGS, sizeof(*reg_list));
|
||||
if (!reg_list) {
|
||||
LOG_ERROR("unable to allocate reg_list");
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
arch_info = calloc(MIPS64_NUM_REGS, sizeof(*arch_info));
|
||||
if (!arch_info) {
|
||||
LOG_ERROR("unable to allocate arch_info");
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < MIPS64_NUM_REGS; i++) {
|
||||
struct mips64_core_reg *a = &arch_info[i];
|
||||
struct reg *r = ®_list[i];
|
||||
|
||||
r->arch_info = &arch_info[i];
|
||||
r->caller_save = true; /* gdb defaults to true */
|
||||
r->exist = true;
|
||||
r->feature = &a->feature;
|
||||
r->feature->name = mips64_regs[i].feature;
|
||||
r->group = mips64_regs[i].group;
|
||||
r->name = mips64_regs[i].name;
|
||||
r->number = i;
|
||||
r->reg_data_type = &a->reg_data_type;
|
||||
r->reg_data_type->type = mips64_regs[i].type;
|
||||
r->size = reg_type2size(mips64_regs[i].type);
|
||||
r->type = &mips64_reg_type;
|
||||
r->value = &a->value[0];
|
||||
|
||||
a->mips64_common = mips64;
|
||||
a->num = mips64_regs[i].id;
|
||||
a->target = target;
|
||||
}
|
||||
|
||||
cache->name = "mips64 registers";
|
||||
cache->reg_list = reg_list;
|
||||
cache->num_regs = MIPS64_NUM_REGS;
|
||||
|
||||
cache_p = register_get_last_cache_p(&target->reg_cache);
|
||||
(*cache_p) = cache;
|
||||
|
||||
mips64->core_cache = cache;
|
||||
|
||||
return ERROR_OK;
|
||||
|
||||
alloc_fail:
|
||||
free(cache);
|
||||
free(reg_list);
|
||||
free(arch_info);
|
||||
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int mips64_init_arch_info(struct target *target, struct mips64_common *mips64,
|
||||
struct jtag_tap *tap)
|
||||
{
|
||||
mips64->bp_scanned = false;
|
||||
mips64->common_magic = MIPS64_COMMON_MAGIC;
|
||||
mips64->data_break_list = NULL;
|
||||
mips64->ejtag_info.tap = tap;
|
||||
mips64->fast_data_area = NULL;
|
||||
mips64->mips64mode32 = false;
|
||||
mips64->read_core_reg = mips64_read_core_reg;
|
||||
mips64->write_core_reg = mips64_write_core_reg;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_run_algorithm(struct target *target, int num_mem_params,
|
||||
struct mem_param *mem_params, int num_reg_params,
|
||||
struct reg_param *reg_params, target_addr_t entry_point,
|
||||
target_addr_t exit_point, int timeout_ms, void *arch_info)
|
||||
{
|
||||
/* TODO */
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_examine(struct target *target)
|
||||
{
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
|
||||
if (target_was_examined(target))
|
||||
return ERROR_OK;
|
||||
|
||||
/* TODO: why we do not do mips64_configure_break_unit() here? */
|
||||
mips64->bp_scanned = false;
|
||||
mips64->num_data_bpoints = 0;
|
||||
mips64->num_data_bpoints_avail = 0;
|
||||
mips64->num_inst_bpoints = 0;
|
||||
mips64->num_inst_bpoints_avail = 0;
|
||||
|
||||
target_set_examined(target);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int mips64_configure_i_break_unit(struct target *target)
|
||||
{
|
||||
/* get pointers to arch-specific information */
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct mips64_comparator *ibl;
|
||||
uint64_t bpinfo;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
/* get number of inst breakpoints */
|
||||
retval = target_read_u64(target, EJTAG64_V25_IBS, &bpinfo);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
mips64->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
|
||||
mips64->num_inst_bpoints_avail = mips64->num_inst_bpoints;
|
||||
ibl = calloc(mips64->num_inst_bpoints, sizeof(*ibl));
|
||||
if (!ibl) {
|
||||
LOG_ERROR("unable to allocate inst_break_list");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
for (i = 0; i < mips64->num_inst_bpoints; i++)
|
||||
ibl[i].reg_address = EJTAG64_V25_IBA0 + (0x100 * i);
|
||||
|
||||
mips64->inst_break_list = ibl;
|
||||
/* clear IBIS reg */
|
||||
retval = target_write_u64(target, EJTAG64_V25_IBS, 0);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int mips64_configure_d_break_unit(struct target *target)
|
||||
{
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
struct mips64_comparator *dbl;
|
||||
uint64_t bpinfo;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
/* get number of data breakpoints */
|
||||
retval = target_read_u64(target, EJTAG64_V25_DBS, &bpinfo);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
mips64->num_data_bpoints = (bpinfo >> 24) & 0x0F;
|
||||
mips64->num_data_bpoints_avail = mips64->num_data_bpoints;
|
||||
|
||||
dbl = calloc(mips64->num_data_bpoints, sizeof(*dbl));
|
||||
|
||||
if (!dbl) {
|
||||
LOG_ERROR("unable to allocate data_break_list");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
for (i = 0; i < mips64->num_data_bpoints; i++)
|
||||
dbl[i].reg_address = EJTAG64_V25_DBA0 + (0x100 * i);
|
||||
|
||||
mips64->data_break_list = dbl;
|
||||
|
||||
/* clear DBIS reg */
|
||||
retval = target_write_u64(target, EJTAG64_V25_DBS, 0);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_configure_break_unit(struct target *target)
|
||||
{
|
||||
struct mips64_common *mips64 = target->arch_info;
|
||||
uint64_t dcr;
|
||||
int retval;
|
||||
|
||||
if (mips64->bp_scanned)
|
||||
return ERROR_OK;
|
||||
|
||||
/* get info about breakpoint support */
|
||||
retval = target_read_u64(target, EJTAG64_DCR, &dcr);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (dcr & EJTAG64_DCR_IB) {
|
||||
retval = mips64_configure_i_break_unit(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (dcr & EJTAG64_DCR_DB) {
|
||||
retval = mips64_configure_d_break_unit(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
LOG_DEBUG("DCR 0x%" PRIx64 " numinst %i numdata %i", dcr,
|
||||
mips64->num_inst_bpoints, mips64->num_data_bpoints);
|
||||
|
||||
mips64->bp_scanned = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int mips64_enable_interrupts(struct target *target, bool enable)
|
||||
{
|
||||
int retval;
|
||||
bool update = false;
|
||||
uint64_t dcr;
|
||||
|
||||
/* read debug control register */
|
||||
retval = target_read_u64(target, EJTAG64_DCR, &dcr);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (enable) {
|
||||
if (!(dcr & EJTAG64_DCR_INTE)) {
|
||||
/* enable interrupts */
|
||||
dcr |= EJTAG64_DCR_INTE;
|
||||
update = true;
|
||||
}
|
||||
} else {
|
||||
if (dcr & EJTAG64_DCR_INTE) {
|
||||
/* disable interrupts */
|
||||
dcr &= ~(uint64_t)EJTAG64_DCR_INTE;
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
retval = target_write_u64(target, EJTAG64_DCR, dcr);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#endif /* BUILD_TARGET64 */
|
|
@ -0,0 +1,226 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Support for processors implementing MIPS64 instruction set
|
||||
*
|
||||
* Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
|
||||
* Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
|
||||
* Copyright (C) 2014-2019 by Peter Mamonov <pmamonov@gmail.com>
|
||||
*
|
||||
* Based on the work of:
|
||||
* Copyright (C) 2008 by Spencer Oliver
|
||||
* Copyright (C) 2008 by David T.L. Wong
|
||||
* Copyright (C) 2010 by Konstantin Kostyukhin, Nikolay Shmyrev
|
||||
*/
|
||||
|
||||
#ifndef OPENOCD_TARGET_MIPS64_H
|
||||
#define OPENOCD_TARGET_MIPS64_H
|
||||
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "mips64_pracc.h"
|
||||
|
||||
#define MIPS64_COMMON_MAGIC 0xB640B640
|
||||
|
||||
/* MIPS64 CP0 registers */
|
||||
#define MIPS64_C0_INDEX 0
|
||||
#define MIPS64_C0_RANDOM 1
|
||||
#define MIPS64_C0_ENTRYLO0 2
|
||||
#define MIPS64_C0_ENTRYLO1 3
|
||||
#define MIPS64_C0_CONTEXT 4
|
||||
#define MIPS64_C0_PAGEMASK 5
|
||||
#define MIPS64_C0_WIRED 6
|
||||
#define MIPS64_C0_BADVADDR 8
|
||||
#define MIPS64_C0_COUNT 9
|
||||
#define MIPS64_C0_ENTRYHI 10
|
||||
#define MIPS64_C0_COMPARE 11
|
||||
#define MIPS64_C0_STATUS 12
|
||||
#define MIPS64_C0_CAUSE 13
|
||||
#define MIPS64_C0_EPC 14
|
||||
#define MIPS64_C0_PRID 15
|
||||
#define MIPS64_C0_CONFIG 16
|
||||
#define MIPS64_C0_LLA 17
|
||||
#define MIPS64_C0_WATCHLO 18
|
||||
#define MIPS64_C0_WATCHHI 19
|
||||
#define MIPS64_C0_XCONTEXT 20
|
||||
#define MIPS64_C0_MEMCTRL 22
|
||||
#define MIPS64_C0_DEBUG 23
|
||||
#define MIPS64_C0_DEPC 24
|
||||
#define MIPS64_C0_PERFCOUNT 25
|
||||
#define MIPS64_C0_ECC 26
|
||||
#define MIPS64_C0_CACHERR 27
|
||||
#define MIPS64_C0_TAGLO 28
|
||||
#define MIPS64_C0_TAGHI 29
|
||||
#define MIPS64_C0_DATAHI 29
|
||||
#define MIPS64_C0_EEPC 30
|
||||
|
||||
/* MIPS64 CP1 registers */
|
||||
#define MIPS64_C1_FIR 0
|
||||
#define MIPS64_C1_FCONFIG 24
|
||||
#define MIPS64_C1_FCSR 31
|
||||
#define MIPS64_C1_FCCR 25
|
||||
#define MIPS64_C1_FEXR 26
|
||||
#define MIPS64_C1_FENR 28
|
||||
|
||||
/* offsets into mips64 register cache */
|
||||
#define MIPS64_NUM_CORE_REGS 34
|
||||
#define MIPS64_NUM_C0_REGS 34
|
||||
#define MIPS64_NUM_FP_REGS 38
|
||||
|
||||
#define MIPS64_NUM_REGS (MIPS64_NUM_CORE_REGS + \
|
||||
MIPS64_NUM_C0_REGS + \
|
||||
MIPS64_NUM_FP_REGS)
|
||||
|
||||
#define MIPS64_NUM_CORE_C0_REGS (MIPS64_NUM_CORE_REGS + MIPS64_NUM_C0_REGS)
|
||||
|
||||
#define MIPS64_PC MIPS64_NUM_CORE_REGS
|
||||
|
||||
struct mips64_comparator {
|
||||
bool used;
|
||||
uint64_t bp_value;
|
||||
uint64_t reg_address;
|
||||
};
|
||||
|
||||
struct mips64_common {
|
||||
uint32_t common_magic;
|
||||
void *arch_info;
|
||||
struct reg_cache *core_cache;
|
||||
struct mips_ejtag ejtag_info;
|
||||
uint64_t core_regs[MIPS64_NUM_REGS];
|
||||
|
||||
struct working_area *fast_data_area;
|
||||
|
||||
bool bp_scanned;
|
||||
int num_inst_bpoints;
|
||||
int num_data_bpoints;
|
||||
int num_inst_bpoints_avail;
|
||||
int num_data_bpoints_avail;
|
||||
struct mips64_comparator *inst_break_list;
|
||||
struct mips64_comparator *data_break_list;
|
||||
|
||||
/* register cache to processor synchronization */
|
||||
int (*read_core_reg)(struct target *target, int num);
|
||||
int (*write_core_reg)(struct target *target, int num);
|
||||
|
||||
bool mips64mode32;
|
||||
};
|
||||
|
||||
struct mips64_core_reg {
|
||||
uint32_t num;
|
||||
struct target *target;
|
||||
struct mips64_common *mips64_common;
|
||||
uint8_t value[8];
|
||||
struct reg_feature feature;
|
||||
struct reg_data_type reg_data_type;
|
||||
};
|
||||
|
||||
#define MIPS64_OP_SRL 0x02
|
||||
#define MIPS64_OP_BEQ 0x04
|
||||
#define MIPS64_OP_BNE 0x05
|
||||
#define MIPS64_OP_ADDI 0x08
|
||||
#define MIPS64_OP_ANDI 0x0c
|
||||
#define MIPS64_OP_DADDI 0x18
|
||||
#define MIPS64_OP_DADDIU 0x19
|
||||
#define MIPS64_OP_AND 0x24
|
||||
#define MIPS64_OP_LUI 0x0F
|
||||
#define MIPS64_OP_LW 0x23
|
||||
#define MIPS64_OP_LD 0x37
|
||||
#define MIPS64_OP_LBU 0x24
|
||||
#define MIPS64_OP_LHU 0x25
|
||||
#define MIPS64_OP_MFHI 0x10
|
||||
#define MIPS64_OP_MTHI 0x11
|
||||
#define MIPS64_OP_MFLO 0x12
|
||||
#define MIPS64_OP_MTLO 0x13
|
||||
#define MIPS64_OP_SB 0x28
|
||||
#define MIPS64_OP_SH 0x29
|
||||
#define MIPS64_OP_SW 0x2B
|
||||
#define MIPS64_OP_SD 0x3F
|
||||
#define MIPS64_OP_ORI 0x0D
|
||||
#define MIPS64_OP_JR 0x08
|
||||
|
||||
#define MIPS64_OP_COP0 0x10
|
||||
#define MIPS64_OP_COP1 0x11
|
||||
#define MIPS64_OP_COP2 0x12
|
||||
|
||||
#define MIPS64_COP_MF 0x00
|
||||
#define MIPS64_COP_DMF 0x01
|
||||
#define MIPS64_COP_MT 0x04
|
||||
#define MIPS64_COP_DMT 0x05
|
||||
#define MIPS64_COP_CF 0x02
|
||||
#define MIPS64_COP_CT 0x06
|
||||
|
||||
#define MIPS64_R_INST(opcode, rs, rt, rd, shamt, funct) \
|
||||
(((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct))
|
||||
#define MIPS64_I_INST(opcode, rs, rt, immd) (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd))
|
||||
#define MIPS64_J_INST(opcode, addr) (((opcode) << 26) | (addr))
|
||||
|
||||
#define MIPS64_NOP 0
|
||||
#define MIPS64_ADDI(tar, src, val) MIPS64_I_INST(MIPS64_OP_ADDI, src, tar, val)
|
||||
#define MIPS64_DADDI(tar, src, val) MIPS64_I_INST(MIPS64_OP_DADDI, src, tar, val)
|
||||
#define MIPS64_DADDIU(tar, src, val) MIPS64_I_INST(MIPS64_OP_DADDIU, src, tar, val)
|
||||
#define MIPS64_AND(reg, off, val) MIPS64_R_INST(0, off, val, reg, 0, MIPS64_OP_AND)
|
||||
#define MIPS64_ANDI(d, s, im) MIPS64_I_INST(MIPS64_OP_ANDI, s, d, im)
|
||||
#define MIPS64_SRL(d, w, sh) MIPS64_R_INST(0, 0, w, d, sh, MIPS64_OP_SRL)
|
||||
#define MIPS64_B(off) MIPS64_BEQ(0, 0, off)
|
||||
#define MIPS64_BEQ(src, tar, off) MIPS64_I_INST(MIPS64_OP_BEQ, src, tar, off)
|
||||
#define MIPS64_BNE(src, tar, off) MIPS64_I_INST(MIPS64_OP_BNE, src, tar, off)
|
||||
#define MIPS64_MFC0(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP0, MIPS64_COP_MF, gpr, cpr, 0, sel)
|
||||
#define MIPS64_DMFC0(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP0, MIPS64_COP_DMF, gpr, cpr, 0, sel)
|
||||
#define MIPS64_MTC0(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP0, MIPS64_COP_MT, gpr, cpr, 0, sel)
|
||||
#define MIPS64_DMTC0(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP0, MIPS64_COP_DMT, gpr, cpr, 0, sel)
|
||||
#define MIPS64_MFC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_MF, gpr, cpr, 0, 0)
|
||||
#define MIPS64_DMFC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_DMF, gpr, cpr, 0, 0)
|
||||
#define MIPS64_MTC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_MT, gpr, cpr, 0, 0)
|
||||
#define MIPS64_DMTC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_DMT, gpr, cpr, 0, 0)
|
||||
#define MIPS64_MFC2(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP2, MIPS64_COP_MF, gpr, cpr, 0, sel)
|
||||
#define MIPS64_MTC2(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP2, MIPS64_COP_MT, gpr, cpr, 0, sel)
|
||||
#define MIPS64_CFC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_CF, gpr, cpr, 0, 0)
|
||||
#define MIPS64_CTC1(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP1, MIPS64_COP_CT, gpr, cpr, 0, 0)
|
||||
#define MIPS64_CFC2(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP2, MIPS64_COP_CF, gpr, cpr, 0, sel)
|
||||
#define MIPS64_CTC2(gpr, cpr, sel) MIPS64_R_INST(MIPS64_OP_COP2, MIPS64_COP_CT, gpr, cpr, 0, sel)
|
||||
#define MIPS64_LBU(reg, off, base) MIPS64_I_INST(MIPS64_OP_LBU, base, reg, off)
|
||||
#define MIPS64_LHU(reg, off, base) MIPS64_I_INST(MIPS64_OP_LHU, base, reg, off)
|
||||
#define MIPS64_LUI(reg, val) MIPS64_I_INST(MIPS64_OP_LUI, 0, reg, val)
|
||||
#define MIPS64_LW(reg, off, base) MIPS64_I_INST(MIPS64_OP_LW, base, reg, off)
|
||||
#define MIPS64_LD(reg, off, base) MIPS64_I_INST(MIPS64_OP_LD, base, reg, off)
|
||||
#define MIPS64_MFLO(reg) MIPS64_R_INST(0, 0, 0, reg, 0, MIPS64_OP_MFLO)
|
||||
#define MIPS64_MFHI(reg) MIPS64_R_INST(0, 0, 0, reg, 0, MIPS64_OP_MFHI)
|
||||
#define MIPS64_MTLO(reg) MIPS64_R_INST(0, reg, 0, 0, 0, MIPS64_OP_MTLO)
|
||||
#define MIPS64_MTHI(reg) MIPS64_R_INST(0, reg, 0, 0, 0, MIPS64_OP_MTHI)
|
||||
#define MIPS64_ORI(src, tar, val) MIPS64_I_INST(MIPS64_OP_ORI, src, tar, val)
|
||||
#define MIPS64_SB(reg, off, base) MIPS64_I_INST(MIPS64_OP_SB, base, reg, off)
|
||||
#define MIPS64_SH(reg, off, base) MIPS64_I_INST(MIPS64_OP_SH, base, reg, off)
|
||||
#define MIPS64_SW(reg, off, base) MIPS64_I_INST(MIPS64_OP_SW, base, reg, off)
|
||||
#define MIPS64_SD(reg, off, base) MIPS64_I_INST(MIPS64_OP_SD, base, reg, off)
|
||||
#define MIPS64_CACHE(op, reg, off) (47 << 26 | (reg) << 21 | (op) << 16 | (off))
|
||||
#define MIPS64_SYNCI(reg, off) (1 << 26 | (reg) << 21 | 0x1f << 16 | (off))
|
||||
#define MIPS64_JR(reg) MIPS64_R_INST(0, reg, 0, 0, 0, MIPS64_OP_JR)
|
||||
|
||||
/* ejtag specific instructions */
|
||||
#define MIPS64_DRET 0x4200001F
|
||||
#define MIPS64_SDBBP 0x7000003F
|
||||
#define MIPS64_SDBBP_LE 0x3f000007
|
||||
#define MIPS64_SDBBP_SIZE 4
|
||||
#define MIPS16_SDBBP_SIZE 2
|
||||
|
||||
#define MIPS64_SYNC 0x0000000F
|
||||
|
||||
int mips64_arch_state(struct target *target);
|
||||
int mips64_init_arch_info(struct target *target, struct mips64_common *mips64, struct jtag_tap *tap);
|
||||
int mips64_restore_context(struct target *target);
|
||||
int mips64_save_context(struct target *target);
|
||||
int mips64_build_reg_cache(struct target *target);
|
||||
int mips64_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params,
|
||||
int num_reg_params, struct reg_param *reg_params,
|
||||
target_addr_t entry_point, target_addr_t exit_point,
|
||||
int timeout_ms, void *arch_info);
|
||||
int mips64_configure_break_unit(struct target *target);
|
||||
int mips64_enable_interrupts(struct target *target, bool enable);
|
||||
int mips64_examine(struct target *target);
|
||||
|
||||
int mips64_register_commands(struct command_context *cmd_ctx);
|
||||
int mips64_invalidate_core_regs(struct target *target);
|
||||
int mips64_get_gdb_reg_list(struct target *target,
|
||||
struct reg **reg_list[], int *reg_list_size,
|
||||
enum target_register_class reg_class);
|
||||
|
||||
#endif /* OPENOCD_TARGET_MIPS64_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Support for processors implementing MIPS64 instruction set
|
||||
*
|
||||
* Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
|
||||
* Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
|
||||
* Copyright (C) 2014-2019 by Peter Mamonov <pmamonov@gmail.com>
|
||||
*
|
||||
* Based on the work of:
|
||||
* Copyright (C) 2008 by Spencer Oliver
|
||||
* Copyright (C) 2008 by David T.L. Wong
|
||||
* Copyright (C) 2010 by Konstantin Kostyukhin, Nikolay Shmyrev
|
||||
*/
|
||||
|
||||
#ifndef OPENOCD_TARGET_MIPS64_PRACC_H
|
||||
#define OPENOCD_TARGET_MIPS64_PRACC_H
|
||||
|
||||
#include "mips_ejtag.h"
|
||||
|
||||
#define MIPS64_PRACC_TEXT 0xffffffffFF200200ull
|
||||
|
||||
#define MIPS64_PRACC_STACK 0xffffffffFF204000ull
|
||||
#define MIPS64_PRACC_PARAM_IN 0xffffffffFF201000ull
|
||||
#define MIPS64_PRACC_PARAM_IN_SIZE 0x1000
|
||||
#define MIPS64_PRACC_PARAM_OUT (MIPS64_PRACC_PARAM_IN + MIPS64_PRACC_PARAM_IN_SIZE)
|
||||
#define MIPS64_PRACC_PARAM_OUT_SIZE 0x1000
|
||||
|
||||
#undef UPPER16
|
||||
#undef LOWER16
|
||||
#define UPPER16(v) ((uint32_t)((v >> 16) & 0xFFFF))
|
||||
#define LOWER16(v) ((uint32_t)(v & 0xFFFF))
|
||||
#define MIPS64_PRACC_FASTDATA_AREA 0xffffffffFF200000
|
||||
#define MIPS64_PRACC_FASTDATA_SIZE 16
|
||||
#define MIPS64_FASTDATA_HANDLER_SIZE 0x80
|
||||
|
||||
/* FIXME: 16-bit NEG */
|
||||
#undef NEG16
|
||||
#define NEG16(v) ((uint32_t)(((~(v)) + 1) & 0xFFFF))
|
||||
|
||||
#define MIPS64_PRACC_ADDR_STEP 4
|
||||
#define MIPS64_PRACC_DATA_STEP 8
|
||||
|
||||
int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf);
|
||||
int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf);
|
||||
|
||||
int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs);
|
||||
int mips64_pracc_write_regs(struct mips_ejtag *ejtag_info, uint64_t *regs);
|
||||
|
||||
int mips64_pracc_exec(struct mips_ejtag *ejtag_info,
|
||||
unsigned code_len, const uint32_t *code,
|
||||
unsigned num_param_in, uint64_t *param_in,
|
||||
unsigned num_param_out, uint64_t *param_out);
|
||||
|
||||
int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info,
|
||||
struct working_area *source,
|
||||
bool write_t, uint64_t addr,
|
||||
unsigned count, uint64_t *buf);
|
||||
|
||||
#endif /* OPENOCD_TARGET_MIPS64_PRACC_H */
|
|
@ -28,6 +28,11 @@
|
|||
#include "mips_ejtag.h"
|
||||
#include "mips32_dmaacc.h"
|
||||
|
||||
#if BUILD_TARGET64 == 1
|
||||
#include "mips64.h"
|
||||
#include "mips64_pracc.h"
|
||||
#endif
|
||||
|
||||
void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr)
|
||||
{
|
||||
assert(ejtag_info->tap != NULL);
|
||||
|
@ -87,6 +92,36 @@ void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32
|
|||
keep_alive();
|
||||
}
|
||||
|
||||
int mips_ejtag_drscan_64(struct mips_ejtag *ejtag_info, uint64_t *data)
|
||||
{
|
||||
struct jtag_tap *tap;
|
||||
tap = ejtag_info->tap;
|
||||
|
||||
if (tap == NULL)
|
||||
return ERROR_FAIL;
|
||||
struct scan_field field;
|
||||
uint8_t t[8], r[8];
|
||||
int retval;
|
||||
|
||||
field.num_bits = 64;
|
||||
field.out_value = t;
|
||||
buf_set_u64(t, 0, field.num_bits, *data);
|
||||
field.in_value = r;
|
||||
|
||||
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||
retval = jtag_execute_queue();
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("register read failed");
|
||||
return retval;
|
||||
}
|
||||
|
||||
*data = buf_get_u64(field.in_value, 0, 64);
|
||||
|
||||
keep_alive();
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void mips_ejtag_drscan_32_queued(struct mips_ejtag *ejtag_info, uint32_t data_out, uint8_t *data_in)
|
||||
{
|
||||
assert(ejtag_info->tap != NULL);
|
||||
|
@ -422,3 +457,112 @@ int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_
|
|||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#if BUILD_TARGET64 == 1
|
||||
|
||||
int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, bool enable_step)
|
||||
{
|
||||
const uint32_t code_enable[] = {
|
||||
MIPS64_MTC0(1, 31, 0), /* move $1 to COP0 DeSave */
|
||||
MIPS64_MFC0(1, 23, 0), /* move COP0 Debug to $1 */
|
||||
MIPS64_ORI(1, 1, 0x0100), /* set SSt bit in debug reg */
|
||||
MIPS64_MTC0(1, 23, 0), /* move $1 to COP0 Debug */
|
||||
MIPS64_B(NEG16(5)),
|
||||
MIPS64_MFC0(1, 31, 0), /* move COP0 DeSave to $1 */
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
};
|
||||
|
||||
const uint32_t code_disable[] = {
|
||||
MIPS64_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
|
||||
MIPS64_LUI(15, UPPER16(MIPS64_PRACC_STACK)), /* $15 = MIPS64_PRACC_STACK */
|
||||
MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_STACK)),
|
||||
MIPS64_SD(1, 0, 15), /* sw $1,($15) */
|
||||
MIPS64_SD(2, 0, 15), /* sw $2,($15) */
|
||||
MIPS64_MFC0(1, 23, 0), /* move COP0 Debug to $1 */
|
||||
MIPS64_LUI(2, 0xFFFF), /* $2 = 0xfffffeff */
|
||||
MIPS64_ORI(2, 2, 0xFEFF),
|
||||
MIPS64_AND(1, 1, 2),
|
||||
MIPS64_MTC0(1, 23, 0), /* move $1 to COP0 Debug */
|
||||
MIPS64_LD(2, 0, 15),
|
||||
MIPS64_LD(1, 0, 15),
|
||||
MIPS64_SYNC,
|
||||
MIPS64_B(NEG16(14)),
|
||||
MIPS64_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
};
|
||||
const uint32_t *code = enable_step ? code_enable : code_disable;
|
||||
unsigned code_len = enable_step ? ARRAY_SIZE(code_enable) :
|
||||
ARRAY_SIZE(code_disable);
|
||||
|
||||
return mips64_pracc_exec(ejtag_info,
|
||||
code_len, code, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
int mips64_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
|
||||
{
|
||||
const uint32_t code[] = {
|
||||
MIPS64_DRET,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
MIPS64_NOP,
|
||||
};
|
||||
LOG_DEBUG("enter mips64_pracc_exec");
|
||||
return mips64_pracc_exec(ejtag_info,
|
||||
ARRAY_SIZE(code), code, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, bool write_t, uint64_t *data)
|
||||
{
|
||||
struct jtag_tap *tap;
|
||||
|
||||
tap = ejtag_info->tap;
|
||||
assert(tap != NULL);
|
||||
|
||||
struct scan_field fields[2];
|
||||
uint8_t spracc = 0;
|
||||
uint8_t t[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
/* fastdata 1-bit register */
|
||||
fields[0].num_bits = 1;
|
||||
fields[0].out_value = &spracc;
|
||||
fields[0].in_value = NULL;
|
||||
|
||||
/* processor access data register 64 bit */
|
||||
fields[1].num_bits = 64;
|
||||
fields[1].out_value = t;
|
||||
|
||||
if (write_t) {
|
||||
fields[1].in_value = NULL;
|
||||
buf_set_u64(t, 0, 64, *data);
|
||||
} else
|
||||
fields[1].in_value = (uint8_t *) data;
|
||||
|
||||
jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
|
||||
|
||||
if (!write_t && data)
|
||||
jtag_add_callback(mips_le_to_h_u64,
|
||||
(jtag_callback_data_t) data);
|
||||
keep_alive();
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#endif /* BUILD_TARGET64 */
|
||||
|
|
|
@ -182,6 +182,20 @@
|
|||
#define EJTAG_VERSION_41 4
|
||||
#define EJTAG_VERSION_51 5
|
||||
|
||||
/*
|
||||
* Additional defines for MIPS64 EJTAG
|
||||
*/
|
||||
#define EJTAG64_DCR 0xFFFFFFFFFF300000ull
|
||||
#define EJTAG64_DCR_ENM (1llu << 29)
|
||||
#define EJTAG64_DCR_DB (1llu << 17)
|
||||
#define EJTAG64_DCR_IB (1llu << 16)
|
||||
#define EJTAG64_DCR_INTE (1llu << 4)
|
||||
#define EJTAG64_DCR_MP (1llu << 2)
|
||||
#define EJTAG64_V25_DBA0 0xFFFFFFFFFF302100ull
|
||||
#define EJTAG64_V25_DBS 0xFFFFFFFFFF302000ull
|
||||
#define EJTAG64_V25_IBA0 0xFFFFFFFFFF301100ull
|
||||
#define EJTAG64_V25_IBS 0xFFFFFFFFFF301000ull
|
||||
|
||||
struct mips_ejtag {
|
||||
struct jtag_tap *tap;
|
||||
uint32_t impcode;
|
||||
|
@ -224,17 +238,21 @@ struct mips_ejtag {
|
|||
void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr);
|
||||
int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info);
|
||||
int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info);
|
||||
int mips64_ejtag_exit_debug(struct mips_ejtag *ejtag_info);
|
||||
int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info);
|
||||
void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info,
|
||||
uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf);
|
||||
int mips_ejtag_drscan_64(struct mips_ejtag *ejtag_info, uint64_t *data);
|
||||
void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data);
|
||||
int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data);
|
||||
void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data);
|
||||
int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data);
|
||||
int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data);
|
||||
int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, bool write_t, uint64_t *data);
|
||||
|
||||
int mips_ejtag_init(struct mips_ejtag *ejtag_info);
|
||||
int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);
|
||||
int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, bool enable_step);
|
||||
|
||||
static inline void mips_le_to_h_u32(jtag_callback_data_t arg)
|
||||
{
|
||||
|
@ -242,4 +260,10 @@ static inline void mips_le_to_h_u32(jtag_callback_data_t arg)
|
|||
*((uint32_t *)arg) = le_to_h_u32(in);
|
||||
}
|
||||
|
||||
static inline void mips_le_to_h_u64(jtag_callback_data_t arg)
|
||||
{
|
||||
uint8_t *in = (uint8_t *)arg;
|
||||
*((uint64_t *)arg) = le_to_h_u64(in);
|
||||
}
|
||||
|
||||
#endif /* OPENOCD_TARGET_MIPS_EJTAG_H */
|
||||
|
|
Loading…
Reference in New Issue