📄 register.c
字号:
/* * target/arm9tdmi/register.c: implements the ARM9TDMI target core's registers * read/write operations. * * Copyright (C) 2003, Rongkai zhan <zhanrk@163.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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* $Id: register.c,v 1.3 2004/10/17 13:54:32 zhanrk Exp $ */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "jtager.h"#include "jtag.h"#include "target.h"core_register_t arm9tdmi_regs[] = { {"R0", 0x0L}, {"R1", 0x0L}, {"R2", 0x0L}, {"R3", 0x0L}, {"R4", 0x0L}, {"R5", 0x0L}, {"R6", 0x0L}, {"R7", 0x0L}, {"R8", 0x0L}, {"R9", 0x0L}, {"R10", 0x0L}, {"R11", 0x0L}, {"R12", 0x0L}, {"R13", 0x0L}, {"R14", 0x0L}, {"R15", 0x0L}, {"PC", 0x0L}, {"CPSR", 0x0L}, {"SPSR", 0x0L}, {NULL, 0x0L} /* the last element must be NULL */};/* * arm9tdmi_r0_read - read the content of R0 register */u32 arm9tdmi_r0_read(void){ scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; u32 value; sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */ sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 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 */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 2nd cycle of STR instruction */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); value = sc1->readout[0]; /* get R0 value */ return value;} /* arm9tdmi_r0_read( ) *//* * arm9tdmi_r0_write - write a new value into R0 register */void arm9tdmi_r0_write(u32 newval){ scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; sc1->writein[0] = 0xE5900000; /* LDR R0, [R0] = 0xE5900000 */ sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* LDR instruction's 1st cycle */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* LDR instruction's 2nd cycle ... scan in data */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = newval; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* LDR instruction's 3rd cycle */ sc1->writein[0] = ARM_NOP; /* NOP */ sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); return;} /* end of arm9tdmi_r0_write(...) */static u32 arm9tdmi_cpsr_read(void){ scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; u32 value; sc1->writein[0] = 0xE10F0000; /* MRS R0, CPSR */ sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* Execute "MRS R0, CPSR" */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 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; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 2nd cycle of STR instruction */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); value = sc1->readout[0]; /* get CPSR value */ return value;} /* end of arm9tdmi_cpsr_read() */static u32 arm9tdmi_spsr_read(void){ scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; u32 value; sc1->writein[0] = 0xE14F0000; /* MRS R0, SPSR */ sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* Execute "MRS R0, CPSR" */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 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; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* 2nd cycle of STR instruction */ sc1->writein[0] = ARM_NOP; /* NOP */ arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); value = sc1->readout[0]; /* get SPSR value */ return value;} /* end of arm9tdmi_spsr_read() *//* * arm9tdmi_get_core_state - Read all registers of cpu core * * NOTE: We use the following instructions sequence to determine * the internal state of ARM7TDMI core: * STMIA R0, {R0-R15} ; make the contents of R1-R15 registers * ; visible on the data bus. * MRS R0, CPSR ; copy CPSR to R0 * STR R0, [R0] ; make CPSR's content visible on the data bus. * MRS R0, SPSR ; copy SPSR to R0 * STR R0, [R0] ; make SPSR's content visible on the data bus. * ; At the same time, we read out the value of CPSR. * MOV R0, R0 ; NOP * MOV R0, R0 ; NOP, read out the value of SPSR. * * NOTICE: All the above instructions are executed in debug-speed. * * STMIA R0, {R0-R15} = 0xE880FFFF * OPCODE: cond = AL (1110), always executed. * bit[27:25] = 100, fixed. * P bit (bit[24]) = 0, Post: add offset after transfer. * U bit (bit[23]) = 1, Up: add offset to base. * S bit (bit[22]) = 0. * W bit (bit[21]) = 0, do not update base register. * L bit (bit[20]) = 0, Store instruction. * Rn (bit[19:16]) = 0000, R0 is the base register. * Register List (bit[15:0]) = FFFF, all register is invovled. * 1110 1000 1000 0000 1111 1111 1111 1111 = 0xE880FFFF * * MRS R0, CPSR = 0xE10F0000 * STR R0, [R0] = 0xE5800000 * MRS R0, SPSR = 0xE14F0000 * MOV R0, R0 ; NOP, OPCODE = 0xE1A00000 */int arm9tdmi_get_core_state(void){ int i, retval; core_register_t *reg_pc = reg_index("PC"); core_register_t *cpsr = reg_index("CPSR"); core_register_t *spsr = reg_index("SPSR"); scan_chain_t *sc1 = &target->sc[1]; if (target->status == TARGET_STATUS_RUNNING) return -ERR_TARGET_IS_RUNNING; else if (target->mode == TARGET_MODE_THUMB) return -ERR_TARGET_IN_THUMB_MODE; /* * 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; /* STMIA R0, {R0-R15} = 0xE880FFFF */ sc1->writein[0] = 0xE880FFFF; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Execute "STMIA R0, {R0-R15} while fetching this instruction. * This is the 1st cycle of STM instruction ... */ sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Read out the contents of r0-r15 registers in the * next 16 cycles of STM instruction. */ sc1->writein[0] = ARM_NOP; for (i = 0; i <= 15; i++) { arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); target->regs[i].value = sc1->readout[0]; } /* * Read CPSR and SPSR registers ... */ cpsr->value = arm9tdmi_cpsr_read(); if ((cpsr->value & 0x1f) != 0x10) { spsr->value = arm9tdmi_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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -