mips32: add micromips isa handling
[openocd.git] / src / target / mips_m4k.c
index 4774c49c9fc2dffce95f7d35051e21ebcc706406..7ab30fe0ea983d7abc570e049b1b58fae8e5603b 100644 (file)
@@ -20,9 +20,7 @@
  *   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.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -43,10 +41,10 @@ static int mips_m4k_set_breakpoint(struct target *target,
 static int mips_m4k_unset_breakpoint(struct target *target,
                struct breakpoint *breakpoint);
 static int mips_m4k_internal_restore(struct target *target, int current,
-               uint32_t address, int handle_breakpoints,
+               target_addr_t address, int handle_breakpoints,
                int debug_execution);
 static int mips_m4k_halt(struct target *target);
-static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
+static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
                uint32_t count, const uint8_t *buffer);
 
 static int mips_m4k_examine_debug_reason(struct target *target)
@@ -110,11 +108,14 @@ static int mips_m4k_debug_entry(struct target *target)
        /* attempt to find halt reason */
        mips_m4k_examine_debug_reason(target);
 
+       mips32_read_config_regs(target);
+
        /* default to mips32 isa, it will be changed below if required */
        mips32->isa_mode = MIPS32_ISA_MIPS32;
 
-       if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
-               mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1);
+       /* other than mips32 only and isa bit set ? */
+       if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1))
+               mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32;
 
        LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
                        buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
@@ -197,6 +198,8 @@ static int mips_m4k_poll(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
+       ejtag_info->isa = (ejtag_ctrl & EJTAG_CTRL_DBGISA) ? 1 : 0;
+
        /* clear this bit before handling polling
         * as after reset registers will read zero */
        if (ejtag_ctrl & EJTAG_CTRL_ROCC) {
@@ -302,6 +305,13 @@ static int mips_m4k_assert_reset(struct target *target)
        struct mips_m4k_common *mips_m4k = target_to_m4k(target);
        struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
 
+       /* TODO: apply hw reset signal in not examined state */
+       if (!(target_was_examined(target))) {
+               LOG_WARNING("Reset is not asserted because the target is not examined.");
+               LOG_WARNING("Use a reset button or power cycle the target.");
+               return ERROR_TARGET_NOT_EXAMINED;
+       }
+
        LOG_DEBUG("target->state: %s",
                target_state_name(target));
 
@@ -318,11 +328,15 @@ static int mips_m4k_assert_reset(struct target *target)
                srst_asserted = true;
        }
 
-       if (target->reset_halt) {
-               /* use hardware to catch reset */
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
-       } else
-               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
+
+       /* EJTAG before v2.5/2.6 does not support EJTAGBOOT or NORMALBOOT */
+       if (ejtag_info->ejtag_version != EJTAG_VERSION_20) {
+               if (target->reset_halt) {
+                       /* use hardware to catch reset */
+                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
+               } else
+                       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
+       }
 
        if (jtag_reset_config & RESET_HAS_SRST) {
                /* here we should issue a srst only, but we may have to assert trst as well */
@@ -420,7 +434,7 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
 }
 
 static int mips_m4k_internal_restore(struct target *target, int current,
-               uint32_t address, int handle_breakpoints, int debug_execution)
+               target_addr_t address, int handle_breakpoints, int debug_execution)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -440,12 +454,13 @@ static int mips_m4k_internal_restore(struct target *target, int current,
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current) {
+               mips_m4k_isa_filter(mips32->isa_imp, &address);
                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;
        }
 
-       if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
+       if ((mips32->isa_imp > 1) &&  debug_execution)  /* if more than one isa supported */
                buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
 
        if (!current)
@@ -460,7 +475,8 @@ static int mips_m4k_internal_restore(struct target *target, int current,
                /* Single step past breakpoint at current address */
                breakpoint = breakpoint_find(target, resume_pc);
                if (breakpoint) {
-                       LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
+                       LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT "",
+                                         breakpoint->address);
                        mips_m4k_unset_breakpoint(target, breakpoint);
                        mips_m4k_single_step_core(target);
                        mips_m4k_set_breakpoint(target, breakpoint);
@@ -491,7 +507,7 @@ static int mips_m4k_internal_restore(struct target *target, int current,
 }
 
 static int mips_m4k_resume(struct target *target, int current,
-               uint32_t address, int handle_breakpoints, int debug_execution)
+               target_addr_t address, int handle_breakpoints, int debug_execution)
 {
        int retval = ERROR_OK;
 
@@ -518,7 +534,7 @@ static int mips_m4k_resume(struct target *target, int current,
 }
 
 static int mips_m4k_step(struct target *target, int current,
-               uint32_t address, int handle_breakpoints)
+               target_addr_t address, int handle_breakpoints)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -532,6 +548,7 @@ static int mips_m4k_step(struct target *target, int current,
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current) {
+               mips_m4k_isa_filter(mips32->isa_imp, &address);
                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;
@@ -638,15 +655,15 @@ static int mips_m4k_set_breakpoint(struct target *target,
                                        breakpoint->orig_instr);
                        if (retval != ERROR_OK)
                                return retval;
-                       retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP);
+                       retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa));
                        if (retval != ERROR_OK)
                                return retval;
 
                        retval = target_read_u32(target, breakpoint->address, &verify);
                        if (retval != ERROR_OK)
                                return retval;
-                       if (verify != MIPS32_SDBBP) {
-                               LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32
+                       if (verify != MIPS32_SDBBP(ejtag_info->isa)) {
+                               LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT
                                                " - check that memory is read/writable", breakpoint->address);
                                return ERROR_OK;
                        }
@@ -657,15 +674,15 @@ static int mips_m4k_set_breakpoint(struct target *target,
                                        breakpoint->orig_instr);
                        if (retval != ERROR_OK)
                                return retval;
-                       retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP);
+                       retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa));
                        if (retval != ERROR_OK)
                                return retval;
 
                        retval = target_read_u16(target, breakpoint->address, &verify);
                        if (retval != ERROR_OK)
                                return retval;
-                       if (verify != MIPS16_SDBBP) {
-                               LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32
+                       if (verify != MIPS16_SDBBP(ejtag_info->isa)) {
+                               LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT
                                                " - check that memory is read/writable", breakpoint->address);
                                return ERROR_OK;
                        }
@@ -725,7 +742,7 @@ static int mips_m4k_unset_breakpoint(struct target *target,
                         */
                        current_instr = target_buffer_get_u32(target, (uint8_t *)&current_instr);
 
-                       if (current_instr == MIPS32_SDBBP) {
+                       if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) {
                                retval = target_write_memory(target, breakpoint->address, 4, 1,
                                                breakpoint->orig_instr);
                                if (retval != ERROR_OK)
@@ -740,7 +757,7 @@ static int mips_m4k_unset_breakpoint(struct target *target,
                        if (retval != ERROR_OK)
                                return retval;
                        current_instr = target_buffer_get_u16(target, (uint8_t *)&current_instr);
-                       if (current_instr == MIPS16_SDBBP) {
+                       if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) {
                                retval = target_write_memory(target, breakpoint->address, 2, 1,
                                                breakpoint->orig_instr);
                                if (retval != ERROR_OK)
@@ -940,13 +957,13 @@ static void mips_m4k_enable_watchpoints(struct target *target)
        }
 }
 
-static int mips_m4k_read_memory(struct target *target, uint32_t address,
+static int mips_m4k_read_memory(struct target *target, target_addr_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
                        address, size, count);
 
        if (target->state != TARGET_HALTED) {
@@ -999,13 +1016,13 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address,
        return retval;
 }
 
-static int mips_m4k_write_memory(struct target *target, uint32_t address,
+static int mips_m4k_write_memory(struct target *target, target_addr_t address,
                uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
                        address, size, count);
 
        if (target->state != TARGET_HALTED) {
@@ -1130,7 +1147,7 @@ static int mips_m4k_examine(struct target *target)
        return ERROR_OK;
 }
 
-static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
+static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
                uint32_t count, const uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -1139,7 +1156,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
        int retval;
        int write_t = 1;
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "",
+                         address, count);
 
        /* check alignment */
        if (address & 0x3u)
@@ -1166,8 +1184,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
 
        if (address <= fast_data_area->address + fast_data_area->size &&
                        fast_data_area->address <= address + count) {
-               LOG_ERROR("fast_data (0x%8.8" PRIx32 ") is within write area "
-                         "(0x%8.8" PRIx32 "-0x%8.8" PRIx32 ").",
+               LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area "
+                         "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
                          fast_data_area->address, address, address + count);
                LOG_ERROR("Change work-area-phys or load_image address!");
                return ERROR_FAIL;
@@ -1330,7 +1348,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command)
                        return ERROR_COMMAND_SYNTAX_ERROR;
 
        command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
-       if (ejtag_info->scan_delay >= 20000000) {
+       if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {
                ejtag_info->mode = 0;
                command_print(CMD_CTX, "running in legacy mode");
        } else {

Linking to existing account procedure

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

SSH host keys fingerprints

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