- 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