From: Salvador Arroyo Date: Sun, 7 May 2017 09:58:25 +0000 (+0200) Subject: mips32, add support for micromips in debug mode X-Git-Tag: v0.11.0-rc1~1393 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=2279c23cdeaea05839a28ff3addf12b9b0f5357e mips32, add support for micromips in debug mode Micromips is 16bit oriented, branch and jumps are 16 bit based. The upper half 16bits of a 32bit instruction with the major opcode, must go first in the instruction stream, hence the SWAP16 macro and swap16 array function, needed if the code is written as 32 bit word in little endian cores. Endianess info added to ejtag_iinfo. Pointer to ejtag_info and isa field added to pracc context. MIPS32 code are renamed to MIPS32_ISA_... To select the isa, the new code has an additional isa parameter (1 for micromips, 0 for mips32). In JR instruction the isa bit must be set to execute micromips code. The suffix u is added to the OP codes to avoid signed/unsigned comparison errors and to make sure the right shift is performed logically. The isa in debug mode is updated in the poll function. Code for miniprograms, in kernel mode, need to be converted. CFI code only for mips32. Change-Id: I79a8b637d49b0e2d92b6dd5eb5aa8aa0520bf938 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4032 Tested-by: jenkins Reviewed-by: Freddie Chopin --- diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index dca33f6a09..ac0db8271d 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -1424,50 +1424,50 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t static const uint32_t mips_word_16_code[] = { /* start: */ - MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ - MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ - MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ - MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ - MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ - MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ + MIPS32_LHU(0, 9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ + MIPS32_ADDI(0, 4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ + MIPS32_SH(0, 13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ + MIPS32_SH(0, 15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ + MIPS32_SH(0, 7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ + MIPS32_SH(0, 9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ MIPS32_NOP, /* nop */ /* busy: */ - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ - MIPS32_NOP, /* nop */ - - MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ - MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ - MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ - MIPS32_NOP, /* nop */ - - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_NOP, /* nop */ + + MIPS32_SRL(0, 10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ + MIPS32_AND(0, 11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ + MIPS32_BNE(0, 11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ + MIPS32_NOP, /* nop */ + + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_NOP, /* nop */ - MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ - MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ + MIPS32_XOR(0, 9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ + MIPS32_BEQ(0, 9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ MIPS32_NOP, /* nop */ /* cont: */ - MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ - MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ + MIPS32_ADDI(0, 6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ + MIPS32_BNE(0, 6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ MIPS32_NOP, /* nop */ - MIPS32_LUI(9, 0), /* lui $t1, 0 */ - MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ + MIPS32_LUI(0, 9, 0), /* lui $t1, 0 */ + MIPS32_ORI(0, 9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ - MIPS32_B(4), /* b done ; goto done */ + MIPS32_B(0, 4), /* b done ; goto done */ MIPS32_NOP, /* nop */ /* cont2: */ - MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ - MIPS32_B(NEG16(33)), /* b start ; goto start */ + MIPS32_ADDI(0, 5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ + MIPS32_B(0, NEG16(33)), /* b start ; goto start */ MIPS32_NOP, /* nop */ /* done: */ - MIPS32_SDBBP, /* sdbbp ; break(); */ + MIPS32_SDBBP(0), /* sdbbp ; break(); */ }; mips32_info.common_magic = MIPS32_COMMON_MAGIC; diff --git a/src/target/mips32.c b/src/target/mips32.c index cec45499a8..5c85fea8bd 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -383,9 +383,11 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s mips32->ejtag_info.tap = tap; mips32->read_core_reg = mips32_read_core_reg; mips32->write_core_reg = mips32_write_core_reg; - - mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; /* Initial default value */ + /* if unknown endianness defaults to little endian, 1 */ + mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1; + mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; mips32->ejtag_info.mode = 0; /* Initial default value */ + mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */ return ERROR_OK; } diff --git a/src/target/mips32.h b/src/target/mips32.h index 968c3f7b41..d79451fb70 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -122,44 +122,49 @@ struct mips32_algorithm { enum mips32_isa_mode isa_mode; }; -#define MIPS32_OP_ADDIU 0x21 -#define MIPS32_OP_ANDI 0x0C -#define MIPS32_OP_BEQ 0x04 -#define MIPS32_OP_BGTZ 0x07 -#define MIPS32_OP_BNE 0x05 -#define MIPS32_OP_ADDI 0x08 -#define MIPS32_OP_AND 0x24 -#define MIPS32_OP_CACHE 0x2F -#define MIPS32_OP_COP0 0x10 -#define MIPS32_OP_J 0x02 -#define MIPS32_OP_JR 0x08 -#define MIPS32_OP_LUI 0x0F -#define MIPS32_OP_LW 0x23 -#define MIPS32_OP_LBU 0x24 -#define MIPS32_OP_LHU 0x25 -#define MIPS32_OP_MFHI 0x10 -#define MIPS32_OP_MTHI 0x11 -#define MIPS32_OP_MFLO 0x12 -#define MIPS32_OP_MTLO 0x13 -#define MIPS32_OP_RDHWR 0x3B -#define MIPS32_OP_SB 0x28 -#define MIPS32_OP_SH 0x29 -#define MIPS32_OP_SW 0x2B -#define MIPS32_OP_ORI 0x0D -#define MIPS32_OP_XORI 0x0E -#define MIPS32_OP_XOR 0x26 -#define MIPS32_OP_SLTU 0x2B -#define MIPS32_OP_SRL 0x03 -#define MIPS32_OP_SYNCI 0x1F - -#define MIPS32_OP_REGIMM 0x01 -#define MIPS32_OP_SDBBP 0x3F -#define MIPS32_OP_SPECIAL 0x00 -#define MIPS32_OP_SPECIAL2 0x07 -#define MIPS32_OP_SPECIAL3 0x1F - -#define MIPS32_COP0_MF 0x00 -#define MIPS32_COP0_MT 0x04 +#define MIPS32_OP_ADDU 0x21u +#define MIPS32_OP_ADDIU 0x09u +#define MIPS32_OP_ANDI 0x0Cu +#define MIPS32_OP_BEQ 0x04u +#define MIPS32_OP_BGTZ 0x07u +#define MIPS32_OP_BNE 0x05u +#define MIPS32_OP_ADDI 0x08u +#define MIPS32_OP_AND 0x24u +#define MIPS32_OP_CACHE 0x2Fu +#define MIPS32_OP_COP0 0x10u +#define MIPS32_OP_J 0x02u +#define MIPS32_OP_JR 0x08u +#define MIPS32_OP_LUI 0x0Fu +#define MIPS32_OP_LW 0x23u +#define MIPS32_OP_LB 0x20u +#define MIPS32_OP_LBU 0x24u +#define MIPS32_OP_LHU 0x25u +#define MIPS32_OP_MFHI 0x10u +#define MIPS32_OP_MTHI 0x11u +#define MIPS32_OP_MFLO 0x12u +#define MIPS32_OP_MTLO 0x13u +#define MIPS32_OP_RDHWR 0x3Bu +#define MIPS32_OP_SB 0x28u +#define MIPS32_OP_SH 0x29u +#define MIPS32_OP_SW 0x2Bu +#define MIPS32_OP_ORI 0x0Du +#define MIPS32_OP_XORI 0x0Eu +#define MIPS32_OP_XOR 0x26u +#define MIPS32_OP_SLTU 0x2Bu +#define MIPS32_OP_SRL 0x03u +#define MIPS32_OP_SYNCI 0x1Fu +#define MIPS32_OP_SLL 0x00u +#define MIPS32_OP_SLTI 0x0Au +#define MIPS32_OP_MOVN 0x0Bu + +#define MIPS32_OP_REGIMM 0x01u +#define MIPS32_OP_SDBBP 0x3Fu +#define MIPS32_OP_SPECIAL 0x00u +#define MIPS32_OP_SPECIAL2 0x07u +#define MIPS32_OP_SPECIAL3 0x1Fu + +#define MIPS32_COP0_MF 0x00u +#define MIPS32_COP0_MT 0x04u #define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct)) @@ -167,41 +172,52 @@ struct mips32_algorithm { (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd)) #define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr)) -#define MIPS32_NOP 0 -#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) -#define MIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDIU) -#define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND) -#define MIPS32_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) -#define MIPS32_B(off) MIPS32_BEQ(0, 0, off) -#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) -#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) -#define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) -#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) -#define MIPS32_J(tar) MIPS32_J_INST(MIPS32_OP_J, tar) -#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) -#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) -#define MIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) -#define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) -#define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) -#define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) -#define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) -#define MIPS32_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) -#define MIPS32_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) -#define MIPS32_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) -#define MIPS32_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) -#define MIPS32_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) -#define MIPS32_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) -#define MIPS32_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) -#define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) -#define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) -#define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) -#define MIPS32_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) -#define MIPS32_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) -#define MIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) -#define MIPS32_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) - -#define MIPS32_SYNC 0xF -#define MIPS32_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ +#define MIPS32_ISA_NOP 0 +#define MIPS32_ISA_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) +#define MIPS32_ISA_ADDIU(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDIU, src, tar, val) +#define MIPS32_ISA_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDU) +#define MIPS32_ISA_AND(dst, src, tar) MIPS32_R_INST(0, src, tar, dst, 0, MIPS32_OP_AND) +#define MIPS32_ISA_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) + +#define MIPS32_ISA_B(off) MIPS32_ISA_BEQ(0, 0, off) +#define MIPS32_ISA_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) +#define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) +#define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) +#define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) +#define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) +#define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) + +#define MIPS32_ISA_LB(reg, off, base) MIPS32_I_INST(MIPS32_OP_LB, base, reg, off) +#define MIPS32_ISA_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) +#define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) +#define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) +#define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) + +#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) +#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) +#define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) +#define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) +#define MIPS32_ISA_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) + +#define MIPS32_ISA_MOVN(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_MOVN) +#define MIPS32_ISA_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) +#define MIPS32_ISA_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) +#define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) +#define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) +#define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) + +#define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) +#define MIPS32_ISA_SLTI(tar, src, val) MIPS32_I_INST(MIPS32_OP_SLTI, src, tar, val) +#define MIPS32_ISA_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) +#define MIPS32_ISA_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) +#define MIPS32_ISA_SYNC 0xFu +#define MIPS32_ISA_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) + +#define MIPS32_ISA_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) +#define MIPS32_ISA_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) + +#define MIPS32_ISA_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ /** * Cache operations definitions @@ -213,9 +229,10 @@ struct mips32_algorithm { #define MIPS32_CACHE_I_HIT_INVALIDATE ((0x0 << 0) | (0x4 << 2)) /* ejtag specific instructions */ -#define MIPS32_DRET 0x4200001F -#define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */ -#define MIPS16_SDBBP 0xE801 +#define MIPS32_ISA_DRET 0x4200001Fu +/* MIPS32_ISA_J_INST(MIPS32_ISA_OP_SPECIAL2, MIPS32_ISA_OP_SDBBP) */ +#define MIPS32_ISA_SDBBP 0x7000003Fu +#define MIPS16_ISA_SDBBP 0xE801u /*MICRO MIPS INSTRUCTIONS, see doc MD00582 */ #define POOL32A 0X00u @@ -270,7 +287,7 @@ struct mips32_algorithm { #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) #define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) -#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, (0x07FFFFFFu & (tar)) >> 1) +#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) #define MMIPS32_JR(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_JALR, POOL32AXf) #define MMIPS32_LB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LB, reg, base, off) #define MMIPS32_LBU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LBU, reg, base, off) @@ -311,6 +328,59 @@ struct mips32_algorithm { #define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1BD, POOL32AXf) */ #define MMIPS16_SDBBP 0x46C0u /* POOL16C instr */ +/* instruction code with isa selection */ +#define MIPS32_NOP 0 /* same for both isa's */ +#define MIPS32_ADDI(isa, tar, src, val) (isa ? MMIPS32_ADDI(tar, src, val) : MIPS32_ISA_ADDI(tar, src, val)) +#define MIPS32_ADDIU(isa, tar, src, val) (isa ? MMIPS32_ADDIU(tar, src, val) : MIPS32_ISA_ADDIU(tar, src, val)) +#define MIPS32_ADDU(isa, dst, src, tar) (isa ? MMIPS32_ADDU(dst, src, tar) : MIPS32_ISA_ADDU(dst, src, tar)) +#define MIPS32_AND(isa, dst, src, tar) (isa ? MMIPS32_AND(dst, src, tar) : MIPS32_ISA_AND(dst, src, tar)) +#define MIPS32_ANDI(isa, tar, src, val) (isa ? MMIPS32_ANDI(tar, src, val) : MIPS32_ISA_ANDI(tar, src, val)) + +#define MIPS32_B(isa, off) (isa ? MMIPS32_B(off) : MIPS32_ISA_B(off)) +#define MIPS32_BEQ(isa, src, tar, off) (isa ? MMIPS32_BEQ(src, tar, off) : MIPS32_ISA_BEQ(src, tar, off)) +#define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) +#define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) +#define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) + +#define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) +#define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) +#define MIPS32_LB(isa, reg, off, base) (isa ? MMIPS32_LB(reg, off, base) : MIPS32_ISA_LB(reg, off, base)) +#define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) +#define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) +#define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) +#define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) + +#define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) +#define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) +#define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) +#define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) +#define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) +#define MIPS32_MTHI(isa, reg) (isa ? MMIPS32_MTHI(reg) : MIPS32_ISA_MTHI(reg)) + +#define MIPS32_MOVN(isa, dst, src, tar) (isa ? MMIPS32_MOVN(dst, src, tar) : MIPS32_ISA_MOVN(dst, src, tar)) +#define MIPS32_ORI(isa, tar, src, val) (isa ? MMIPS32_ORI(tar, src, val) : MIPS32_ISA_ORI(tar, src, val)) +#define MIPS32_RDHWR(isa, tar, dst) (isa ? MMIPS32_RDHWR(tar, dst) : MIPS32_ISA_RDHWR(tar, dst)) +#define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) +#define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) +#define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) + +#define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) +#define MIPS32_SLTI(isa, tar, src, val) (isa ? MMIPS32_SLTI(tar, src, val) : MIPS32_ISA_SLTI(tar, src, val)) +#define MIPS32_SLTU(isa, dst, src, tar) (isa ? MMIPS32_SLTU(dst, src, tar) : MIPS32_ISA_SLTU(dst, src, tar)) +#define MIPS32_SRL(isa, reg, src, off) (isa ? MMIPS32_SRL(reg, src, off) : MIPS32_ISA_SRL(reg, src, off)) + +#define MIPS32_SYNCI(isa, off, base) (isa ? MMIPS32_SYNCI(off, base) : MIPS32_ISA_SYNCI(off, base)) +#define MIPS32_SYNC(isa) (isa ? MMIPS32_SYNC : MIPS32_ISA_SYNC) +#define MIPS32_XOR(isa, reg, val1, val2) (isa ? MMIPS32_XOR(reg, val1, val2) : MIPS32_ISA_XOR(reg, val1, val2)) +#define MIPS32_XORI(isa, tar, src, val) (isa ? MMIPS32_XORI(tar, src, val) : MIPS32_ISA_XORI(tar, src, val)) + +#define MIPS32_SYNCI_STEP 0x1 + +/* ejtag specific instructions */ +#define MIPS32_DRET(isa) (isa ? MMIPS32_DRET : MIPS32_ISA_DRET) +#define MIPS32_SDBBP(isa) (isa ? MMIPS32_SDBBP : MIPS32_ISA_SDBBP) + +#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP) extern const struct command_registration mips32_command_handlers[]; diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 7324246388..790c8dc93e 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -122,8 +122,8 @@ static void mips32_pracc_finish(struct mips_ejtag *ejtag_info) 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 +148,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); @@ -163,7 +163,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct 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; @@ -186,12 +186,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); @@ -202,8 +202,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; } @@ -227,7 +227,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; @@ -264,13 +265,14 @@ 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; } @@ -307,6 +309,7 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) ctx->store_count = 0; ctx->max_code = 0; ctx->pracc_list = NULL; + ctx->isa = ctx->ejtag_info->isa ? 1 : 0; } void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) @@ -332,12 +335,12 @@ void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) 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(reg_num, UPPER16(data))); /* load only upper value */ + 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(reg_num, 0, LOWER16(data))); /* load only lower */ + pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, 0, LOWER16(data))); /* load only lower */ else { - pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load upper and lower */ - pracc_add(ctx, 0, MIPS32_ORI(reg_num, reg_num, LOWER16(data))); + 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))); } } @@ -355,6 +358,10 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in 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, check_last); @@ -449,17 +456,17 @@ exit: int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - 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) */ + 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(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + 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, 1); pracc_queue_free(&ctx); @@ -471,10 +478,10 @@ 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); + uint32_t *data = NULL; if (size != 4) { data = malloc(256 * sizeof(uint32_t)); if (data == NULL) { @@ -490,35 +497,36 @@ 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_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, 1); @@ -549,17 +557,17 @@ exit: 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - 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, 1); pracc_queue_free(&ctx); @@ -568,14 +576,14 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ - pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ - 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, 1); pracc_queue_free(&ctx); @@ -612,23 +620,23 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); /** 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_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, &clsiz, 1); if (ctx.retval != ERROR_OK) @@ -663,45 +671,48 @@ 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, 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, 1); exit: @@ -712,7 +723,7 @@ 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); const uint32_t *buf32 = buf; @@ -722,31 +733,32 @@ 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) { - pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */ - pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */ + 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; @@ -754,8 +766,8 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, 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, 1); if (ctx.retval != ERROR_OK) @@ -824,18 +836,18 @@ 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); + 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); @@ -844,10 +856,10 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) 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, 1); @@ -859,37 +871,37 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) 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; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - 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, 1); @@ -909,38 +921,40 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) 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[] = { /* 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 */ + 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(11, 0, 8) : MIPS32_LW(11, 0, 9), /* from xfer area : from memory */ - write_t ? MIPS32_SW(11, 0, 9) : MIPS32_SW(11, 0, 8), /* to memory : to xfer area */ + 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(10, 9, NEG16(3)), /* bne $t2,t1,loop */ - MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ + MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)), /* bne $t2,t1,loop */ + MIPS32_ADDI(isa, 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_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(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 */ + 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; + 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); @@ -951,12 +965,14 @@ 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); uint32_t jmp_code[] = { - MIPS32_LUI(15, UPPER16(source->address)), /* load addr of jump in $15 */ - MIPS32_ORI(15, 15, LOWER16(source->address)), - MIPS32_JR(15), /* jump to ram program */ - MIPS32_NOP, + 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); diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index e990f8d0c7..fe9f814a39 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -40,6 +40,7 @@ #define UPPER16(uint32_t) (uint32_t >> 16) #define LOWER16(uint32_t) (uint32_t & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF) +#define SWAP16(v) ((LOWER16(v) << 16) | (UPPER16(v))) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ #define PRACC_BLOCK 128 /* 1 Kbyte */ @@ -50,12 +51,15 @@ typedef struct { } pa_list; struct pracc_queue_info { + struct mips_ejtag *ejtag_info; + unsigned isa; int retval; int code_count; int store_count; int max_code; /* max intstructions with currently allocated memory */ pa_list *pracc_list; /* Code and store addresses at dmseg */ }; + void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize); @@ -108,4 +112,11 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); +inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) +{ + if (ejtag_info->isa && ejtag_info->endianness) + for (int i = 0; i != count; i++) + buf[i] = SWAP16(buf[i]); +} + #endif /* OPENOCD_TARGET_MIPS32_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index e35758d1f8..d335c1bbd8 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -197,18 +197,18 @@ void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) /* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 23, 0)); /* move COP0 Debug to $8 */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, 0x0100)); /* set SSt bit in debug reg */ if (!enable_step) - pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_XORI(ctx.isa, 8, 8, 0x0100)); /* clear SSt bit in debug reg */ - pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */ - 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 */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 8, 23, 0)); /* move $8 to COP0 Debug */ + 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, NULL, 1); pracc_queue_free(&ctx); @@ -269,11 +269,11 @@ error: int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { - pa_list pracc_list = {.instr = MIPS32_DRET, .addr = 0}; + pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0}; struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 3043df90e9..ade1b4c709 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -58,6 +58,7 @@ #define EJTAG_CTRL_DERR (1 << 10) #define EJTAG_CTRL_DSTRT (1 << 11) #define EJTAG_CTRL_JTAGBRK (1 << 12) +#define EJTAG_CTRL_DBGISA (1 << 13) #define EJTAG_CTRL_SETDEV (1 << 14) #define EJTAG_CTRL_PROBEN (1 << 15) #define EJTAG_CTRL_PRRST (1 << 16) @@ -189,6 +190,8 @@ struct mips_ejtag { uint32_t pa_ctrl; uint32_t pa_addr; unsigned int ejtag_version; + uint32_t isa; + uint32_t endianness; /* Memory-Mapped Registers. This addresses are not same on different * EJTAG versions. */ diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index bd3c602288..8b32d115a2 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -195,6 +195,8 @@ static int mips_m4k_poll(struct target *target) if (retval != ERROR_OK) return retval; + ejtag_info->isa = (ejtag_ctrl & EJTAG_CTRL_DBGISA) ? 1 : 0; + /* clear this bit before handling polling * as after reset registers will read zero */ if (ejtag_ctrl & EJTAG_CTRL_ROCC) { @@ -648,14 +650,14 @@ static int mips_m4k_set_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP); + retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa)); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS32_SDBBP) { + if (verify != MIPS32_SDBBP(ejtag_info->isa)) { LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; @@ -667,14 +669,14 @@ static int mips_m4k_set_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP); + retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa)); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS16_SDBBP) { + if (verify != MIPS16_SDBBP(ejtag_info->isa)) { LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; @@ -735,7 +737,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, */ current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS32_SDBBP) { + if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) { retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) @@ -750,7 +752,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS16_SDBBP) { + if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) { retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK)