From: David B. <dbr...@us...> - 2009-12-12 00:27:22
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 75c706cc043183d98592dbe3c6f170d627849d0f (commit) via 838d41af29c0b703fd55ebb5c3aebcb4e0bea460 (commit) via cfd79e96a6436cea427245a2c2f18fd52001898b (commit) from 08589462adf3f81b480faacecb8352428212a2f5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 75c706cc043183d98592dbe3c6f170d627849d0f Author: David Brownell <dbr...@us...> Date: Fri Dec 11 15:26:10 2009 -0800 ARM DPM: support updating HW breakpoints Abstract the DPM breakpoint and watchpoint data structures to have a shared core for housekeeping. Abstract the code updating the watchpoint registers so that it can be used to update breakpoint registers. Then do so, when something has set up the breakpoint state used by this code. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index bd9c5d1..0908ca9 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -277,6 +277,51 @@ fail: return retval; } +/* Avoid needless I/O ... leave breakpoints and watchpoints alone + * unless they're removed, or need updating because of single-stepping + * or running debugger code. + */ +static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, + struct dpm_bpwp *xp, int *set_p) +{ + int retval = ERROR_OK; + bool disable; + + if (!set_p) { + if (!xp->dirty) + goto done; + xp->dirty = false; + /* removed or startup; we must disable it */ + disable = true; + } else if (bpwp) { + if (!xp->dirty) + goto done; + /* disabled, but we must set it */ + xp->dirty = disable = false; + *set_p = true; + } else { + if (!*set_p) + goto done; + /* set, but we must temporarily disable it */ + xp->dirty = disable = true; + *set_p = false; + } + + if (disable) + retval = dpm->bpwp_disable(dpm, xp->number); + else + retval = dpm->bpwp_enable(dpm, xp->number, + xp->address, xp->control); + + if (retval != ERROR_OK) + LOG_ERROR("%s: can't %s HW bp/wp %d", + disable ? "disable" : "enable", + target_name(dpm->arm->target), + xp->number); +done: + return retval; +} + /** * Writes all modified core registers for all processor modes. In normal * operation this is called on exit from halting debug state. @@ -296,47 +341,22 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) if (retval != ERROR_OK) goto done; + /* enable/disable hardware breakpoints */ + for (unsigned i = 0; i < dpm->nbp; i++) { + struct dpm_bp *dbp = dpm->dbp + i; + struct breakpoint *bp = dbp->bp; + + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, + bp ? &bp->set : NULL); + } + /* enable/disable watchpoints */ for (unsigned i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; - bool disable; - - /* Avoid needless I/O ... leave watchpoints alone - * unless they're removed, or need updating because - * of single-stepping or running debugger code. - */ - if (!wp) { - if (!dwp->dirty) - continue; - dwp->dirty = false; - /* removed or startup; we must disable it */ - disable = true; - } else if (bpwp) { - if (!dwp->dirty) - continue; - /* disabled, but we must set it */ - dwp->dirty = disable = false; - wp->set = true; - } else { - if (!wp->set) - continue; - /* set, but we must temporarily disable it */ - dwp->dirty = disable = true; - wp->set = false; - } - - if (disable) - retval = dpm->bpwp_disable(dpm, 16 + i); - else - retval = dpm->bpwp_enable(dpm, 16 + i, - wp->address & ~3, dwp->control); - if (retval != ERROR_OK) - LOG_ERROR("%s: can't %s HW watchpoint %d", - target_name(arm->target), - disable ? "disable" : "enable", - i); + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, + wp ? &wp->set : NULL); } /* NOTE: writes to breakpoint and watchpoint registers might @@ -696,8 +716,9 @@ static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index, */ dpm->dwp[index].wp = wp; - dpm->dwp[index].control = control; - dpm->dwp[index].dirty = true; + dpm->dwp[index].bpwp.address = addr & ~3; + dpm->dwp[index].bpwp.control = control; + dpm->dwp[index].bpwp.dirty = true; /* hardware is updated in write_dirty_registers() */ return ERROR_OK; @@ -731,7 +752,7 @@ static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp) for (unsigned i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; - dpm->dwp[i].dirty = true; + dpm->dwp[i].bpwp.dirty = true; /* hardware is updated in write_dirty_registers() */ retval = ERROR_OK; @@ -869,10 +890,14 @@ int arm_dpm_initialize(struct arm_dpm *dpm) if (dpm->bpwp_disable) { unsigned i; - for (i = 0; i < dpm->nbp; i++) + for (i = 0; i < dpm->nbp; i++) { + dpm->dbp[i].bpwp.number = i; (void) dpm->bpwp_disable(dpm, i); - for (i = 0; i < dpm->nwp; i++) + } + for (i = 0; i < dpm->nwp; i++) { + dpm->dwp[i].bpwp.number = 16 + i; (void) dpm->bpwp_disable(dpm, 16 + i); + } } else LOG_WARNING("%s: can't disable breakpoints and watchpoints", target_name(dpm->arm->target)); diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 135e3db..5d75ed4 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -31,24 +31,22 @@ * registers are compatible. */ -struct dpm_bp { - struct breakpoint *bp; - /* bp->address == breakpoint value register - * control == breakpoint control register - */ +struct dpm_bpwp { + unsigned number; + uint32_t address; uint32_t control; /* true if hardware state needs flushing */ bool dirty; }; +struct dpm_bp { + struct breakpoint *bp; + struct dpm_bpwp bpwp; +}; + struct dpm_wp { struct watchpoint *wp; - /* wp->address == watchpoint value register - * control == watchpoint control register - */ - uint32_t control; - /* true if hardware state needs flushing */ - bool dirty; + struct dpm_bpwp bpwp; }; /** commit 838d41af29c0b703fd55ebb5c3aebcb4e0bea460 Author: David Brownell <dbr...@us...> Date: Fri Dec 11 15:24:08 2009 -0800 ARM: disassembly fixes for LDC/STC/MRRC/MCRR Properly detect all of these, including the "2" variants; and bugfix parameter display for LDC and STC. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 5c8ad6a..770c5e9 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -288,8 +288,13 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, mnemonic = "MRRC"; } - snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i", - address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm); + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 + "\t%s%s%s p%i, %x, r%i, r%i, c%i", + address, opcode, mnemonic, + ((opcode & 0xf0000000) == 0xf0000000) + ? "2" : COND(opcode), + COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm); } else /* LDC or STC */ { @@ -300,7 +305,7 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, CRd = (opcode & 0xf000) >> 12; Rn = (opcode & 0xf0000) >> 16; - offset = (opcode & 0xff); + offset = (opcode & 0xff) << 2; /* load/store */ if (opcode & 0x00100000) @@ -318,19 +323,27 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, N = (opcode & 0x00400000) >> 22; /* addressing modes */ - if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */ - snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset); - else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */ - snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset); - else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */ - snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset); + if ((opcode & 0x01200000) == 0x01000000) /* offset */ + snprintf(addressing_mode, 32, "[r%i, #%s%d]", + Rn, U ? "" : "-", offset); + else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */ + snprintf(addressing_mode, 32, "[r%i, #%s%d]!", + Rn, U ? "" : "-", offset); + else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */ + snprintf(addressing_mode, 32, "[r%i], #%s%d", + Rn, U ? "" : "-", offset); else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */ - snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset); + snprintf(addressing_mode, 32, "[r%i], {%d}", + Rn, offset >> 2); - snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s", - address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2", - (N) ? "L" : "", - cp_num, CRd, addressing_mode); + snprintf(instruction->text, 128, "0x%8.8" PRIx32 + "\t0x%8.8" PRIx32 + "\t%s%s%s p%i, c%i, %s", + address, opcode, mnemonic, + ((opcode & 0xf0000000) == 0xf0000000) + ? "2" : COND(opcode), + (opcode & (1 << 22)) ? "L" : "", + cp_num, CRd, addressing_mode); } return ERROR_OK; @@ -1638,7 +1651,8 @@ static int evaluate_data_proc(uint32_t opcode, return ERROR_OK; } -int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) +int arm_evaluate_opcode(uint32_t opcode, uint32_t address, + struct arm_instruction *instruction) { /* clear fields, to avoid confusion */ memset(instruction, 0, sizeof(struct arm_instruction)); @@ -1760,7 +1774,7 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instructio } /* catch opcodes with [27:25] = b110 */ - if ((opcode & 0x0e000000) == 0x0a000000) + if ((opcode & 0x0e000000) == 0x0c000000) { /* Coprocessor load/store and double register transfers */ return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction); @@ -1782,7 +1796,8 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instructio return evaluate_cdp_mcr_mrc(opcode, address, instruction); } - LOG_ERROR("should never reach this point"); + LOG_ERROR("ARM: should never reach this point (opcode=%08x)", + (unsigned) opcode); return -1; } @@ -2796,7 +2811,7 @@ int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruct } } - LOG_ERROR("should never reach this point (opcode=%04x)",opcode); + LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode); return -1; } commit cfd79e96a6436cea427245a2c2f18fd52001898b Author: David Brownell <dbr...@us...> Date: Fri Dec 11 15:24:08 2009 -0800 ARM11: minor cleanup, mostly ITR comments ITR register handling seemed to be giving me problems, so I updated the comments to better say what the code is trying to do ... and to note the preconditions (one of which seems to be an issue) as listed in the ARM1136 TRM. Also removed the unused "ARM11_TAP_DEFAULT" from the ITR scan code; all the callers already specify an exit path, since this register isn't usable with such vague semantics. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm11.c b/src/target/arm11.c index 7b29f53..7c747c0 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -1012,27 +1012,25 @@ static int arm11_write_memory_inner(struct target *target, } case 4: { + /* increment: STC p14,c5,[R0],#4 */ + /* no increment: STC p14,c5,[R0]*/ uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00; /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t*)buffer; + /* "burst" here just means trusting each instruction executes + * fully before we run the next one: per-word roundtrips, to + * check the Ready flag, are not used. + */ if (!burst) - { - /* STC p14,c5,[R0],#4 */ - /* STC p14,c5,[R0]*/ - retval = arm11_run_instr_data_to_core(arm11, instr, words, count); - if (retval != ERROR_OK) - return retval; - } + retval = arm11_run_instr_data_to_core(arm11, + instr, words, count); else - { - /* STC p14,c5,[R0],#4 */ - /* STC p14,c5,[R0]*/ - retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count); - if (retval != ERROR_OK) - return retval; - } + retval = arm11_run_instr_data_to_core_noack(arm11, + instr, words, count); + if (retval != ERROR_OK) + return retval; break; } @@ -1309,7 +1307,7 @@ static const struct command_registration arm11_mw_command_handlers[] = { .name = "burst", .handler = &arm11_handle_bool_memwrite_burst, .mode = COMMAND_ANY, - .help = "Enable/Disable non-standard but fast burst mode" + .help = "Enable/Disable potentially risky fast burst mode" " (default: enabled)", }, { diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index 9ad5662..554d6e2 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -230,22 +230,23 @@ int arm11_add_debug_SCAN_N(struct arm11_common *arm11, return jtag_execute_queue(); } -/** Write an instruction into the ITR register +/** + * Queue a DR scan of the ITR register. Caller must have selected + * scan chain 4 (ITR), possibly using ITRSEL. * * \param arm11 Target state variable. * \param inst An ARM11 processor instruction/opcode. - * \param flag Optional parameter to retrieve the InstCompl flag - * (this will be written when the JTAG chain is executed). - * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default - * value (Run-Test/Idle). + * \param flag Optional parameter to retrieve the Ready flag; + * this address will be written when the JTAG chain is scanned. + * \param state The TAP state to enter after the DR scan. * - * \remarks By default this ends with Run-Test/Idle state - * and causes the instruction to be executed. If - * a subsequent write to DTR is needed before - * executing the instruction then TAP_DRPAUSE should be - * passed to \p state. + * Going through the TAP_DRUPDATE state writes ITR only if Ready was + * previously set. Only the Ready flag is readable by the scan. * - * \remarks This adds to the JTAG command queue but does \em not execute it. + * An instruction loaded into ITR is executed when going through the + * TAP_IDLE state only if Ready was previously set and the debug state + * is properly set up. Depending on the instruction, you may also need + * to ensure that the rDTR is ready before that Run-Test/Idle state. */ static void arm11_add_debug_INST(struct arm11_common * arm11, uint32_t inst, uint8_t * flag, tap_state_t state) @@ -257,7 +258,7 @@ static void arm11_add_debug_INST(struct arm11_common * arm11, arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); - arm11_add_dr_scan_vc(ARRAY_SIZE(itr), itr, state == ARM11_TAP_DEFAULT ? TAP_IDLE : state); + arm11_add_dr_scan_vc(ARRAY_SIZE(itr), itr, state); } /** @@ -374,7 +375,11 @@ int arm11_run_instr_data_finish(struct arm11_common * arm11) -/** Execute one or multiple instructions via ITR +/** + * Execute one or more instructions via ITR. + * Caller guarantees that processor is in debug state, that DSCR_ITR_EN + * is set, the ITR Ready flag is set (as seen on the previous entry to + * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * @@ -444,6 +449,10 @@ int arm11_run_instr_no_data1(struct arm11_common * arm11, uint32_t opcode) /** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * + * Caller guarantees that processor is in debug state, that DSCR_ITR_EN + * is set, the ITR Ready flag is set (as seen on the previous entry to + * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. + * * The executed instruction \em must read data from DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block @@ -570,6 +579,10 @@ static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = /** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * + * Caller guarantees that processor is in debug state, that DSCR_ITR_EN + * is set, the ITR Ready flag is set (as seen on the previous entry to + * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. + * * No Ready check during transmission. * * The executed instruction \em must read data from DTR. @@ -678,6 +691,10 @@ int arm11_run_instr_data_to_core1(struct arm11_common * arm11, uint32_t opcode, /** Execute one instruction via ITR repeatedly while * reading data from the core via DTR on each execution. * + * Caller guarantees that processor is in debug state, that DSCR_ITR_EN + * is set, the ITR Ready flag is set (as seen on the previous entry to + * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. + * * The executed instruction \em must write data to DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block ----------------------------------------------------------------------- Summary of changes: src/target/arm11.c | 28 +++++------ src/target/arm11_dbgtap.c | 43 +++++++++++----- src/target/arm_disassembler.c | 51 +++++++++++++------- src/target/arm_dpm.c | 107 +++++++++++++++++++++++++---------------- src/target/arm_dpm.h | 20 ++++---- 5 files changed, 151 insertions(+), 98 deletions(-) hooks/post-receive -- Main OpenOCD repository |