void arm9tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc) { int retval = ERROR_OK; /* get pointers to arch-specific information */ armv4_5_common_t *armv4_5 = target->arch_info; arm7_9_common_t *arm7_9 = armv4_5->arch_info; arm_jtag_t *jtag_info = &arm7_9->jtag_info; /* save r0 before using it and put system in ARM state * to allow common handling of ARM and THUMB debugging */ /* fetch STR r0, [r0] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* STR r0, [r0] in Memory */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0); /* MOV r0, r15 fetched, STR in Decode */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* nothing fetched, STR r0, [r0] in Memory */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0); /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0); /* LDR in Decode */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* LDR in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* LDR in Memory (to account for interlock) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* fetch BX */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0); /* NOP fetched, BX in Decode, MOV in Execute */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); /* NOP fetched, BX in Execute (1) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0); if((retval = jtag_execute_queue()) != ERROR_OK) { return; } /* fix program counter: * MOV r0, r15 was the 5th instruction (+8) * reading PC in Thumb state gives address of instruction + 4 */ *pc -= 0xc; }
static void arm7tdmi_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* save r0 before using it and put system in ARM state * to allow common handling of ARM and THUMB debugging */ /* fetch STR r0, [r0] */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, r0); /* MOV r0, r15 fetched, STR in Decode */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, pc); /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* nothing fetched, data for LDR r0, [PC, #0] */ arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0); /* nothing fetched, data from previous cycle is written to register */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* fetch BX */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0); /* NOP fetched, BX in Decode, MOV in Execute */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); /* NOP fetched, BX in Execute (1) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); jtag_execute_queue(); /* fix program counter: * MOV r0, r15 was the 4th instruction (+6) * reading PC in Thumb state gives address of instruction + 4 */ *pc -= 0xa; }