mips: optimize mips32_pracc_read_u32() function
[fw/openocd] / src / target / mips32_pracc.c
index 267a4ffd94c89c24a263ffe17854263daf44a4e4..72effb8e8a7381eb8582ea119a7e484e7cd04306 100644 (file)
@@ -125,9 +125,9 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
 
        /* wait for the PrAcc to become "1" */
        mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-       ejtag_ctrl = ejtag_info->ejtag_ctrl;
 
        while (1) {
+               ejtag_ctrl = ejtag_info->ejtag_ctrl;
                retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
                if (retval != ERROR_OK)
                        return retval;
@@ -153,18 +153,22 @@ static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t add
        uint32_t ejtag_ctrl, data;
 
        if ((address >= MIPS32_PRACC_PARAM_IN)
-               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
                data = ctx->local_iparam[offset];
        } else if ((address >= MIPS32_PRACC_PARAM_OUT)
-               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
                data = ctx->local_oparam[offset];
        } else if ((address >= MIPS32_PRACC_TEXT)
-               && (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
+               && (address < MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
                offset = (address - MIPS32_PRACC_TEXT) / 4;
                data = ctx->code[offset];
        } else if (address == MIPS32_PRACC_STACK) {
+               if (ctx->stack_offset <= 0) {
+                       LOG_ERROR("Error: Pracc stack out of bounds");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
                /* save to our debug stack */
                data = ctx->stack[--ctx->stack_offset];
        } else {
@@ -209,14 +213,18 @@ static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t ad
                return retval;
 
        if ((address >= MIPS32_PRACC_PARAM_IN)
-               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
                ctx->local_iparam[offset] = data;
        } else if ((address >= MIPS32_PRACC_PARAM_OUT)
-               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
                ctx->local_oparam[offset] = data;
        } else if (address == MIPS32_PRACC_STACK) {
+               if (ctx->stack_offset >= 32) {
+                       LOG_ERROR("Error: Pracc stack out of bounds");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
                /* save data onto our stack */
                ctx->stack[ctx->stack_offset++] = data;
        } else {
@@ -231,7 +239,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
                int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
 {
        uint32_t ejtag_ctrl;
-       uint32_t address, data;
+       uint32_t address;
        struct mips32_pracc_context ctx;
        int retval;
        int pass = 0;
@@ -250,7 +258,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
                if (retval != ERROR_OK)
                        return retval;
 
-               address = data = 0;
+               address = 0;
                mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
                retval = mips_ejtag_drscan_32(ejtag_info, &address);
                if (retval != ERROR_OK)
@@ -343,10 +351,10 @@ static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        int retval = ERROR_OK;
        int blocksize;
-       int bytesread;
+       int wordsread;
        uint32_t param_in[2];
 
-       bytesread = 0;
+       wordsread = 0;
 
        while (count > 0) {
                blocksize = count;
@@ -357,13 +365,13 @@ static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                               ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1);
+                               ARRAY_SIZE(param_in), param_in, blocksize, &buf[wordsread], 1);
                if (retval != ERROR_OK)
                        return retval;
 
                count -= blocksize;
-               addr += blocksize;
-               bytesread += blocksize;
+               addr += blocksize*sizeof(uint32_t);
+               wordsread += blocksize;
        }
 
        return retval;
@@ -371,34 +379,22 @@ static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr,
 
 static int mips32_pracc_read_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_LW(8, NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), /* load R8 @ param_in[0] = address */
+       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_LW(8, 0, 8),                                                                     /* lw $8,0($8), Load $8 with the word @mem[$8] */
-               MIPS32_SW(8, NEG16(MIPS32_PRACC_STACK - MIPS32_PRACC_PARAM_OUT), 15), /* store R8 @ param_out[0] */
+               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, 0, 15),                                                            /* lw $8,($15) */
-               MIPS32_B(NEG16(9)),                                                                     /* b start */
-               MIPS32_MFC0(15, 31, 0),                                                         /* move COP0 DeSave to $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 */
        };
 
-       int retval = ERROR_OK;
-       uint32_t param_in[1];
-
-       param_in[0] = addr;
-
-       retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, 1, buf, 1);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return retval;
+       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)
@@ -442,14 +438,17 @@ static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        /* TODO remove array */
        uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       int i;
+       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) */
-       {
+       while (count > 0) {
                blocksize = count;
                if (count > 0x400)
                        blocksize = 0x400;
@@ -458,17 +457,21 @@ static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, count, param_out, 1);
+                       ARRAY_SIZE(param_in), param_in, blocksize, &param_out[hwordsread], 1);
+
+               if (retval != ERROR_OK)
+                       return retval;
 
-/*             count -= blocksize; */
-/*             addr += blocksize; */
+               count -= blocksize;
+               addr += blocksize*sizeof(uint16_t);
+               hwordsread += blocksize;
        }
 
-       for (i = 0; i < count; i++)
+       int i;
+       for (i = 0; i < hwordsread; i++)
                buf[i] = param_out[i];
 
        free(param_out);
-
        return retval;
 }
 
@@ -513,14 +516,17 @@ static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        /* TODO remove array */
        uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       int i;
+       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) */
-       {
+       while (count > 0) {
                blocksize = count;
                if (count > 0x400)
                        blocksize = 0x400;
@@ -529,17 +535,20 @@ static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, count, param_out, 1);
+                       ARRAY_SIZE(param_in), param_in, count, &param_out[bytesread], 1);
 
-/*             count -= blocksize; */
-/*             addr += blocksize; */
-       }
+               if (retval != ERROR_OK)
+                       return retval;
 
-       for (i = 0; i < count; i++)
+               count -= blocksize;
+               addr += blocksize;
+               bytesread += blocksize;
+       }
+       int i;
+       for (i = 0; i < bytesread; i++)
                buf[i] = param_out[i];
 
        free(param_out);
-
        return retval;
 }
 
@@ -547,26 +556,20 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r
 {
        /**
         * Do not make this code static, but regenerate it every time,
-        * as 5th element has to be changed to add parameters
+        * as 3th element has to be changed to add parameters
         */
        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) */
-
-               /* 5 */ MIPS32_MFC0(8, 0, 0),                                           /* move COP0 [cp0_reg select] to $8 */
+                                                                                                               /* 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(9, UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11 = MIPS32_PRACC_PARAM_OUT */
-               MIPS32_ORI(9, 9, LOWER16(MIPS32_PRACC_PARAM_OUT)),
-               MIPS32_SW(8, 0, 9),                                                                     /* sw $8,0($9) */
+               /* 3 */ MIPS32_MFC0(8, 0, 0),                                           /* move COP0 [cp0_reg select] to $8 */
+               MIPS32_SW(8, PRACC_OUT_OFFSET, 15),                                     /* sw $8,PRACC_OUT_OFFSET($15) */
 
-               MIPS32_LW(9, 0, 15),                                                            /* lw $9,($15) */
-               MIPS32_LW(8, 0, 15),                                                            /* lw $8,($15) */
-               MIPS32_B(NEG16(12)),                                                            /* b start */
-               MIPS32_MFC0(15, 31, 0),                                                         /* move COP0 DeSave to $15 */
+               MIPS32_LW(8, PRACC_STACK_OFFSET, 15),                                   /* lw $8,PRACC_STACK_OFFSET($15) */
+               MIPS32_B(NEG16(7)),                                                     /* b start */
+               MIPS32_MFC0(15, 31, 0),                                                 /* move COP0 DeSave to $15 */
        };
 
        /**
@@ -583,56 +586,32 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r
         * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
         * In order to insert our parameters, we must change rd and funct fields.
         */
-       code[5] |= (cp0_reg << 11) | cp0_sel;  /* change rd and funct of MIPS32_R_INST macro */
-
-       /* TODO remove array */
-       uint32_t *param_out = val;
-       int retval;
-
-       retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, param_out, 1);
+       code[3] |= (cp0_reg << 11) | cp0_sel;  /* change rd and funct of MIPS32_R_INST macro */
 
-       return retval;
+       return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 1, val, 1);
 }
 
-int mips32_cp0_write(struct mips_ejtag *ejtag_info,
-               uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
+int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
 {
        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_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 val to $9 */
+               MIPS32_MTC0(15, 31, 0),                                                 /* move $15 to COP0 DeSave */
+               MIPS32_LUI(15, UPPER16(val)),                                           /* Load val to $15 */
+               MIPS32_ORI(15, 15, LOWER16(val)),
 
-               /* 8 */ MIPS32_MTC0(9, 0, 0),                                           /* move $9 to COP0 [cp0_reg select] */
+               /* 3 */ MIPS32_MTC0(15, 0, 0),                                          /* move $15 to COP0 [cp0_reg select] */
 
-               MIPS32_LW(9, 0, 15),                                                            /* lw $9,($15) */
-               MIPS32_LW(8, 0, 15),                                                            /* lw $8,($15) */
-               MIPS32_B(NEG16(12)),                                                            /* b start */
-               MIPS32_MFC0(15, 31, 0),                                                         /* move COP0 DeSave to $15 */
+               MIPS32_B(NEG16(5)),                                                     /* b start */
+               MIPS32_MFC0(15, 31, 0),                                                 /* move COP0 DeSave to $15 */
        };
 
        /**
         * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
         * In order to insert our parameters, we must change rd and funct fields.
         */
-       code[8] |= (cp0_reg << 11) | cp0_sel;  /* change rd and funct fields of MIPS32_R_INST macro */
-
-       /* TODO remove array */
-       uint32_t *param_in = malloc(1 * sizeof(uint32_t));
-       int retval;
-       param_in[0] = val;
-
-       retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 1, param_in, 0, NULL, 1);
+       code[3] |= (cp0_reg << 11) | cp0_sel;  /* change rd and funct fields of MIPS32_R_INST macro */
 
-       free(param_in);
-
-       return retval;
+       return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, 0, NULL, 0, NULL, 1);
 }
 
 /**
@@ -816,6 +795,9 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
        uint32_t conf = 0;
        int cached = 0;
 
+       if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
+               return retval; /*Nothing to do*/
+
        mips32_cp0_read(ejtag_info, &conf, 16, 0);
 
        switch (KSEGX(addr)) {
@@ -825,9 +807,6 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
                case KSEG0:
                        cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
                        break;
-               case KSEG1:
-                       /* uncachable segment - nothing to do */
-                       break;
                case KSEG2:
                case KSEG3:
                        cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;