?? register.c
字號:
/*
* target/arm7tdmi/register.c: implements the ARM7TDMI 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$ */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jtager.h"
#include "jtag.h"
#include "target.h"
#define JTAGER_REGISTER_DEBUG
core_register_t arm7tdmi_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 */
};
/*
* arm7tdmi_r0_read - read the content of R0 register
*/
u32 arm7tdmi_r0_read(void)
{
scan_chain_t *sc1 = &arm7tdmi_target.sc[1];
u32 value;
sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */
sc1->writein[1] = DEBUG_SPEED;
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);
value = sc1->readout[0]; /* get R0 value */
return value;
} /* arm7tdmi_r0_read( ) */
/*
* arm7tdmi_r0_write - write a new value into R0 register
*
* NOTE: It seems only if we must perform two write stage,
* the things will work. What's wrong??? Who can tell me?
* (1) Stage1: write a zero to R0 register.
* (2) Stage2: write the true new value to R0 register.
*/
void arm7tdmi_r0_write(u32 newval)
{
scan_chain_t *sc1 = &arm7tdmi_target.sc[1];
/*
* Stage 1: zero R0 register.
*/
sc1->writein[0] = 0xE5900000; /* LDR R0, [R0] = 0xE5900000 */
sc1->writein[1] = DEBUG_SPEED;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* 1st cycle of LDR instruction */
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* 2nd cycle of LDR instruction -- scan in data */
sc1->writein[0] = 0;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* 3rd cycle of LDR instruction */
sc1->writein[0] = ARM_NOP;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/*
* Stage 2: write the true new value.
*/
sc1->writein[0] = 0xE5900000; /* LDR R0, [R0] = 0xE5900000 */
sc1->writein[1] = DEBUG_SPEED;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* LDR instruction's 1st cycle */
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* LDR instruction's 2nd cycle ... scan in data */
sc1->writein[0] = newval; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* LDR instruction's 3rd cycle */
sc1->writein[0] = ARM_NOP; /* NOP */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
return;
} /* end of arm7tdmi_r0_write(...) */
static u32 arm7tdmi_cpsr_read(void)
{
scan_chain_t *sc1 = &arm7tdmi_target.sc[1];
u32 value;
sc1->writein[0] = 0xE10F0000; /* MRS R0, CPSR */
sc1->writein[1] = DEBUG_SPEED;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* Execute "MRS R0, CPSR" */
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;
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);
value = sc1->readout[0]; /* get CPSR value */
return value;
} /* end of arm7tdmi_cpsr_read() */
static u32 arm7tdmi_spsr_read(void)
{
scan_chain_t *sc1 = &arm7tdmi_target.sc[1];
u32 value;
sc1->writein[0] = 0xE14F0000; /* MRS R0, SPSR */
sc1->writein[1] = DEBUG_SPEED;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = 0xE5800000; /* STR R0, [R0] */
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/* Execute "MRS R0, CPSR" */
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;
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);
value = sc1->readout[0]; /* get SPSR value */
return value;
} /* end of arm7tdmi_spsr_read() */
/*
* arm7tdmi_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 arm7tdmi_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;
/* all the following instructions are executed in debug-speed */
sc1->writein[1] = DEBUG_SPEED;
/* STMIA R0, {R0-R15} = 0xE880FFFF */
sc1->writein[0] = 0xE880FFFF;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
sc1->writein[0] = ARM_NOP;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/*
* Execute "STMIA R0, {R0-R15} while fetching this instruction.
* This is the 1st cycle of STM instruction ...
*/
sc1->writein[0] = ARM_NOP;
arm7tdmi_exec_instruction(sc1->writein, sc1->readout);
/*
* 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++) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -