openocd: fix SPDX tag format for files .c
[fw/openocd] / src / target / mips32_pracc.c
index 4ca92aebb1207a092db8e2b4bd0c21cb2d51c445..c4704b5a5d90f68e424df1d046da23a7cc5746c3 100644 (file)
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
@@ -8,19 +10,6 @@
  *                                                                         *
  *   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     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 /*
@@ -68,7 +57,9 @@
 #include "config.h"
 #endif
 
+#include <helper/align.h>
 #include <helper/time_support.h>
+#include <jtag/adapter.h>
 
 #include "mips32.h"
 #include "mips32_pracc.h"
@@ -120,10 +111,10 @@ static void mips32_pracc_finish(struct mips_ejtag *ejtag_info)
        mips_ejtag_drscan_32_out(ejtag_info, ctrl);
 }
 
-int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
+static int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
 {
-       uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2);
-
+       uint32_t jt_code = MIPS32_J(ejtag_info->isa, MIPS32_PRACC_TEXT);
+       pracc_swap16_array(ejtag_info, &jt_code, 1);
        /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */
        for (int i = 0; i != 5; i++) {
                /* Wait for pracc */
@@ -148,7 +139,7 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
                if (retval != ERROR_OK)
                        return retval;
 
-               if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) {         /* LEXRA/BMIPS ?, shift out another NOP, max 2 */
+               if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */
                        mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
                        mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP);
                        mips32_pracc_finish(ejtag_info);
@@ -159,10 +150,11 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
        return ERROR_OK;
 }
 
-int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out)
+static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
+                                       uint32_t *param_out, bool check_last)
 {
        int code_count = 0;
-       int store_pending = 0;          /* increases with every store instruction at dmseg, decreases with every store pa */
+       int store_pending = 0;          /* increases with every store instr at dmseg, decreases with every store pa */
        uint32_t max_store_addr = 0;    /* for store pa address testing */
        bool restart = 0;               /* restarting control */
        int restart_count = 0;
@@ -185,12 +177,12 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                        LOG_DEBUG("restarting code");
                }
 
-               retval = mips32_pracc_read_ctrl_addr(ejtag_info);               /* update current pa info: control and address */
+               retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */
                if (retval != ERROR_OK)
                        return retval;
 
                /* Check for read or write access */
-               if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) {                                            /* write/store access */
+               if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) {                            /* write/store access */
                        /* Check for pending store from a previous store instruction at dmseg */
                        if (store_pending == 0) {
                                LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr);
@@ -201,8 +193,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                                        return ERROR_JTAG_DEVICE_ERROR;
                        } else {
                                /* check address */
-                               if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) {
-
+                               if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT ||
+                                               ejtag_info->pa_addr > max_store_addr) {
                                        LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr);
                                        return ERROR_JTAG_DEVICE_ERROR;
                                }
@@ -226,7 +218,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                                                        ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
 
                                        /* restart code execution only in some cases */
-                                       if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) {
+                                       if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT &&
+                                                                               restart_count == 0) {
                                                LOG_DEBUG("restarting, without clean jump");
                                                restart_count++;
                                                code_count = 0;
@@ -235,18 +228,17 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                                                restart = 1;
                                                continue;
                                        }
-
                                        return ERROR_JTAG_DEVICE_ERROR;
                                }
                                /* check for store instruction at dmseg */
-                               uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count];
+                               uint32_t store_addr = ctx->pracc_list[code_count].addr;
                                if (store_addr != 0) {
                                        if (store_addr > max_store_addr)
                                                max_store_addr = store_addr;
                                        store_pending++;
                                }
 
-                               instr = ctx->pracc_list[code_count++];
+                               instr = ctx->pracc_list[code_count++].instr;
                                if (code_count == ctx->code_count)      /* last instruction, start final check */
                                        final_check = 1;
 
@@ -264,18 +256,19 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                                        }
                                } else {
                                        if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
-                                               LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x",
-                                                         ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
+                                               LOG_DEBUG("unexpected read address in final check: %"
+                                                       PRIx32 ", expected: %x", ejtag_info->pa_addr,
+                                                       MIPS32_PRACC_TEXT + code_count * 4);
                                                return ERROR_JTAG_DEVICE_ERROR;
                                        }
                                }
                                if (!pass) {
-                                       if ((code_count - ctx->code_count) > 1) {        /* allow max 2 instruction delay slot */
+                                       if ((code_count - ctx->code_count) > 1) { /* allow max 2 instr delay slot */
                                                LOG_DEBUG("failed to jump back to pracc text");
                                                return ERROR_JTAG_DEVICE_ERROR;
                                        }
                                } else
-                                       if (code_count > 10) {          /* enough, abandone */
+                                       if (code_count > 10) {          /* enough, abandon */
                                                LOG_DEBUG("execution abandoned, store pending: %d", store_pending);
                                                return ERROR_JTAG_DEVICE_ERROR;
                                        }
@@ -290,7 +283,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct
                /* finish processor access, let the processor eat! */
                mips32_pracc_finish(ejtag_info);
 
-               if (instr == MIPS32_DRET)       /* after leaving debug mode nothing to do */
+               if (final_check && !check_last)                 /* last instr, don't check, execute and exit */
                        return jtag_execute_queue();
 
                if (store_pending == 0 && pass) {       /* store access done, but after passing pracc text */
@@ -305,34 +298,62 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx)
        ctx->retval = ERROR_OK;
        ctx->code_count = 0;
        ctx->store_count = 0;
-
-       ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t));
-       if (ctx->pracc_list == NULL) {
-               LOG_ERROR("Out of memory");
-               ctx->retval = ERROR_FAIL;
-       }
+       ctx->max_code = 0;
+       ctx->pracc_list = NULL;
+       ctx->isa = ctx->ejtag_info->isa ? 1 : 0;
 }
 
-inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
+void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
 {
-       ctx->pracc_list[ctx->max_code + ctx->code_count] = addr;
-       ctx->pracc_list[ctx->code_count++] = instr;
+       if (ctx->retval != ERROR_OK)    /* On previous out of memory, return */
+               return;
+       if (ctx->code_count == ctx->max_code) {
+               void *p = realloc(ctx->pracc_list, sizeof(struct pa_list) * (ctx->max_code + PRACC_BLOCK));
+               if (p) {
+                       ctx->max_code += PRACC_BLOCK;
+                       ctx->pracc_list = p;
+               } else {
+                       ctx->retval = ERROR_FAIL;       /* Out of memory */
+                       return;
+               }
+       }
+       ctx->pracc_list[ctx->code_count].instr = instr;
+       ctx->pracc_list[ctx->code_count++].addr = addr;
        if (addr)
                ctx->store_count++;
 }
 
+static void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize)
+{
+       if (LOWER16(data) == 0 && optimize)
+               pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data)));        /* load only upper value */
+       else if (UPPER16(data) == 0 && optimize)
+               pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, 0, LOWER16(data)));     /* load only lower */
+       else {
+               pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data)));        /* load upper and lower */
+               pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, reg_num, LOWER16(data)));
+       }
+}
+
 inline void pracc_queue_free(struct pracc_queue_info *ctx)
 {
-       if (ctx->code_count > ctx->max_code)    /* Only for internal check, will be erased */
-               LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code);
-       if (ctx->pracc_list != NULL)
-               free(ctx->pracc_list);
+       free(ctx->pracc_list);
 }
 
-int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf)
+int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
+                                       uint32_t *buf, bool check_last)
 {
+       if (ctx->retval != ERROR_OK) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
+       if (ejtag_info->isa && ejtag_info->endianness)
+               for (int i = 0; i != ctx->code_count; i++)
+                       ctx->pracc_list[i].instr = SWAP16(ctx->pracc_list[i].instr);
+
        if (ejtag_info->mode == 0)
-               return mips32_pracc_exec(ejtag_info, ctx, buf);
+               return mips32_pracc_exec(ejtag_info, ctx, buf, check_last);
 
        union scan_in {
                uint8_t scan_96[12];
@@ -343,28 +364,28 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in
                } scan_32;
 
        } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count));
-       if (scan_in == NULL) {
+       if (!scan_in) {
                LOG_ERROR("Out of memory");
                return ERROR_FAIL;
        }
 
        unsigned num_clocks =
-               ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
+               ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000;
 
        uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
        mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL);
 
        int scan_count = 0;
-       for (int i = 0; i != 2 * ctx->code_count; i++) {
-               uint32_t data = 0;
-               if (i & 1u) {                   /* Check store address from previous instruction, if not the first */
-                       if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1])
-                               continue;
-               } else
-                       data = ctx->pracc_list[i / 2];
-
+       for (int i = 0; i != ctx->code_count; i++) {
                jtag_add_clocks(num_clocks);
-               mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96);
+               mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, ctx->pracc_list[i].instr,
+                                      scan_in[scan_count++].scan_96);
+
+               /* Check store address from previous instruction, if not the first */
+               if (i > 0 && ctx->pracc_list[i - 1].addr) {
+                       jtag_add_clocks(num_clocks);
+                       mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, 0, scan_in[scan_count++].scan_96);
+               }
        }
 
        int retval = jtag_execute_queue();              /* execute queued scans */
@@ -373,24 +394,35 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in
 
        uint32_t fetch_addr = MIPS32_PRACC_TEXT;                /* start address */
        scan_count = 0;
-       for (int i = 0; i != 2 * ctx->code_count; i++) {                                /* verify every pracc access */
-               uint32_t store_addr = 0;
-               if (i & 1u) {                   /* Read store addres from previous instruction, if not the first */
-                       store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1];
-                       if (i < 2 || 0 == store_addr)
-                               continue;
-               }
-
+       for (int i = 0; i != ctx->code_count; i++) {                            /* verify every pracc access */
+               /* check pracc bit */
                ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
+               uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
                if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
                        LOG_ERROR("Error: access not pending  count: %d", scan_count);
                        retval = ERROR_FAIL;
                        goto exit;
                }
+               if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
+                       LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
+                       retval = ERROR_FAIL;
+                       goto exit;
+               }
+               if (addr != fetch_addr) {
+                       LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
+                                         addr, fetch_addr, scan_count);
+                       retval = ERROR_FAIL;
+                       goto exit;
+               }
+               fetch_addr += 4;
+               scan_count++;
 
-               uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
+               /* check if previous instruction is a store instruction at dmesg */
+               if (i > 0 && ctx->pracc_list[i - 1].addr) {
+                       uint32_t store_addr = ctx->pracc_list[i - 1].addr;
+                       ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
+                       addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
 
-               if (store_addr != 0) {
                        if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
                                LOG_ERROR("Not a store/write access, count: %d", scan_count);
                                retval = ERROR_FAIL;
@@ -398,53 +430,35 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in
                        }
                        if (addr != store_addr) {
                                LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
-                                               addr, store_addr, scan_count);
+                                                             addr, store_addr, scan_count);
                                retval = ERROR_FAIL;
                                goto exit;
                        }
                        int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
                        buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
-
-               } else {
-                       if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
-                               LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
-                               retval = ERROR_FAIL;
-                               goto exit;
-                       }
-                       if (addr != fetch_addr) {
-                               LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
-                                         addr, fetch_addr, scan_count);
-                               retval = ERROR_FAIL;
-                               goto exit;
-                       }
-                       fetch_addr += 4;
+                       scan_count++;
                }
-               scan_count++;
        }
 exit:
        free(scan_in);
        return retval;
 }
 
-int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
+static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
 {
-       struct pracc_queue_info ctx = {.max_code = 8};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
-       pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR));                      /* $15 = MIPS32_PRACC_BASE_ADDR */
-       pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000))));            /* load  $8 with modified upper address */
-       pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8));                             /* lw $8, LOWER16(addr)($8) */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR));     /* $15 = MIPS32_PRACC_BASE_ADDR */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16((addr + 0x8000)))); /* load  $8 with modified upper addr */
+       pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 8));                    /* lw $8, LOWER16(addr)($8) */
        pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
-                               MIPS32_SW(8, PRACC_OUT_OFFSET, 15));                    /* sw $8,PRACC_OUT_OFFSET($15) */
-       pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8)));           /* restore upper 16 of $8 */
-       pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)));                /* restore lower 16 of $8 */
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                                     /* move COP0 DeSave to $15 */
+                               MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15));   /* sw $8,PRACC_OUT_OFFSET($15) */
+       pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0);                           /* restore $8 */
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                            /* move COP0 DeSave to $15 */
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
-exit:
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1);
        pracc_queue_free(&ctx);
        return ctx.retval;
 }
@@ -454,15 +468,13 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size
        if (count == 1 && size == 4)
                return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
 
-       uint32_t *data = NULL;
-       struct pracc_queue_info ctx = {.max_code = 256 * 3 + 8 + 1};    /* alloc memory for the worst case */
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
+       uint32_t *data = NULL;
        if (size != 4) {
                data = malloc(256 * sizeof(uint32_t));
-               if (data == NULL) {
+               if (!data) {
                        LOG_ERROR("Out of memory");
                        goto exit;
                }
@@ -475,45 +487,44 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size
        while (count) {
                ctx.code_count = 0;
                ctx.store_count = 0;
+
                int this_round_count = (count > 256) ? 256 : count;
                uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
 
-               pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR));                      /* $15 = MIPS32_PRACC_BASE_ADDR */
-               pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr));                /* load the upper memory address in $9 */
+               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
+               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, last_upper_base_addr));       /* upper memory addr to $9 */
 
                for (int i = 0; i != this_round_count; i++) {                   /* Main code loop */
                        uint32_t upper_base_addr = UPPER16((addr + 0x8000));
-                       if (last_upper_base_addr != upper_base_addr) {                  /* if needed, change upper address in $9 */
-                               pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr));
+                       if (last_upper_base_addr != upper_base_addr) {  /* if needed, change upper addr in $9 */
+                               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, upper_base_addr));
                                last_upper_base_addr = upper_base_addr;
                        }
 
-                       if (size == 4)
-                               pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9));             /* load from memory to $8 */
+                       if (size == 4)                          /* load from memory to $8 */
+                               pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 9));
                        else if (size == 2)
-                               pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9));
+                               pracc_add(&ctx, 0, MIPS32_LHU(ctx.isa, 8, LOWER16(addr), 9));
                        else
-                               pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9));
+                               pracc_add(&ctx, 0, MIPS32_LBU(ctx.isa, 8, LOWER16(addr), 9));
 
-                       pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,
-                                         MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15));          /* store $8 at param out */
+                       pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,                 /* store $8 at param out */
+                                         MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + i * 4, 15));
                        addr += size;
                }
-               pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8)));           /* restore upper 16 bits of reg 8 */
-               pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)));        /* restore lower 16 bits of reg 8 */
-               pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9)));           /* restore upper 16 bits of reg 9 */
-               pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9)));        /* restore lower 16 bits of reg 9 */
+               pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0);                           /* restore $8 */
+               pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0);                           /* restore $9 */
 
-               pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                /* jump to start */
-               pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                                     /* restore $15 from DeSave */
+               pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));  /* jump to start */
+               pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                    /* restore $15 from DeSave */
 
                if (size == 4) {
-                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32);
+                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1);
                        if (ctx.retval != ERROR_OK)
                                goto exit;
                        buf32 += this_round_count;
                } else {
-                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data);
+                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data, 1);
                        if (ctx.retval != ERROR_OK)
                                goto exit;
 
@@ -529,50 +540,41 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size
        }
 exit:
        pracc_queue_free(&ctx);
-       if (data != NULL)
-               free(data);
+       free(data);
        return ctx.retval;
 }
 
 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
 {
-       struct pracc_queue_info ctx = {.max_code = 7};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
-       pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR));                      /* $15 = MIPS32_PRACC_BASE_ADDR */
-       pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel));                   /* move cp0 reg / sel to $8 */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR));     /* $15 = MIPS32_PRACC_BASE_ADDR */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, cp0_reg, cp0_sel));          /* move cp0 reg / sel to $8 */
        pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
-                               MIPS32_SW(8, PRACC_OUT_OFFSET, 15));                    /* store $8 to pracc_out */
-       pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                                     /* restore $15 from DeSave */
-       pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8)));           /* restore upper 16 bits  of $8 */
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)));                /* restore lower 16 bits of $8 */
+                               MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15));   /* store $8 to pracc_out */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                            /* restore $15 from DeSave */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8)));  /* restore upper 16 bits  of $8 */
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val);
-exit:
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
        pracc_queue_free(&ctx);
        return ctx.retval;
 }
 
 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
 {
-       struct pracc_queue_info ctx = {.max_code = 6};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
-
-       pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val)));                       /* Load val to $15 */
-       pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val)));
 
-       pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel));                  /* write $15 to cp0 reg / sel */
+       pracc_add_li32(&ctx, 15, val, 0);                               /* Load val to $15 */
 
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                             /* restore $15 from DeSave */
+       pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, cp0_reg, cp0_sel));         /* write $15 to cp0 reg / sel */
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                    /* restore $15 from DeSave */
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-exit:
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
        pracc_queue_free(&ctx);
        return ctx.retval;
 }
@@ -607,26 +609,25 @@ exit:
 static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
                                         uint32_t start_addr, uint32_t end_addr, int cached, int rel)
 {
-       struct pracc_queue_info ctx = {.max_code = 256 * 2 + 5};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
+
        /** Find cache line size in bytes */
        uint32_t clsiz;
        if (rel) {      /* Release 2 (rel = 1) */
-               pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR));                      /* $15 = MIPS32_PRACC_BASE_ADDR */
+               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
 
-               pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP));                 /* load synci_step value to $8 */
+               pracc_add(&ctx, 0, MIPS32_RDHWR(ctx.isa, 8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
 
                pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
-                               MIPS32_SW(8, PRACC_OUT_OFFSET, 15));                    /* store $8 to pracc_out */
+                               MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15));           /* store $8 to pracc_out */
 
-               pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8)));                   /* restore upper 16 bits  of $8 */
-               pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)));                /* restore lower 16 bits of $8 */
-               pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-               pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                                     /* move COP0 DeSave to $15 */
+               pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0);                           /* restore $8 */
 
-               ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz);
+               pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));  /* jump to start */
+               pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                    /* restore $15 from DeSave */
+
+               ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1);
                if (ctx.retval != ERROR_OK)
                        goto exit;
 
@@ -648,7 +649,7 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
                goto exit;  /* Nothing to do */
 
        /* make sure clsiz is power of 2 */
-       if (clsiz & (clsiz - 1)) {
+       if (!IS_PWR_OF_2(clsiz)) {
                LOG_DEBUG("clsiz must be power of 2");
                ctx.retval = ERROR_FAIL;
                goto exit;
@@ -659,47 +660,50 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
        end_addr |= clsiz - 1;
 
        ctx.code_count = 0;
+       ctx.store_count = 0;
+
        int count = 0;
        uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000));
 
-       pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr));               /* load upper memory base address to $15 */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); /* load upper memory base addr to $15 */
 
        while (start_addr <= end_addr) {                                                /* main loop */
                uint32_t upper_base_addr = UPPER16((start_addr + 0x8000));
-               if (last_upper_base_addr != upper_base_addr) {                          /* if needed, change upper address in $15 */
-                       pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr));
+               if (last_upper_base_addr != upper_base_addr) {          /* if needed, change upper addr in $15 */
+                       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr));
                        last_upper_base_addr = upper_base_addr;
                }
-               if (rel)
-                       pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15));              /* synci instruction, offset($15) */
+               if (rel)                        /* synci instruction, offset($15) */
+                       pracc_add(&ctx, 0, MIPS32_SYNCI(ctx.isa, LOWER16(start_addr), 15));
 
                else {
-                       if (cached == 3)
-                               pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK,
-                                                       LOWER16(start_addr), 15));              /* cache Hit_Writeback_D, offset($15) */
-
-                       pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE,
-                                                       LOWER16(start_addr), 15));              /* cache Hit_Invalidate_I, offset($15) */
+                       if (cached == 3)        /* cache Hit_Writeback_D, offset($15) */
+                               pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_D_HIT_WRITEBACK,
+                                                       LOWER16(start_addr), 15));
+                       /* cache Hit_Invalidate_I, offset($15) */
+                       pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_I_HIT_INVALIDATE,
+                                                       LOWER16(start_addr), 15));
                }
                start_addr += clsiz;
                count++;
-               if (count == 256 && start_addr <= end_addr) {                           /* more ?, then execute code list */
-                       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                /* jump to start */
-                       pracc_add(&ctx, 0, MIPS32_NOP);                                         /* nop in delay slot */
+               if (count == 256 && start_addr <= end_addr) {                   /* more ?, then execute code list */
+                       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));  /* to start */
+                       pracc_add(&ctx, 0, MIPS32_NOP);                                 /* nop in delay slot */
 
-                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
+                       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
                        if (ctx.retval != ERROR_OK)
                                goto exit;
 
-                       ctx.code_count = 0;
+                       ctx.code_count = 0;     /* reset counters for another loop */
+                       ctx.store_count = 0;
                        count = 0;
                }
        }
-       pracc_add(&ctx, 0, MIPS32_SYNC);
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                                     /* restore $15 from DeSave*/
+       pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa));
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                            /* restore $15 from DeSave*/
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
 exit:
        pracc_queue_free(&ctx);
        return ctx.retval;
@@ -708,10 +712,8 @@ exit:
 static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
                uint32_t addr, int size, int count, const void *buf)
 {
-       struct pracc_queue_info ctx = {.max_code = 128 * 3 + 5 + 1};    /* alloc memory for the worst case */
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
        const uint32_t *buf32 = buf;
        const uint16_t *buf16 = buf;
@@ -720,50 +722,43 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
        while (count) {
                ctx.code_count = 0;
                ctx.store_count = 0;
+
                int this_round_count = (count > 128) ? 128 : count;
                uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
-
-               pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr));               /* load $15 with memory base address */
+                             /* load $15 with memory base address */
+               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr));
 
                for (int i = 0; i != this_round_count; i++) {
                        uint32_t upper_base_addr = UPPER16((addr + 0x8000));
-                       if (last_upper_base_addr != upper_base_addr) {
-                               pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr));    /* if needed, change upper address in $15*/
+                       if (last_upper_base_addr != upper_base_addr) {  /* if needed, change upper address in $15*/
+                               pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr));
                                last_upper_base_addr = upper_base_addr;
                        }
 
-                       if (size == 4) {                        /* for word writes check if one half word is 0 and load it accordingly */
-                               if (LOWER16(*buf32) == 0)
-                                       pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32)));             /* load only upper value */
-                               else if (UPPER16(*buf32) == 0)
-                                               pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32)));  /* load only lower */
-                               else {
-                                       pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32)));             /* load upper and lower */
-                                       pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32)));
-                               }
-                               pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15));            /* store word to memory */
+                       if (size == 4) {
+                               pracc_add_li32(&ctx, 8, *buf32, 1);             /* load with li32, optimize */
+                               pracc_add(&ctx, 0, MIPS32_SW(ctx.isa, 8, LOWER16(addr), 15)); /* store word to mem */
                                buf32++;
 
                        } else if (size == 2) {
-                               pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16));           /* load lower value */
-                               pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15));    /* store half word to memory */
+                               pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf16));          /* load lower value */
+                               pracc_add(&ctx, 0, MIPS32_SH(ctx.isa, 8, LOWER16(addr), 15)); /* store half word */
                                buf16++;
 
                        } else {
-                               pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8));            /* load lower value */
-                               pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15));    /* store byte to memory */
+                               pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf8));           /* load lower value */
+                               pracc_add(&ctx, 0, MIPS32_SB(ctx.isa, 8, LOWER16(addr), 15));   /* store byte */
                                buf8++;
                        }
                        addr += size;
                }
 
-               pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8)));           /* restore upper 16 bits of reg 8 */
-               pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8)));        /* restore lower 16 bits of reg 8 */
+               pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0);                           /* restore $8 */
 
-               pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                /* jump to start */
-               pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0));                             /* restore $15 from DeSave */
+               pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));  /* jump to start */
+               pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0));                    /* restore $15 from DeSave */
 
-               ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
+               ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
                if (ctx.retval != ERROR_OK)
                        goto exit;
                count -= this_round_count;
@@ -783,7 +778,7 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
         * If we are in the cacheable region and cache is activated,
         * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write,
         * so that changes do not continue to live only in D$ (if CCA = 3), but to be
-        * replicated in I$ also (maybe we wrote the istructions)
+        * replicated in I$ also (maybe we wrote the instructions)
         */
        uint32_t conf = 0;
        int cached = 0;
@@ -810,7 +805,7 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
        }
 
        /**
-        * Check cachablitiy bits coherency algorithm
+        * Check cacheability bits coherency algorithm
         * is the region cacheable or uncached.
         * If cacheable we have to synchronize the cache
         */
@@ -830,92 +825,77 @@ 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 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) */
-       };
-
-       struct pracc_queue_info ctx = {.max_code = 37 * 2 + 7 + 1};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
-       /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */
-       for (int i = 2; i < 32; i++) {
-               if (LOWER16((regs[i])) == 0)                                    /* if lower half word is 0, lui instruction only */
-                       pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
-               else if (UPPER16((regs[i])) == 0)                                       /* if upper half word is 0, ori with $0 only*/
-                       pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i]))));
-               else {                                                                  /* default, load with lui and ori instructions */
-                       pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
-                       pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i]))));
-               }
-       }
+       uint32_t cp0_write_code[] = {
+               MIPS32_MTC0(ctx.isa, 1, 12, 0),                                 /* move $1 to status */
+               MIPS32_MTLO(ctx.isa, 1),                                                /* move $1 to lo */
+               MIPS32_MTHI(ctx.isa, 1),                                                /* move $1 to hi */
+               MIPS32_MTC0(ctx.isa, 1, 8, 0),                                  /* move $1 to badvaddr */
+               MIPS32_MTC0(ctx.isa, 1, 13, 0),                                 /* move $1 to cause*/
+               MIPS32_MTC0(ctx.isa, 1, 24, 0),                                 /* move $1 to depc (pc) */
+       };
+
+       /* load registers 2 to 31 with li32, optimize */
+       for (int i = 2; i < 32; i++)
+               pracc_add_li32(&ctx, i, regs[i], 1);
 
        for (int i = 0; i != 6; i++) {
-               pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32]))));             /* load CPO value in $1, with lui and ori */
-               pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32]))));
-               pracc_add(&ctx, 0, cp0_write_code[i]);                                  /* write value from $1 to CPO register */
+               pracc_add_li32(&ctx, 1, regs[i + 32], 0);       /* load CPO value in $1 */
+               pracc_add(&ctx, 0, cp0_write_code[i]);                  /* write value from $1 to CPO register */
        }
-       pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0));                             /* load $15 in DeSave */
-       pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1]))));                  /* load upper half word in $1 */
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1]))));               /* load lower half word in $1 */
+       pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));                            /* load $15 in DeSave */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1]))));         /* load upper half word in $1 */
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1]))));      /* load lower half word in $1 */
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
 
        ejtag_info->reg8 = regs[8];
        ejtag_info->reg9 = regs[9];
-exit:
        pracc_queue_free(&ctx);
        return ctx.retval;
 }
 
 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
 {
-       static int cp0_read_code[] = {
-               MIPS32_MFC0(8, 12, 0),                                                  /* move status to $8 */
-               MIPS32_MFLO(8),                                                                 /* move lo to $8 */
-               MIPS32_MFHI(8),                                                                 /* move hi to $8 */
-               MIPS32_MFC0(8, 8, 0),                                                   /* move badvaddr to $8 */
-               MIPS32_MFC0(8, 13, 0),                                                  /* move cause to $8 */
-               MIPS32_MFC0(8, 24, 0),                                                  /* move depc (pc) to $8 */
-       };
-
-       struct pracc_queue_info ctx = {.max_code = 49};
+       struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
        pracc_queue_init(&ctx);
-       if (ctx.retval != ERROR_OK)
-               goto exit;
 
-       pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0));                                              /* move $1 to COP0 DeSave */
-       pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR));                               /* $1 = MIP32_PRACC_BASE_ADDR */
+       uint32_t cp0_read_code[] = {
+               MIPS32_MFC0(ctx.isa, 8, 12, 0),                                 /* move status to $8 */
+               MIPS32_MFLO(ctx.isa, 8),                                                /* move lo to $8 */
+               MIPS32_MFHI(ctx.isa, 8),                                                /* move hi to $8 */
+               MIPS32_MFC0(ctx.isa, 8, 8, 0),                                  /* move badvaddr to $8 */
+               MIPS32_MFC0(ctx.isa, 8, 13, 0),                                 /* move cause to $8 */
+               MIPS32_MFC0(ctx.isa, 8, 24, 0),                                 /* move depc (pc) to $8 */
+       };
+
+       pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0));                             /* move $1 to COP0 DeSave */
+       pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR));      /* $1 = MIP32_PRACC_BASE_ADDR */
 
        for (int i = 2; i != 32; i++)                                   /* store GPR's 2 to 31 */
                pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
-                                 MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1));
+                                 MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1));
 
        for (int i = 0; i != 6; i++) {
                pracc_add(&ctx, 0, cp0_read_code[i]);                           /* load COP0 needed registers to $8 */
                pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,                  /* store $8 at PARAM OUT */
-                                 MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
+                                 MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
        }
-       pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0));                                      /* move DeSave to $8, reg1 value */
-       pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4,                                     /* store reg1 value from $8 to param out */
-                         MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1));
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0));                     /* move DeSave to $8, reg1 value */
+       pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4,                     /* store reg1 value from $8 to param out */
+                         MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1));
 
-       pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0));                                      /* move COP0 DeSave to $1, restore reg1 */
-       pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1)));                                        /* jump to start */
-       pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0));                                     /* load $15 in DeSave */
+       pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0));             /* move COP0 DeSave to $1, restore reg1 */
+       pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));          /* jump to start */
+       pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));                            /* load $15 in DeSave */
 
-       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs);
+       ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1);
 
        ejtag_info->reg8 = regs[8];     /* reg8 is saved but not restored, next called function should restore it */
        ejtag_info->reg9 = regs[9];
-exit:
        pracc_queue_free(&ctx);
        return ctx.retval;
 }
@@ -930,54 +910,41 @@ exit:
 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
                int write_t, uint32_t addr, int count, uint32_t *buf)
 {
+       uint32_t isa = ejtag_info->isa ? 1 : 0;
        uint32_t handler_code[] = {
-               /* caution when editing, table is modified below */
                /* r15 points to the start of this code */
-               MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
-               MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
-               MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
-               MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
+               MIPS32_SW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
+               MIPS32_SW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
+               MIPS32_SW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
+               MIPS32_SW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
                /* start of fastdata area in t0 */
-               MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
-               MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
-               MIPS32_LW(9, 0, 8),                                                             /* start addr in t1 */
-               MIPS32_LW(10, 0, 8),                                                    /* end addr to t2 */
-                                                                                                               /* loop: */
-               /* 8 */ MIPS32_LW(11, 0, 0),                                    /* lw t3,[t8 | r9] */
-               /* 9 */ MIPS32_SW(11, 0, 0),                                    /* sw t3,[r9 | r8] */
-               MIPS32_BNE(10, 9, NEG16(3)),                                    /* bne $t2,t1,loop */
-               MIPS32_ADDI(9, 9, 4),                                                   /* addi t1,t1,4 */
-
-               MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
-               MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
-               MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
-               MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
-
-               MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
-               MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
-               MIPS32_JR(15),                                                          /* jr start */
-               MIPS32_MFC0(15, 31, 0),                                         /* move COP0 DeSave to $15 */
-       };
-
-       uint32_t jmp_code[] = {
-               /* 0 */ MIPS32_LUI(15, 0),              /* addr of working area added below */
-               /* 1 */ MIPS32_ORI(15, 15, 0),  /* addr of working area added below */
-               MIPS32_JR(15),                                  /* jump to ram program */
-               MIPS32_NOP,
+               MIPS32_LUI(isa, 8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
+               MIPS32_ORI(isa, 8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
+               MIPS32_LW(isa, 9, 0, 8),                                                /* start addr in t1 */
+               MIPS32_LW(isa, 10, 0, 8),                                               /* end addr to t2 */
+                                       /* loop: */
+               write_t ? MIPS32_LW(isa, 11, 0, 8) : MIPS32_LW(isa, 11, 0, 9),  /* from xfer area : from memory */
+               write_t ? MIPS32_SW(isa, 11, 0, 9) : MIPS32_SW(isa, 11, 0, 8),  /* to memory      : to xfer area */
+
+               MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)),                        /* bne $t2,t1,loop */
+               MIPS32_ADDI(isa, 9, 9, 4),                                      /* addi t1,t1,4 */
+
+               MIPS32_LW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
+               MIPS32_LW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
+               MIPS32_LW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
+               MIPS32_LW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
+
+               MIPS32_LUI(isa, 15, UPPER16(MIPS32_PRACC_TEXT)),
+               MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_PRACC_TEXT) | isa),      /* isa bit for JR instr */
+               MIPS32_JR(isa, 15),                                                             /* jr start */
+               MIPS32_MFC0(isa, 15, 31, 0),                                    /* move COP0 DeSave to $15 */
        };
 
        if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-       if (write_t) {
-               handler_code[8] = MIPS32_LW(11, 0, 8);  /* load data from probe at fastdata area */
-               handler_code[9] = MIPS32_SW(11, 0, 9);  /* store data to RAM @ r9 */
-       } else {
-               handler_code[8] = MIPS32_LW(11, 0, 9);  /* load data from RAM @ r9 */
-               handler_code[9] = MIPS32_SW(11, 0, 8);  /* store data to probe at fastdata area */
-       }
-
-       /* write program into RAM */
+       pracc_swap16_array(ejtag_info, handler_code, ARRAY_SIZE(handler_code));
+               /* write program into RAM */
        if (write_t != ejtag_info->fast_access_save) {
                mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
                /* save previous operation to speed to any consecutive read/writes */
@@ -986,9 +953,16 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are
 
        LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address);
 
-       jmp_code[0] |= UPPER16(source->address);
-       jmp_code[1] |= LOWER16(source->address);
+       uint32_t jmp_code[] = {
+               MIPS32_LUI(isa, 15, UPPER16(source->address)),                  /* load addr of jump in $15 */
+               MIPS32_ORI(isa, 15, 15, LOWER16(source->address) | isa),        /* isa bit for JR instr */
+               MIPS32_JR(isa, 15),                                             /* jump to ram program */
+               isa ? MIPS32_XORI(isa, 15, 15, 1) : MIPS32_NOP, /* drop isa bit, needed for LW/SW instructions */
+       };
+
+       pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code));
 
+       /* execute jump code, with no address check */
        for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) {
                int retval = wait_for_pracc_rw(ejtag_info);
                if (retval != ERROR_OK)
@@ -1026,13 +1000,11 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are
 
        unsigned num_clocks = 0;        /* like in legacy code */
        if (ejtag_info->mode != 0)
-               num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
+               num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000;
 
        for (int i = 0; i < count; i++) {
                jtag_add_clocks(num_clocks);
-               retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
-               if (retval != ERROR_OK)
-                       return retval;
+               mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
        }
 
        retval = jtag_execute_queue();