URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 138 to Rev 139
- ↔ Reverse comparison
Rev 138 → Rev 139
/trunk/or1ksim/cpu/or1k/sprs.c
26,6 → 26,7
|
extern int cont_run; /* defined in toplevel.c */ |
extern int tt_stopped; /* defined in tick.c */ |
extern int GlobalMode; /* CZ 21/06/01 */ |
|
static sprword sprs[MAX_SPRS]; |
|
66,9 → 67,41
printf("MTSPR(0x1234, %x);\n", value); |
break; |
} |
|
/* What the hell is happening here? This looks like a bug |
waiting to happen. Assume regno = 2*MAX_SPRS_PER_GRP+3, |
which presumably means I want to set register 3 in |
group 2. Instead, I calculate ofs as 3, and regno as |
2, and get a final value of 5??? Is this correct? |
Oh well...I didn't write this. Who knows what it is |
actually supposed to do. It doesn't matter if regno |
is less than MAX_SPRS_PER_GRP, which is the only |
way I use it. CZ - 21/06/01 |
*/ |
|
regno /= MAX_SPRS_PER_GRP; |
regno += ofs; |
|
/* CZ 21/06/01 ... the debugger wants to do this! */ |
if(GlobalMode) |
{ |
extern unsigned long pc; |
|
if(regno == SPR_PC) |
{ |
sprs[SPR_PC] = value; |
#if 0 |
/* There is currently a problem with symbol tables by |
gdb. It doesn't properly set up the CPU. We'll ignore |
this for now. */ |
pc = value; |
pc_phy = simulate_ic_mmu_fetch(pc); |
pcnext = pc+4; |
#endif |
return; |
} |
} |
|
/* printf("mtspr(%x, %x)\n", regno, value); |
*/ if (regno < MAX_SPRS) |
sprs[regno] = value; |
86,6 → 119,15
regno /= MAX_SPRS_PER_GRP; |
regno += ofs; |
|
/* CZ 21/06/01 ... the debugger wants to do this! */ |
if(GlobalMode) |
{ |
extern unsigned long pc; |
|
if(regno == SPR_PC) |
return pc; |
} |
|
/* MM: l.rfe, for example, temporarly disables |
exceptions. We will make it appear as SR bit |
is set. */ |
/trunk/or1ksim/cpu/or1k/except.c
25,6 → 25,8
#include "except.h" |
#include "sprs.h" |
|
static void except_handle_backend(int,unsigned long,unsigned long); |
|
extern int cont_run; |
extern struct iqueue_entry iqueue[20]; |
extern unsigned long pc; |
35,15 → 37,99
extern int delay_insn; |
int cycle_delay = 0; /* Added by CZ 27/05/01 */ |
|
static struct { |
int valid; |
int type; |
unsigned long address; |
unsigned long saved; |
} pending; |
|
void ClearPendingException() |
{ |
if(pending.valid && pending.type != EXCEPT_RESET) |
{ |
pending.valid = 0; |
pending.type = 0; |
pending.address = 0; |
pending.saved = 0; |
} |
} |
|
/* The delayed_pc and delayed_pcnext are fields which hold |
the original value of the PC across breakpoint exceptions |
in the case of a development interface. Due to an implementation |
issues, DIR injected instructions can modify these values |
when in fact they should not. So we save and restore them |
later on. */ |
static unsigned long delayed_pc = 0; |
static unsigned long delayed_pcnext = 0; |
static int delayed_pc_valid = 0; |
|
void PrepareExceptionPC(unsigned long t_pc,unsigned long t_pcnext) |
{ |
/* If a real exception occurred which has stalled |
the CPU, we are expecting to halt before the end |
of the instruction. Otherwise, if it is a single |
step that has caused the halt, we are expected to |
complete the entire instruction and stop after |
it is finished. */ |
|
if(pending.valid) |
{ |
delayed_pc = t_pc; |
delayed_pcnext = t_pcnext; |
delayed_pc_valid = 1; |
} |
else |
_execute_update_pc(t_pc,t_pcnext); |
} |
|
void PrepareException() |
{ |
if(delayed_pc_valid) |
{ |
pc = delayed_pc; |
pcnext = delayed_pcnext; |
pc_phy = simulate_ic_mmu_fetch(pc); |
if ((pc_phy < MEMORY_START) || (pc_phy > MEMORY_START + MEMORY_LEN)) |
except_handle(EXCEPT_BUSERR, pc); |
delayed_pc_valid = delayed_pc = delayed_pcnext = 0; |
} |
|
if(pending.valid) |
except_handle_backend(pending.type,pending.address,pending.saved); |
} |
|
/* Handle OR1K exceptions. */ |
void except_handle(int except, unsigned long ea) |
{ |
unsigned long pc_saved; |
printf("Exception 0x%x (%s): ", except, EXCEPT_NAME(except)); |
printf("Iqueue[0].insn_addr: 0x%x Eff ADDR: 0x%x\n", iqueue[0].insn_addr, ea); |
printf(" pc: 0x%x pcnext: 0x%x\n", pc, pcnext); |
|
printf("Exception 0x%x (%s): ", except, EXCEPT_NAME(except)); |
printf("Iqueue[0].insn_addr: 0x%x Eff ADDR: 0x%x\n", iqueue[0].insn_addr, ea); |
printf(" pc: 0x%x pcnext: 0x%x\n", pc, pcnext); |
|
pending.valid = 1; |
pending.type = except; |
pending.address = ea; |
pending.saved = pc; |
|
if(DebugCheckException(except)) |
{ |
pending.valid = 0; |
pending.type = 0; |
pending.address = 0; |
pending.saved = 0; |
} |
|
cycle_delay = 0; /* An exception stalls the CPU 0 clock cycles */ |
} |
|
static void except_handle_backend(int except, unsigned long ea, unsigned long pc_saved) |
{ |
pending.valid = 0; |
pending.type = 0; |
pending.address = 0; |
pending.saved = 0; |
|
#if ONLY_VIRTUAL_MACHINE |
printf("WARNING: No exception processing while ONLY_VIRTUAL_MACHINE is defined.\n"); |
cont_run = 0; |
81,15 → 167,27
mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_EXR); /* Disable except. */ |
pc = (unsigned long)except; |
|
/* This has been removed. All exceptions (not just SYSCALL) suffer |
from the same problem. The solution is to continue just like |
the pipeline would, and issue the exception on the next |
clock cycle. We assume now that this function is being called |
->BEFORE<- the instruction fetch and after the previous update |
which always yields the correct behavior. This has the added |
advantage that a debugger can prevent an exception from |
taking place by resetting the pc. */ |
#if 0 |
/* MM: We do pc update after the execute (in the simulator), so we |
decrease it by 4 so that next instruction points to first exception |
instruction. */ |
if (except == EXCEPT_SYSCALL) |
pc -= 4; |
#endif |
|
pcnext = pc+4; |
|
/* Added by CZ 27/05/01 */ |
pc_phy = pc; |
cycle_delay = 7; /* An exception stalls the CPU 7 clock cycles */ |
pc_phy = pc; /* An exception always turns off the MMU, so |
pc is always pc_phy */ |
|
#endif |
} |
/trunk/or1ksim/cpu/or1k/spr_defs.h
42,9 → 42,10
/* System control and status group */ |
#define SPR_VR (SPRGROUP_SYS + 0) |
#define SPR_UPR (SPRGROUP_SYS + 1) |
#define SPR_SR (SPRGROUP_SYS + 2) |
#define SPR_EPCR_BASE (SPRGROUP_SYS + 16) |
#define SPR_EPCR_LAST (SPRGROUP_SYS + 31) |
#define SPR_PC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */ |
#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */ |
#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */ |
#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */ |
#define SPR_EEAR_BASE (SPRGROUP_SYS + 48) |
#define SPR_EEAR_LAST (SPRGROUP_SYS + 63) |
#define SPR_ESR_BASE (SPRGROUP_SYS + 64) |
/trunk/or1ksim/toplevel.c
79,7 → 79,7
int GlobalMode = 0; /* Start off in the orginal mode */ |
|
/* CVS revision number. */ |
const char rcsrev[] = "$Revision: 1.18 $"; |
const char rcsrev[] = "$Revision: 1.19 $"; |
|
/* Continuos run versus single step tracing switch. */ |
int cont_run; |
1061,10 → 1061,15
JTAGProxyWriteResponse resp_write; |
JTAGProxyReadResponse resp_read; |
JTAGProxyChainResponse resp_chain; |
JTAGProxyBlockWriteMessage *msg_bwrite; |
JTAGProxyBlockReadMessage msg_bread; |
JTAGProxyBlockWriteResponse resp_bwrite; |
JTAGProxyBlockReadResponse *resp_bread; |
char *buf; |
unsigned long long data; |
int err; |
int err = 0; |
uint32_t command,length; |
int len,i; |
|
/* First, we must read the incomming command */ |
if(gdb_read(&command,sizeof(uint32_t)) < 0) |
1158,6 → 1163,103
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_WRITE: |
if(length < sizeof(JTAGProxyBlockWriteMessage)-8) |
{ |
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
if(!(buf = (char*)malloc(8+length))) |
{ |
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf; |
if(gdb_read(&buf[8],length) < 0) |
{ |
if(gdb_fd) |
{ |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
msg_bwrite->address = ntohl(msg_bwrite->address); |
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters); |
for(i=0;i<msg_bwrite->nRegisters;i++) |
{ |
int t_err; |
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]); |
t_err = DebugSetRegister(msg_bwrite->address+i,msg_bwrite->data[i]); |
err = err ? err : t_err; |
} |
resp_bwrite.status = htonl(err); |
free(buf); |
buf = msg_bwrite = NULL; |
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0) |
{ |
if(gdb_fd) |
{ |
perror("gdb socket - 4"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_READ: |
if(length != sizeof(msg_bread) - 8) |
{ |
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_bread; |
if(gdb_read(&buf[8],length) < 0) |
{ |
if(gdb_fd) |
{ |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_bread.address = ntohl(msg_bread.address); |
msg_bread.nRegisters = ntohl(msg_bread.nRegisters); |
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1); |
if(!(buf = (char*)malloc(len))) |
{ |
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
resp_bread = (JTAGProxyBlockReadResponse*)buf; |
for(i=0;i<msg_bread.nRegisters;i++) |
{ |
int t_err; |
|
t_err = DebugGetRegister(msg_bread.address+i,&resp_bread->data[i]); |
resp_bread->data[i] = htonl(resp_bread->data[i]); |
err = err ? err : t_err; |
} |
resp_bread->status = htonl(err); |
resp_bread->nRegisters = htonl(msg_bread.nRegisters); |
if(gdb_write(resp_bread,len) < 0) |
{ |
if(gdb_fd) |
{ |
perror("gdb socket - 6"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
free(buf); |
buf = resp_bread = NULL; |
break; |
case JTAG_COMMAND_CHAIN: |
if(length != sizeof(msg_chain) - 8) |
{ |