X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fmips_m4k.c;h=2a64372f72679ac513ab319570cdae28c8e142cc;hp=03c996941e0c54e8381cda7a151575bf4e85707a;hb=4668bd264cfe64c3e3ddd0f75cb5bf2e5e85f717;hpb=524d79ebe74e28d751c88e665aabac2ea4d04e5c diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 03c996941e..2a64372f72 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -6,6 +6,9 @@ * * * Copyright (C) 2009 by David N. Claffey * * * + * Copyright (C) 2011 by Drasko DRASKOVIC * + * drasko.draskovic@gmail.com * + * * * 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 * @@ -616,6 +619,14 @@ static int mips_m4k_unset_breakpoint(struct target *target, { return retval; } + + /** + * target_read_memory() gets us data in _target_ endianess. + * If we want to use this data on the host for comparisons with some macros + * we must first transform it to _host_ endianess using target_buffer_get_u32(). + */ + current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); + if (current_instr == MIPS32_SDBBP) { if ((retval = target_write_memory(target, breakpoint->address, 4, 1, @@ -635,7 +646,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, { return retval; } - + current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); if (current_instr == MIPS16_SDBBP) { if ((retval = target_write_memory(target, breakpoint->address, 2, 1, @@ -854,40 +865,54 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address, /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; + /* since we don't know if buffer is aligned, we allocate new mem that is always aligned */ + void *t = NULL; + + if (size > 1) + { + t = malloc(count * size * sizeof(uint8_t)); + if (t == NULL) + { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + } + else + { + t = buffer; + } + /* if noDMA off, use DMAACC mode for memory read */ int retval; if (ejtag_info->impcode & EJTAG_IMP_NODMA) - retval = mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer); + retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t); else - retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, (void *)buffer); - if (ERROR_OK != retval) - return retval; + retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, t); /* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */ /* endianness, but byte array should represent target endianness */ - uint32_t i, t32; - uint16_t t16; - for(i = 0; i < (count*size); i += size) + if (ERROR_OK == retval) { switch(size) { case 4: - t32 = *(uint32_t*)&buffer[i]; - target_buffer_set_u32(target,&buffer[i], t32); + target_buffer_set_u32_array(target,buffer,count,t); break; case 2: - t16 = *(uint16_t*)&buffer[i]; - target_buffer_set_u16(target,&buffer[i], t16); + target_buffer_set_u16_array(target,buffer,count,t); break; } } - return ERROR_OK; + if ((size > 1) && (t != NULL)) + free(t); + + return retval; } static int mips_m4k_write_memory(struct target *target, uint32_t address, @@ -907,38 +932,35 @@ static int mips_m4k_write_memory(struct target *target, uint32_t address, /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; - /* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */ - /* endianness, but byte array represents target endianness */ - uint8_t * t = NULL; - t = malloc(count * sizeof(uint32_t)); - if (t == NULL) + /** correct endianess if we have word or hword access */ + void *t = NULL; + if (size > 1) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } + /* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */ + /* endianness, but byte array represents target endianness */ + t = malloc(count * size * sizeof(uint8_t)); + if (t == NULL) + { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } - uint32_t i, t32; - uint16_t t16; - for(i = 0; i < (count*size); i += size) - { switch(size) { case 4: - t32 = target_buffer_get_u32(target,&buffer[i]); - *(uint32_t*)&t[i] = t32; + target_buffer_get_u32_array(target,buffer,count,(uint32_t*)t); break; case 2: - t16 = target_buffer_get_u16(target,&buffer[i]); - *(uint16_t*)&t[i] = t16; + target_buffer_get_u16_array(target,buffer,count,(uint16_t*)t); break; } + buffer = t; } - buffer = t; /* if noDMA off, use DMAACC mode for memory write */ int retval; @@ -1062,7 +1084,7 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */ /* but byte array represents target endianness */ - uint8_t * t = NULL; + uint32_t *t = NULL; t = malloc(count * sizeof(uint32_t)); if (t == NULL) { @@ -1070,15 +1092,10 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, return ERROR_FAIL; } - uint32_t i, t32; - for(i = 0; i < (count*4); i += 4) - { - t32 = target_buffer_get_u32(target,&buffer[i]); - *(uint32_t*)&t[i] = t32; - } - + target_buffer_get_u32_array(target,buffer,count,t); + retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, - count, (uint32_t*) (void *)t); + count, t); if (t != NULL) free(t); @@ -1093,6 +1110,106 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, return retval; } +static int mips_m4k_verify_pointer(struct command_context *cmd_ctx, + struct mips_m4k_common *mips_m4k) +{ + if (mips_m4k->common_magic != MIPSM4K_COMMON_MAGIC) { + command_print(cmd_ctx, "target is not an MIPS_M4K"); + return ERROR_TARGET_INVALID; + } + return ERROR_OK; +} + +COMMAND_HANDLER(mips_m4k_handle_cp0_command) +{ + int retval; + struct target *target = get_current_target(CMD_CTX); + struct mips_m4k_common *mips_m4k = target_to_m4k(target); + struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; + + retval = mips_m4k_verify_pointer(CMD_CTX, mips_m4k); + if (retval != ERROR_OK) + return retval; + + if (target->state != TARGET_HALTED) + { + command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); + return ERROR_OK; + } + + /* two or more argument, access a single register/select (write if third argument is given) */ + if (CMD_ARGC < 2) + { + command_print(CMD_CTX, "command requires more arguments."); + } + else + { + uint32_t cp0_reg, cp0_sel; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); + + if (CMD_ARGC == 2) + { + uint32_t value; + + if ((retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel)) != ERROR_OK) + { + command_print(CMD_CTX, + "couldn't access reg %" PRIi32, + cp0_reg); + return ERROR_OK; + } + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + return retval; + } + + command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, + cp0_reg, cp0_sel, value); + } + else if (CMD_ARGC == 3) + { + uint32_t value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); + if ((retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel)) != ERROR_OK) + { + command_print(CMD_CTX, + "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32, + cp0_reg, cp0_sel); + return ERROR_OK; + } + command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32, + cp0_reg, cp0_sel, value); + } + } + + return ERROR_OK; +} + +static const struct command_registration mips_m4k_exec_command_handlers[] = { + { + .name = "cp0", + .handler = mips_m4k_handle_cp0_command, + .mode = COMMAND_EXEC, + .usage = "regnum [value]", + .help = "display/modify cp0 register", + }, + COMMAND_REGISTRATION_DONE +}; + +const struct command_registration mips_m4k_command_handlers[] = { + { + .chain = mips32_command_handlers, + }, + { + .name = "mips_m4k", + .mode = COMMAND_ANY, + .help = "mips_m4k command group", + .chain = mips_m4k_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + struct target_type mips_m4k_target = { .name = "mips_m4k", @@ -1125,6 +1242,7 @@ struct target_type mips_m4k_target = .add_watchpoint = mips_m4k_add_watchpoint, .remove_watchpoint = mips_m4k_remove_watchpoint, + .commands = mips_m4k_command_handlers, .target_create = mips_m4k_target_create, .init_target = mips_m4k_init_target, .examine = mips_m4k_examine,