URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 129 to Rev 130
- ↔ Reverse comparison
Rev 129 → Rev 130
/trunk/or1ksim/peripheral/debug_unit.c
0,0 → 1,728
/* debug_unit.c -- Simulation of Or1k debug unit |
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
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., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* |
This is an architectural level simulation of the Or1k debug |
unit as described in OpenRISC 1000 System Architecture Manual, |
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 |
respect to the registers and the behavior. There are no known |
limitations at this time. |
*/ |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <inttypes.h> |
|
#include "debug_unit.h" |
#include "sim-config.h" |
#include "except.h" |
#include "arch.h" |
#include "abstract.h" |
#include "parse.h" |
#include "trace.h" |
#include "../gdb.h" |
#include "../cpu/or1k/except.h" |
|
DebugUnit debug_unit; |
DevelopmentInterface development; |
|
typedef enum { |
false = 0, |
true = 1, |
} Boolean; |
static void ExecuteInducedInstruction(unsigned long); |
|
/* External STALL signal to debug interface */ |
int cpu_stalled = false; |
int in_reset = false; |
|
/* An induced instruction has been written to the DIR register */ |
static Boolean induced = false; |
static unsigned long induced_insn; |
|
/* A flag to indicate that we must perform an ic mmu cycle */ |
static Boolean lookup_physical_address = false; |
|
/* Variables for implementing ExecuteInducedInstruction */ |
extern unsigned long pc; |
extern unsigned long pcnext; |
extern unsigned long pcdelay; |
extern unsigned long pc_phy; |
extern int delay_insn; |
static void GetIQueueEntry(struct iqueue_entry*,char*); |
|
static int watchpoint[10]; |
|
/* This function returns true if an induced instruction has |
been inserted into the instruction stream. It will remove |
that instruction and return the result. This function is |
called from the fetch() routine. */ |
int OverrideFetch(struct iqueue_entry *iq_entry,char* sTemp) |
{ |
int valid = induced; |
induced = false; |
|
if(valid) |
GetIQueueEntry(iq_entry,sTemp); |
return valid; |
} |
|
void InduceImmediateInstruction(unsigned long insn) |
{ |
induced = true; |
induced_insn = insn; |
|
if(in_reset) |
return; |
|
if(cpu_stalled) |
{ |
if(lookup_physical_address) |
pc_phy = simulate_ic_mmu_fetch(pc); |
ExecuteInducedInstruction(insn); |
induced_insn = 0; |
induced = false; |
} |
} |
|
void SetCPUStallState(int state) |
{ |
if(debug_unit.DMR1.DXFW) /* If debugger disabled */ |
state = false; |
|
if(state == cpu_stalled) |
return; |
|
if(state && induced) |
{ |
ExecuteInducedInstruction(induced_insn); |
induced_insn = 0; |
induced = false; |
} |
|
cpu_stalled = state; |
} |
|
void ResetDebugUnit() |
{ |
memset(&debug_unit,'\0',sizeof(DebugUnit)); |
cpu_stalled = 0; |
} |
|
int CheckDebugUnit(DebugUnitAction action,unsigned long udata) |
{ |
int i; |
DCR_CT_Settings condition = DCR_CT_Disabled; |
long data = (long)udata; |
int match; |
|
if(in_reset) |
return 0; |
|
switch(action) |
{ |
case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break; |
case DebugLoadAddress: condition = DCR_CT_LoadAddress; break; |
case DebugStoreAddress: condition = DCR_CT_StoreAddress; break; |
case DebugLoadData: condition = DCR_CT_LoadData; break; |
case DebugStoreData: condition = DCR_CT_StoreData; break; |
} |
|
for(i=0;i<8;i++) |
{ |
if(debug_unit.DCR[i].DP == DCR_DP_Absent) |
continue; |
|
if(debug_unit.DCR[i].CT == condition) |
{ |
if(debug_unit.DCR[i].SC == DCR_SC_Signed) |
{ |
switch(debug_unit.DCR[i].CC) |
{ |
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_LessEqual: 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_NotEqual: match = data != (int)debug_unit.DVR[i]; break; |
default: match = 0; break; |
} |
} |
else |
{ |
switch(debug_unit.DCR[i].CC) |
{ |
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_LessEqual: 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_NotEqual: match = udata != debug_unit.DVR[i]; break; |
default: match = 0; break; |
} |
} |
} |
match <<= i; |
debug_unit.DCR_hit &= ~match; /* Clear DCR compare if it has changed */ |
debug_unit.DCR_hit |= match; /* Save the state of each DCR compare */ |
} |
|
return CalculateWatchpoints(); |
} |
|
int CalculateWatchpoints() |
{ |
int spec[11]; |
int breakpoint = 0; |
int i,bit; |
|
spec[0] = debug_unit.DMR1.CW0; |
spec[1] = debug_unit.DMR1.CW1; |
spec[2] = debug_unit.DMR1.CW2; |
spec[3] = debug_unit.DMR1.CW3; |
spec[4] = debug_unit.DMR1.CW4; |
spec[5] = debug_unit.DMR1.CW5; |
spec[6] = debug_unit.DMR1.CW6; |
spec[7] = debug_unit.DMR1.CW7; |
spec[8] = debug_unit.DMR1.CW8; |
spec[9] = debug_unit.DMR1.CW9; |
spec[10] = debug_unit.DMR1.CW10; |
|
for(i=0,bit=1;i<11;i++,bit<<=1) |
{ |
int chain1,chain2; |
int match = 0; |
|
switch(i) |
{ |
case 0: |
chain1 = chain2 = debug_unit.DCR_hit & 0x01; |
break; |
case 8: |
chain1 = debug_unit.DWCR[0].COUNT == debug_unit.DWCR[0].MATCH; |
chain2 = debug_unit.watchpoint & (1 << 7); |
break; |
case 9: |
chain1 = debug_unit.DWCR[1].COUNT == debug_unit.DWCR[1].MATCH; |
chain2 = debug_unit.watchpoint & (1 << 8); |
break; |
case 10: |
chain1 = debug_unit.DCR_hit & 0x100; /* External hit */ |
chain2 = debug_unit.watchpoint & (1 << 9); |
break; |
default: |
chain1 = debug_unit.DCR_hit & bit; |
chain2 = debug_unit.watchpoint & (bit >> 1); |
break; |
} |
|
switch(spec[i]) |
{ |
case 0: match = chain1; break; |
case 1: match = chain1 && chain2; break; |
case 2: match = chain1 || chain2; break; |
default: |
break; |
} |
|
if(match & !(debug_unit.watchpoint & bit)) |
{ |
int counter = (debug_unit.DMR2.AWPC & bit) ? 1 : 0; |
int enabled = counter ? debug_unit.DMR2.WCE1 : debug_unit.DMR2.WCE0; |
|
if(enabled) |
debug_unit.DWCR[counter].COUNT++; |
|
if(debug_unit.DMR2.WGB & bit) |
breakpoint = 1; |
} |
|
debug_unit.watchpoint &= ~bit; |
debug_unit.watchpoint |= bit; |
} |
|
return breakpoint; |
} |
|
static void GetIQueueEntry(struct iqueue_entry* iq_entry,char* sTemp) |
{ |
int len = disassemble_insn(induced_insn); |
extern char *disassembled; |
char *code = NULL; |
char *args[4]; |
char *s; |
int n = 0; /* Number of arguments to this function */ |
|
strcpy(sTemp,disassembled); |
|
/* Trim the whitespace from the end of the string */ |
for(len = strlen(sTemp);len > 0 && isspace(sTemp[len-1]); len--); |
sTemp[len] = '\0'; |
|
/* Trim the whitespace from the beginning of the string */ |
for(s = sTemp;*s && isspace(*s);s++); |
code = s; |
|
args[0] = args[1] = args[2] = args[3] = ""; |
/* Skip over the opcode */ |
for(;*s && !isspace(*s);s++); /* A faster strcspn() */ |
|
if(!*s) /* If we hit the end, there are no arguments */ |
s = NULL; |
|
while(s) |
{ |
*s++ = '\0'; /* Terminate the previous string */ |
for(;*s && isspace(*s);s++); /* Skip leading white space */ |
args[n++] = s; /* Note where the arg begins */ |
if(s = strchr(s,OPERAND_DELIM[0])) /* Look for the terminator */ |
{ |
char *r; |
for(r=s-1;*r && isspace(*r);r--); /* Nuke the trailing white space */ |
*(++r) = '\0'; /* Terminate the argument string */ |
} |
} |
iq_entry->insn_index = insn_index(code); |
strcpy(iq_entry->op1,args[0]); |
strcpy(iq_entry->op2,args[1]); |
strcpy(iq_entry->op3,args[2]); |
strcpy(iq_entry->op4,args[3]); |
iq_entry->insn_addr = pc_phy; |
iq_entry->dependdst = NULL; |
iq_entry->dependsrc1 = NULL; |
iq_entry->dependsrc2 = NULL; |
} |
|
static void ExecuteInducedInstruction(unsigned long insn) |
{ |
struct iqueue_entry iq_entry; |
char sTemp[256]; |
|
GetIQueueEntry(&iq_entry,sTemp); |
decode_execute(&iq_entry); |
if(delay_insn) |
{ |
pc = pcdelay; |
pcnext = pcdelay; |
lookup_physical_address = true; |
delay_insn = 0; |
} |
else |
lookup_physical_address = false; |
} |
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL; |
|
int DebugGetRegister(unsigned int address,int32_t* data) |
{ |
int err; |
|
switch(current_scan_chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
err = GetDebugUnitRegister(address,data); |
break; |
case JTAG_CHAIN_TRACE: |
*data = 0; /* Scan chain not yet implemented */ |
err = 0; |
break; |
case JTAG_CHAIN_DEVELOPMENT: |
err = GetDevelopmentInterfaceRegister(address,data); |
break; |
} |
return err; |
} |
|
int DebugSetRegister(unsigned int address,int32_t data) |
{ |
int err; |
|
switch(current_scan_chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
err = SetDebugUnitRegister(address,data); |
break; |
case JTAG_CHAIN_TRACE: |
err = JTAG_PROXY_ACCESS_EXCEPTION; |
break; |
case JTAG_CHAIN_DEVELOPMENT: |
err = SetDevelopmentInterfaceRegister(address,data); |
break; |
} |
return err; |
} |
|
int DebugSetChain(int chain) |
{ |
switch(chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
case JTAG_CHAIN_TRACE: |
case JTAG_CHAIN_DEVELOPMENT: |
current_scan_chain = chain; |
break; |
default: /* All other chains not implemented */ |
return JTAG_PROXY_INVALID_CHAIN; |
} |
|
return 0; |
} |
|
/* 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 |
to be working in a non standard environment, you may need to rewrite |
this routine or the SET_REG32 macro. */ |
int SetDevelopmentInterfaceRegister(unsigned int address,uint32_t data) |
{ |
int err = 0; |
uint32_t value = data; |
int old_value; |
char *t_ptr = (char*)&development.RISCOP; |
|
switch(address) |
{ |
case DEVELOPINT_MODER: |
SET_REG32(development.MODER,value); |
break; |
case DEVELOPINT_TSEL: |
SET_REG32(development.TSEL,value); |
break; |
case DEVELOPINT_QSEL: |
SET_REG32(development.QSEL,value); |
break; |
case DEVELOPINT_SSEL: |
SET_REG32(development.SSEL,value); |
break; |
case DEVELOPINT_RISCOP: |
old_value = development.RISCOP.RESET; |
SET_REG32(development.RISCOP,value); |
|
in_reset = development.RISCOP.RESET; |
|
/* Reset the cpu on the negative edge of RESET */ |
if(old_value && !development.RISCOP.RESET) |
{ |
uart_reset(); |
tick_reset(); |
pm_reset(); |
pic_reset(); |
reset(); /* Old or new mode */ |
} |
|
SetCPUStallState(development.RISCOP.RISCSTALL); |
break; |
case DEVELOPINT_RECWP0: |
case DEVELOPINT_RECWP1: |
case DEVELOPINT_RECWP2: |
case DEVELOPINT_RECWP3: |
case DEVELOPINT_RECWP4: |
case DEVELOPINT_RECWP5: |
case DEVELOPINT_RECWP6: |
case DEVELOPINT_RECWP7: |
case DEVELOPINT_RECWP8: |
case DEVELOPINT_RECWP9: |
case DEVELOPINT_RECWP10: |
SET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value); |
break; |
case DEVELOPINT_RECBP0: |
SET_REG32(development.RECBP[0],value); |
break; |
default: |
err = JTAG_PROXY_INVALID_ADDRESS; |
break; |
} |
return err; |
} |
|
int GetDevelopmentInterfaceRegister(unsigned int address,uint32_t *data) |
{ |
int err = 0; |
uint32_t value = 0; |
|
switch(address) |
{ |
case DEVELOPINT_MODER: GET_REG32(development.MODER,value); break; |
case DEVELOPINT_TSEL: GET_REG32(development.TSEL,value); break; |
case DEVELOPINT_QSEL: GET_REG32(development.QSEL,value); break; |
case DEVELOPINT_SSEL: GET_REG32(development.SSEL,value); break; |
case DEVELOPINT_RISCOP: GET_REG32(development.RISCOP,value); break; |
case DEVELOPINT_RECWP0: |
case DEVELOPINT_RECWP1: |
case DEVELOPINT_RECWP2: |
case DEVELOPINT_RECWP3: |
case DEVELOPINT_RECWP4: |
case DEVELOPINT_RECWP5: |
case DEVELOPINT_RECWP6: |
case DEVELOPINT_RECWP7: |
case DEVELOPINT_RECWP8: |
case DEVELOPINT_RECWP9: |
case DEVELOPINT_RECWP10: GET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value); break; |
case DEVELOPINT_RECBP0: GET_REG32(development.RECBP[0],value); break; |
default: err = JTAG_PROXY_INVALID_ADDRESS; break; |
} |
|
*data = value; |
return err; |
} |
|
/* 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 |
to be working in a non standard environment, you may need to rewrite |
this routine or the SET_REG32 macro. */ |
int SetDebugUnitRegister(unsigned int address,uint32_t data) |
{ |
int err = 0; |
uint32_t value = data; |
int old_value; |
int group = address >> 11; |
|
/* This is a memory location */ |
if(address & 0x80000000) |
{ |
address &= 0x7FFFFFFF; |
address <<= 2; |
|
if(address < MEMORY_START || address >= MEMORY_LEN) |
err = JTAG_PROXY_INVALID_ADDRESS; |
else |
{ |
unsigned char t_data[4]; |
int *tmp = (int*)t_data; |
extern char null_str[1]; /* From cpu/common/parse.c */ |
int i; |
|
*tmp = htonl(data); /* We have already converted to host order */ |
|
/* Make sure we clear out any cached instruction references */ |
for(i=address;i<address+4;i++) |
{ |
if(mem[i].insn) |
{ |
mem[i].insn->insn_index = -1; |
if(mem[i].insn->op1 != null_str) free(mem[i].insn->op1); |
if(mem[i].insn->op2 != null_str) free(mem[i].insn->op2); |
if(mem[i].insn->op3 != null_str) free(mem[i].insn->op3); |
if(mem[i].insn->op4 != null_str) free(mem[i].insn->op4); |
free(mem[i].insn); |
mem[i].insn = NULL; |
} |
} |
|
mem[address++].data = t_data[0]; /* Back to network byte order */ |
mem[address++].data = t_data[1]; |
mem[address++].data = t_data[2]; |
mem[address++].data = t_data[3]; |
} |
return err; |
} |
|
address &= 0x07FF; |
|
/*****************************************************/ |
/* TEMPORARY!!!! */ |
/*****************************************************/ |
if(group == 6) |
address -= 32; |
|
if(group == 6) |
{ |
switch(address) |
{ |
case DEBUGINT_DVR0: |
case DEBUGINT_DVR1: |
case DEBUGINT_DVR2: |
case DEBUGINT_DVR3: |
case DEBUGINT_DVR4: |
case DEBUGINT_DVR5: |
case DEBUGINT_DVR6: |
case DEBUGINT_DVR7: |
printf("DVR %d set to 0x%08x\n",address-DEBUGINT_DVR0,value); |
SET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value); |
break; |
case DEBUGINT_DCR0: |
case DEBUGINT_DCR1: |
case DEBUGINT_DCR2: |
case DEBUGINT_DCR3: |
case DEBUGINT_DCR4: |
case DEBUGINT_DCR5: |
case DEBUGINT_DCR6: |
case DEBUGINT_DCR7: |
printf("DCR %d set to 0x%08x\n",address-DEBUGINT_DCR0,value); |
SET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value); |
break; |
case DEBUGINT_DMR1: |
SET_REG32(debug_unit.DMR1,value); |
break; |
case DEBUGINT_DMR2: |
SET_REG32(debug_unit.DMR2,value); |
break; |
case DEBUGINT_DWCR0: |
SET_REG32(debug_unit.DWCR[0],value); |
break; |
case DEBUGINT_DWCR1: |
SET_REG32(debug_unit.DWCR[1],value); |
break; |
case DEBUGINT_DSR: |
SET_REG32(debug_unit.DSR,value); |
break; |
case DEBUGINT_DRR: |
SET_REG32(debug_unit.DRR,value); |
break; |
case DEBUGINT_DIR: |
InduceImmediateInstruction(value); |
break; |
default: |
err = JTAG_PROXY_INVALID_ADDRESS; |
break; |
} |
} |
else if(group == 0) |
{ |
extern unsigned long reg[32]; |
|
if(!address) |
err = JTAG_PROXY_ACCESS_EXCEPTION; |
else if(address < 32) |
reg[address] = data; |
else if(address >= 0x0400 && address < 0x0420) |
reg[address - 0x0400] = data; |
else if(address < 0x0600 || address >= 0x0620) |
err = JTAG_PROXY_INVALID_ADDRESS; |
} |
else |
err = JTAG_PROXY_INVALID_ADDRESS; |
|
return err; |
} |
|
int GetDebugUnitRegister(unsigned int address,uint32_t *data) |
{ |
int err = 0; |
uint32_t value = 0; |
int group = address >> 11; |
|
/* This is a memory location */ |
if(address & 0x80000000) |
{ |
address &= 0x7FFFFFFF; |
|
if(address < MEMORY_START || address >= MEMORY_LEN) |
err = JTAG_PROXY_INVALID_ADDRESS; |
else |
{ |
unsigned char t_data[4]; |
int *tmp = (int*)t_data; |
|
t_data[0] = mem[address++].data; |
t_data[1] = mem[address++].data; |
t_data[2] = mem[address++].data; |
t_data[3] = mem[address++].data; /* Already in network byte order */ |
|
*data = ntohl(*tmp); /* But we assume it is in host order later */ |
} |
return err; |
} |
|
address &= 0x07FF; |
|
/*****************************************************/ |
/* TEMPORARY!!!! */ |
/*****************************************************/ |
if(group == 6) |
address -= 32; |
|
if(group == 6) |
{ |
switch(address) |
{ |
case DEBUGINT_DVR0: |
case DEBUGINT_DVR1: |
case DEBUGINT_DVR2: |
case DEBUGINT_DVR3: |
case DEBUGINT_DVR4: |
case DEBUGINT_DVR5: |
case DEBUGINT_DVR6: |
case DEBUGINT_DVR7: GET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value); break; |
case DEBUGINT_DCR0: |
case DEBUGINT_DCR1: |
case DEBUGINT_DCR2: |
case DEBUGINT_DCR3: |
case DEBUGINT_DCR4: |
case DEBUGINT_DCR5: |
case DEBUGINT_DCR6: |
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_DMR2: GET_REG32(debug_unit.DMR2,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_DSR: GET_REG32(debug_unit.DSR,value); break; |
case DEBUGINT_DRR: GET_REG32(debug_unit.DRR,value); break; |
case DEBUGINT_DIR: err = JTAG_PROXY_ACCESS_EXCEPTION; break; |
default: err = JTAG_PROXY_INVALID_ADDRESS; break; |
} |
} |
else if(group == 0) |
{ |
extern unsigned long reg[32]; |
|
if(address < 32) |
value = reg[address]; |
else if(address >= 0x0400 && address < 0x0420) |
value = reg[address - 0x400]; |
else if(address >= 0x0600 && address < 0x0620) |
value = 0; |
else |
err = JTAG_PROXY_INVALID_ADDRESS; |
} |
else |
err = JTAG_PROXY_INVALID_ADDRESS; |
|
*data = value; |
return err; |
} |
|
void DebugCheckException(int exception) |
{ |
int result = 0; |
|
switch(exception) |
{ |
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_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_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_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_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_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_BREAK: result = debug_unit.DRR.BE = debug_unit.DSR.BE; break; |
default: |
break; |
} |
|
if(result) |
SetCPUStallState(true); |
} |