- merged mips target into svn trunk
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sat, 26 Jul 2008 10:32:11 +0000 (10:32 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sat, 26 Jul 2008 10:32:11 +0000 (10:32 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@874 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/target/Makefile.am
src/target/mips32.c [new file with mode: 0644]
src/target/mips32.h [new file with mode: 0644]
src/target/mips32_pracc.c [new file with mode: 0644]
src/target/mips32_pracc.h [new file with mode: 0644]
src/target/mips_ejtag.c [new file with mode: 0644]
src/target/mips_ejtag.h [new file with mode: 0644]
src/target/mips_m4k.c [new file with mode: 0644]
src/target/mips_m4k.h [new file with mode: 0644]
src/target/target.c
src/target/target/pic32mx.cfg [new file with mode: 0644]

index 5b0ef6e527a14f495cfb6e775a4b86e795843df9..adf1add4b99bde93e1d5029d8b2234924a62e500 100644 (file)
@@ -12,11 +12,12 @@ noinst_LIBRARIES = libtarget.a
 libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
        arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
        arm966e.c arm926ejs.c feroceon.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c \
-       etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c arm11.c arm11_dbgtap.c
+       etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c arm11.c arm11_dbgtap.c mips32.c mips_m4k.c \
+       mips32_pracc.c mips_ejtag.c
 noinst_HEADERS = target.h trace.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
        arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
        arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h \
-       etm_dummy.h oocd_trace.h target_request.h trace.h arm11.h
+       etm_dummy.h oocd_trace.h target_request.h trace.h arm11.h mips32.h mips_m4k.h mips_ejtag.h mips32_pracc.h
 
 nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script target/at91eb40a.cfg \
        event/at91r40008_reset.script event/sam7s256_reset.script event/sam7x256_reset.script \
@@ -35,6 +36,6 @@ nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script
        interface/chameleon.cfg interface/at91rm9200.cfg interface/jlink.cfg interface/arm-usb-ocd.cfg \
        interface/signalyzer.cfg event/eir-sam7se512_reset.script target/eir-sam7se512.cfg \
        event/hammer_reset.script interface/flyswatter.cfg target/hammer.cfg target/mx31.cfg  \
-       event/str730_program.script event/str750_program.script interface/olimex-jtag-tiny-a.cfg
-       
+       event/str730_program.script event/str750_program.script interface/olimex-jtag-tiny-a.cfg \
+       target/pic32mx.cfg
 
diff --git a/src/target/mips32.c b/src/target/mips32.c
new file mode 100644 (file)
index 0000000..f338c1d
--- /dev/null
@@ -0,0 +1,338 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mips32.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+char* mips32_core_reg_list[] =
+{
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+       "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+       "status", "lo", "hi", "badvaddr", "cause", "pc"
+};
+
+mips32_core_reg_t mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] = 
+{
+       {0, NULL, NULL},
+       {1, NULL, NULL},
+       {2, NULL, NULL},
+       {3, NULL, NULL},
+       {4, NULL, NULL},
+       {5, NULL, NULL},
+       {6, NULL, NULL},
+       {7, NULL, NULL},
+       {8, NULL, NULL},
+       {9, NULL, NULL},
+       {10, NULL, NULL},
+       {11, NULL, NULL},
+       {12, NULL, NULL},
+       {13, NULL, NULL},
+       {14, NULL, NULL},
+       {15, NULL, NULL},
+       {16, NULL, NULL},
+       {17, NULL, NULL},
+       {18, NULL, NULL},
+       {19, NULL, NULL},
+       {20, NULL, NULL},
+       {21, NULL, NULL},
+       {22, NULL, NULL},
+       {23, NULL, NULL},
+       {24, NULL, NULL},
+       {25, NULL, NULL},
+       {26, NULL, NULL},
+       {27, NULL, NULL},
+       {28, NULL, NULL},
+       {29, NULL, NULL},
+       {30, NULL, NULL},
+       {31, NULL, NULL},
+       
+       {32, NULL, NULL},
+       {33, NULL, NULL},
+       {34, NULL, NULL},
+       {35, NULL, NULL},
+       {36, NULL, NULL},
+       {37, NULL, NULL},
+};
+
+u8 mips32_gdb_dummy_fsr_value[] = {0, 0, 0, 0};
+
+reg_t mips32_gdb_dummy_fsr_reg =
+{
+       "GDB dummy floating-point status register", mips32_gdb_dummy_fsr_value, 0, 1, 32, NULL, 0, NULL, 0
+};
+
+u8 mips32_gdb_dummy_fir_value[] = {0, 0, 0, 0};
+
+reg_t mips32_gdb_dummy_fir_reg =
+{
+       "GDB dummy floating-point register", mips32_gdb_dummy_fir_value, 0, 1, 32, NULL, 0, NULL, 0
+};
+
+int mips32_core_reg_arch_type = -1;
+
+int mips32_get_core_reg(reg_t *reg)
+{
+       int retval;
+       mips32_core_reg_t *mips32_reg = reg->arch_info;
+       target_t *target = mips32_reg->target;
+       mips32_common_t *mips32_target = target->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       retval = mips32_target->read_core_reg(target, mips32_reg->num);
+       
+       return retval;
+}
+
+int mips32_set_core_reg(reg_t *reg, u8 *buf)
+{
+       mips32_core_reg_t *mips32_reg = reg->arch_info;
+       target_t *target = mips32_reg->target;
+       u32 value = buf_get_u32(buf, 0, 32);
+               
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+               
+       buf_set_u32(reg->value, 0, 32, value);
+       reg->dirty = 1;
+       reg->valid = 1;
+
+       return ERROR_OK;
+}
+
+int mips32_read_core_reg(struct target_s *target, int num)
+{
+       u32 reg_value;
+       mips32_core_reg_t *mips_core_reg;
+       
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+               
+       if ((num < 0) || (num >= MIPS32NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+
+       mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
+       reg_value = mips32->core_regs[num];
+       buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+       mips32->core_cache->reg_list[num].valid = 1;
+       mips32->core_cache->reg_list[num].dirty = 0;
+       
+       return ERROR_OK;        
+}
+
+int mips32_write_core_reg(struct target_s *target, int num)
+{
+       u32 reg_value;
+       mips32_core_reg_t *mips_core_reg;
+       
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+
+       if ((num < 0) || (num >= MIPS32NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+       
+       reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
+       mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
+       mips32->core_regs[num] = reg_value;
+       LOG_DEBUG("write core reg %i value 0x%x", num , reg_value);
+       mips32->core_cache->reg_list[num].valid = 1;
+       mips32->core_cache->reg_list[num].dirty = 0;
+       
+       return ERROR_OK;
+}
+
+int mips32_invalidate_core_regs(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+       int i;
+       
+       for (i = 0; i < mips32->core_cache->num_regs; i++)
+       {
+               mips32->core_cache->reg_list[i].valid = 0;
+               mips32->core_cache->reg_list[i].dirty = 0;
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
+{
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+       int i;
+       
+       /* include fsr/fir reg */
+       *reg_list_size = MIPS32NUMCOREREGS + 2;
+       *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
+       
+       for (i = 0; i < MIPS32NUMCOREREGS; i++)
+       {
+               (*reg_list)[i] = &mips32->core_cache->reg_list[i];
+       }
+       
+       /* add dummy floating points regs */
+       (*reg_list)[38] = &mips32_gdb_dummy_fsr_reg;
+       (*reg_list)[39] = &mips32_gdb_dummy_fir_reg;
+       
+       return ERROR_OK;
+}
+
+int mips32_save_context(target_t *target)
+{
+       int i;
+       
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       /* read core registers */
+       mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
+       
+       for (i = 0; i < MIPS32NUMCOREREGS; i++)
+       {
+               if (!mips32->core_cache->reg_list[i].valid)
+               {
+                       mips32->read_core_reg(target, i);
+               }
+       }
+       
+       return ERROR_OK;                
+}
+
+int mips32_restore_context(target_t *target)
+{
+       int i;
+       
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       for (i = 0; i < MIPS32NUMCOREREGS; i++)
+       {
+               if (mips32->core_cache->reg_list[i].dirty)
+               {
+                       mips32->write_core_reg(target, i);
+               }
+       }
+       
+       /* write core regs */
+       mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
+       
+       return ERROR_OK;                
+}
+
+int mips32_arch_state(struct target_s *target)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       
+       if (mips32->common_magic != MIPS32_COMMON_MAGIC)
+       {
+               LOG_ERROR("BUG: called for a non-MIPS32 target");
+               exit(-1);
+       }
+       
+       LOG_USER("target halted due to %s, pc: 0x%8.8x",
+               target_debug_reason_strings[target->debug_reason],
+               buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
+       
+       return ERROR_OK;
+}
+
+reg_cache_t *mips32_build_reg_cache(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+
+       int num_regs = MIPS32NUMCOREREGS;
+       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+       reg_cache_t *cache = malloc(sizeof(reg_cache_t));
+       reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
+       mips32_core_reg_t *arch_info = malloc(sizeof(mips32_core_reg_t) * num_regs);
+       int i;
+       
+       if (mips32_core_reg_arch_type == -1)
+               mips32_core_reg_arch_type = register_reg_arch_type(mips32_get_core_reg, mips32_set_core_reg);
+               
+       /* Build the process context cache */ 
+       cache->name = "mips32 registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = num_regs;
+       (*cache_p) = cache;
+       mips32->core_cache = cache;
+       
+       for (i = 0; i < num_regs; i++)
+       {
+               arch_info[i] = mips32_core_reg_list_arch_info[i];
+               arch_info[i].target = target;
+               arch_info[i].mips32_common = mips32;
+               reg_list[i].name = mips32_core_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].arch_type = mips32_core_reg_arch_type;
+               reg_list[i].arch_info = &arch_info[i];
+       }
+       
+       return cache;
+}
+
+int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, int chain_pos, char *variant)
+{
+       target->arch_info = mips32;
+       mips32->common_magic = MIPS32_COMMON_MAGIC;
+       
+       mips32->ejtag_info.chain_pos = chain_pos;
+       mips32->read_core_reg = mips32_read_core_reg;
+       mips32->write_core_reg = mips32_write_core_reg;
+       
+       return ERROR_OK;
+}
+
+int mips32_register_commands(struct command_context_s *cmd_ctx)
+{
+       return ERROR_OK;
+}
+
+int mips32_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
+{
+       /*TODO*/
+       return ERROR_OK;
+}
diff --git a/src/target/mips32.h b/src/target/mips32.h
new file mode 100644 (file)
index 0000000..aeed1a6
--- /dev/null
@@ -0,0 +1,112 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifndef MIPS32_H
+#define MIPS32_H
+
+#include "target.h"
+#include "register.h"
+#include "mips_ejtag.h"
+#include "mips32_pracc.h"
+
+#define MIPS32_COMMON_MAGIC            0xB320B320
+
+/* offsets into mips32 core register cache */
+enum 
+{
+       MIPS32_PC = 37,
+       MIPS32NUMCOREREGS
+};
+
+typedef struct mips32_common_s
+{
+       int common_magic;
+       void *arch_info;
+       reg_cache_t *core_cache;
+       mips_ejtag_t ejtag_info;
+       u32 core_regs[MIPS32NUMCOREREGS];
+       
+       /* register cache to processor synchronization */
+       int (*read_core_reg)(struct target_s *target, int num);
+       int (*write_core_reg)(struct target_s *target, int num);
+} mips32_common_t;
+
+typedef struct mips32_core_reg_s
+{
+       u32 num;
+       target_t *target;
+       mips32_common_t *mips32_common;
+} mips32_core_reg_t;
+
+#define MIPS32_OP_BEQ  0x04
+#define MIPS32_OP_ADDI 0x08
+#define MIPS32_OP_AND  0x24
+#define MIPS32_OP_COP0 0x10
+#define MIPS32_OP_LUI  0x0F
+#define MIPS32_OP_LW   0x23
+#define MIPS32_OP_LBU  0x24
+#define MIPS32_OP_LHU  0x25
+#define MIPS32_OP_MFHI 0x10
+#define MIPS32_OP_MFLO 0x12
+#define MIPS32_OP_SB   0x28
+#define MIPS32_OP_SH   0x29
+#define MIPS32_OP_SW   0x2B
+#define MIPS32_OP_ORI  0x0D
+
+#define MIPS32_COP0_MF 0x00
+#define MIPS32_COP0_MT 0x04
+
+#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct)        (((opcode)<<26) |((rs)<<21)|((rt)<<16)|((rd)<<11)| ((shamt)<<5) | (funct))
+#define MIPS32_I_INST(opcode, rs, rt, immd)    (((opcode)<<26) |((rs)<<21)|((rt)<<16)|(immd))
+#define MIPS32_J_INST(opcode, addr)    (((opcode)<<26) |(addr))
+
+#define MIPS32_NOP                                     0
+#define MIPS32_ADDI(tar, src, val)     MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val)
+#define MIPS32_AND(reg, off, val)      MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND)
+#define MIPS32_B(off)                          MIPS32_BEQ(0, 0, off)
+#define MIPS32_BEQ(src,tar,off)                MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off)
+#define MIPS32_MFC0(gpr, cpr, sel)     MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel)
+#define MIPS32_MTC0(gpr,cpr, sel)      MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel)
+#define MIPS32_LBU(reg, off, base)     MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off)
+#define MIPS32_LHU(reg, off, base)     MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off)
+#define MIPS32_LUI(reg, val)           MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val)
+#define MIPS32_LW(reg, off, base)      MIPS32_I_INST(MIPS32_OP_LW, base, reg, off)
+#define MIPS32_LO(reg)                         MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI)
+#define MIPS32_HI(reg)                         MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO)
+#define MIPS32_ORI(src, tar, val)      MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val)
+#define MIPS32_SB(reg, off, base)      MIPS32_I_INST(MIPS32_OP_SB, base, reg, off)
+#define MIPS32_SH(reg, off, base)      MIPS32_I_INST(MIPS32_OP_SH, base, reg, off)
+#define MIPS32_SW(reg, off, base)      MIPS32_I_INST(MIPS32_OP_SW, base, reg, off)
+#define MIPS32_DRET                                    0x4200001F
+
+extern int mips32_arch_state(struct target_s *target);
+extern int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, int chain_pos, char *variant);
+extern int mips32_restore_context(target_t *target);
+extern int mips32_save_context(target_t *target);
+extern reg_cache_t *mips32_build_reg_cache(target_t *target);
+extern int mips32_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
+
+extern int mips32_register_commands(struct command_context_s *cmd_ctx);
+extern int mips32_invalidate_core_regs(target_t *target);
+extern int mips32_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size);
+
+#endif /*MIPS32_H*/
diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
new file mode 100644 (file)
index 0000000..400227e
--- /dev/null
@@ -0,0 +1,781 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "mips32.h"
+#include "mips32_pracc.h"
+
+typedef struct {
+       u32 *local_iparam;
+       int num_iparam;
+       u32 *local_oparam;
+       int num_oparam;
+       u32 *code;
+       int code_len;
+       u32 stack[32];
+       int stack_offset;
+       mips_ejtag_t *ejtag_info;
+} mips32_pracc_context;
+
+static int wait_for_pracc_rw(mips_ejtag_t *ejtag_info, u32 *ctrl)
+{
+       u32 ejtag_ctrl;
+       
+       while (1) 
+       {
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+               ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
+               mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+               if (ejtag_ctrl & EJTAG_CTRL_PRACC)
+                       break;
+               LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       
+       *ctrl = ejtag_ctrl;
+       return ERROR_OK;
+}
+
+static int mips32_pracc_exec_read(mips32_pracc_context *ctx, u32 address)
+{
+       int offset;
+       u32 ctrl, data;
+
+       if ((address >= MIPS32_PRACC_PARAM_IN)
+               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
+       {
+               offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
+               data = ctx->local_iparam[offset];
+       }
+       else if ((address >= MIPS32_PRACC_PARAM_OUT)
+               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
+       {
+               offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
+               data = ctx->local_oparam[offset];
+       }
+       else if ((address >= MIPS32_PRACC_TEXT)
+               && (address <= MIPS32_PRACC_TEXT + ctx->code_len*4))
+       {
+               offset = (address - MIPS32_PRACC_TEXT) / 4;
+               data = ctx->code[offset];
+       }
+       else if (address == MIPS32_PRACC_STACK)
+       {
+               /* save to our debug stack */
+               data = ctx->stack[--ctx->stack_offset];
+       }
+       else
+       {
+               /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
+                * to start of debug vector */
+               
+               data = 0;
+               LOG_ERROR("Error reading unexpected address");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       
+       /* Send the data out */
+       mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
+       mips_ejtag_drscan_32(ctx->ejtag_info, &data);
+
+       /* Clear the access pending bit (let the processor eat!) */
+       ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
+       mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
+       mips_ejtag_drscan_32(ctx->ejtag_info, &ctrl);
+       
+       return ERROR_OK;
+}
+
+static int mips32_pracc_exec_write(mips32_pracc_context *ctx, u32 address)
+{
+       u32 ctrl,data;
+       int offset;
+       
+       mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
+       mips_ejtag_drscan_32(ctx->ejtag_info, &data);
+       
+       /* Clear access pending bit */
+       ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
+       mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
+       mips_ejtag_drscan_32(ctx->ejtag_info, &ctrl);
+       
+       if ((address >= MIPS32_PRACC_PARAM_IN)
+               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
+       {
+               offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
+               ctx->local_iparam[offset] = data;
+       }
+       else if ((address >= MIPS32_PRACC_PARAM_OUT )
+               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
+       {
+               offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
+               ctx->local_oparam[offset] = data;
+       }
+       else if (address == MIPS32_PRACC_STACK)
+       {
+               /* save data onto our stack */
+               ctx->stack[ctx->stack_offset++] = data;
+       }
+       else
+       {
+               LOG_ERROR("Error writing unexpected address");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_pracc_exec( mips_ejtag_t *ejtag_info, int code_len, u32 *code, int num_param_in, u32 *param_in, int num_param_out, u32 *param_out, int cycle)
+{
+       u32 ctrl;
+       u32 address, data;
+       mips32_pracc_context ctx;
+       int retval;
+       int pass = 0;
+       
+       ctx.local_iparam = param_in;
+       ctx.local_oparam = param_out;
+       ctx.num_iparam = num_param_in;
+       ctx.num_oparam = num_param_out;
+       ctx.code = code;
+       ctx.code_len = code_len;
+       ctx.ejtag_info = ejtag_info;
+       ctx.stack_offset = 0;
+       
+       while (1)
+       {
+               if ((retval = wait_for_pracc_rw(ejtag_info, &ctrl)) != ERROR_OK)
+                       return retval;
+               
+               address = data = 0;
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
+               mips_ejtag_drscan_32(ejtag_info, &address);
+               
+               /* Check for read or write */
+               if (ctrl & EJTAG_CTRL_PRNW)
+               {
+                       if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
+                               return retval;
+               }
+               else
+               {
+                       /* Check to see if its reading at the debug vector. The first pass through
+                        * the module is always read at the vector, so the first one we allow.  When
+                        * the second read from the vector occurs we are done and just exit. */
+                       if ((address == MIPS32_PRACC_TEXT) && (pass++))
+                       {
+                               break;
+                       }
+                       
+                       if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
+                               return retval;
+               }
+               
+               if (cycle == 0)
+                       break;
+       }
+       
+       /* stack sanity check */
+       if (ctx.stack_offset != 0)
+       {
+               LOG_DEBUG("Pracc Stack not zero");
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_pracc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
+{
+       switch (size)
+       {
+               case 1:
+                       return mips32_pracc_read_mem8(ejtag_info, addr, count, (u8*)buf);
+               case 2:
+                       return mips32_pracc_read_mem16(ejtag_info, addr, count, (u16*)buf);
+               case 4:
+                       return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf);
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
+{      
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+                       
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
+               MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
+               MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
+               MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                                     /* beq 0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LW(12,0,9),                                                                      /* lw $12,0($9), Load $12 with the word @mem[$9] */
+               MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,4),                                                             /* $1+=4 */
+               MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
+               
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+                                                                                                                       /* end: */
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(31)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+       
+       int retval;
+       int blocksize;
+       int bytesread;
+       u32 param_in[2];
+       
+       bytesread = 0;
+       
+       while (count > 0)
+       {       
+               blocksize = count;
+               if (count > 0x400)
+                       blocksize = 0x400;
+               
+               param_in[0] = addr;
+               param_in[1] = blocksize;
+               
+               if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+                       sizeof(param_in)/sizeof(param_in[0]), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
+                       return retval;
+               
+               count -= blocksize;
+               addr += blocksize;
+               bytesread += blocksize;
+       }
+
+       return retval;
+}
+
+int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
+{
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+                       
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
+               MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
+               MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
+               MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LHU(12,0,9),                                                             /* lw $12,0($9), Load $12 with the halfword @mem[$9] */
+               MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
+               MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(31)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+
+//     /* TODO remove array */
+       u32 param_out[count];
+       int i;
+       
+//     int retval;
+       int blocksize;
+       int bytesread;
+       u32 param_in[2];
+       
+       bytesread = 0;
+       
+       //while (count > 0)
+       {       
+               blocksize = count;
+               if (count > 0x400)
+                       blocksize = 0x400;
+               
+               param_in[0] = addr;
+               param_in[1] = blocksize;
+               
+               mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+                       sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
+               
+//             count -= blocksize;
+//             addr += blocksize;
+//             bytesread += blocksize;
+       }
+       
+       for (i = 0; i < count; i++)
+       {
+               buf[i] = param_out[i];
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
+{
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+                       
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
+               MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
+               MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
+               MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LBU(12,0,9),                                                             /* lw $12,0($9), Load t4 with the byte @mem[t1] */
+               MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
+               MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+                                                                                                                       /* end: */
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(31)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+       
+//     /* TODO remove array */
+       u32 param_out[count];
+       int i;
+       
+//     int retval;
+       int blocksize;
+       int bytesread;
+       u32 param_in[2];
+       
+       bytesread = 0;
+       
+//     while (count > 0)
+       {       
+               blocksize = count;
+               if (count > 0x400)
+                       blocksize = 0x400;
+               
+               param_in[0] = addr;
+               param_in[1] = blocksize;
+               
+               mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+                       sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
+               
+//             count -= blocksize;
+//             addr += blocksize;
+//             bytesread += blocksize;
+       }
+       
+       for (i = 0; i < count; i++)
+       {
+               buf[i] = param_out[i];
+       }
+
+       return ERROR_OK;
+}
+
+int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
+{
+       switch (size)
+       {
+               case 1:
+                       return mips32_pracc_write_mem8(ejtag_info, addr, count, (u8*)buf);
+               case 2:
+                       return mips32_pracc_write_mem16(ejtag_info, addr, count,(u16*)buf);
+               case 4:
+                       return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf);
+       }
+       
+       return ERROR_OK;
+}
+
+int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
+{
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+               
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
+               MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
+               MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
+               MIPS32_SW(11,0,9),                                                                      /* sw $11,0($9) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,4),                                                             /* $9+=4 */
+               MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+                                                                                                                       /* end: */
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(30)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+       
+       /* TODO remove array */
+       u32 param_in[count+2];
+       param_in[0] = addr;
+       param_in[1] = count;
+       
+       memcpy(&param_in[2], buf, count * sizeof(u32));
+       
+       mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1);
+
+       return ERROR_OK;
+}
+
+int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
+{
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+               
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
+               MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
+               MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
+               MIPS32_SH(11,0,9),                                                                      /* sh $11,0($9) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
+               MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
+               
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+                                                                                                                       /* end: */
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(30)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+       
+       /* TODO remove array */
+       u32 param_in[count+2];
+       int i;
+       param_in[0] = addr;
+       param_in[1] = count;
+       
+       for (i = 0; i < count; i++)
+       {
+               param_in[i+2] = buf[i];
+       }
+       
+       mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
+
+       return ERROR_OK;
+}
+
+int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
+{
+       u32 code[] = {
+                                                                                                                       /* start: */
+               MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
+               
+               MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
+               MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
+               MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
+               MIPS32_NOP,
+                                                                                                                       /* loop: */
+               MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
+               MIPS32_NOP,
+               
+               MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
+               MIPS32_SB(11,0,9),                                                                      /* sb $11,0($9) */
+               
+               MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
+               MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
+               MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
+               
+               MIPS32_NOP,
+               MIPS32_B(NEG16(9)),                                                                     /* b loop */
+               MIPS32_NOP,
+                                                                                                                       /* end: */
+               MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
+               MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
+               MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
+               MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
+               MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(30)),                                                            /* b start */
+               MIPS32_NOP,
+       };
+       
+       /* TODO remove array */
+       u32 param_in[count+2];
+       int retval;
+       int i;
+       param_in[0] = addr;
+       param_in[1] = count;
+       
+       for (i = 0; i < count; i++)
+       {
+               param_in[i+2] = buf[i];
+       }
+       
+       retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
+
+       return retval;
+}
+
+int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs)
+{
+       /* TODO restore all core registers */
+       
+       u32 code[] = {
+                                                                                                               /* start: */
+               MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
+               MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $2 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               /*MIPS32_LW(0,0*4,2),*/                                                 /* lw $0,0*4($2) */
+               MIPS32_LW(1,1*4,2),                                                     /* lw $1,1*4($2) */
+               MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
+               
+               MIPS32_MTC0(1,31,0),                                                    /* move $1 to COP0 DeSave */
+               MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $1 = MIPS32_PRACC_PARAM_IN */
+               MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
+               MIPS32_LW(2,2*4,1),                                                     /* lw $2,2*4($1) */
+               MIPS32_LW(3,3*4,1),                                                     /* lw $3,3*4($1) */
+               MIPS32_LW(4,4*4,1),                                                     /* lw $4,4*4($1) */
+               MIPS32_LW(5,5*4,1),                                                     /* lw $5,5*4($1) */
+               MIPS32_LW(6,6*4,1),                                                     /* lw $6,6*4($1) */
+               MIPS32_LW(7,7*4,1),                                                     /* lw $7,7*4($1) */
+               MIPS32_LW(8,8*4,1),                                                     /* lw $8,8*4($1) */
+               MIPS32_LW(9,9*4,1),                                                     /* lw $9,9*4($1) */
+               MIPS32_LW(10,10*4,1),                                                   /* lw $10,10*4($1) */
+               MIPS32_LW(11,11*4,1),                                                   /* lw $11,11*4($1) */
+               MIPS32_LW(12,12*4,1),                                                   /* lw $12,12*4($1) */
+               MIPS32_LW(13,13*4,1),                                                   /* lw $13,13*4($1) */
+               MIPS32_LW(14,14*4,1),                                                   /* lw $14,14*4($1) */
+               MIPS32_LW(15,15*4,1),                                                   /* lw $15,15*4($1) */
+               MIPS32_LW(16,16*4,1),                                                   /* lw $16,16*4($1) */
+               MIPS32_LW(17,17*4,1),                                                   /* lw $17,17*4($1) */
+               MIPS32_LW(18,18*4,1),                                                   /* lw $18,18*4($1) */
+               MIPS32_LW(19,19*4,1),                                                   /* lw $19,19*4($1) */
+               MIPS32_LW(20,20*4,1),                                                   /* lw $20,20*4($1) */
+               MIPS32_LW(21,21*4,1),                                                   /* lw $21,21*4($1) */
+               MIPS32_LW(22,22*4,1),                                                   /* lw $22,22*4($1) */
+               MIPS32_LW(23,23*4,1),                                                   /* lw $23,23*4($1) */
+               MIPS32_LW(24,24*4,1),                                                   /* lw $24,24*4($1) */
+               MIPS32_LW(25,25*4,1),                                                   /* lw $25,25*4($1) */
+               MIPS32_LW(26,26*4,1),                                                   /* lw $26,26*4($1) */
+               MIPS32_LW(27,27*4,1),                                                   /* lw $27,27*4($1) */
+               MIPS32_LW(28,28*4,1),                                                   /* lw $28,28*4($1) */
+               MIPS32_LW(29,29*4,1),                                                   /* lw $29,29*4($1) */
+               MIPS32_LW(30,30*4,1),                                                   /* lw $30,30*4($1) */
+               MIPS32_LW(31,31*4,1),                                                   /* lw $31,31*4($1) */
+               
+               MIPS32_MFC0(1,31,0),                                                    /* move COP0 DeSave to $1 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(41)),                                                    /* b start */
+               MIPS32_NOP,
+       };
+       
+       int retval;
+       
+       retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               32, regs, 0, NULL, 1);
+       
+       return retval;
+}
+
+int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs)
+{
+       u32 code[] = {
+                                                                                                               /* start: */
+               MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
+               MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $2 = MIPS32_PRACC_PARAM_OUT */
+               MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+               MIPS32_SW(0,0*4,2),                                                             /* sw $0,0*4($2) */
+               MIPS32_SW(1,1*4,2),                                                     /* sw $1,1*4($2) */
+               MIPS32_SW(15,15*4,2),                                                   /* sw $15,15*4($2) */
+               MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
+               MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
+               MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+               MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
+               MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
+               MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
+               MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+               MIPS32_SW(2,2*4,1),                                                     /* sw $2,2*4($1) */
+               MIPS32_SW(3,3*4,1),                                                     /* sw $3,3*4($1) */
+               MIPS32_SW(4,4*4,1),                                                     /* sw $4,4*4($1) */
+               MIPS32_SW(5,5*4,1),                                                     /* sw $5,5*4($1) */
+               MIPS32_SW(6,6*4,1),                                                     /* sw $6,6*4($1) */
+               MIPS32_SW(7,7*4,1),                                                     /* sw $7,7*4($1) */
+               MIPS32_SW(8,8*4,1),                                                     /* sw $8,8*4($1) */
+               MIPS32_SW(9,9*4,1),                                                     /* sw $9,9*4($1) */
+               MIPS32_SW(10,10*4,1),                                                   /* sw $10,10*4($1) */
+               MIPS32_SW(11,11*4,1),                                                   /* sw $11,11*4($1) */
+               MIPS32_SW(12,12*4,1),                                                   /* sw $12,12*4($1) */
+               MIPS32_SW(13,13*4,1),                                                   /* sw $13,13*4($1) */
+               MIPS32_SW(14,14*4,1),                                                   /* sw $14,14*4($1) */
+               MIPS32_SW(16,16*4,1),                                                   /* sw $16,16*4($1) */
+               MIPS32_SW(17,17*4,1),                                                   /* sw $17,17*4($1) */
+               MIPS32_SW(18,18*4,1),                                                   /* sw $18,18*4($1) */
+               MIPS32_SW(19,19*4,1),                                                   /* sw $19,19*4($1) */
+               MIPS32_SW(20,20*4,1),                                                   /* sw $20,20*4($1) */
+               MIPS32_SW(21,21*4,1),                                                   /* sw $21,21*4($1) */
+               MIPS32_SW(22,22*4,1),                                                   /* sw $22,22*4($1) */
+               MIPS32_SW(23,23*4,1),                                                   /* sw $23,23*4($1) */
+               MIPS32_SW(24,24*4,1),                                                   /* sw $24,24*4($1) */
+               MIPS32_SW(25,25*4,1),                                                   /* sw $25,25*4($1) */
+               MIPS32_SW(26,26*4,1),                                                   /* sw $26,26*4($1) */
+               MIPS32_SW(27,27*4,1),                                                   /* sw $27,27*4($1) */
+               MIPS32_SW(28,28*4,1),                                                   /* sw $28,28*4($1) */
+               MIPS32_SW(29,29*4,1),                                                   /* sw $29,29*4($1) */
+               MIPS32_SW(30,30*4,1),                                                   /* sw $30,30*4($1) */
+               MIPS32_SW(31,31*4,1),                                                   /* sw $31,31*4($1) */
+               
+               MIPS32_MFC0(2,12,0),                                                    /* move status to $2 */
+               MIPS32_SW(2,32*4,1),                                                    /* sw $2,32*4($1) */
+               MIPS32_LO(2),                                                                   /* move lo to $2 */
+               MIPS32_SW(2,33*4,1),                                                    /* sw $2,33*4($1) */
+               MIPS32_HI(2),                                                                   /* move hi to $2 */
+               MIPS32_SW(2,34*4,1),                                                    /* sw $2,34*4($1) */
+               MIPS32_MFC0(2,8,0),                                                             /* move badvaddr to $2 */
+               MIPS32_SW(2,35*4,1),                                                    /* sw $2,35*4($1) */
+               MIPS32_MFC0(2,13,0),                                                    /* move cause to $2 */
+               MIPS32_SW(2,36*4,1),                                                    /* sw $2,36*4($1) */
+               MIPS32_MFC0(2,24,0),                                                    /* move pc to $2 */
+               MIPS32_SW(2,37*4,1),                                                    /* sw $2,37*4($1) */
+               
+               MIPS32_LW(2,0,15),                                                              /* sw $2,($15) */
+               MIPS32_LW(1,0,15),                                                              /* sw $1,($15) */
+               MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
+               MIPS32_NOP,
+               MIPS32_B(NEG16(60)),                                                    /* b start */
+               MIPS32_NOP,
+       };
+       
+       int retval;
+       
+       retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               0, NULL, 38, regs, 1);
+       
+       return retval;
+}
diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h
new file mode 100644 (file)
index 0000000..5cda497
--- /dev/null
@@ -0,0 +1,55 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef MIPS32_PRACC_H
+#define MIPS32_PRACC_H
+
+#include "mips_ejtag.h"
+
+#define MIPS32_PRACC_TEXT                      0xFF200200
+#define MIPS32_PRACC_STACK                     0xFF2FFFFC
+#define MIPS32_PRACC_PARAM_IN          0xFF201000
+#define MIPS32_PRACC_PARAM_IN_SIZE     0x1000
+#define MIPS32_PRACC_PARAM_OUT         (MIPS32_PRACC_PARAM_IN + MIPS32_PRACC_PARAM_IN_SIZE)
+#define MIPS32_PRACC_PARAM_OUT_SIZE    0x1000
+
+#define UPPER16(u32) (u32 >> 16)
+#define LOWER16(u32) (u32 & 0xFFFF)
+#define NEG16(v) (((~(v)) + 1) & 0xFFFF)
+//#define NEG18(v) ( ((~(v)) + 1) & 0x3FFFF )
+
+extern int mips32_pracc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf);
+extern int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf);
+
+extern int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf);
+extern int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf);
+extern int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf);
+
+extern int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf);
+extern int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf);
+extern int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf);
+
+extern int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs);
+extern int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs);
+
+extern int mips32_pracc_exec( mips_ejtag_t *ejtag_info, int code_len, u32 *code, int num_param_in, u32 *param_in, int num_param_out, u32 *param_out, int cycle);
+
+#endif
diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c
new file mode 100644 (file)
index 0000000..d220368
--- /dev/null
@@ -0,0 +1,283 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mips32.h"
+#include "mips_ejtag.h"
+
+#include "binarybuffer.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+int mips_ejtag_set_instr(mips_ejtag_t *ejtag_info, int new_instr, in_handler_t handler)
+{
+       jtag_device_t *device = jtag_get_device(ejtag_info->chain_pos);
+       
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+               u8 t[4];
+               
+               field.device = ejtag_info->chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = t;
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = handler;
+               field.in_handler_priv = NULL;
+               jtag_add_ir_scan(1, &field, -1);
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_get_idcode(mips_ejtag_t *ejtag_info, u32 *idcode, in_handler_t handler)
+{
+       scan_field_t field;
+       
+       jtag_add_end_state(TAP_RTI);
+       
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE, NULL);
+       
+       field.device = ejtag_info->chain_pos;
+       field.num_bits = 32;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = (void*)idcode;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       jtag_add_dr_scan(1, &field, -1);
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               LOG_ERROR("register read failed");
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_get_impcode(mips_ejtag_t *ejtag_info, u32 *impcode, in_handler_t handler)
+{
+       scan_field_t field;
+       
+       jtag_add_end_state(TAP_RTI);
+       
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE, NULL);
+       
+       field.device = ejtag_info->chain_pos;
+       field.num_bits = 32;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = (void*)impcode;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       jtag_add_dr_scan(1, &field, -1);
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               LOG_ERROR("register read failed");
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_drscan_32(mips_ejtag_t *ejtag_info, u32 *data)
+{
+       jtag_device_t *device;
+       device = jtag_get_device(ejtag_info->chain_pos);
+       scan_field_t field;
+       u8 t[4];
+       int retval;
+       
+       field.device = ejtag_info->chain_pos;
+       field.num_bits = 32;
+       field.out_value = t;
+       buf_set_u32(field.out_value, 0, field.num_bits, *data);
+       field.out_mask = NULL;
+       field.in_value = (u8*)data;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       jtag_add_dr_scan(1, &field, -1);
+       
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               LOG_ERROR("register read failed");
+               return retval;
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_step_enable(mips_ejtag_t *ejtag_info)
+{      
+       u32 code[] = {
+                       MIPS32_MTC0(1,31,0),                    /* move $1 to COP0 DeSave */
+                       MIPS32_MFC0(1,23,0),                    /* move COP0 Debug to $1 */
+                       MIPS32_ORI(1,1,0x0100),                 /* set SSt bit in debug reg */
+                       MIPS32_MTC0(1,23,0),                    /* move $1 to COP0 Debug */
+                       MIPS32_MFC0(1,31,0),                    /* move COP0 DeSave to $1 */
+                       MIPS32_NOP,
+                       MIPS32_B(NEG16(7)),
+                       MIPS32_NOP,
+       };
+       
+       mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               0, NULL, 0, NULL, 1);
+       
+       return ERROR_OK;
+}
+int mips_ejtag_step_disable(mips_ejtag_t *ejtag_info)
+{
+       u32 code[] = {
+                       MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
+                       MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
+                       MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+                       MIPS32_SW(1,0,15),                                                              /* sw $2,($15) */
+                       MIPS32_SW(2,0,15),                                                              /* sw $3,($15) */
+                       MIPS32_MFC0(1,23,0),                                                    /* move COP0 Debug to $1 */
+                       MIPS32_LUI(2,0xFFFF),                                                   /* $2 = 0xfffffeff */
+                       MIPS32_ORI(2,2,0xFEFF),
+                       MIPS32_AND(1,1,2),
+                       MIPS32_MTC0(1,23,0),                                                    /* move $1 to COP0 Debug */
+                       MIPS32_LW(2,0,15),
+                       MIPS32_LW(1,0,15),
+                       MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
+                       MIPS32_NOP,
+                       MIPS32_B(NEG16(15)),
+                       MIPS32_NOP,
+       };
+       
+       mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               0, NULL, 0, NULL, 1);
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_config_step(mips_ejtag_t *ejtag_info, int enable_step)
+{      
+       if (enable_step)
+               return mips_ejtag_step_enable(ejtag_info);      
+       return mips_ejtag_step_disable(ejtag_info);
+}
+
+int mips_ejtag_enter_debug(mips_ejtag_t *ejtag_info)
+{
+       jtag_add_end_state(TAP_RTI);
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+       
+       /* set debug break bit */
+       ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV | EJTAG_CTRL_JTAGBRK;
+       mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
+       
+       /* break bit will be cleared by hardware */
+       ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
+       mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_exit_debug(mips_ejtag_t *ejtag_info, int enable_interrupts)
+{
+       u32 inst;
+       inst = MIPS32_DRET;
+       
+       /* TODO : enable/disable interrrupts */
+       
+       /* execute our dret instruction */
+       mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_read_debug(mips_ejtag_t *ejtag_info, u32* debug_reg)
+{
+       u32 code[] = {
+                       MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
+                       MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
+                       MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
+                       MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
+                       MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
+                       MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
+                       MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
+                       MIPS32_MFC0(2,23,0),                                                    /* move COP0 Debug to $1 */
+                       MIPS32_SW(2,0,1),
+                       MIPS32_LW(2,0,15),
+                       MIPS32_LW(1,0,15),
+                       MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
+                       MIPS32_NOP,
+                       MIPS32_B(NEG16(14)),
+                       MIPS32_NOP,
+       };
+       
+       mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
+               0, NULL, 1, debug_reg, 1);
+       
+       return ERROR_OK;
+}
+
+int mips_ejtag_init(mips_ejtag_t *ejtag_info)
+{
+       u32 ejtag_version;
+       
+       mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode, NULL);
+       LOG_DEBUG("impcode: 0x%8.8x", ejtag_info->impcode);
+       
+       /* get ejtag version */
+       ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
+       
+       switch (ejtag_version)
+       {
+               case 0:
+                       LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
+                       break;
+               case 1:
+                       LOG_DEBUG("EJTAG: Version 2.5 Detected");
+                       break;
+               case 2:
+                       LOG_DEBUG("EJTAG: Version 2.6 Detected");
+                       break;
+               case 3:
+                       LOG_DEBUG("EJTAG: Version 3.1 Detected");
+                       break;
+               default:
+                       LOG_DEBUG("EJTAG: Unknown Version Detected");
+                       break;
+       }
+       
+       /* set initial state for ejtag control reg */
+       ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
+       
+       return ERROR_OK;
+}
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
new file mode 100644 (file)
index 0000000..b25bd02
--- /dev/null
@@ -0,0 +1,107 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifndef MIPS_EJTAG
+#define MIPS_EJTAG
+
+#include "types.h"
+#include "jtag.h"
+
+#define EJTAG_INST_IDCODE              0x01
+#define EJTAG_INST_IMPCODE             0x03
+#define EJTAG_INST_ADDRESS             0x08
+#define EJTAG_INST_DATA                        0x09
+#define EJTAG_INST_CONTROL             0x0A
+#define EJTAG_INST_ALL                 0x0B
+#define EJTAG_INST_EJTAGBOOT   0x0C
+#define EJTAG_INST_NORMALBOOT  0x0D
+#define EJTAG_INST_FASTDATA            0x0E
+#define EJTAG_INST_TCBCONTROLA 0x10
+#define EJTAG_INST_TCBCONTROLB 0x11
+#define EJTAG_INST_TCBDATA             0x12
+#define EJTAG_INST_BYPASS              0x1F
+
+#define EJTAG_CTRL_TOF                 (1 << 1)
+#define EJTAG_CTRL_TIF                 (1 << 2)
+#define EJTAG_CTRL_BRKST               (1 << 3)
+#define EJTAG_CTRL_DLOCK               (1 << 5)
+#define EJTAG_CTRL_DRWN                        (1 << 9)
+#define EJTAG_CTRL_DERR                        (1 << 10)
+#define EJTAG_CTRL_DSTRT               (1 << 11)
+#define EJTAG_CTRL_JTAGBRK             (1 << 12)
+#define EJTAG_CTRL_SETDEV              (1 << 14)
+#define EJTAG_CTRL_PROBEN              (1 << 15)
+#define EJTAG_CTRL_PRRST               (1 << 16)
+#define EJTAG_CTRL_DMAACC              (1 << 17)
+#define EJTAG_CTRL_PRACC               (1 << 18)
+#define EJTAG_CTRL_PRNW                        (1 << 19)
+#define EJTAG_CTRL_PERRST              (1 << 20)
+#define EJTAG_CTRL_SYNC                        (1 << 23)
+#define EJTAG_CTRL_DNM                 (1 << 28)
+#define EJTAG_CTRL_ROCC                        (1 << 31)
+
+/* Debug Register (CP0 Register 23, Select 0) */
+
+#define EJTAG_DEBUG_DSS                        (1 << 0)
+#define EJTAG_DEBUG_DBP                        (1 << 1)
+#define EJTAG_DEBUG_DDBL               (1 << 2)
+#define EJTAG_DEBUG_DDBS               (1 << 3)
+#define EJTAG_DEBUG_DIB                        (1 << 4)
+#define EJTAG_DEBUG_DINT               (1 << 5)
+#define EJTAG_DEBUG_OFFLINE            (1 << 7)
+#define EJTAG_DEBUG_SST                        (1 << 8)
+#define EJTAG_DEBUG_NOSST              (1 << 9)
+#define EJTAG_DEBUG_DDBLIMPR   (1 << 18)
+#define EJTAG_DEBUG_DDBSIMPR   (1 << 19)
+#define EJTAG_DEBUG_IEXI               (1 << 20)
+#define EJTAG_DEBUG_DBUSEP             (1 << 21)
+#define EJTAG_DEBUG_CACHEEP            (1 << 22)
+#define EJTAG_DEBUG_MCHECKP            (1 << 23)
+#define EJTAG_DEBUG_IBUSEP             (1 << 24)
+#define EJTAG_DEBUG_COUNTDM            (1 << 25)
+#define EJTAG_DEBUG_HALT               (1 << 26)
+#define EJTAG_DEBUG_DOZE               (1 << 27)
+#define EJTAG_DEBUG_LSNM               (1 << 28)
+#define EJTAG_DEBUG_NODCR              (1 << 29)
+#define EJTAG_DEBUG_DM                 (1 << 30)
+#define EJTAG_DEBUG_DBD                        (1 << 31)
+
+typedef struct mips_ejtag_s
+{
+       int chain_pos;
+       u32 impcode;
+//     int use_dma;
+       u32 ejtag_ctrl;
+} mips_ejtag_t;
+
+extern int mips_ejtag_set_instr(mips_ejtag_t *ejtag_info, int new_instr, in_handler_t handler);
+extern int mips_ejtag_enter_debug(mips_ejtag_t *ejtag_info);
+extern int mips_ejtag_exit_debug(mips_ejtag_t *ejtag_info, int enable_interrupts);
+extern int mips_ejtag_get_impcode(mips_ejtag_t *ejtag_info, u32 *impcode, in_handler_t handler);
+extern int mips_ejtag_get_idcode(mips_ejtag_t *ejtag_info, u32 *idcode, in_handler_t handler);
+extern int mips_ejtag_drscan_32(mips_ejtag_t *ejtag_info, u32 *data);
+
+extern int mips_ejtag_init(mips_ejtag_t *ejtag_info);
+extern int mips_ejtag_config_step(mips_ejtag_t *ejtag_info, int enable_step);
+extern int mips_ejtag_read_debug(mips_ejtag_t *ejtag_info, u32* debug_reg);
+
+#endif /* MIPS_EJTAG */
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
new file mode 100644 (file)
index 0000000..8695a62
--- /dev/null
@@ -0,0 +1,642 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mips32.h"
+#include "mips_m4k.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* cli handling */
+
+/* forward declarations */
+int mips_m4k_poll(target_t *target);
+int mips_m4k_halt(struct target_s *target);
+int mips_m4k_soft_reset_halt(struct target_s *target);
+int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int mips_m4k_register_commands(struct command_context_s *cmd_ctx);
+int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int mips_m4k_quit();
+int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+
+int mips_m4k_examine(struct command_context_s *cmd_ctx, struct target_s *target);
+int mips_m4k_assert_reset(target_t *target);
+int mips_m4k_deassert_reset(target_t *target);
+
+target_type_t mips_m4k_target =
+{
+       .name = "mips_m4k",
+
+       .poll = mips_m4k_poll,
+       .arch_state = mips32_arch_state,
+
+       .target_request_data = NULL,
+
+       .halt = mips_m4k_halt,
+       .resume = mips_m4k_resume,
+       .step = mips_m4k_step,
+
+       .assert_reset = mips_m4k_assert_reset,
+       .deassert_reset = mips_m4k_deassert_reset,
+       .soft_reset_halt = mips_m4k_soft_reset_halt,
+       
+       .get_gdb_reg_list = mips32_get_gdb_reg_list,
+
+       .read_memory = mips_m4k_read_memory,
+       .write_memory = mips_m4k_write_memory,
+       .bulk_write_memory = mips_m4k_bulk_write_memory,
+       .checksum_memory = NULL,
+       .blank_check_memory = NULL,
+       
+       .run_algorithm = mips32_run_algorithm,
+
+       .add_breakpoint = mips_m4k_add_breakpoint,
+       .remove_breakpoint = mips_m4k_remove_breakpoint,
+       .add_watchpoint = mips_m4k_add_watchpoint,
+       .remove_watchpoint = mips_m4k_remove_watchpoint,
+
+       .register_commands = mips_m4k_register_commands,
+       .target_command = mips_m4k_target_command,
+       .init_target = mips_m4k_init_target,
+       .examine = mips_m4k_examine,
+       .quit = mips_m4k_quit
+};
+
+int mips_m4k_debug_entry(target_t *target)
+{
+       u32 debug_reg;
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       /* read debug register */
+       mips_ejtag_read_debug(ejtag_info, &debug_reg);
+       
+       if ((target->debug_reason != DBG_REASON_DBGRQ)
+               && (target->debug_reason != DBG_REASON_SINGLESTEP))
+       {
+//             if (cortex_m3->nvic_dfsr & DFSR_BKPT)
+//             {
+//                     target->debug_reason = DBG_REASON_BREAKPOINT;
+//                     if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
+//                             target->debug_reason = DBG_REASON_WPTANDBKPT;
+//             }
+//             else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
+//                     target->debug_reason = DBG_REASON_WATCHPOINT;
+       }
+       
+       if (debug_reg & EJTAG_DEBUG_DSS)
+       {
+               /* stopped due to single step - clear step bit */
+               mips_ejtag_config_step(ejtag_info, 0);
+       }
+       
+       mips32_save_context(target);
+       
+       LOG_DEBUG("entered debug state at PC 0x%x, target->state: %s", \
+               *(u32*)(mips32->core_cache->reg_list[MIPS32_PC].value), target_state_strings[target->state]);
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_poll(target_t *target)
+{
+       int retval;
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       /* read ejtag control reg */
+       jtag_add_end_state(TAP_RTI);
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+       mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
+       
+       if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_BRKST)
+       {
+               if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
+               {
+                       jtag_add_end_state(TAP_RTI);
+                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
+                       
+                       target->state = TARGET_HALTED;
+                       
+                       if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
+                               return retval;
+                       
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
+               else if (target->state == TARGET_DEBUG_RUNNING)
+               {
+                       target->state = TARGET_HALTED;
+                       
+                       if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
+                               return retval;
+                       
+                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+               }
+       }
+       else
+       {
+               target->state = TARGET_RUNNING;
+       }
+       
+       if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_ROCC)
+       {
+               /* we have detected a reset, clear flag
+                * otherwise ejtag will not work */
+               jtag_add_end_state(TAP_RTI);
+               ejtag_info->ejtag_ctrl &= ~EJTAG_CTRL_ROCC;
+               
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
+               mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
+               LOG_DEBUG("Reset Detected");
+       }
+       
+//     LOG_DEBUG("ctrl=0x%08X", ejtag_info->ejtag_ctrl);
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_halt(struct target_s *target)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       if (target->state == TARGET_HALTED)
+       {
+               LOG_DEBUG("target was already halted");
+               return ERROR_OK;
+       }
+       
+       if (target->state == TARGET_UNKNOWN)
+       {
+               LOG_WARNING("target was in unknown state when halt was requested");
+       }
+       
+       if (target->state == TARGET_RESET) 
+       {
+               if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
+               {
+                       LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
+                       return ERROR_TARGET_FAILURE;
+               }
+               else
+               {
+                       /* we came here in a reset_halt or reset_init sequence
+                        * debug entry was already prepared in mips32_prepare_reset_halt()
+                        */
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       
+                       return ERROR_OK;
+               }
+       }
+       
+       /* break processor */
+       mips_ejtag_enter_debug(ejtag_info);
+       
+       target->debug_reason = DBG_REASON_DBGRQ;
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_assert_reset(target_t *target)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       if (!(jtag_reset_config & RESET_HAS_SRST))
+       {
+               LOG_ERROR("Can't assert SRST");
+               return ERROR_FAIL;
+       }
+       
+       if (target->reset_halt)
+       {
+               /* use hardware to catch reset */
+               jtag_add_end_state(TAP_RTI);
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT, NULL);
+       }
+       else
+       {
+               jtag_add_end_state(TAP_RTI);
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
+       }
+       
+       /* here we should issue a srst only, but we may have to assert trst as well */
+       if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+       {
+               jtag_add_reset(1, 1);
+       }
+       else
+       {
+               jtag_add_reset(0, 1);
+       }
+       
+       target->state = TARGET_RESET;
+       jtag_add_sleep(50000);
+
+       mips32_invalidate_core_regs(target);
+
+       return ERROR_OK;
+}
+
+int mips_m4k_deassert_reset(target_t *target)
+{
+       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       /* deassert reset lines */
+       jtag_add_reset(0, 0);
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_soft_reset_halt(struct target_s *target)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       breakpoint_t *breakpoint = NULL;
+       u32 resume_pc;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       if (!debug_execution)
+       {
+               target_free_all_working_areas(target);
+               mips_m4k_enable_breakpoints(target);
+               mips_m4k_enable_watchpoints(target);
+       }
+       
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current) 
+       {
+               buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
+               mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
+               mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
+       }
+       
+       resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
+       
+       mips32_restore_context(target);
+       
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+       {
+               /* Single step past breakpoint at current address */
+               if ((breakpoint = breakpoint_find(target, resume_pc)))
+               {
+                       LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
+                       mips_m4k_unset_breakpoint(target, breakpoint);
+                       //mips_m4k_single_step_core(target);
+                       mips_m4k_set_breakpoint(target, breakpoint);
+               }
+       }
+       
+       /* exit debug mode - enable interrupts if required */
+       mips_ejtag_exit_debug(ejtag_info, !debug_execution);
+       
+       /* registers are now invalid */
+       mips32_invalidate_core_regs(target);
+       
+       if (!debug_execution)
+       {
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               LOG_DEBUG("target resumed at 0x%x", resume_pc);
+       }
+       else
+       {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+               LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+       /* get pointers to arch-specific information */
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       breakpoint_t *breakpoint = NULL;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+               buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
+       
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+               if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32))))
+                       mips_m4k_unset_breakpoint(target, breakpoint);
+       
+       /* restore context */
+       mips32_restore_context(target);
+       
+       /* configure single step mode */
+       mips_ejtag_config_step(ejtag_info, 1);
+       
+       target->debug_reason = DBG_REASON_SINGLESTEP;
+       
+       target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+       
+       /* exit debug mode */
+       mips_ejtag_exit_debug(ejtag_info, 1);
+       
+       /* registers are now invalid */
+       mips32_invalidate_core_regs(target);
+       
+       if (breakpoint)
+               mips_m4k_set_breakpoint(target, breakpoint);
+
+       LOG_DEBUG("target stepped ");
+       
+       mips_m4k_debug_entry(target);
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+       
+       return ERROR_OK;
+}
+
+void mips_m4k_enable_breakpoints(struct target_s *target)
+{
+       breakpoint_t *breakpoint = target->breakpoints;
+       
+       /* set any pending breakpoints */
+       while (breakpoint)
+       {
+               if (breakpoint->set == 0)
+                       mips_m4k_set_breakpoint(target, breakpoint);
+               breakpoint = breakpoint->next;
+       }
+}
+
+int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* TODO */
+       return ERROR_OK;
+}
+
+void mips_m4k_enable_watchpoints(struct target_s *target)
+{
+       watchpoint_t *watchpoint = target->watchpoints;
+       
+       /* set any pending watchpoints */
+       while (watchpoint)
+       {
+               if (watchpoint->set == 0)
+                       mips_m4k_set_watchpoint(target, watchpoint);
+               watchpoint = watchpoint->next;
+       }
+}
+
+int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       
+       switch (size)
+       {
+               case 4:
+               case 2:
+               case 1:
+                       return mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer);
+               default:
+                       LOG_ERROR("BUG: we shouldn't get here");
+                       exit(-1);
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       
+       LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       
+       switch (size)
+       {
+               case 4:
+               case 2:
+               case 1:
+                       mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
+                       break;
+               default:
+                       LOG_ERROR("BUG: we shouldn't get here");
+                       exit(-1);
+                       break;
+       }
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       
+       retval = mips32_register_commands(cmd_ctx);
+       return retval;
+}
+
+int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       mips32_build_reg_cache(target);
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_quit()
+{
+       return ERROR_OK;
+}
+
+int mips_m4k_init_arch_info(target_t *target, mips_m4k_common_t *mips_m4k, int chain_pos, char *variant)
+{
+       mips32_common_t *mips32 = &mips_m4k->mips32_common;
+       
+       if (variant)
+       {
+               mips_m4k->variant = strdup(variant);
+       }
+       else
+       {
+               mips_m4k->variant = strdup("");
+       }
+       
+       mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
+       
+       /* initialize mips4k specific info */
+       mips32_init_arch_info(target, mips32, chain_pos, variant);
+       mips32->arch_info = mips_m4k;
+               
+       return ERROR_OK;
+}
+
+int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       mips_m4k_common_t *mips_m4k = malloc(sizeof(mips_m4k_common_t));
+       
+       if (argc < 4)
+       {
+               LOG_ERROR("'target mips4k' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       mips_m4k_init_arch_info(target, mips_m4k, chain_pos, variant);
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_examine(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       int retval;
+       mips32_common_t *mips32 = target->arch_info;
+       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       u32 idcode = 0;
+       
+       target->type->examined = 1;
+       
+       mips_ejtag_get_idcode(ejtag_info, &idcode, NULL);
+       
+       if (((idcode >> 1) & 0x7FF) == 0x29)
+       {
+               /* we are using a pic32mx so select ejtag port
+                * as it is not selected by default */
+               mips_ejtag_set_instr(ejtag_info, 0x05, NULL);
+               LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
+       }
+       
+       /* init rest of ejtag interface */
+       if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK)
+               return retval;
+       
+       return ERROR_OK;
+}
+
+int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
+{
+       return mips_m4k_write_memory(target, address, 4, count, buffer);
+}
diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h
new file mode 100644 (file)
index 0000000..4f5d3bf
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by David T.L. Wong                                 *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifndef MIPS_M4K_H
+#define MIPS_M4K_H
+
+#include "register.h"
+#include "target.h"
+
+#define MIPSM4K_COMMON_MAGIC   0xB321B321
+
+typedef struct mips_m4k_common_s
+{
+       int common_magic;
+       mips32_common_t mips32_common;
+       
+       char *variant;
+} mips_m4k_common_t;
+
+extern int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
+
+extern void mips_m4k_enable_breakpoints(struct target_s *target);
+extern int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+extern int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+extern int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+extern int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+extern int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+extern int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+extern int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+extern int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+extern void mips_m4k_enable_watchpoints(struct target_s *target);
+
+#endif /*MIPS_M4K_H*/
index 3d0c4afdad9f300be50b36218e435702e97f109e..58a940bd7d6000cc290a069735d404783c15aa14 100644 (file)
@@ -92,6 +92,7 @@ extern target_type_t feroceon_target;
 extern target_type_t xscale_target;
 extern target_type_t cortexm3_target;
 extern target_type_t arm11_target;
+extern target_type_t mips_m4k_target;
 
 target_type_t *target_types[] =
 {
@@ -105,6 +106,7 @@ target_type_t *target_types[] =
        &xscale_target,
        &cortexm3_target,
        &arm11_target,
+       &mips_m4k_target,
        NULL,
 };
 
diff --git a/src/target/target/pic32mx.cfg b/src/target/target/pic32mx.cfg
new file mode 100644 (file)
index 0000000..25ef029
--- /dev/null
@@ -0,0 +1,22 @@
+jtag_nsrst_delay 100
+jtag_ntrst_delay 100
+
+#use combined on interfaces or targets that can't set TRST/SRST separately
+reset_config srst_only
+
+#jtag scan chain
+#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
+jtag_device 5 0x1 0x1 0x1e
+
+#target <type> <startup mode>
+#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
+target mips_m4k little 0
+run_and_halt_time 0 30
+
+working_area 0 0xa0000000 16384 nobackup
+
+#flash bank str7x <base> <size> 0 0 <target#> <variant>
+#flash bank stm32x 0 0 0 0 0
+
+# For more information about the configuration files, take a look at:
+# http://openfacts.berlios.de/index-en.phtml?title=Open+On-Chip+Debugger

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)