Clean up more tracing.
FIX interrupt delivery - was zapping PSW before it had been saved. FIX interrupt return, was one instruction out.
This commit is contained in:
parent
175c6fd375
commit
a72f8fb439
5 changed files with 112 additions and 211 deletions
|
@ -1,3 +1,15 @@
|
||||||
|
Wed Sep 17 16:21:08 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* simops.c: Move "mov", "reti", to v850.igen, fix tracing.
|
||||||
|
|
||||||
|
* interp.c (hash): Delete.
|
||||||
|
|
||||||
|
* v850.igen (nop): Really do nothing.
|
||||||
|
|
||||||
|
* interp.c (do_interrupt): Mask interrupts after PSW is saved, not
|
||||||
|
before.
|
||||||
|
* v850.igen (reti): Return to current PC not previous.
|
||||||
|
|
||||||
start-sanitize-v850e
|
start-sanitize-v850e
|
||||||
Wed Sep 17 14:02:10 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Wed Sep 17 14:02:10 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
|
|
@ -66,151 +66,117 @@ do_interrupt (sd, data)
|
||||||
char **interrupt_name = (char**)data;
|
char **interrupt_name = (char**)data;
|
||||||
enum interrupt_type inttype;
|
enum interrupt_type inttype;
|
||||||
inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
|
inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
|
||||||
/* Disable further interrupts. */
|
|
||||||
PSW |= PSW_ID;
|
/* For a hardware reset, drop everything and jump to the start
|
||||||
/* Indicate that we're doing interrupt not exception processing. */
|
address */
|
||||||
PSW &= ~PSW_EP;
|
|
||||||
if (inttype == int_reset)
|
if (inttype == int_reset)
|
||||||
{
|
{
|
||||||
PC = 0;
|
PC = 0;
|
||||||
PSW = 0x20;
|
PSW = 0x20;
|
||||||
ECR = 0;
|
ECR = 0;
|
||||||
/* (Might be useful to init other regs with random values.) */
|
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||||
}
|
}
|
||||||
else if (inttype == int_nmi)
|
|
||||||
|
/* Deliver an NMI when allowed */
|
||||||
|
if (inttype == int_nmi)
|
||||||
{
|
{
|
||||||
if (PSW & PSW_NP)
|
if (PSW & PSW_NP)
|
||||||
{
|
{
|
||||||
/* We're already working on an NMI, so this one must wait
|
/* We're already working on an NMI, so this one must wait
|
||||||
around until the previous one is done. The processor
|
around until the previous one is done. The processor
|
||||||
ignores subsequent NMIs, so we don't need to count them. */
|
ignores subsequent NMIs, so we don't need to count them.
|
||||||
State.pending_nmi = 1;
|
Just keep re-scheduling a single NMI until it manages to
|
||||||
|
be delivered */
|
||||||
|
if (STATE_CPU (sd, 0)->pending_nmi != NULL)
|
||||||
|
sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
|
||||||
|
STATE_CPU (sd, 0)->pending_nmi =
|
||||||
|
sim_events_schedule (sd, 1, do_interrupt, data);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* NMI can be delivered. Do not deschedule pending_nmi as
|
||||||
|
that, if still in the event queue, is a second NMI that
|
||||||
|
needs to be delivered later. */
|
||||||
FEPC = PC;
|
FEPC = PC;
|
||||||
FEPSW = PSW;
|
FEPSW = PSW;
|
||||||
/* Set the FECC part of the ECR. */
|
/* Set the FECC part of the ECR. */
|
||||||
ECR &= 0x0000ffff;
|
ECR &= 0x0000ffff;
|
||||||
ECR |= 0x10;
|
ECR |= 0x10;
|
||||||
PSW |= PSW_NP;
|
PSW |= PSW_NP;
|
||||||
|
PSW &= ~PSW_EP;
|
||||||
|
PSW |= PSW_ID;
|
||||||
PC = 0x10;
|
PC = 0x10;
|
||||||
|
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/* deliver maskable interrupt when allowed */
|
||||||
|
if (inttype > int_nmi && inttype < num_int_types)
|
||||||
{
|
{
|
||||||
EIPC = PC;
|
if ((PSW & PSW_NP) || (PSW & PSW_ID))
|
||||||
EIPSW = PSW;
|
|
||||||
/* Clear the EICC part of the ECR, will set below. */
|
|
||||||
ECR &= 0xffff0000;
|
|
||||||
switch (inttype)
|
|
||||||
{
|
{
|
||||||
case int_intov1:
|
/* Can't deliver this interrupt, reschedule it for later */
|
||||||
PC = 0x80;
|
sim_events_schedule (sd, 1, do_interrupt, data);
|
||||||
ECR |= 0x80;
|
return;
|
||||||
break;
|
|
||||||
case int_intp10:
|
|
||||||
PC = 0x90;
|
|
||||||
ECR |= 0x90;
|
|
||||||
break;
|
|
||||||
case int_intp11:
|
|
||||||
PC = 0xa0;
|
|
||||||
ECR |= 0xa0;
|
|
||||||
break;
|
|
||||||
case int_intp12:
|
|
||||||
PC = 0xb0;
|
|
||||||
ECR |= 0xb0;
|
|
||||||
break;
|
|
||||||
case int_intp13:
|
|
||||||
PC = 0xc0;
|
|
||||||
ECR |= 0xc0;
|
|
||||||
break;
|
|
||||||
case int_intcm4:
|
|
||||||
PC = 0xd0;
|
|
||||||
ECR |= 0xd0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Should never be possible. */
|
|
||||||
abort ();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* save context */
|
||||||
|
EIPC = PC;
|
||||||
|
EIPSW = PSW;
|
||||||
|
/* Disable further interrupts. */
|
||||||
|
PSW |= PSW_ID;
|
||||||
|
/* Indicate that we're doing interrupt not exception processing. */
|
||||||
|
PSW &= ~PSW_EP;
|
||||||
|
/* Clear the EICC part of the ECR, will set below. */
|
||||||
|
ECR &= 0xffff0000;
|
||||||
|
switch (inttype)
|
||||||
|
{
|
||||||
|
case int_intov1:
|
||||||
|
PC = 0x80;
|
||||||
|
ECR |= 0x80;
|
||||||
|
break;
|
||||||
|
case int_intp10:
|
||||||
|
PC = 0x90;
|
||||||
|
ECR |= 0x90;
|
||||||
|
break;
|
||||||
|
case int_intp11:
|
||||||
|
PC = 0xa0;
|
||||||
|
ECR |= 0xa0;
|
||||||
|
break;
|
||||||
|
case int_intp12:
|
||||||
|
PC = 0xb0;
|
||||||
|
ECR |= 0xb0;
|
||||||
|
break;
|
||||||
|
case int_intp13:
|
||||||
|
PC = 0xc0;
|
||||||
|
ECR |= 0xc0;
|
||||||
|
break;
|
||||||
|
case int_intcm4:
|
||||||
|
PC = 0xd0;
|
||||||
|
ECR |= 0xd0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Should never be possible. */
|
||||||
|
sim_engine_abort (sd, NULL, NULL_CIA,
|
||||||
|
"do_interrupt - internal error - bad switch");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* some other interrupt? */
|
||||||
|
sim_engine_abort (sd, NULL, NULL_CIA,
|
||||||
|
"do_interrupt - internal error - interrupt %d unknown",
|
||||||
|
inttype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These default values correspond to expected usage for the chip. */
|
/* These default values correspond to expected usage for the chip. */
|
||||||
|
|
||||||
int v850_debug;
|
|
||||||
|
|
||||||
uint32 OP[4];
|
uint32 OP[4];
|
||||||
|
|
||||||
static long hash PARAMS ((long));
|
|
||||||
#if 0
|
|
||||||
static void do_format_1_2 PARAMS ((uint32));
|
|
||||||
static void do_format_3 PARAMS ((uint32));
|
|
||||||
static void do_format_4 PARAMS ((uint32));
|
|
||||||
static void do_format_5 PARAMS ((uint32));
|
|
||||||
static void do_format_6 PARAMS ((uint32));
|
|
||||||
static void do_format_7 PARAMS ((uint32));
|
|
||||||
static void do_format_8 PARAMS ((uint32));
|
|
||||||
static void do_format_9_10 PARAMS ((uint32));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_HASH 63
|
|
||||||
|
|
||||||
struct hash_entry
|
|
||||||
{
|
|
||||||
struct hash_entry *next;
|
|
||||||
unsigned long opcode;
|
|
||||||
unsigned long mask;
|
|
||||||
struct simops *ops;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hash_entry hash_table[MAX_HASH+1];
|
|
||||||
|
|
||||||
|
|
||||||
static INLINE long
|
|
||||||
hash(insn)
|
|
||||||
long insn;
|
|
||||||
{
|
|
||||||
if ( (insn & 0x0600) == 0
|
|
||||||
|| (insn & 0x0700) == 0x0200
|
|
||||||
|| (insn & 0x0700) == 0x0600
|
|
||||||
|| (insn & 0x0780) == 0x0700)
|
|
||||||
return (insn & 0x07e0) >> 5;
|
|
||||||
|
|
||||||
if ((insn & 0x0700) == 0x0300
|
|
||||||
|| (insn & 0x0700) == 0x0400
|
|
||||||
|| (insn & 0x0700) == 0x0500)
|
|
||||||
return (insn & 0x0780) >> 7;
|
|
||||||
|
|
||||||
if ((insn & 0x07c0) == 0x0780)
|
|
||||||
return (insn & 0x07c0) >> 6;
|
|
||||||
|
|
||||||
return (insn & 0x07e0) >> 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static struct hash_entry *
|
|
||||||
lookup_hash (sd, ins)
|
|
||||||
SIM_DESC sd;
|
|
||||||
uint32 ins;
|
|
||||||
{
|
|
||||||
struct hash_entry *h;
|
|
||||||
|
|
||||||
h = &hash_table[hash(ins)];
|
|
||||||
|
|
||||||
while ((ins & h->mask) != h->opcode)
|
|
||||||
{
|
|
||||||
if (h->next == NULL)
|
|
||||||
{
|
|
||||||
sim_io_error (sd, "ERROR looking up hash for 0x%lx, PC=0x%lx",
|
|
||||||
(long) ins, (long) PC);
|
|
||||||
}
|
|
||||||
h = h->next;
|
|
||||||
}
|
|
||||||
return (h);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SIM_DESC
|
SIM_DESC
|
||||||
sim_open (kind, cb, abfd, argv)
|
sim_open (kind, cb, abfd, argv)
|
||||||
|
@ -329,66 +295,6 @@ sim_stop (sd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void
|
|
||||||
sim_engine_run (sd, next_cpu_nr, siggnal)
|
|
||||||
SIM_DESC sd;
|
|
||||||
int next_cpu_nr;
|
|
||||||
int siggnal;
|
|
||||||
{
|
|
||||||
uint32 inst;
|
|
||||||
SIM_ADDR oldpc;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
struct hash_entry * h;
|
|
||||||
/* Fetch the current instruction. */
|
|
||||||
inst = RLW (PC);
|
|
||||||
oldpc = PC;
|
|
||||||
|
|
||||||
h = lookup_hash (sd, inst);
|
|
||||||
OP[0] = inst & 0x1f;
|
|
||||||
OP[1] = (inst >> 11) & 0x1f;
|
|
||||||
OP[2] = (inst >> 16) & 0xffff;
|
|
||||||
OP[3] = inst;
|
|
||||||
|
|
||||||
/* fprintf (stderr, "PC = %x, SP = %x\n", PC, SP ); */
|
|
||||||
|
|
||||||
if (inst == 0)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "NOP encountered!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PC += h->ops->func ();
|
|
||||||
|
|
||||||
if (oldpc == PC)
|
|
||||||
{
|
|
||||||
sim_io_eprintf (sd, "simulator loop at %lx\n", (long) PC );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sim_events_tick (sd))
|
|
||||||
{
|
|
||||||
sim_events_process (sd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
sim_trace (sd)
|
|
||||||
SIM_DESC sd;
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
v850_debug = DEBUG;
|
|
||||||
#endif
|
|
||||||
sim_resume (sd, 0, 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sim_info (sd, verbose)
|
sim_info (sd, verbose)
|
||||||
SIM_DESC sd;
|
SIM_DESC sd;
|
||||||
|
|
|
@ -41,7 +41,6 @@ typedef struct _v850_regs {
|
||||||
reg_t sregs[32]; /* system registers, including psw */
|
reg_t sregs[32]; /* system registers, including psw */
|
||||||
reg_t pc;
|
reg_t pc;
|
||||||
int dummy_mem; /* where invalid accesses go */
|
int dummy_mem; /* where invalid accesses go */
|
||||||
int pending_nmi;
|
|
||||||
} v850_regs;
|
} v850_regs;
|
||||||
|
|
||||||
struct _sim_cpu
|
struct _sim_cpu
|
||||||
|
@ -49,6 +48,7 @@ struct _sim_cpu
|
||||||
/* ... simulator specific members ... */
|
/* ... simulator specific members ... */
|
||||||
v850_regs reg;
|
v850_regs reg;
|
||||||
reg_t psw_mask; /* only allow non-reserved bits to be set */
|
reg_t psw_mask; /* only allow non-reserved bits to be set */
|
||||||
|
sim_event *pending_nmi;
|
||||||
/* ... base type ... */
|
/* ... base type ... */
|
||||||
sim_cpu_base base;
|
sim_cpu_base base;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1330,19 +1330,6 @@ OP_160 ()
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mov reg, reg */
|
|
||||||
int
|
|
||||||
OP_0 ()
|
|
||||||
{
|
|
||||||
trace_input ("mov", OP_REG_REG_MOVE, 0);
|
|
||||||
|
|
||||||
State.regs[ OP[1] ] = State.regs[ OP[0] ];
|
|
||||||
|
|
||||||
trace_output (OP_REG_REG_MOVE);
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mov sign_extend(imm5), reg */
|
/* mov sign_extend(imm5), reg */
|
||||||
int
|
int
|
||||||
OP_200 ()
|
OP_200 ()
|
||||||
|
@ -1826,28 +1813,6 @@ OP_12007E0 ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reti */
|
|
||||||
int
|
|
||||||
OP_14007E0 ()
|
|
||||||
{
|
|
||||||
trace_input ("reti", OP_NONE, 0);
|
|
||||||
trace_output (OP_NONE);
|
|
||||||
|
|
||||||
/* Restore for NMI if only NP on, otherwise is interrupt or exception. */
|
|
||||||
if ((PSW & (PSW_NP | PSW_EP)) == PSW_NP)
|
|
||||||
{
|
|
||||||
PC = FEPC - 4;
|
|
||||||
PSW = FEPSW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PC = EIPC - 4;
|
|
||||||
PSW = EIPSW;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* trap */
|
/* trap */
|
||||||
int
|
int
|
||||||
OP_10007E0 ()
|
OP_10007E0 ()
|
||||||
|
|
|
@ -631,9 +631,12 @@ regID,111111,RRRRR + 0000000000100000:IX:::ldsr
|
||||||
rrrrr!0,000000,RRRRR:I:::mov
|
rrrrr!0,000000,RRRRR:I:::mov
|
||||||
"mov r<reg1>, r<reg2>"
|
"mov r<reg1>, r<reg2>"
|
||||||
{
|
{
|
||||||
COMPAT_1 (OP_0 ());
|
TRACE_ALU_INPUT0 ();
|
||||||
|
GR[reg2] = GR[reg1];
|
||||||
|
TRACE_ALU_RESULT (GR[reg2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rrrrr!0,010000,iiiii:II:::mov
|
rrrrr!0,010000,iiiii:II:::mov
|
||||||
"mov <imm5>, r<reg2>"
|
"mov <imm5>, r<reg2>"
|
||||||
{
|
{
|
||||||
|
@ -757,7 +760,7 @@ rrrrr,111111,iiiii + wwwww,01001,IIII,10:XII:::mulu
|
||||||
0000000000000000:I:::nop
|
0000000000000000:I:::nop
|
||||||
"nop"
|
"nop"
|
||||||
{
|
{
|
||||||
COMPAT_1 (OP_0 ());
|
/* do nothing, trace nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -886,7 +889,22 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori
|
||||||
0000011111100000 + 0000000101000000:X:::reti
|
0000011111100000 + 0000000101000000:X:::reti
|
||||||
"reti"
|
"reti"
|
||||||
{
|
{
|
||||||
COMPAT_2 (OP_14007E0 ());
|
if ((PSW & PSW_EP))
|
||||||
|
{
|
||||||
|
nia = (EIPC & ~1);
|
||||||
|
PSW = EIPSW;
|
||||||
|
}
|
||||||
|
else if ((PSW & PSW_NP))
|
||||||
|
{
|
||||||
|
nia = (FEPC & ~1);
|
||||||
|
PSW = FEPSW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nia = (EIPC & ~1);
|
||||||
|
PSW = EIPSW;
|
||||||
|
}
|
||||||
|
TRACE_BRANCH1 (PSW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue