📄 register.c
字号:
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
target->regs[i].value = sc1->readout[0];
}
/*
* Read CPSR and SPSR registers ...
*/
cpsr->value = arm7tdmi_cpsr_read();
if ((cpsr->value & 0x1f) != 0x10) {
spsr->value = arm7tdmi_spsr_read();
} else {
/* If the target is in User-Mode, the don't touch SPSR register,
* because there is no SPSR register in User-Mode.
*/
spsr->value = 0;
}
/*
* restore R0 register
*/
arm7tdmi_r0_write(arm7tdmi_target.regs[0].value);
/*
* Finally, correct the value of PC to the real halted point.
* Entry into debug state by external DBGRQ will advance
* the PC by three addresses or 12 bytes. Reading out the
* value of R15 needs to execute two instructions in debug
* state, which will advance the PC by two addresses or 8
* bytes.
*/
if (target->halt_reason == TARGET_HALTED_BY_DBGRQ)
target->regs[15].value -= (3 + 2) * 4;
else
target->regs[15].value -= (4 + 2) * 4;
reg_pc->value = target->regs[15].value;
return 0;
} /* end of arm7tdmi_get_core_state(...) */
/*
* arm7tdmi_register_read - read some specific register
*/
int arm7tdmi_register_read(core_register_t *reg)
{
scan_chain_t *sc1 = &target->sc[1];
u32 r0_val; /* the value of R0 */
char *tmp;
u32 reg_num;
int retval;
if (!reg || !reg->name)
return -ERR_TARGET_UNKNOWN_REG;
else if (target->status == TARGET_STATUS_RUNNING)
return -ERR_TARGET_IS_RUNNING;
else if (target->mode == TARGET_MODE_THUMB)
return -ERR_TARGET_IN_THUMB_MODE;
else if (strcasecmp(reg->name, "SPSR") == 0) {
/* Only if we have an valid CPSR register value, we can
* read/write SPSR register value.
*/
if (reg_index("CPSR")->value == 0)
return -ERR_TARGET_INVALID_CPSR;
/* no SPSR register in user mode */
if ((reg_index("CPSR")->value & 0x1F) == 0x10)
return -ERR_TARGET_NO_SPSR;
}
/*
* Select scan chain 1, and use INTEST instruction to make scan
* chain 1 into the internal test mode.
*/
retval = jtag_select_scanchain(1);
if (retval)
return retval;
retval = jtag_write_ireg(JTAG_INTEST);
if (retval)
return retval;
/* all the following instructions are executed in debug-speed */
sc1->writein[1] = DEBUG_SPEED;
/*
* If the register to read is not R0, then we first
* save the content of R0 register.
*/
r0_val = arm7tdmi_r0_read();
if (strcasecmp(reg->name, "R0") == 0) {
/* just return directly */
reg->value = r0_val;
return 0;
}
/*
* We first copy the content of Source Register to R0.
* NOTE: This will clobber R0 register.
*/
if (strcasecmp(reg->name, "CPSR") == 0) {
/* MRS R0, CPSR = 0xE10F0000 */
sc1->writein[0] = 0xE10F0000;
} else if (strcasecmp(reg->name, "SPSR") == 0) {
/* MRS R0, SPSR = 0xE14F0000 */
sc1->writein[0] = 0xE14F0000;
} else if (strcasecmp(reg->name, "PC") == 0) {
/* MOV R0, PC = 0xE1A0000F */
sc1->writein[0] = 0xE1A0000F;
} else { /* R1 - R15 */
/* MOV R0, Rxx = 0xE1A0000x */
sc1->writein[0] = 0xE1A00000;
tmp = reg->name + 1;
str2int(tmp, ®_num);
/* set the Rm bits (bit[3:0]) of the OPCODE of
* the "MOV R0, Rxx" instruction
*/
sc1->writein[0] |= (reg_num & 0x0f);
}
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* Execute "STR R0, [R0]" -- read out R0
* This is 1st cycle of STR instruction.
* In the 2nd cycle, R0's value will be visible on the data bus.
*/
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* 2nd cycle of STR instruction */
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/*
* OK, we get the value we want ...
*/
reg->value = sc1->readout[0];
/*
* Finally, restore R0 register ...
*/
arm7tdmi_r0_write(r0_val);
return 0;
} /* end of arm7tdmi_register_read(...) */
/*
* LDR R0, [R0] = 0xE5900000
* OPCODE: cond = AL (1110), always executed.
* bit[27:26] = 01, fixed.
* I bit (bit[25]) = 0, Offset is an immediate value.
* P bit (bit[24]) = 1, Pre: add offset before transfer.
* U bit (bit[23]) = 1, Up: Add offset to base.
* B bit (bit[22]) = 0, transfer word quantity.
* W bit(bit[21]) = 0, No write-back to base.
* L bit(bit[20]) = 1, Store instruction.
* Rn (bit[19:16]) = 0000, R0 is the Base Register.
* Rd (bit[15:12]) = 0000, R0 is the Source Register.
* Offset (bit[11:0]) = 0x0.
* 1110 0101 1001 0000 0000 0000 0000 0000 = 0xE5900000
*/
int arm7tdmi_register_write(core_register_t *reg, u32 value)
{
scan_chain_t *sc1 = &target->sc[1];
u32 r0_val = 0; /* the value of R0 */
u32 data;
char *tmp;
u32 reg_num;
int retval;
if (!reg || !reg->name)
return -ERR_TARGET_UNKNOWN_REG;
else if (target->status == TARGET_STATUS_RUNNING)
return -ERR_TARGET_IS_RUNNING;
else if (target->mode == TARGET_MODE_THUMB)
return -ERR_TARGET_IN_THUMB_MODE;
else if (strcasecmp(reg->name, "SPSR") == 0) {
/* Only if we have an valid CPSR register value, we can
* read/write SPSR register value.
*/
if (reg_index("CPSR")->value == 0)
return -ERR_TARGET_INVALID_CPSR;
/* no SPSR register in user mode */
if ((reg_index("CPSR")->value & 0x1F) == 0x10)
return -ERR_TARGET_NO_SPSR;
}
/*
* Select scan chain 1, and use INTEST instruction to make scan
* chain 1 into the internal test mode.
*/
retval = jtag_select_scanchain(1);
if (retval)
return retval;
retval = jtag_write_ireg(JTAG_INTEST);
if (retval)
return retval;
/* all instructions are executed in debug-speed */
sc1->writein[1] = DEBUG_SPEED;
/*
* Step 1: If the register to write is not R0, then
* we first save the content of R0 register.
*/
if (strcasecmp(reg->name, "R0") != 0)
r0_val = arm7tdmi_r0_read();
/*
* Step 2: write the new value into R0 register.
* And if R0 is the destination register, just return directly.
*/
data = value;
if (strcasecmp(reg->name, "CPSR") == 0) {
data &= 0xF00000FF;
data &= (~(0x00000020)); /* never change T bit (bit[5]) */
if ((reg->value & 0x0000001F) == 0x10) {
/* in User mode : never change the
* control bits of CPSR (bit[7:0])
*/
data &= 0xFFFFFF00;
}
} else if (strcasecmp(reg->name, "SPSR") == 0) {
data &= 0xF00000FF;
data &= (~(0x00000020)); /* never change T bit (bit[5]) */
}
reg->value = data; /* update our copy */
arm7tdmi_r0_write(data); /* write new value into R0 */
if (strcasecmp(reg->name, "R0") == 0)
return 0;
/*
* Step 3: move the value of R0 to the dest register.
*/
if (strcasecmp(reg->name, "CPSR") == 0) {
/* MSR CPSR, R0 */
sc1->writein[0] = 0xE129F000;
} else if (strcasecmp(reg->name, "SPSR") == 0) {
/* MSR SPSR, R0 */
sc1->writein[0] = 0xE169F000;
} else if (strcasecmp(reg->name, "PC") == 0) {
/* MOV R15, R0 */
sc1->writein[0] = 0xE1A0F000;
} else { /* R1 - R15 */
/* MOV Rxx, R0 */
sc1->writein[0] = 0xE1A00000;
tmp = reg->name + 1;
str2int(tmp, ®_num);
/* set the Rd bits (bit[15:12]) of the OPCODE of
* the "MOV Rxx, R0" instruction
*/
sc1->writein[0] |= ((reg_num << 12) & 0x0000F000);
}
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/*
* Finally, restore R0 register
*/
arm7tdmi_r0_write(r0_val);
return 0;
} /* end of arm7tdmi_register_write(...) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -