/* 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.
|
*/
|
*/
|
|
|
#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 "trace.h"
|
#include "trace.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"
|
|
|
DebugUnit debug_unit;
|
DebugUnit debug_unit;
|
DevelopmentInterface development;
|
DevelopmentInterface development;
|
|
|
typedef enum {
|
typedef enum {
|
false = 0,
|
false = 0,
|
true = 1,
|
true = 1,
|
} Boolean;
|
} Boolean;
|
static void ExecuteInducedInstruction(unsigned long);
|
static void ExecuteInducedInstruction(unsigned long);
|
|
|
/* External STALL signal to debug interface */
|
/* External STALL signal to debug interface */
|
int cpu_stalled = false;
|
int cpu_stalled = false;
|
int in_reset = false;
|
int in_reset = false;
|
|
|
/* An induced instruction has been written to the DIR register */
|
/* An induced instruction has been written to the DIR register */
|
static Boolean induced = false;
|
static Boolean induced = false;
|
static unsigned long induced_insn;
|
static unsigned long induced_insn;
|
|
|
/* A flag to indicate that we must perform an ic mmu cycle */
|
/* A flag to indicate that we must perform an ic mmu cycle */
|
static Boolean lookup_physical_address = false;
|
static Boolean lookup_physical_address = false;
|
|
|
/* Variables for implementing ExecuteInducedInstruction */
|
/* Variables for implementing ExecuteInducedInstruction */
|
extern unsigned long pc;
|
extern unsigned long pc;
|
extern unsigned long pcnext;
|
extern unsigned long pcnext;
|
extern unsigned long pcdelay;
|
extern unsigned long pcdelay;
|
extern unsigned long pc_phy;
|
extern unsigned long pc_phy;
|
extern int delay_insn;
|
extern int delay_insn;
|
static void GetIQueueEntry(struct iqueue_entry*);
|
static void GetIQueueEntry(struct iqueue_entry*);
|
|
|
static int CalculateWatchpoints(void);
|
static int CalculateWatchpoints(void);
|
|
|
static int watchpoint[10];
|
static int watchpoint[10];
|
|
|
/* This function returns true if an induced instruction has
|
/* This function returns true if an induced instruction has
|
been inserted into the instruction stream. It will remove
|
been inserted into the instruction stream. It will remove
|
that instruction and return the result. This function is
|
that instruction and return the result. This function is
|
called from the fetch() routine. */
|
called from the fetch() routine. */
|
int OverrideFetch(unsigned long* insn)
|
int OverrideFetch(unsigned long* insn)
|
{
|
{
|
int valid = induced;
|
int valid = induced;
|
induced = false;
|
induced = false;
|
|
|
if(valid)
|
if(valid)
|
*insn = induced_insn;
|
*insn = induced_insn;
|
return valid;
|
return valid;
|
}
|
}
|
|
|
void InduceImmediateInstruction(unsigned long insn)
|
void InduceImmediateInstruction(unsigned long insn)
|
{
|
{
|
induced = true;
|
induced = true;
|
induced_insn = insn;
|
induced_insn = insn;
|
|
|
if(in_reset)
|
if(in_reset)
|
return;
|
return;
|
|
|
if(cpu_stalled)
|
if(cpu_stalled)
|
{
|
{
|
ExecuteInducedInstruction(insn);
|
ExecuteInducedInstruction(insn);
|
induced_insn = 0;
|
induced_insn = 0;
|
induced = false;
|
induced = false;
|
}
|
}
|
}
|
}
|
|
|
void SetCPUStallState(int state)
|
void SetCPUStallState(int state)
|
{
|
{
|
if(debug_unit.DMR1.DXFW) /* If debugger disabled */
|
if(debug_unit.DMR1.DXFW) /* If debugger disabled */
|
state = false;
|
state = false;
|
|
|
if(state == cpu_stalled)
|
if(state == cpu_stalled)
|
return;
|
return;
|
|
|
if(state && induced)
|
if(state && induced)
|
{
|
{
|
ExecuteInducedInstruction(induced_insn);
|
ExecuteInducedInstruction(induced_insn);
|
induced_insn = 0;
|
induced_insn = 0;
|
induced = false;
|
induced = false;
|
}
|
}
|
|
|
cpu_stalled = state;
|
cpu_stalled = state;
|
}
|
}
|
|
|
void ResetDebugUnit()
|
void ResetDebugUnit()
|
{
|
{
|
memset(&debug_unit,'\0',sizeof(DebugUnit));
|
memset(&debug_unit,'\0',sizeof(DebugUnit));
|
cpu_stalled = 0;
|
cpu_stalled = 0;
|
}
|
}
|
|
|
#ifdef DEBUGMOD_OFF
|
#ifdef DEBUGMOD_OFF
|
#define CheckDebugUnit(x,y) 0
|
#define CheckDebugUnit(x,y) 0
|
#else
|
#else
|
inline int CheckDebugUnit(DebugUnitAction action,unsigned long udata)
|
inline int CheckDebugUnit(DebugUnitAction action,unsigned long udata)
|
{
|
{
|
int i;
|
int i;
|
DCR_CT_Settings condition = DCR_CT_Disabled;
|
DCR_CT_Settings condition = DCR_CT_Disabled;
|
long data = (long)udata;
|
long data = (long)udata;
|
int match;
|
int match;
|
|
|
if(in_reset)
|
if(DEBUG_ENABLED || in_reset)
|
return 0;
|
return 0;
|
|
|
/* If we're single stepping, always stop */
|
/* If we're single stepping, always stop */
|
if(debug_unit.DMR1.ST && action == DebugInstructionFetch)
|
if(debug_unit.DMR1.ST && action == DebugInstructionFetch)
|
return 1;
|
return 1;
|
|
|
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;
|
}
|
}
|
|
|
for(i=0;i<8;i++)
|
for(i=0;i<8;i++)
|
{
|
{
|
if(debug_unit.DCR[i].DP == DCR_DP_Absent)
|
if(debug_unit.DCR[i].DP == DCR_DP_Absent)
|
continue;
|
continue;
|
|
|
if(debug_unit.DCR[i].CT == condition)
|
if(debug_unit.DCR[i].CT == condition)
|
{
|
{
|
if(debug_unit.DCR[i].SC == DCR_SC_Signed)
|
if(debug_unit.DCR[i].SC == DCR_SC_Signed)
|
{
|
{
|
switch(debug_unit.DCR[i].CC)
|
switch(debug_unit.DCR[i].CC)
|
{
|
{
|
case DCR_CC_Equal: match = data == (int)debug_unit.DVR[i]; break;
|
case DCR_CC_Equal: match = data == (int)debug_unit.DVR[i]; break;
|
case DCR_CC_LessThan: match = data < (int)debug_unit.DVR[i]; break;
|
case DCR_CC_LessThan: match = data < (int)debug_unit.DVR[i]; break;
|
case DCR_CC_LessEqual: match = data <= (int)debug_unit.DVR[i]; break;
|
case DCR_CC_LessEqual: match = data <= (int)debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterThan: match = data > (int)debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterThan: match = data > (int)debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterEqual: match = data >= (int)debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterEqual: match = data >= (int)debug_unit.DVR[i]; break;
|
case DCR_CC_NotEqual: match = data != (int)debug_unit.DVR[i]; break;
|
case DCR_CC_NotEqual: match = data != (int)debug_unit.DVR[i]; break;
|
default: match = 0; break;
|
default: match = 0; break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
switch(debug_unit.DCR[i].CC)
|
switch(debug_unit.DCR[i].CC)
|
{
|
{
|
case DCR_CC_Equal: match = udata == debug_unit.DVR[i]; break;
|
case DCR_CC_Equal: match = udata == debug_unit.DVR[i]; break;
|
case DCR_CC_LessThan: match = udata < debug_unit.DVR[i]; break;
|
case DCR_CC_LessThan: match = udata < debug_unit.DVR[i]; break;
|
case DCR_CC_LessEqual: match = udata <= debug_unit.DVR[i]; break;
|
case DCR_CC_LessEqual: match = udata <= debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterThan: match = udata > debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterThan: match = udata > debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterEqual: match = udata >= debug_unit.DVR[i]; break;
|
case DCR_CC_GreaterEqual: match = udata >= debug_unit.DVR[i]; break;
|
case DCR_CC_NotEqual: match = udata != debug_unit.DVR[i]; break;
|
case DCR_CC_NotEqual: match = udata != debug_unit.DVR[i]; break;
|
default: match = 0; break;
|
default: match = 0; break;
|
}
|
}
|
}
|
}
|
}
|
}
|
match <<= i;
|
match <<= i;
|
debug_unit.DCR_hit &= ~match; /* Clear DCR compare if it has changed */
|
debug_unit.DCR_hit &= ~match; /* Clear DCR compare if it has changed */
|
debug_unit.DCR_hit |= match; /* Save the state of each DCR compare */
|
debug_unit.DCR_hit |= match; /* Save the state of each DCR compare */
|
}
|
}
|
|
|
return CalculateWatchpoints();
|
return CalculateWatchpoints();
|
}
|
}
|
#endif
|
#endif
|
|
|
static int CalculateWatchpoints()
|
static int CalculateWatchpoints()
|
{
|
{
|
int spec[11];
|
int spec[11];
|
int breakpoint = 0;
|
int breakpoint = 0;
|
int i,bit;
|
int i,bit;
|
|
|
spec[0] = debug_unit.DMR1.CW0;
|
spec[0] = debug_unit.DMR1.CW0;
|
spec[1] = debug_unit.DMR1.CW1;
|
spec[1] = debug_unit.DMR1.CW1;
|
spec[2] = debug_unit.DMR1.CW2;
|
spec[2] = debug_unit.DMR1.CW2;
|
spec[3] = debug_unit.DMR1.CW3;
|
spec[3] = debug_unit.DMR1.CW3;
|
spec[4] = debug_unit.DMR1.CW4;
|
spec[4] = debug_unit.DMR1.CW4;
|
spec[5] = debug_unit.DMR1.CW5;
|
spec[5] = debug_unit.DMR1.CW5;
|
spec[6] = debug_unit.DMR1.CW6;
|
spec[6] = debug_unit.DMR1.CW6;
|
spec[7] = debug_unit.DMR1.CW7;
|
spec[7] = debug_unit.DMR1.CW7;
|
spec[8] = debug_unit.DMR1.CW8;
|
spec[8] = debug_unit.DMR1.CW8;
|
spec[9] = debug_unit.DMR1.CW9;
|
spec[9] = debug_unit.DMR1.CW9;
|
spec[10] = debug_unit.DMR1.CW10;
|
spec[10] = debug_unit.DMR1.CW10;
|
|
|
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;
|
|
|
switch(i)
|
switch(i)
|
{
|
{
|
case 0:
|
case 0:
|
chain1 = chain2 = debug_unit.DCR_hit & 0x01;
|
chain1 = chain2 = debug_unit.DCR_hit & 0x01;
|
break;
|
break;
|
case 8:
|
case 8:
|
chain1 = debug_unit.DWCR[0].COUNT == debug_unit.DWCR[0].MATCH;
|
chain1 = debug_unit.DWCR[0].COUNT == debug_unit.DWCR[0].MATCH;
|
chain2 = debug_unit.watchpoint & (1 << 7);
|
chain2 = debug_unit.watchpoint & (1 << 7);
|
break;
|
break;
|
case 9:
|
case 9:
|
chain1 = debug_unit.DWCR[1].COUNT == debug_unit.DWCR[1].MATCH;
|
chain1 = debug_unit.DWCR[1].COUNT == debug_unit.DWCR[1].MATCH;
|
chain2 = debug_unit.watchpoint & (1 << 8);
|
chain2 = debug_unit.watchpoint & (1 << 8);
|
break;
|
break;
|
case 10:
|
case 10:
|
chain1 = debug_unit.DCR_hit & 0x100; /* External hit */
|
chain1 = debug_unit.DCR_hit & 0x100; /* External hit */
|
chain2 = debug_unit.watchpoint & (1 << 9);
|
chain2 = debug_unit.watchpoint & (1 << 9);
|
break;
|
break;
|
default:
|
default:
|
chain1 = debug_unit.DCR_hit & bit;
|
chain1 = debug_unit.DCR_hit & bit;
|
chain2 = debug_unit.watchpoint & (bit >> 1);
|
chain2 = debug_unit.watchpoint & (bit >> 1);
|
break;
|
break;
|
}
|
}
|
|
|
switch(spec[i])
|
switch(spec[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 & !(debug_unit.watchpoint & bit))
|
if(match & !(debug_unit.watchpoint & bit))
|
{
|
{
|
int counter = (debug_unit.DMR2.AWPC & bit) ? 1 : 0;
|
int counter = (debug_unit.DMR2.AWPC & bit) ? 1 : 0;
|
int enabled = counter ? debug_unit.DMR2.WCE1 : debug_unit.DMR2.WCE0;
|
int enabled = counter ? debug_unit.DMR2.WCE1 : debug_unit.DMR2.WCE0;
|
|
|
if(enabled)
|
if(enabled)
|
debug_unit.DWCR[counter].COUNT++;
|
debug_unit.DWCR[counter].COUNT++;
|
|
|
if(debug_unit.DMR2.WGB & bit)
|
if(debug_unit.DMR2.WGB & bit)
|
breakpoint = 1;
|
breakpoint = 1;
|
}
|
}
|
|
|
debug_unit.watchpoint &= ~bit;
|
debug_unit.watchpoint &= ~bit;
|
debug_unit.watchpoint |= bit;
|
debug_unit.watchpoint |= bit;
|
}
|
}
|
|
|
return breakpoint;
|
return breakpoint;
|
}
|
}
|
|
|
static void GetIQueueEntry(struct iqueue_entry* iq_entry)
|
static void GetIQueueEntry(struct iqueue_entry* iq_entry)
|
{
|
{
|
iq_entry->insn = induced_insn;
|
iq_entry->insn = induced_insn;
|
iq_entry->insn_index = insn_decode(induced_insn);
|
iq_entry->insn_index = insn_decode(induced_insn);
|
iq_entry->insn_addr = pc_phy;
|
iq_entry->insn_addr = pc_phy;
|
iq_entry->op[0] = 0;
|
iq_entry->op[0] = 0;
|
iq_entry->op[MAX_OPERANDS] = OPTYPE_LAST;
|
iq_entry->op[MAX_OPERANDS] = OPTYPE_LAST;
|
}
|
}
|
|
|
static void ExecuteInducedInstruction(unsigned long insn)
|
static void ExecuteInducedInstruction(unsigned long insn)
|
{
|
{
|
struct iqueue_entry iq_entry;
|
struct iqueue_entry iq_entry;
|
unsigned long pc_saved = pc;
|
unsigned long pc_saved = pc;
|
unsigned long pcnext_saved = pcnext;
|
unsigned long pcnext_saved = pcnext;
|
unsigned long pcdelay_saved = pcdelay;
|
unsigned long pcdelay_saved = pcdelay;
|
unsigned long pc_phy_saved = pc_phy;
|
unsigned long pc_phy_saved = pc_phy;
|
|
|
GetIQueueEntry(&iq_entry);
|
GetIQueueEntry(&iq_entry);
|
decode_execute(&iq_entry);
|
decode_execute(&iq_entry);
|
|
|
pc = pc_saved;
|
pc = pc_saved;
|
pcnext = pcnext_saved;
|
pcnext = pcnext_saved;
|
pcdelay = pcdelay_saved;
|
pcdelay = pcdelay_saved;
|
pc_phy = pc_phy_saved;
|
pc_phy = pc_phy_saved;
|
}
|
}
|
|
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
|
|
int DebugGetRegister(unsigned int address,int32_t* data)
|
int DebugGetRegister(unsigned int address,int32_t* 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:
|
err = GetDebugUnitRegister(address,data);
|
err = GetDebugUnitRegister(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 = GetDevelopmentInterfaceRegister(address,data);
|
err = GetDevelopmentInterfaceRegister(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,int32_t data)
|
int DebugSetRegister(unsigned int address,int32_t 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:
|
err = SetDebugUnitRegister(address,data);
|
err = SetDebugUnitRegister(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 = SetDevelopmentInterfaceRegister(address,data);
|
err = SetDevelopmentInterfaceRegister(address,data);
|
break;
|
break;
|
case JTAG_CHAIN_WISHBONE:
|
case JTAG_CHAIN_WISHBONE:
|
err = SetWishboneMemory(address,data);
|
err = SetWishboneMemory(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;
|
}
|
}
|
|
|
/* Nearly all compilers today store these bit fields as a packed structure
|
/* Nearly all compilers today store these bit fields as a packed structure
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
to be working in a non standard environment, you may need to rewrite
|
to be working in a non standard environment, you may need to rewrite
|
this routine or the SET_REG32 macro. */
|
this routine or the SET_REG32 macro. */
|
int SetDevelopmentInterfaceRegister(unsigned int address,uint32_t data)
|
int SetDevelopmentInterfaceRegister(unsigned int address,uint32_t data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = data;
|
uint32_t value = data;
|
int old_value;
|
int old_value;
|
char *t_ptr = (char*)&development.RISCOP;
|
char *t_ptr = (char*)&development.RISCOP;
|
|
|
switch(address)
|
switch(address)
|
{
|
{
|
case DEVELOPINT_MODER:
|
case DEVELOPINT_MODER:
|
SET_REG32(development.MODER,value);
|
SET_REG32(development.MODER,value);
|
break;
|
break;
|
case DEVELOPINT_TSEL:
|
case DEVELOPINT_TSEL:
|
SET_REG32(development.TSEL,value);
|
SET_REG32(development.TSEL,value);
|
break;
|
break;
|
case DEVELOPINT_QSEL:
|
case DEVELOPINT_QSEL:
|
SET_REG32(development.QSEL,value);
|
SET_REG32(development.QSEL,value);
|
break;
|
break;
|
case DEVELOPINT_SSEL:
|
case DEVELOPINT_SSEL:
|
SET_REG32(development.SSEL,value);
|
SET_REG32(development.SSEL,value);
|
break;
|
break;
|
case DEVELOPINT_RISCOP:
|
case DEVELOPINT_RISCOP:
|
old_value = development.RISCOP.RESET;
|
old_value = development.RISCOP.RESET;
|
SET_REG32(development.RISCOP,value);
|
SET_REG32(development.RISCOP,value);
|
|
|
in_reset = development.RISCOP.RESET;
|
in_reset = development.RISCOP.RESET;
|
|
|
/* Reset the cpu on the negative edge of RESET */
|
/* Reset the cpu on the negative edge of RESET */
|
if(old_value && !development.RISCOP.RESET)
|
if(old_value && !development.RISCOP.RESET)
|
{
|
{
|
uart_reset();
|
uart_reset();
|
tick_reset();
|
tick_reset();
|
pm_reset();
|
pm_reset();
|
pic_reset();
|
pic_reset();
|
reset(); /* Old or new mode */
|
reset(); /* Old or new mode */
|
}
|
}
|
|
|
SetCPUStallState(development.RISCOP.RISCSTALL);
|
SetCPUStallState(development.RISCOP.RISCSTALL);
|
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:
|
case DEVELOPINT_RECWP10:
|
SET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value);
|
SET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value);
|
break;
|
break;
|
case DEVELOPINT_RECBP0:
|
case DEVELOPINT_RECBP0:
|
SET_REG32(development.RECBP[0],value);
|
SET_REG32(development.RECBP[0],value);
|
break;
|
break;
|
default:
|
default:
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
break;
|
break;
|
}
|
}
|
return err;
|
return err;
|
}
|
}
|
|
|
int GetDevelopmentInterfaceRegister(unsigned int address,uint32_t *data)
|
int GetDevelopmentInterfaceRegister(unsigned int address,uint32_t *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = 0;
|
uint32_t value = 0;
|
|
|
switch(address)
|
switch(address)
|
{
|
{
|
case DEVELOPINT_MODER: GET_REG32(development.MODER,value); break;
|
case DEVELOPINT_MODER: GET_REG32(development.MODER,value); break;
|
case DEVELOPINT_TSEL: GET_REG32(development.TSEL,value); break;
|
case DEVELOPINT_TSEL: GET_REG32(development.TSEL,value); break;
|
case DEVELOPINT_QSEL: GET_REG32(development.QSEL,value); break;
|
case DEVELOPINT_QSEL: GET_REG32(development.QSEL,value); break;
|
case DEVELOPINT_SSEL: GET_REG32(development.SSEL,value); break;
|
case DEVELOPINT_SSEL: GET_REG32(development.SSEL,value); break;
|
case DEVELOPINT_RISCOP: GET_REG32(development.RISCOP,value); break;
|
case DEVELOPINT_RISCOP: GET_REG32(development.RISCOP,value); 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: GET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value); break;
|
case DEVELOPINT_RECWP10: GET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value); break;
|
case DEVELOPINT_RECBP0: GET_REG32(development.RECBP[0],value); break;
|
case DEVELOPINT_RECBP0: GET_REG32(development.RECBP[0],value); break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
}
|
}
|
|
|
*data = value;
|
*data = value;
|
return err;
|
return err;
|
}
|
}
|
|
|
/* Nearly all compilers today store these bit fields as a packed structure
|
/* Nearly all compilers today store these bit fields as a packed structure
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
to be working in a non standard environment, you may need to rewrite
|
to be working in a non standard environment, you may need to rewrite
|
this routine or the SET_REG32 macro. */
|
this routine or the SET_REG32 macro. */
|
int SetDebugUnitRegister(unsigned int address,uint32_t data)
|
int SetDebugUnitRegister(unsigned int address,uint32_t data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = data;
|
uint32_t value = data;
|
int old_value;
|
int old_value;
|
int group = address >> 11;
|
int group = address >> 11;
|
|
|
address &= 0x07FF;
|
address &= 0x07FF;
|
|
|
/*****************************************************/
|
/*****************************************************/
|
/* TEMPORARY!!!! */
|
/* TEMPORARY!!!! */
|
/*****************************************************/
|
/*****************************************************/
|
if(group == 6)
|
if(group == 6)
|
address -= 32;
|
address -= 32;
|
|
|
if(group == 6)
|
if(group == 6)
|
{
|
{
|
switch(address)
|
switch(address)
|
{
|
{
|
case DEBUGINT_DVR0:
|
case DEBUGINT_DVR0:
|
case DEBUGINT_DVR1:
|
case DEBUGINT_DVR1:
|
case DEBUGINT_DVR2:
|
case DEBUGINT_DVR2:
|
case DEBUGINT_DVR3:
|
case DEBUGINT_DVR3:
|
case DEBUGINT_DVR4:
|
case DEBUGINT_DVR4:
|
case DEBUGINT_DVR5:
|
case DEBUGINT_DVR5:
|
case DEBUGINT_DVR6:
|
case DEBUGINT_DVR6:
|
case DEBUGINT_DVR7:
|
case DEBUGINT_DVR7:
|
printf("DVR %d set to 0x%08x\n",address-DEBUGINT_DVR0,value);
|
printf("DVR %d set to 0x%08x\n",address-DEBUGINT_DVR0,value);
|
SET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value);
|
SET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value);
|
break;
|
break;
|
case DEBUGINT_DCR0:
|
case DEBUGINT_DCR0:
|
case DEBUGINT_DCR1:
|
case DEBUGINT_DCR1:
|
case DEBUGINT_DCR2:
|
case DEBUGINT_DCR2:
|
case DEBUGINT_DCR3:
|
case DEBUGINT_DCR3:
|
case DEBUGINT_DCR4:
|
case DEBUGINT_DCR4:
|
case DEBUGINT_DCR5:
|
case DEBUGINT_DCR5:
|
case DEBUGINT_DCR6:
|
case DEBUGINT_DCR6:
|
case DEBUGINT_DCR7:
|
case DEBUGINT_DCR7:
|
printf("DCR %d set to 0x%08x\n",address-DEBUGINT_DCR0,value);
|
printf("DCR %d set to 0x%08x\n",address-DEBUGINT_DCR0,value);
|
SET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value);
|
SET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value);
|
break;
|
break;
|
case DEBUGINT_DMR1:
|
case DEBUGINT_DMR1:
|
SET_REG32(debug_unit.DMR1,value);
|
SET_REG32(debug_unit.DMR1,value);
|
break;
|
break;
|
case DEBUGINT_DMR2:
|
case DEBUGINT_DMR2:
|
SET_REG32(debug_unit.DMR2,value);
|
SET_REG32(debug_unit.DMR2,value);
|
break;
|
break;
|
case DEBUGINT_DWCR0:
|
case DEBUGINT_DWCR0:
|
SET_REG32(debug_unit.DWCR[0],value);
|
SET_REG32(debug_unit.DWCR[0],value);
|
break;
|
break;
|
case DEBUGINT_DWCR1:
|
case DEBUGINT_DWCR1:
|
SET_REG32(debug_unit.DWCR[1],value);
|
SET_REG32(debug_unit.DWCR[1],value);
|
break;
|
break;
|
case DEBUGINT_DSR:
|
case DEBUGINT_DSR:
|
SET_REG32(debug_unit.DSR,value);
|
SET_REG32(debug_unit.DSR,value);
|
break;
|
break;
|
case DEBUGINT_DRR:
|
case DEBUGINT_DRR:
|
SET_REG32(debug_unit.DRR,value);
|
SET_REG32(debug_unit.DRR,value);
|
break;
|
break;
|
case DEBUGINT_DIR:
|
case DEBUGINT_DIR:
|
InduceImmediateInstruction(value);
|
InduceImmediateInstruction(value);
|
break;
|
break;
|
default:
|
default:
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else if(group == 0)
|
else if(group == 0)
|
{
|
{
|
extern unsigned long reg[32];
|
extern unsigned long reg[32];
|
|
|
if(!address)
|
if(!address)
|
err = JTAG_PROXY_ACCESS_EXCEPTION;
|
err = JTAG_PROXY_ACCESS_EXCEPTION;
|
else if(address < 32)
|
else if(address < 32)
|
{
|
{
|
/* Assume that a write to the PC implies
|
/* Assume that a write to the PC implies
|
that the debugging software has recognized
|
that the debugging software has recognized
|
the exception and wants to do something
|
the exception and wants to do something
|
else instead. */
|
else instead. */
|
|
|
if(address == SPR_PC)
|
if(address == SPR_PC)
|
{
|
{
|
ClearPendingException();
|
ClearPendingException();
|
ClearPreparedPCState();
|
ClearPreparedPCState();
|
}
|
}
|
mtspr(address,data);
|
mtspr(address,data);
|
}
|
}
|
else if(address >= 0x0400 && address < 0x0420)
|
else if(address >= 0x0400 && address < 0x0420)
|
reg[address - 0x0400] = data;
|
reg[address - 0x0400] = data;
|
else if(address < 0x0600 || address >= 0x0620)
|
else if(address < 0x0600 || address >= 0x0620)
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
}
|
}
|
else
|
else
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
|
|
return err;
|
return err;
|
}
|
}
|
|
|
int GetDebugUnitRegister(unsigned int address,uint32_t *data)
|
int GetDebugUnitRegister(unsigned int address,uint32_t *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = 0;
|
uint32_t value = 0;
|
int group = address >> 11;
|
int group = address >> 11;
|
|
|
address &= 0x07FF;
|
address &= 0x07FF;
|
|
|
/*****************************************************/
|
/*****************************************************/
|
/* TEMPORARY!!!! */
|
/* TEMPORARY!!!! */
|
/*****************************************************/
|
/*****************************************************/
|
if(group == 6)
|
if(group == 6)
|
address -= 32;
|
address -= 32;
|
|
|
if(group == 6)
|
if(group == 6)
|
{
|
{
|
switch(address)
|
switch(address)
|
{
|
{
|
case DEBUGINT_DVR0:
|
case DEBUGINT_DVR0:
|
case DEBUGINT_DVR1:
|
case DEBUGINT_DVR1:
|
case DEBUGINT_DVR2:
|
case DEBUGINT_DVR2:
|
case DEBUGINT_DVR3:
|
case DEBUGINT_DVR3:
|
case DEBUGINT_DVR4:
|
case DEBUGINT_DVR4:
|
case DEBUGINT_DVR5:
|
case DEBUGINT_DVR5:
|
case DEBUGINT_DVR6:
|
case DEBUGINT_DVR6:
|
case DEBUGINT_DVR7: GET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value); break;
|
case DEBUGINT_DVR7: GET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value); break;
|
case DEBUGINT_DCR0:
|
case DEBUGINT_DCR0:
|
case DEBUGINT_DCR1:
|
case DEBUGINT_DCR1:
|
case DEBUGINT_DCR2:
|
case DEBUGINT_DCR2:
|
case DEBUGINT_DCR3:
|
case DEBUGINT_DCR3:
|
case DEBUGINT_DCR4:
|
case DEBUGINT_DCR4:
|
case DEBUGINT_DCR5:
|
case DEBUGINT_DCR5:
|
case DEBUGINT_DCR6:
|
case DEBUGINT_DCR6:
|
case DEBUGINT_DCR7: GET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value); break;
|
case DEBUGINT_DCR7: GET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value); break;
|
case DEBUGINT_DMR1: GET_REG32(debug_unit.DMR1,value); break;
|
case DEBUGINT_DMR1: GET_REG32(debug_unit.DMR1,value); break;
|
case DEBUGINT_DMR2: GET_REG32(debug_unit.DMR2,value); break;
|
case DEBUGINT_DMR2: GET_REG32(debug_unit.DMR2,value); break;
|
case DEBUGINT_DWCR0: GET_REG32(debug_unit.DWCR[0],value); break;
|
case DEBUGINT_DWCR0: GET_REG32(debug_unit.DWCR[0],value); break;
|
case DEBUGINT_DWCR1: GET_REG32(debug_unit.DWCR[1],value); break;
|
case DEBUGINT_DWCR1: GET_REG32(debug_unit.DWCR[1],value); break;
|
case DEBUGINT_DSR: GET_REG32(debug_unit.DSR,value); break;
|
case DEBUGINT_DSR: GET_REG32(debug_unit.DSR,value); break;
|
case DEBUGINT_DRR: GET_REG32(debug_unit.DRR,value); break;
|
case DEBUGINT_DRR: GET_REG32(debug_unit.DRR,value); break;
|
case DEBUGINT_DIR: err = JTAG_PROXY_ACCESS_EXCEPTION; break;
|
case DEBUGINT_DIR: err = JTAG_PROXY_ACCESS_EXCEPTION; break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
default: err = JTAG_PROXY_INVALID_ADDRESS; break;
|
}
|
}
|
}
|
}
|
else if(group == 0)
|
else if(group == 0)
|
{
|
{
|
extern unsigned long reg[32];
|
extern unsigned long reg[32];
|
|
|
if(address < 32)
|
if(address < 32)
|
value = mfspr(address);
|
value = mfspr(address);
|
else if(address >= 0x0400 && address < 0x0420)
|
else if(address >= 0x0400 && address < 0x0420)
|
value = reg[address - 0x400];
|
value = reg[address - 0x400];
|
else if(address >= 0x0600 && address < 0x0620)
|
else if(address >= 0x0600 && address < 0x0620)
|
value = 0;
|
value = 0;
|
else
|
else
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
}
|
}
|
else
|
else
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
|
|
*data = value;
|
*data = value;
|
return err;
|
return err;
|
}
|
}
|
|
|
/* Nearly all compilers today store these bit fields as a packed structure
|
/* Nearly all compilers today store these bit fields as a packed structure
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
in network byte order (Big Endian). If you happen to be unlucky enough
|
to be working in a non standard environment, you may need to rewrite
|
to be working in a non standard environment, you may need to rewrite
|
this routine or the SET_REG32 macro. */
|
this routine or the SET_REG32 macro. */
|
int SetWishboneMemory(unsigned int address,uint32_t data)
|
int SetWishboneMemory(unsigned int address,uint32_t data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = data;
|
uint32_t value = data;
|
int old_value;
|
int old_value;
|
int group = address >> 11;
|
int group = address >> 11;
|
|
|
address <<= 2;
|
address <<= 2;
|
|
|
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,uint32_t *data)
|
int GetWishboneMemory(unsigned int address,uint32_t *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
uint32_t value = 0;
|
uint32_t value = 0;
|
int group = address >> 11;
|
int group = address >> 11;
|
|
|
address <<= 2;
|
address <<= 2;
|
|
|
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 */
|
}
|
}
|
return err;
|
return err;
|
}
|
}
|
|
|
/* DebugCheckException returns 1 if the exception should be ignored.
|
/* DebugCheckException returns 1 if the exception should be ignored.
|
Currently, this is true only if the exception is a breakpoint
|
Currently, this is true only if the exception is a breakpoint
|
exception and debug_unit.DMR1.ST is set. Sorry, this is a quick
|
exception and debug_unit.DMR1.ST is set. Sorry, this is a quick
|
hack to disable processing of breakpoint exceptions on single
|
hack to disable processing of breakpoint exceptions on single
|
stepping. Just one of those historical accidents. Feel free
|
stepping. Just one of those historical accidents. Feel free
|
to rewrite the behavior. */
|
to rewrite the behavior. */
|
int DebugCheckException(int exception)
|
int DebugCheckException(int exception)
|
{
|
{
|
int result = 0;
|
int result = 0;
|
|
|
switch(exception)
|
switch(exception)
|
{
|
{
|
case EXCEPT_RESET: result = debug_unit.DRR.RSTE = debug_unit.DSR.RSTE; break;
|
case EXCEPT_RESET: result = debug_unit.DRR.RSTE = debug_unit.DSR.RSTE; break;
|
case EXCEPT_BUSERR: result = debug_unit.DRR.BUSEE = debug_unit.DSR.BUSEE; break;
|
case EXCEPT_BUSERR: result = debug_unit.DRR.BUSEE = debug_unit.DSR.BUSEE; break;
|
case EXCEPT_DPF: result = debug_unit.DRR.DPFE = debug_unit.DSR.DPFE; break;
|
case EXCEPT_DPF: result = debug_unit.DRR.DPFE = debug_unit.DSR.DPFE; break;
|
case EXCEPT_IPF: result = debug_unit.DRR.IPFE = debug_unit.DSR.IPFE; break;
|
case EXCEPT_IPF: result = debug_unit.DRR.IPFE = debug_unit.DSR.IPFE; break;
|
case EXCEPT_LPINT: result = debug_unit.DRR.LPINTE = debug_unit.DSR.LPINTE; break;
|
case EXCEPT_LPINT: result = debug_unit.DRR.LPINTE = debug_unit.DSR.LPINTE; break;
|
case EXCEPT_ALIGN: result = debug_unit.DRR.AE = debug_unit.DSR.AE; break;
|
case EXCEPT_ALIGN: result = debug_unit.DRR.AE = debug_unit.DSR.AE; break;
|
case EXCEPT_ILLEGAL: result = debug_unit.DRR.IIE = debug_unit.DSR.IIE; break;
|
case EXCEPT_ILLEGAL: result = debug_unit.DRR.IIE = debug_unit.DSR.IIE; break;
|
case EXCEPT_HPINT: result = debug_unit.DRR.HPINTE = debug_unit.DSR.HPINTE; break;
|
case EXCEPT_HPINT: result = debug_unit.DRR.HPINTE = debug_unit.DSR.HPINTE; break;
|
case EXCEPT_DTLBMISS: result = debug_unit.DRR.DME = debug_unit.DSR.DME; break;
|
case EXCEPT_DTLBMISS: result = debug_unit.DRR.DME = debug_unit.DSR.DME; break;
|
case EXCEPT_ITLBMISS: result = debug_unit.DRR.IME = debug_unit.DSR.IME; break;
|
case EXCEPT_ITLBMISS: result = debug_unit.DRR.IME = debug_unit.DSR.IME; break;
|
case EXCEPT_RANGE: result = debug_unit.DRR.RE = debug_unit.DSR.RE; break;
|
case EXCEPT_RANGE: result = debug_unit.DRR.RE = debug_unit.DSR.RE; break;
|
case EXCEPT_SYSCALL: result = debug_unit.DRR.SCE = debug_unit.DSR.SCE; break;
|
case EXCEPT_SYSCALL: result = debug_unit.DRR.SCE = debug_unit.DSR.SCE; break;
|
case EXCEPT_BREAK: result = debug_unit.DRR.BE = debug_unit.DSR.BE; break;
|
case EXCEPT_BREAK: result = debug_unit.DRR.BE = debug_unit.DSR.BE; break;
|
case EXCEPT_TRAP: result = debug_unit.DRR.TE = debug_unit.DSR.TE; break;
|
case EXCEPT_TRAP: result = debug_unit.DRR.TE = debug_unit.DSR.TE; break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
|
|
if(result)
|
if(result)
|
SetCPUStallState(true);
|
SetCPUStallState(true);
|
|
|
return (debug_unit.DMR1.ST && exception == EXCEPT_BREAK);
|
return (debug_unit.DMR1.ST && exception == EXCEPT_BREAK);
|
}
|
}
|
|
|