mips: optimize read code for speed
[fw/openocd] / src / target / mips32_pracc.c
index 72effb8e8a7381eb8582ea119a7e484e7cd04306..3ac294958ae0ac366b56233372cdeb2593771cc0 100644 (file)
@@ -93,12 +93,6 @@ struct mips32_pracc_context {
        struct mips_ejtag *ejtag_info;
 };
 
-static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info,
-               uint32_t addr, int count, uint8_t *buf);
-static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info,
-               uint32_t addr, int count, uint16_t *buf);
-static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info,
-               uint32_t addr, int count, uint32_t *buf);
 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info,
                uint32_t addr, uint32_t *buf);
 
@@ -294,86 +288,102 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
 
 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
 {
-       switch (size) {
-               case 1:
-                       return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
-               case 2:
-                       return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
-               case 4:
-                       if (count == 1)
-                               return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
-                       else
-                               return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
-       }
+       if (count == 1 && size == 4)
+               return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
 
-       return ERROR_OK;
-}
+       int retval = ERROR_FAIL;
 
-static int mips32_pracc_read_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) */
+       uint32_t *code = NULL;
+       uint32_t *data = NULL;
 
-               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),                                                                     /* $9 = mem[$8]; read addr */
-               MIPS32_LW(10, 4, 8),                                                            /* $10 = mem[$8 + 4]; read count */
-               MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)),        /* $11 = MIPS32_PRACC_PARAM_OUT */
-               MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
-                                                                                                                       /* loop: */
-               MIPS32_BEQ(0, 10, 8),                                                           /* beq 0, $10, end */
-               MIPS32_NOP,
+       code = malloc((256 * 2 + 10) * sizeof(uint32_t));
+       if (code == NULL) {
+               LOG_ERROR("Out of memory");
+               goto exit;
+       }
 
-               MIPS32_LW(8, 0, 9),                                                                     /* lw $8,0($9), Load $8 with the word @mem[$9] */
-               MIPS32_SW(8, 0, 11),                                                            /* sw $8,0($11) */
+       if (size != 4) {
+               data = malloc(256 * sizeof(uint32_t));
+               if (data == NULL) {
+                       LOG_ERROR("Out of memory");
+                       goto exit;
+               }
+       }
 
-               MIPS32_ADDI(10, 10, NEG16(1)),                                          /* $10-- */
-               MIPS32_ADDI(9, 9, 4),                                                           /* $1 += 4 */
-               MIPS32_ADDI(11, 11, 4),                                                         /* $11 += 4 */
+       uint32_t *buf32 = buf;
+       uint16_t *buf16 = buf;
+       uint8_t *buf8 = buf;
 
-               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(27)),                                                            /* b start */
-               MIPS32_MFC0(15, 31, 0),                                                         /* move COP0 DeSave to $15 */
-       };
+       int i;
+       uint32_t upper_base_addr, last_upper_base_addr;
+       int this_round_count;
+       int code_len;
 
-       int retval = ERROR_OK;
-       int blocksize;
-       int wordsread;
-       uint32_t param_in[2];
+       while (count) {
+               this_round_count = (count > 256) ? 256 : count;
+               last_upper_base_addr = UPPER16((addr + 0x8000));
+               uint32_t *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 and $9 to pracc stack */
+               *code_p++ = MIPS32_SW(9, PRACC_STACK_OFFSET, 15);
+               *code_p++ = MIPS32_LUI(9, last_upper_base_addr);                        /* load the upper memory address in $9*/
+               code_len = 5;
+
+               for (i = 0; i != this_round_count; i++) {               /* Main code loop */
+                       upper_base_addr = UPPER16((addr + 0x8000));
+                       if (last_upper_base_addr != upper_base_addr) {
+                               *code_p++ = MIPS32_LUI(9, upper_base_addr);             /* if needed, change upper address in $9*/
+                               code_len++;
+                               last_upper_base_addr = upper_base_addr;
+                       }
+
+                       if (size == 4)
+                               *code_p++ = MIPS32_LW(8, LOWER16(addr), 9);             /* load from memory to $8 */
+                       else if (size == 2)
+                               *code_p++ = MIPS32_LHU(8, LOWER16(addr), 9);
+                       else
+                               *code_p++ = MIPS32_LBU(8, LOWER16(addr), 9);
 
-       wordsread = 0;
+                       *code_p++ = MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15);         /* store $8 at param out */
 
-       while (count > 0) {
-               blocksize = count;
-               if (count > 0x400)
-                       blocksize = 0x400;
+                       code_len += 2;
+                       addr += size;
+               }
 
-               param_in[0] = addr;
-               param_in[1] = blocksize;
+               *code_p++ = MIPS32_LW(9, PRACC_STACK_OFFSET, 15);                       /* restore $8 and $9 from pracc stack */
+               *code_p++ = MIPS32_LW(8, PRACC_STACK_OFFSET, 15);
 
-               retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                               ARRAY_SIZE(param_in), param_in, blocksize, &buf[wordsread], 1);
-               if (retval != ERROR_OK)
-                       return retval;
+               code_len += 4;
+               *code_p++ = MIPS32_B(NEG16(code_len - 1));                                      /* jump to start */
+               *code_p = MIPS32_MFC0(15, 31, 0);                                       /* restore $15 from DeSave */
 
-               count -= blocksize;
-               addr += blocksize*sizeof(uint32_t);
-               wordsread += blocksize;
+               if (size == 4) {
+                       retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, this_round_count, buf32, 1);
+                       if (retval != ERROR_OK)
+                               goto exit;
+                       buf32 += this_round_count;
+               } else {
+                       retval = mips32_pracc_exec(ejtag_info, code_len, code, 0, NULL, this_round_count, data, 1);
+                       if (retval != ERROR_OK)
+                               goto exit;
+                       uint32_t *data_p = data;
+                       for (i = 0; i != this_round_count; i++) {
+                               if (size == 2)
+                                       *buf16++ = *data_p++;
+                               else
+                                       *buf8++ = *data_p++;
+                       }
+               }
+               count -= this_round_count;
        }
 
+exit:
+       if (code)
+               free(code);
+       if (data)
+               free(data);
        return retval;
 }
 
@@ -397,161 +407,6 @@ static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, u
        return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, buf, 1);
 }
 
-static int mips32_pracc_read_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),                                                                     /* $9 = mem[$8]; read addr */
-               MIPS32_LW(10, 4, 8),                                                            /* $10 = mem[$8 + 4]; read count */
-               MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)),        /* $11 = MIPS32_PRACC_PARAM_OUT */
-               MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
-                                                                                                                       /* loop: */
-               MIPS32_BEQ(0, 10, 8),                                                           /* beq 0, $10, end */
-               MIPS32_NOP,
-
-               MIPS32_LHU(8, 0, 9),                                                            /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
-               MIPS32_SW(8, 0, 11),                                                            /* sw $8,0($11) */
-
-               MIPS32_ADDI(10, 10, NEG16(1)),                                          /* $10-- */
-               MIPS32_ADDI(9, 9, 2),                                                           /* $9 += 2 */
-               MIPS32_ADDI(11, 11, 4),                                                         /* $11 += 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(27)),                                                            /* b start */
-               MIPS32_MFC0(15, 30, 0),                                                         /* move COP0 DeSave to $15 */
-       };
-
-       /* TODO remove array */
-       uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       if (param_out == NULL) {
-               LOG_ERROR("Out of memory");
-               return ERROR_FAIL;
-       }
-
-       int retval = ERROR_OK;
-       int blocksize;
-       int hwordsread = 0;
-       uint32_t param_in[2];
-
-       while (count > 0) {
-               blocksize = count;
-               if (count > 0x400)
-                       blocksize = 0x400;
-
-               param_in[0] = addr;
-               param_in[1] = blocksize;
-
-               retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, blocksize, &param_out[hwordsread], 1);
-
-               if (retval != ERROR_OK)
-                       return retval;
-
-               count -= blocksize;
-               addr += blocksize*sizeof(uint16_t);
-               hwordsread += blocksize;
-       }
-
-       int i;
-       for (i = 0; i < hwordsread; i++)
-               buf[i] = param_out[i];
-
-       free(param_out);
-       return retval;
-}
-
-static int mips32_pracc_read_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),                                                                     /* $9 = mem[$8]; read addr */
-               MIPS32_LW(10, 4, 8),                                                            /* $10 = mem[$8 + 4]; read count */
-               MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT)),        /* $11 = MIPS32_PRACC_PARAM_OUT */
-               MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT)),
-                                                                                                                       /* loop: */
-               MIPS32_BEQ(0, 10, 8),                                                           /* beq 0, $10, end */
-               MIPS32_NOP,
-
-               MIPS32_LBU(8, 0, 9),                                                            /* lw $8,0($9), Load t4 with the byte @mem[t1] */
-               MIPS32_SW(8, 0, 11),                                                            /* sw $8,0($11) */
-
-               MIPS32_ADDI(10, 10, NEG16(1)),                                          /* $10-- */
-               MIPS32_ADDI(9, 9, 1),                                                           /* $9 += 1 */
-               MIPS32_ADDI(11, 11, 4),                                                         /* $11 += 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(27)),                                                            /* b start */
-               MIPS32_MFC0(15, 31, 0),                                                         /* move COP0 DeSave to $15 */
-       };
-
-       /* TODO remove array */
-       uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       if (param_out == NULL) {
-               LOG_ERROR("Out of memory");
-               return ERROR_FAIL;
-       }
-
-       int retval = ERROR_OK;
-       int blocksize;
-       uint32_t param_in[2];
-       int bytesread = 0;
-
-       while (count > 0) {
-               blocksize = count;
-               if (count > 0x400)
-                       blocksize = 0x400;
-
-               param_in[0] = addr;
-               param_in[1] = blocksize;
-
-               retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, count, &param_out[bytesread], 1);
-
-               if (retval != ERROR_OK)
-                       return retval;
-
-               count -= blocksize;
-               addr += blocksize;
-               bytesread += blocksize;
-       }
-       int i;
-       for (i = 0; i < bytesread; i++)
-               buf[i] = param_out[i];
-
-       free(param_out);
-       return retval;
-}
-
 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
 {
        /**