⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 register.c

📁 一个简易调试器(支持ARM7TDMI)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -