Commit e3205881 authored by Salvador Arroyo's avatar Salvador Arroyo Committed by Freddie Chopin
Browse files

mips32, add option to avoid check in last instruction



This option is needed, for example, when exiting
debug mode in bmips targets. The last instruction
is a NOP, not a DERET. When working in async mode
this check is not done, mips32_pracc_queue_exec() pass
the parameter to mips32_pracc_exec() and never use it.

Change-Id: I4c7ed4feb1588b62e2645b955b501b6671113b36
Signed-off-by: default avatarSalvador Arroyo <sarroyofdez@yahoo.es>
Reviewed-on: http://openocd.zylin.com/4021


Tested-by: jenkins
Reviewed-by: default avatarFreddie Chopin <freddie.chopin@gmail.com>
parent 1392c27c
......@@ -159,7 +159,8 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
return ERROR_OK;
}
int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out)
int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
uint32_t *param_out, bool check_last)
{
int code_count = 0;
int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */
......@@ -289,7 +290,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
/* finish processor access, let the processor eat! */
mips32_pracc_finish(ejtag_info);
if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */
if (final_check && !check_last) /* last instr, don't check, execute and exit */
return jtag_execute_queue();
if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */
......@@ -346,7 +347,8 @@ inline void pracc_queue_free(struct pracc_queue_info *ctx)
free(ctx->pracc_list);
}
int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf)
int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
uint32_t *buf, bool check_last)
{
if (ctx->retval != ERROR_OK) {
LOG_ERROR("Out of memory");
......@@ -354,7 +356,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in
}
if (ejtag_info->mode == 0)
return mips32_pracc_exec(ejtag_info, ctx, buf);
return mips32_pracc_exec(ejtag_info, ctx, buf, check_last);
union scan_in {
uint8_t scan_96[12];
......@@ -459,7 +461,7 @@ int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1);
pracc_queue_free(&ctx);
return ctx.retval;
}
......@@ -491,40 +493,40 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size
int this_round_count = (count > 256) ? 256 : count;
uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */
for (int i = 0; i != this_round_count; i++) { /* Main code loop */
uint32_t upper_base_addr = UPPER16((addr + 0x8000));
if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */
if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */
pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr));
last_upper_base_addr = upper_base_addr;
}
if (size == 4)
pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */
pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */
else if (size == 2)
pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9));
else
pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9));
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,
MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */
MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */
addr += size;
}
pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
if (size == 4) {
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1);
if (ctx.retval != ERROR_OK)
goto exit;
buf32 += this_round_count;
} else {
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data, 1);
if (ctx.retval != ERROR_OK)
goto exit;
......@@ -550,16 +552,16 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r
struct pracc_queue_info ctx;
pracc_queue_init(&ctx);
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
pracc_queue_free(&ctx);
return ctx.retval;
}
......@@ -575,7 +577,7 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
pracc_queue_free(&ctx);
return ctx.retval;
}
......@@ -616,19 +618,19 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
/** Find cache line size in bytes */
uint32_t clsiz;
if (rel) { /* Release 2 (rel = 1) */
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1);
if (ctx.retval != ERROR_OK)
goto exit;
......@@ -689,7 +691,7 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
if (ctx.retval != ERROR_OK)
goto exit;
......@@ -701,7 +703,7 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
exit:
pracc_queue_free(&ctx);
return ctx.retval;
......@@ -755,7 +757,7 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
if (ctx.retval != ERROR_OK)
goto exit;
count -= this_round_count;
......@@ -847,7 +849,7 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
ejtag_info->reg8 = regs[8];
ejtag_info->reg9 = regs[9];
......@@ -889,7 +891,7 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1);
ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
ejtag_info->reg9 = regs[9];
......
......@@ -61,7 +61,7 @@ void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr);
void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize);
void pracc_queue_free(struct pracc_queue_info *ctx);
int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info,
struct pracc_queue_info *ctx, uint32_t *buf);
struct pracc_queue_info *ctx, uint32_t *buf, bool check_last);
int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info,
uint32_t addr, int size, int count, void *buf);
......@@ -73,7 +73,8 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out);
int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
uint32_t *param_out, bool check_last);
/**
* \b mips32_cp0_read
......
......@@ -210,7 +210,7 @@ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
pracc_queue_free(&ctx);
return ctx.retval;
}
......@@ -273,7 +273,7 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0};
/* execute our dret instruction */
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0);
/* pic32mx workaround, false pending at low core clock */
jtag_add_sleep(1000);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment