/* debug_unit.c -- Simulation of Or1k debug unit
|
/* debug_unit.c -- Simulation of Or1k debug unit
|
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
|
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
/*
|
/*
|
This is an architectural level simulation of the Or1k debug
|
This is an architectural level simulation of the Or1k debug
|
unit as described in OpenRISC 1000 System Architecture Manual,
|
unit as described in OpenRISC 1000 System Architecture Manual,
|
v. 0.1 on 22 April, 2001. This unit is described in Section 13.
|
v. 0.1 on 22 April, 2001. This unit is described in Section 13.
|
|
|
Every attempt has been made to be as accurate as possible with
|
Every attempt has been made to be as accurate as possible with
|
respect to the registers and the behavior. There are no known
|
respect to the registers and the behavior. There are no known
|
limitations at this time.
|
limitations at this time.
|
*/
|
*/
|
|
|
//#define DEBUG_JTAG 0
|
//#define DEBUG_JTAG 0
|
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <string.h>
|
#include <string.h>
|
#include <inttypes.h>
|
#include <inttypes.h>
|
|
|
#include "debug_unit.h"
|
#include "debug_unit.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "except.h"
|
#include "except.h"
|
#include "arch.h"
|
#include "arch.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "parse.h"
|
#include "parse.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "gdb.h"
|
#include "gdb.h"
|
#include "../cpu/or1k/except.h"
|
#include "../cpu/or1k/except.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
|
|
DevelopmentInterface development;
|
DevelopmentInterface development;
|
|
|
/* External STALL signal to debug interface */
|
/* External STALL signal to debug interface */
|
int in_reset = 0;
|
int in_reset = 0;
|
|
|
/* Risc stall state */
|
/* Risc stall state */
|
int cpu_stalled = 0;
|
int cpu_stalled = 0;
|
|
|
/* Current watchpoint state */
|
/* Current watchpoint state */
|
unsigned long watchpoints = 0;
|
unsigned long watchpoints = 0;
|
|
|
static int calculate_watchpoints ();
|
static int calculate_watchpoints ();
|
|
|
static int watchpoint[10];
|
static int watchpoint[10];
|
|
|
void set_stall_state(int state)
|
void set_stall_state(int state)
|
{
|
{
|
development.riscop &= ~RISCOP_STALL;
|
development.riscop &= ~RISCOP_STALL;
|
development.riscop |= state ? RISCOP_STALL : 0;
|
development.riscop |= state ? RISCOP_STALL : 0;
|
if(testsprbits(SPR_DMR1, SPR_DMR1_DXFW)) /* If debugger disabled */
|
if(testsprbits(SPR_DMR1, SPR_DMR1_DXFW)) /* If debugger disabled */
|
state = 0;
|
state = 0;
|
cpu_stalled = state;
|
cpu_stalled = state;
|
}
|
}
|
|
|
void du_reset()
|
void du_reset()
|
{
|
{
|
development.riscop = 0;
|
development.riscop = 0;
|
set_stall_state (0);
|
set_stall_state (0);
|
}
|
}
|
|
|
inline int CheckDebugUnit(DebugUnitAction action, unsigned long udata)
|
inline int CheckDebugUnit(DebugUnitAction action, unsigned long udata)
|
{
|
{
|
/* Do not stop, if we have debug module disabled or during reset */
|
/* Do not stop, if we have debug module disabled or during reset */
|
if(!config.debug.enabled || in_reset)
|
if(!config.debug.enabled || in_reset)
|
return 0;
|
return 0;
|
|
|
/* If we're single stepping, always stop */
|
/* If we're single stepping, always stop */
|
if(action == DebugInstructionFetch && testsprbits (SPR_DMR1, SPR_DMR1_ST))
|
if(action == DebugInstructionFetch && testsprbits (SPR_DMR1, SPR_DMR1_ST))
|
return 1;
|
return 1;
|
|
|
return 0;
|
return 0;
|
/* TODO: Enable matchpoints
|
/* TODO: Enable matchpoints
|
switch(action)
|
switch(action)
|
{
|
{
|
case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break;
|
case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break;
|
case DebugLoadAddress: condition = DCR_CT_LoadAddress; break;
|
case DebugLoadAddress: condition = DCR_CT_LoadAddress; break;
|
case DebugStoreAddress: condition = DCR_CT_StoreAddress; break;
|
case DebugStoreAddress: condition = DCR_CT_StoreAddress; break;
|
case DebugLoadData: condition = DCR_CT_LoadData; break;
|
case DebugLoadData: condition = DCR_CT_LoadData; break;
|
case DebugStoreData: condition = DCR_CT_StoreData; break;
|
case DebugStoreData: condition = DCR_CT_StoreData; break;
|
}
|
}
|
|
|
return calculate_watchpoints(); */
|
return calculate_watchpoints(); */
|
}
|
}
|
|
|
/* Checks whether we should stall the RISC or cause an exception */
|
/* Checks whether we should stall the RISC or cause an exception */
|
static int calculate_watchpoints()
|
static int calculate_watchpoints()
|
{
|
{
|
int breakpoint = 0;
|
int breakpoint = 0;
|
int i, bit;
|
int i, bit;
|
|
|
/* Hopefully this loop would be unrolled run at max. speed */
|
/* Hopefully this loop would be unrolled run at max. speed */
|
for(i = 0, bit = 1; i < 11; i++, bit <<= 1) {
|
for(i = 0, bit = 1; i < 11; i++, bit <<= 1) {
|
int chain1, chain2;
|
int chain1, chain2;
|
int match = 0;
|
int match = 0;
|
int DCR_hit = 0;
|
int DCR_hit = 0;
|
|
|
/* Calculate first 8 matchpoints, result is put into DCR_hit */
|
/* Calculate first 8 matchpoints, result is put into DCR_hit */
|
if (i < 8) {
|
if (i < 8) {
|
unsigned long dcr = mfspr (SPR_DCR(i));
|
unsigned long dcr = mfspr (SPR_DCR(i));
|
/* Whether this matchpoint is enabled, calculate conditions */
|
/* Whether this matchpoint is enabled, calculate conditions */
|
if ((dcr & SPR_DCR_DP) && (dcr & SPR_DCR_CT != SPR_DCR_CT_DISABLED)) {
|
if ((dcr & SPR_DCR_DP) && (dcr & SPR_DCR_CT != SPR_DCR_CT_DISABLED)) {
|
/* Get one operand */
|
/* Get one operand */
|
unsigned long op1;
|
unsigned long op1;
|
unsigned long op2 = mfspr (SPR_DVR(i));
|
unsigned long op2 = mfspr (SPR_DVR(i));
|
switch (dcr & SPR_DCR_CT) {
|
switch (dcr & SPR_DCR_CT) {
|
case SPR_DCR_CT_IFEA: op1 = runtime.cpu.ifea; break;
|
case SPR_DCR_CT_IFEA: op1 = runtime.cpu.ifea; break;
|
case SPR_DCR_CT_LEA: op1 = runtime.cpu.lea; break;
|
case SPR_DCR_CT_LEA: op1 = runtime.cpu.lea; break;
|
case SPR_DCR_CT_SEA: op1 = runtime.cpu.sea; break;
|
case SPR_DCR_CT_SEA: op1 = runtime.cpu.sea; break;
|
case SPR_DCR_CT_LD: op1 = runtime.cpu.ld; break;
|
case SPR_DCR_CT_LD: op1 = runtime.cpu.ld; break;
|
case SPR_DCR_CT_SD: op1 = runtime.cpu.sd; break;
|
case SPR_DCR_CT_SD: op1 = runtime.cpu.sd; break;
|
case SPR_DCR_CT_LSEA: op1 = runtime.cpu.lsea; break;
|
case SPR_DCR_CT_LSEA: op1 = runtime.cpu.lsea; break;
|
}
|
}
|
/* Perform signed comparison? */
|
/* Perform signed comparison? */
|
if (dcr & SPR_DCR_SC) {
|
if (dcr & SPR_DCR_SC) {
|
long sop1 = op1, sop2 = op2; /* Convert to signed */
|
long sop1 = op1, sop2 = op2; /* Convert to signed */
|
switch(dcr & SPR_DCR_CC) {
|
switch(dcr & SPR_DCR_CC) {
|
case SPR_DCR_CC_MASKED: DCR_hit = sop1 & sop2; break;
|
case SPR_DCR_CC_MASKED: DCR_hit = sop1 & sop2; break;
|
case SPR_DCR_CC_EQUAL: DCR_hit = sop1 == sop2; break;
|
case SPR_DCR_CC_EQUAL: DCR_hit = sop1 == sop2; break;
|
case SPR_DCR_CC_NEQUAL: DCR_hit = sop1 != sop2; break;
|
case SPR_DCR_CC_NEQUAL: DCR_hit = sop1 != sop2; break;
|
case SPR_DCR_CC_LESS: DCR_hit = sop1 < sop2; break;
|
case SPR_DCR_CC_LESS: DCR_hit = sop1 < sop2; break;
|
case SPR_DCR_CC_LESSE: DCR_hit = sop1 <= sop2; break;
|
case SPR_DCR_CC_LESSE: DCR_hit = sop1 <= sop2; break;
|
case SPR_DCR_CC_GREAT: DCR_hit = sop1 > sop2; break;
|
case SPR_DCR_CC_GREAT: DCR_hit = sop1 > sop2; break;
|
case SPR_DCR_CC_GREATE: DCR_hit = sop1 >= sop2; break;
|
case SPR_DCR_CC_GREATE: DCR_hit = sop1 >= sop2; break;
|
}
|
}
|
} else {
|
} else {
|
switch(dcr & SPR_DCR_CC) {
|
switch(dcr & SPR_DCR_CC) {
|
case SPR_DCR_CC_MASKED: DCR_hit = op1 & op2; break;
|
case SPR_DCR_CC_MASKED: DCR_hit = op1 & op2; break;
|
case SPR_DCR_CC_EQUAL: DCR_hit = op1 == op2; break;
|
case SPR_DCR_CC_EQUAL: DCR_hit = op1 == op2; break;
|
case SPR_DCR_CC_NEQUAL: DCR_hit = op1 != op2; break;
|
case SPR_DCR_CC_NEQUAL: DCR_hit = op1 != op2; break;
|
case SPR_DCR_CC_LESS: DCR_hit = op1 < op2; break;
|
case SPR_DCR_CC_LESS: DCR_hit = op1 < op2; break;
|
case SPR_DCR_CC_LESSE: DCR_hit = op1 <= op2; break;
|
case SPR_DCR_CC_LESSE: DCR_hit = op1 <= op2; break;
|
case SPR_DCR_CC_GREAT: DCR_hit = op1 > op2; break;
|
case SPR_DCR_CC_GREAT: DCR_hit = op1 > op2; break;
|
case SPR_DCR_CC_GREATE: DCR_hit = op1 >= op2; break;
|
case SPR_DCR_CC_GREATE: DCR_hit = op1 >= op2; break;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Chain matchpoints */
|
/* Chain matchpoints */
|
switch(i) {
|
switch(i) {
|
case 0:
|
case 0:
|
chain1 = chain2 = DCR_hit;
|
chain1 = chain2 = DCR_hit;
|
break;
|
break;
|
case 8:
|
case 8:
|
chain1 = getsprbits (SPR_DWCR0, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR0, SPR_DWCR_MATCH);
|
chain1 = getsprbits (SPR_DWCR0, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR0, SPR_DWCR_MATCH);
|
chain2 = watchpoints & (1 << 7);
|
chain2 = watchpoints & (1 << 7);
|
break;
|
break;
|
case 9:
|
case 9:
|
chain1 = getsprbits (SPR_DWCR1, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR1, SPR_DWCR_MATCH);
|
chain1 = getsprbits (SPR_DWCR1, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR1, SPR_DWCR_MATCH);
|
chain2 = watchpoints & (1 << 8);
|
chain2 = watchpoints & (1 << 8);
|
break;
|
break;
|
case 10:
|
case 10:
|
/* TODO: External watchpoint - not yet handled! */
|
/* TODO: External watchpoint - not yet handled! */
|
#if 0
|
#if 0
|
chain1 = external_watchpoint;
|
chain1 = external_watchpoint;
|
chain2 = watchpoints & (1 << 9);
|
chain2 = watchpoints & (1 << 9);
|
#else
|
#else
|
chain1 = chain2 = 0;
|
chain1 = chain2 = 0;
|
#endif
|
#endif
|
break;
|
break;
|
default:
|
default:
|
chain1 = DCR_hit;
|
chain1 = DCR_hit;
|
chain2 = watchpoints & (bit >> 1);
|
chain2 = watchpoints & (bit >> 1);
|
break;
|
break;
|
}
|
}
|
|
|
switch(getsprbits (SPR_DMR1, SPR_DMR1_CW0 << i)) {
|
switch(getsprbits (SPR_DMR1, SPR_DMR1_CW0 << i)) {
|
case 0: match = chain1; break;
|
case 0: match = chain1; break;
|
case 1: match = chain1 && chain2; break;
|
case 1: match = chain1 && chain2; break;
|
case 2: match = chain1 || chain2; break;
|
case 2: match = chain1 || chain2; break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
|
|
if(match & !(watchpoints & bit)) {
|
if(match & !(watchpoints & bit)) {
|
int counter = (getsprbits (SPR_DMR2, SPR_DMR2_AWTC) & bit) ? 1 : 0;
|
int counter = (getsprbits (SPR_DMR2, SPR_DMR2_AWTC) & bit) ? 1 : 0;
|
int enabled = counter ? getsprbits (SPR_DMR2, SPR_DMR2_WCE1) : getsprbits (SPR_DMR2, SPR_DMR2_WCE0);
|
int enabled = counter ? getsprbits (SPR_DMR2, SPR_DMR2_WCE1) : getsprbits (SPR_DMR2, SPR_DMR2_WCE0);
|
|
|
if(enabled)
|
if(enabled)
|
setsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT, getsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT) + 1);
|
setsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT, getsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT) + 1);
|
|
|
if(getsprbits (SPR_DMR2, SPR_DMR2_WGB) & bit)
|
if(getsprbits (SPR_DMR2, SPR_DMR2_WGB) & bit)
|
breakpoint = 1;
|
breakpoint = 1;
|
}
|
}
|
|
|
watchpoints &= ~bit;
|
watchpoints &= ~bit;
|
watchpoints |= bit;
|
watchpoints |= bit;
|
}
|
}
|
|
|
return breakpoint;
|
return breakpoint;
|
}
|
}
|
|
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
|
|
int DebugGetRegister(unsigned int address, unsigned long* data)
|
int DebugGetRegister(unsigned int address, unsigned long* data)
|
{
|
{
|
int err;
|
int err;
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("Debug get register %x\n",address);
|
printf("Debug get register %x\n",address);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
switch(current_scan_chain)
|
switch(current_scan_chain)
|
{
|
{
|
case JTAG_CHAIN_DEBUG_UNIT:
|
case JTAG_CHAIN_DEBUG_UNIT:
|
*data = mfspr (address);
|
*data = mfspr (address);
|
debug (2, "READ (%08x) = %08x\n", address, *data);
|
debug (2, "READ (%08x) = %08x\n", address, *data);
|
if (runtime.sim.fspr_log) {
|
if (runtime.sim.fspr_log) {
|
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", address, value);
|
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", address, *data);
|
}
|
}
|
break;
|
break;
|
case JTAG_CHAIN_TRACE:
|
case JTAG_CHAIN_TRACE:
|
*data = 0; /* Scan chain not yet implemented */
|
*data = 0; /* Scan chain not yet implemented */
|
err = 0;
|
err = 0;
|
break;
|
break;
|
case JTAG_CHAIN_DEVELOPMENT:
|
case JTAG_CHAIN_DEVELOPMENT:
|
err = get_devint_reg(address,data);
|
err = get_devint_reg(address,data);
|
break;
|
break;
|
case JTAG_CHAIN_WISHBONE:
|
case JTAG_CHAIN_WISHBONE:
|
err = GetWishboneMemory(address,data);
|
err = GetWishboneMemory(address,data);
|
break;
|
break;
|
}
|
}
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("!get reg %x\n", *data);
|
printf("!get reg %x\n", *data);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
return err;
|
return err;
|
}
|
}
|
|
|
int DebugSetRegister(unsigned int address,unsigned long data)
|
int DebugSetRegister(unsigned int address,unsigned long data)
|
{
|
{
|
int err;
|
int err;
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("Debug set register %x <- %x\n", address, data);
|
printf("Debug set register %x <- %x\n", address, data);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
switch(current_scan_chain)
|
switch(current_scan_chain)
|
{
|
{
|
case JTAG_CHAIN_DEBUG_UNIT:
|
case JTAG_CHAIN_DEBUG_UNIT:
|
debug (2, "WRITE (%08x) = %08x\n", address, data);
|
debug (2, "WRITE (%08x) = %08x\n", address, data);
|
if (runtime.sim.fspr_log) {
|
if (runtime.sim.fspr_log) {
|
fprintf(runtime.sim.fspr_log, "Write to SPR : [%08lX] <- [%08lX]\n", address, value);
|
fprintf(runtime.sim.fspr_log, "Write to SPR : [%08lX] <- [%08lX]\n", address, data);
|
}
|
}
|
mtspr(address, data);
|
mtspr(address, data);
|
break;
|
break;
|
case JTAG_CHAIN_TRACE:
|
case JTAG_CHAIN_TRACE:
|
err = JTAG_PROXY_ACCESS_EXCEPTION;
|
err = JTAG_PROXY_ACCESS_EXCEPTION;
|
break;
|
break;
|
case JTAG_CHAIN_DEVELOPMENT:
|
case JTAG_CHAIN_DEVELOPMENT:
|
err = set_devint_reg (address, data);
|
err = set_devint_reg (address, data);
|
break;
|
break;
|
case JTAG_CHAIN_WISHBONE:
|
case JTAG_CHAIN_WISHBONE:
|
err = debug_set_mem (address, data);
|
err = debug_set_mem (address, data);
|
break;
|
break;
|
}
|
}
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("!set reg\n");
|
printf("!set reg\n");
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
return err;
|
return err;
|
}
|
}
|
|
|
int DebugSetChain(int chain)
|
int DebugSetChain(int chain)
|
{
|
{
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("Debug set chain %x\n",chain);
|
printf("Debug set chain %x\n",chain);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
switch(chain)
|
switch(chain)
|
{
|
{
|
case JTAG_CHAIN_DEBUG_UNIT:
|
case JTAG_CHAIN_DEBUG_UNIT:
|
case JTAG_CHAIN_TRACE:
|
case JTAG_CHAIN_TRACE:
|
case JTAG_CHAIN_DEVELOPMENT:
|
case JTAG_CHAIN_DEVELOPMENT:
|
case JTAG_CHAIN_WISHBONE:
|
case JTAG_CHAIN_WISHBONE:
|
current_scan_chain = chain;
|
current_scan_chain = chain;
|
break;
|
break;
|
default: /* All other chains not implemented */
|
default: /* All other chains not implemented */
|
return JTAG_PROXY_INVALID_CHAIN;
|
return JTAG_PROXY_INVALID_CHAIN;
|
}
|
}
|
|
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("!set chain\n");
|
printf("!set chain\n");
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void sim_reset ();
|
void sim_reset ();
|
|
|
/* Sets development interface register */
|
/* Sets development interface register */
|
int set_devint_reg(unsigned int address, unsigned long data)
|
int set_devint_reg(unsigned int address, unsigned long data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
unsigned long value = data;
|
unsigned long value = data;
|
int old_value;
|
int old_value;
|
|
|
switch(address) {
|
switch(address) {
|
case DEVELOPINT_MODER: development.moder = value; break;
|
case DEVELOPINT_MODER: development.moder = value; break;
|
case DEVELOPINT_TSEL: development.tsel = value; break;
|
case DEVELOPINT_TSEL: development.tsel = value; break;
|
case DEVELOPINT_QSEL: development.qsel = value; break;
|
case DEVELOPINT_QSEL: development.qsel = value; break;
|
case DEVELOPINT_SSEL: development.ssel = value; break;
|
case DEVELOPINT_SSEL: development.ssel = value; break;
|
case DEVELOPINT_RISCOP:
|
case DEVELOPINT_RISCOP:
|
old_value = (development.riscop & RISCOP_RESET) != 0;
|
old_value = (development.riscop & RISCOP_RESET) != 0;
|
development.riscop = value;
|
development.riscop = value;
|
in_reset = (development.riscop & RISCOP_RESET) != 0;
|
in_reset = (development.riscop & RISCOP_RESET) != 0;
|
/* Reset the cpu on the negative edge of RESET */
|
/* Reset the cpu on the negative edge of RESET */
|
if(old_value && !in_reset)
|
if(old_value && !in_reset)
|
sim_reset(); /* Reset all units */
|
sim_reset(); /* Reset all units */
|
set_stall_state((development.riscop & RISCOP_STALL) != 0);
|
set_stall_state((development.riscop & RISCOP_STALL) != 0);
|
break;
|
break;
|
case DEVELOPINT_RECWP0:
|
case DEVELOPINT_RECWP0:
|
case DEVELOPINT_RECWP1:
|
case DEVELOPINT_RECWP1:
|
case DEVELOPINT_RECWP2:
|
case DEVELOPINT_RECWP2:
|
case DEVELOPINT_RECWP3:
|
case DEVELOPINT_RECWP3:
|
case DEVELOPINT_RECWP4:
|
case DEVELOPINT_RECWP4:
|
case DEVELOPINT_RECWP5:
|
case DEVELOPINT_RECWP5:
|
case DEVELOPINT_RECWP6:
|
case DEVELOPINT_RECWP6:
|
case DEVELOPINT_RECWP7:
|
case DEVELOPINT_RECWP7:
|
case DEVELOPINT_RECWP8:
|
case DEVELOPINT_RECWP8:
|
case DEVELOPINT_RECWP9:
|
case DEVELOPINT_RECWP9:
|
case DEVELOPINT_RECWP10: development.recwp[address - DEVELOPINT_RECWP0] = value; break;
|
case DEVELOPINT_RECWP10: development.recwp[address - DEVELOPINT_RECWP0] = value; break;
|
case DEVELOPINT_RECBP0: development.recbp = value; break;
|
case DEVELOPINT_RECBP0: development.recbp = value; break;
|
default:
|
default:
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
break;
|
break;
|
}
|
}
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("set_devint_reg %08x = %08x\n", address, data);
|
printf("set_devint_reg %08x = %08x\n", address, data);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
return err;
|
return err;
|
}
|
}
|
|
|
int get_devint_reg(unsigned int address,unsigned long *data)
|
int get_devint_reg(unsigned int address,unsigned long *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
unsigned long value = 0;
|
unsigned long value = 0;
|
|
|
switch(address) {
|
switch(address) {
|
case DEVELOPINT_MODER: value = development.moder; break;
|
case DEVELOPINT_MODER: value = development.moder; break;
|
case DEVELOPINT_TSEL: value = development.tsel; break;
|
case DEVELOPINT_TSEL: value = development.tsel; break;
|
case DEVELOPINT_QSEL: value = development.qsel; break;
|
case DEVELOPINT_QSEL: value = development.qsel; break;
|
case DEVELOPINT_SSEL: value = development.ssel; break;
|
case DEVELOPINT_SSEL: value = development.ssel; break;
|
case DEVELOPINT_RISCOP: value = development.riscop; break;
|
case DEVELOPINT_RISCOP: value = development.riscop; break;
|
case DEVELOPINT_RECWP0:
|
case DEVELOPINT_RECWP0:
|
case DEVELOPINT_RECWP1:
|
case DEVELOPINT_RECWP1:
|
case DEVELOPINT_RECWP2:
|
case DEVELOPINT_RECWP2:
|
case DEVELOPINT_RECWP3:
|
case DEVELOPINT_RECWP3:
|
case DEVELOPINT_RECWP4:
|
case DEVELOPINT_RECWP4:
|
case DEVELOPINT_RECWP5:
|
case DEVELOPINT_RECWP5:
|
case DEVELOPINT_RECWP6:
|
case DEVELOPINT_RECWP6:
|
case DEVELOPINT_RECWP7:
|
case DEVELOPINT_RECWP7:
|
case DEVELOPINT_RECWP8:
|
case DEVELOPINT_RECWP8:
|
case DEVELOPINT_RECWP9:
|
case DEVELOPINT_RECWP9:
|
case DEVELOPINT_RECWP10: value = development.recwp[address - DEVELOPINT_RECWP0]; break;
|
case DEVELOPINT_RECWP10: value = development.recwp[address - DEVELOPINT_RECWP0]; break;
|
case DEVELOPINT_RECBP0: value = development.recbp; break;
|
case DEVELOPINT_RECBP0: value = development.recbp; break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
}
|
}
|
|
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
printf("get_devint_reg %08x = %08x\n", address, value);
|
printf("get_devint_reg %08x = %08x\n", address, value);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
*data = value;
|
*data = value;
|
return err;
|
return err;
|
}
|
}
|
|
|
/* Writes to bus address */
|
/* Writes to bus address */
|
int debug_set_mem (unsigned int address,unsigned long data)
|
int debug_set_mem (unsigned int address,unsigned long data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
debug (2, "MEMWRITE (%08x) = %08x\n", address, data);
|
debug (2, "MEMWRITE (%08x) = %08x\n", address, data);
|
|
|
|
|
if(!verify_memoryarea(address))
|
if(!verify_memoryarea(address))
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
else {
|
else {
|
unsigned char t_data[4];
|
unsigned char t_data[4];
|
int *tmp = (int*)t_data;
|
int *tmp = (int*)t_data;
|
extern char null_str[1]; /* From cpu/common/parse.c */
|
extern char null_str[1]; /* From cpu/common/parse.c */
|
int i;
|
int i;
|
|
|
*tmp = htonl(data); /* We have already converted to host order */
|
*tmp = htonl(data); /* We have already converted to host order */
|
|
|
setsim_mem8(address++, t_data[0]); /* Back to network byte order */
|
setsim_mem8(address++, t_data[0]); /* Back to network byte order */
|
setsim_mem8(address++, t_data[1]);
|
setsim_mem8(address++, t_data[1]);
|
setsim_mem8(address++, t_data[2]);
|
setsim_mem8(address++, t_data[2]);
|
setsim_mem8(address++, t_data[3]);
|
setsim_mem8(address++, t_data[3]);
|
}
|
}
|
return err;
|
return err;
|
}
|
}
|
|
|
int GetWishboneMemory(unsigned int address,unsigned long *data)
|
int GetWishboneMemory(unsigned int address,unsigned long *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
if(!verify_memoryarea(address))
|
if(!verify_memoryarea(address))
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
else
|
else
|
{
|
{
|
unsigned char t_data[4];
|
unsigned char t_data[4];
|
int *tmp = (int*)t_data;
|
int *tmp = (int*)t_data;
|
int bp;
|
int bp;
|
|
|
t_data[0] = evalsim_mem8(address++);
|
t_data[0] = evalsim_mem8(address++);
|
t_data[1] = evalsim_mem8(address++);
|
t_data[1] = evalsim_mem8(address++);
|
t_data[2] = evalsim_mem8(address++);
|
t_data[2] = evalsim_mem8(address++);
|
t_data[3] = evalsim_mem8(address++); /* Already in network byte order */
|
t_data[3] = evalsim_mem8(address++); /* Already in network byte order */
|
|
|
*data = ntohl(*tmp); /* But we assume it is in host order later */
|
*data = ntohl(*tmp); /* But we assume it is in host order later */
|
}
|
}
|
debug (2, "MEMREAD (%08x) = %08x\n", address, *data);
|
debug (2, "MEMREAD (%08x) = %08x\n", address, *data);
|
return err;
|
return err;
|
}
|
}
|
|
|
/* debug_ignore_exception returns 1 if the exception should be ignored. */
|
/* debug_ignore_exception returns 1 if the exception should be ignored. */
|
int debug_ignore_exception (unsigned long except)
|
int debug_ignore_exception (unsigned long except)
|
{
|
{
|
int result = 0;
|
int result = 0;
|
unsigned long dsr = mfspr (SPR_DSR);
|
unsigned long dsr = mfspr (SPR_DSR);
|
unsigned long drr = mfspr (SPR_DRR);
|
unsigned long drr = mfspr (SPR_DRR);
|
|
|
&debug_ignore_exception;
|
&debug_ignore_exception;
|
printf ("0x%08x 0x%08x \n", dsr, drr);
|
printf ("0x%08x 0x%08x \n", dsr, drr);
|
switch(except) {
|
switch(except) {
|
case EXCEPT_RESET: drr |= result = dsr & SPR_DSR_RSTE; break;
|
case EXCEPT_RESET: drr |= result = dsr & SPR_DSR_RSTE; break;
|
case EXCEPT_BUSERR: drr |= result = dsr & SPR_DSR_BUSEE; break;
|
case EXCEPT_BUSERR: drr |= result = dsr & SPR_DSR_BUSEE; break;
|
case EXCEPT_DPF: drr |= result = dsr & SPR_DSR_DPFE; break;
|
case EXCEPT_DPF: drr |= result = dsr & SPR_DSR_DPFE; break;
|
case EXCEPT_IPF: drr |= result = dsr & SPR_DSR_IPFE; break;
|
case EXCEPT_IPF: drr |= result = dsr & SPR_DSR_IPFE; break;
|
case EXCEPT_TICK: drr |= result = dsr & SPR_DSR_TTE; break;
|
case EXCEPT_TICK: drr |= result = dsr & SPR_DSR_TTE; break;
|
case EXCEPT_ALIGN: drr |= result = dsr & SPR_DSR_AE; break;
|
case EXCEPT_ALIGN: drr |= result = dsr & SPR_DSR_AE; break;
|
case EXCEPT_ILLEGAL: drr |= result = dsr & SPR_DSR_IIE; break;
|
case EXCEPT_ILLEGAL: drr |= result = dsr & SPR_DSR_IIE; break;
|
case EXCEPT_INT: drr |= result = dsr & SPR_DSR_IE; break;
|
case EXCEPT_INT: drr |= result = dsr & SPR_DSR_IE; break;
|
case EXCEPT_DTLBMISS: drr |= result = dsr & SPR_DSR_DME; break;
|
case EXCEPT_DTLBMISS: drr |= result = dsr & SPR_DSR_DME; break;
|
case EXCEPT_ITLBMISS: drr |= result = dsr & SPR_DSR_IME; break;
|
case EXCEPT_ITLBMISS: drr |= result = dsr & SPR_DSR_IME; break;
|
case EXCEPT_RANGE: drr |= result = dsr & SPR_DSR_RE; break;
|
case EXCEPT_RANGE: drr |= result = dsr & SPR_DSR_RE; break;
|
case EXCEPT_SYSCALL: drr |= result = dsr & SPR_DSR_SCE; break;
|
case EXCEPT_SYSCALL: drr |= result = dsr & SPR_DSR_SCE; break;
|
case EXCEPT_TRAP: drr |= result = dsr & SPR_DSR_TE; break;
|
case EXCEPT_TRAP: drr |= result = dsr & SPR_DSR_TE; break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
printf ("0x%08x 0x%08x %i\n", dsr, drr, result);
|
printf ("0x%08x 0x%08x %i\n", dsr, drr, result);
|
|
|
mtspr (SPR_DRR, drr);
|
mtspr (SPR_DRR, drr);
|
set_stall_state (result != 0);
|
set_stall_state (result != 0);
|
return (result != 0);
|
return (result != 0);
|
}
|
}
|
|
|