mips: optimize mips32_pracc_write_regs() code.

All the the loads are done with lui and ori instructions, there is
no need to save any register, they will be overwritten.
Like in the previous patch, for speed optimization in write code,
same instructions can be saved if the lower half word or the upper
half word is 0.
If the lower half word is 0, it can be loaded with only a lui instruction.
If the higher half word is 0 it can be done with an ori instruction with register 0.
This code saves 10 pracc accesses at a minimum, and 40 at a maximum,
obviously if register 2 to 31 are 0 or a half word is 0
Current code needs 91 pracc accesses.

Change-Id: I892c5b440191d0c7a474c96845d41c373b7fc637
Signed-off-by: Salvador Arroyo <sarroyofdez@yahoo.es>
Reviewed-on: http://openocd.zylin.com/957
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
Tested-by: jenkins
This commit is contained in:
Salvador Arroyo 2012-11-03 11:29:46 +01:00 committed by Spencer Oliver
parent f3e01106d9
commit 18077654af
1 changed files with 43 additions and 61 deletions

View File

@ -767,71 +767,53 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
{
static const uint32_t code[] = {
/* start: */
MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $2 = MIPS32_PRACC_PARAM_IN */
MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_IN)),
MIPS32_LW(1, 1*4, 2), /* lw $1,1*4($2) */
MIPS32_LW(15, 15*4, 2), /* lw $15,15*4($2) */
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(1, 0, 15), /* sw $1,($15) */
MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_IN)), /* $1 = MIPS32_PRACC_PARAM_IN */
MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_IN)),
MIPS32_LW(3, 3*4, 1), /* lw $3,3*4($1) */
MIPS32_LW(4, 4*4, 1), /* lw $4,4*4($1) */
MIPS32_LW(5, 5*4, 1), /* lw $5,5*4($1) */
MIPS32_LW(6, 6*4, 1), /* lw $6,6*4($1) */
MIPS32_LW(7, 7*4, 1), /* lw $7,7*4($1) */
MIPS32_LW(8, 8*4, 1), /* lw $8,8*4($1) */
MIPS32_LW(9, 9*4, 1), /* lw $9,9*4($1) */
MIPS32_LW(10, 10*4, 1), /* lw $10,10*4($1) */
MIPS32_LW(11, 11*4, 1), /* lw $11,11*4($1) */
MIPS32_LW(12, 12*4, 1), /* lw $12,12*4($1) */
MIPS32_LW(13, 13*4, 1), /* lw $13,13*4($1) */
MIPS32_LW(14, 14*4, 1), /* lw $14,14*4($1) */
MIPS32_LW(16, 16*4, 1), /* lw $16,16*4($1) */
MIPS32_LW(17, 17*4, 1), /* lw $17,17*4($1) */
MIPS32_LW(18, 18*4, 1), /* lw $18,18*4($1) */
MIPS32_LW(19, 19*4, 1), /* lw $19,19*4($1) */
MIPS32_LW(20, 20*4, 1), /* lw $20,20*4($1) */
MIPS32_LW(21, 21*4, 1), /* lw $21,21*4($1) */
MIPS32_LW(22, 22*4, 1), /* lw $22,22*4($1) */
MIPS32_LW(23, 23*4, 1), /* lw $23,23*4($1) */
MIPS32_LW(24, 24*4, 1), /* lw $24,24*4($1) */
MIPS32_LW(25, 25*4, 1), /* lw $25,25*4($1) */
MIPS32_LW(26, 26*4, 1), /* lw $26,26*4($1) */
MIPS32_LW(27, 27*4, 1), /* lw $27,27*4($1) */
MIPS32_LW(28, 28*4, 1), /* lw $28,28*4($1) */
MIPS32_LW(29, 29*4, 1), /* lw $29,29*4($1) */
MIPS32_LW(30, 30*4, 1), /* lw $30,30*4($1) */
MIPS32_LW(31, 31*4, 1), /* lw $31,31*4($1) */
MIPS32_LW(2, 32*4, 1), /* lw $2,32*4($1) */
MIPS32_MTC0(2, 12, 0), /* move $2 to status */
MIPS32_LW(2, 33*4, 1), /* lw $2,33*4($1) */
MIPS32_MTLO(2), /* move $2 to lo */
MIPS32_LW(2, 34*4, 1), /* lw $2,34*4($1) */
MIPS32_MTHI(2), /* move $2 to hi */
MIPS32_LW(2, 35*4, 1), /* lw $2,35*4($1) */
MIPS32_MTC0(2, 8, 0), /* move $2 to badvaddr */
MIPS32_LW(2, 36*4, 1), /* lw $2,36*4($1) */
MIPS32_MTC0(2, 13, 0), /* move $2 to cause*/
MIPS32_LW(2, 37*4, 1), /* lw $2,37*4($1) */
MIPS32_MTC0(2, 24, 0), /* move $2 to depc (pc) */
MIPS32_LW(2, 2*4, 1), /* lw $2,2*4($1) */
MIPS32_LW(1, 0, 15), /* lw $1,($15) */
MIPS32_B(NEG16(53)), /* b start */
MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
static const uint32_t cp0_write_code[] = {
MIPS32_MTC0(1, 12, 0), /* move $1 to status */
MIPS32_MTLO(1), /* move $1 to lo */
MIPS32_MTHI(1), /* move $1 to hi */
MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
};
int retval;
uint32_t *code;
code = malloc((37 * 2 + 6 + 1) * sizeof(uint32_t)); /* alloc memory for the worst case */
if (code == NULL) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
MIPS32NUMCOREREGS, regs, 0, NULL, 1);
uint32_t *code_p = code;
int code_len = 0;
/* load registers 2 to 31 with lui an ori instructions, check if same instructions can be saved */
for (int i = 2; i < 32; i++) {
if (LOWER16((regs[i])) == 0) {
*code_p++ = MIPS32_LUI(i, UPPER16((regs[i]))); /* if lower half word is 0, lui instruction only */
code_len++;
} else if (UPPER16((regs[i])) == 0) {
*code_p++ = MIPS32_ORI(i, 0, LOWER16((regs[i]))); /* if upper half word is 0, ori with $0 only*/
code_len++;
} else {
*code_p++ = MIPS32_LUI(i, UPPER16((regs[i]))); /* default, load with lui and ori instructions */
*code_p++ = MIPS32_ORI(i, i, LOWER16((regs[i])));
code_len += 2;
}
}
for (int i = 0; i != 6; i++) {
*code_p++ = MIPS32_LUI(1, UPPER16((regs[i + 32]))); /* load CPO value in $1, with lui and ori */
*code_p++ = MIPS32_ORI(1, 1, LOWER16((regs[i + 32])));
*code_p++ = cp0_write_code[i]; /* write value from $1 to CPO register */
code_len += 3;
}
*code_p++ = MIPS32_LUI(1, UPPER16((regs[1]))); /* load upper half word in $1 */
code_len += 3;
*code_p++ = MIPS32_B(NEG16(code_len - 1)), /* b start */
*code_p = MIPS32_ORI(1, 1, LOWER16((regs[1]))); /* load lower half word in $1 */
int retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, 0, NULL, 1);
free(code);
return retval;
}