This is an automated email from Gerrit. Salvador Arroyo ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/956
-- gerrit commit 960fe1b5f005ee09ebdef85517176de715ce64ec Author: Salvador Arroyo <[email protected]> Date: Fri Nov 2 16:08:31 2012 +0100 mips: optimize write code for speed All the writes are done by the new function mips32_pracc_write_mem_generic(). The code is similar to the read generic code. The reuse of register 15 as memory base address saves 3 pracc accesses. The first write takes 13(12) pracc accesses and for additional writes 3(2). Loading miniprograms should take 25% less time and loading fastdata transfer handler code should be over 2x faster. Change-Id: Ia3b24ba084af33be99da19f00a7fd4d1b291f350 Signed-off-by: Salvador Arroyo <[email protected]> diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index e97737c..ed949f3 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -93,18 +93,6 @@ struct mips32_pracc_context { struct mips_ejtag *ejtag_info; }; -static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, - uint32_t addr, uint32_t *buf); - -static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, - uint32_t addr, int count, uint8_t *buf); -static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, - uint32_t addr, int count, uint16_t *buf); -static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, - uint32_t addr, int count, uint32_t *buf); -static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, - uint32_t addr, uint32_t *buf); - static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr); static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info, @@ -286,6 +274,26 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_ return ERROR_OK; } +static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) +{ + uint32_t code[] = { + /* start: */ + MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */ + MIPS32_SW(8, PRACC_STACK_OFFSET, 15), /* sw $8,PRACC_STACK_OFFSET($15) */ + + MIPS32_LUI(8, UPPER16((addr + 0x8000))), /* load $8 with modified upper address */ + MIPS32_LW(8, LOWER16(addr), 8), /* lw $8, LOWER16(addr)($8) */ + MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */ + + MIPS32_LW(8, PRACC_STACK_OFFSET, 15), /* lw $8,PRACC_STACK_OFFSET($15) */ + MIPS32_B(NEG16(8)), /* b start */ + MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ + }; + + return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, buf, 1); +} + int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { if (count == 1 && size == 4) @@ -382,26 +390,6 @@ exit: return retval; } -static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) -{ - uint32_t code[] = { - /* start: */ - MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */ - MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), /* $15 = MIPS32_PRACC_BASE_ADDR */ - MIPS32_SW(8, PRACC_STACK_OFFSET, 15), /* sw $8,PRACC_STACK_OFFSET($15) */ - - MIPS32_LUI(8, UPPER16((addr + 0x8000))), /* load $8 with modified upper address */ - MIPS32_LW(8, LOWER16(addr), 8), /* lw $8, LOWER16(addr)($8) */ - MIPS32_SW(8, PRACC_OUT_OFFSET, 15), /* sw $8,PRACC_OUT_OFFSET($15) */ - - MIPS32_LW(8, PRACC_STACK_OFFSET, 15), /* lw $8,PRACC_STACK_OFFSET($15) */ - MIPS32_B(NEG16(8)), /* b start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ - }; - - return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, buf, 1); -} - int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel) { /** @@ -614,27 +602,106 @@ static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info, return retval; } +static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) +{ + uint32_t *code; + code = malloc((128 * 3 + 9) * sizeof(uint32_t)); /* alloc memory for the worst case */ + if (code == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + uint32_t *buf32 = buf; + uint16_t *buf16 = buf; + uint8_t *buf8 = buf; + + int i; + int retval = ERROR_FAIL; + uint32_t *code_p; + uint32_t upper_base_addr, last_upper_base_addr; + int this_round_count; + int code_len; + + while (count) { + this_round_count = (count > 128) ? 128 : count; + last_upper_base_addr = UPPER16((addr + 0x8000)); + code_p = code; + + *code_p++ = MIPS32_MTC0(15, 31, 0); /* save $15 in DeSave */ + *code_p++ = MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR); /* $15 = MIPS32_PRACC_BASE_ADDR */ + *code_p++ = MIPS32_SW(8, PRACC_STACK_OFFSET, 15); /* save $8 to pracc stack */ + *code_p++ = MIPS32_LUI(15, last_upper_base_addr); /* reuse $15 as memory base address */ + code_len = 4; + + for (i = 0; i != this_round_count; i++) { + upper_base_addr = UPPER16((addr + 0x8000)); + if (last_upper_base_addr != upper_base_addr) { + *code_p++ = MIPS32_LUI(15, upper_base_addr); /* if needed, change upper address in $15*/ + code_len++; + last_upper_base_addr = upper_base_addr; + } + + if (size == 4) { /* for word write check if one half word is 0 and load it accordingly */ + if (LOWER16(*buf32) == 0) { + *code_p++ = MIPS32_LUI(8, UPPER16(*buf32)); /* load only upper value */ + code_len++; + } else if (UPPER16(*buf32) == 0) { + *code_p++ = MIPS32_ORI(8, 0, LOWER16(*buf32)); /* load only lower value */ + code_len++; + } else { + *code_p++ = MIPS32_LUI(8, UPPER16(*buf32)); /* load upper and lower */ + *code_p++ = MIPS32_ORI(8, 8, LOWER16(*buf32)); + code_len += 2; + } + *code_p++ = MIPS32_SW(8, LOWER16(addr), 15); /* store word to memory */ + code_len++; + buf32++; + + } else if (size == 2) { + *code_p++ = MIPS32_ORI(8, 0, *buf16); /* load lower value */ + *code_p++ = MIPS32_SH(8, LOWER16(addr), 15); /* store half word to memory */ + code_len += 2; + buf16++; + + } else { + *code_p++ = MIPS32_ORI(8, 0, *buf8); /* load lower value */ + *code_p++ = MIPS32_SB(8, LOWER16(addr), 15); /* store byte to memory */ + code_len += 2; + buf8++; + } + + addr += size; + } + + *code_p++ = MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR); /* $15 = MIPS32_PRACC_BASE_ADDR */ + *code_p++ = MIPS32_LW(8, PRACC_STACK_OFFSET, 15); /* restore $8 from pracc stack */ + + code_len += 3; + *code_p++ = MIPS32_B(NEG16(code_len)); /* jump to start */ + *code_p = MIPS32_MFC0(15, 31, 0); /* restore $15 from DeSave */ + + retval = mips32_pracc_exec(ejtag_info, code_len + 1, code, 0, NULL, 0, NULL, 1); + if (retval != ERROR_OK) + goto exit; + + count -= this_round_count; + } + +exit: + free(code); + return retval; +} int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { int retval; + if (size == 4 || size == 2 || size == 1) + retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf); + else + retval = ERROR_FAIL; - switch (size) { - case 1: - retval = mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t *)buf); - break; - case 2: - retval = mips32_pracc_write_mem16(ejtag_info, addr, count, (uint16_t *)buf); - break; - case 4: - if (count == 1) - retval = mips32_pracc_write_u32(ejtag_info, addr, (uint32_t *)buf); - else - retval = mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t *)buf); - break; - default: - retval = ERROR_FAIL; - } + if (retval != ERROR_OK) + return retval; /** * If we are in the cachable regoion and cache is activated, @@ -698,200 +765,6 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz return retval; } -static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf) -{ - static const uint32_t 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 $11,($15) */ - - MIPS32_ADDI(8, 15, NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)), /* $8= 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 beginning of data */ - - /* loop: */ - 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(9, 9, 4), /* $9 += 4 */ - MIPS32_BNE(10, 9, NEG16(4)), /* bne $10, $9, loop */ - MIPS32_ADDI(8, 8, 4), /* $8 += 4 */ - - /* end: */ - MIPS32_LW(11, 0, 15), /* lw $11,($15) */ - MIPS32_LW(10, 0, 15), /* lw $10,($15) */ - MIPS32_LW(9, 0, 15), /* lw $9,($15) */ - MIPS32_LW(8, 0, 15), /* lw $8,($15) */ - MIPS32_B(NEG16(21)), /* b start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ - }; - - /* TODO remove array */ - uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t)); - param_in[0] = addr; - param_in[1] = addr + (count * sizeof(uint32_t)); /* last address */ - - memcpy(¶m_in[2], buf, count * sizeof(uint32_t)); - - int retval; - retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, - count + 2, param_in, 0, NULL, 1); - - free(param_in); - - return retval; -} - -static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) -{ - static const uint32_t 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_LW(8, NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15), /* load R8 @ param_in[1] = data */ - MIPS32_LW(9, NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), /* load R9 @ param_in[0] = address */ - - MIPS32_SW(8, 0, 9), /* sw $8,0($9) */ - - MIPS32_LW(9, 0, 15), /* lw $9,($15) */ - MIPS32_LW(8, 0, 15), /* lw $8,($15) */ - MIPS32_B(NEG16(11)), /* b start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ - }; - - /* TODO remove array */ - uint32_t param_in[1 + 1]; - param_in[0] = addr; - param_in[1] = *buf; - - return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, - ARRAY_SIZE(param_in), param_in, 0, NULL, 1); -} - -static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf) -{ - static const uint32_t 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 $11,($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 */ - /* loop: */ - MIPS32_BEQ(0, 10, 8), /* 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_B(NEG16(8)), /* b loop */ - MIPS32_NOP, - /* end: */ - MIPS32_LW(11, 0, 15), /* lw $11,($15) */ - MIPS32_LW(10, 0, 15), /* lw $10,($15) */ - MIPS32_LW(9, 0, 15), /* lw $9,($15) */ - MIPS32_LW(8, 0, 15), /* lw $8,($15) */ - MIPS32_B(NEG16(26)), /* b start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ - }; - - /* TODO remove array */ - uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t)); - int i; - param_in[0] = addr; - param_in[1] = count; - - for (i = 0; i < count; i++) - param_in[i + 2] = buf[i]; - - int retval; - retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, - count + 2, param_in, 0, NULL, 1); - - free(param_in); - - return retval; -} - -static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf) -{ - static const uint32_t 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 $11,($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 */ - /* loop: */ - MIPS32_BEQ(0, 10, 8), /* 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_B(NEG16(8)), /* b loop */ - MIPS32_NOP, - /* end: */ - MIPS32_LW(11, 0, 15), /* lw $11,($15) */ - MIPS32_LW(10, 0, 15), /* lw $10,($15) */ - MIPS32_LW(9, 0, 15), /* lw $9,($15) */ - MIPS32_LW(8, 0, 15), /* lw $8,($15) */ - MIPS32_B(NEG16(26)), /* b start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ - }; - - /* TODO remove array */ - uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t)); - 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, ARRAY_SIZE(code), code, - count + 2, param_in, 0, NULL, 1); - - free(param_in); - - return retval; -} - int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { static const uint32_t code[] = { @@ -1100,7 +973,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are /* write program into RAM */ if (write_t != ejtag_info->fast_access_save) { - mips32_pracc_write_mem32(ejtag_info, source->address, ARRAY_SIZE(handler_code), handler_code); + mips32_pracc_write_mem_generic(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); /* save previous operation to speed to any consecutive read/writes */ ejtag_info->fast_access_save = write_t; } -- ------------------------------------------------------------------------------ LogMeIn Central: Instant, anywhere, Remote PC access and management. Stay in control, update software, and manage PCs from one command center Diagnose problems and improve visibility into emerging IT issues Automate, monitor and manage. Do more in less time with Central http://p.sf.net/sfu/logmein12331_d2d _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
