+#include "config.h"
+
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include "d10v_sim.h"
#include "simops.h"
#include "sys/syscall.h"
-#include "bfd.h"
extern char *strrchr ();
#define trace_output(result) do { if (d10v_debug) trace_output_func (result); } while (0)
-static int init_text_p = 0;
-static asection *text;
-static bfd_vma text_start;
-static bfd_vma text_end;
-extern bfd *exec_bfd;
-
#ifndef SIZE_INSTRUCTION
#define SIZE_INSTRUCTION 8
#endif
char *p;
long tmp;
char *type;
- asection *s;
const char *filename;
const char *functionname;
unsigned int linenumber;
else
{
- if (!init_text_p)
- {
- init_text_p = 1;
- for (s = exec_bfd->sections; s; s = s->next)
- if (strcmp (bfd_get_section_name (exec_bfd, s), ".text") == 0)
- {
- text = s;
- text_start = bfd_get_section_vma (exec_bfd, s);
- text_end = text_start + bfd_section_size (exec_bfd, s);
- break;
- }
- }
-
buf[0] = '\0';
- byte_pc = (bfd_vma)PC << 2;
+ byte_pc = decode_pc ();
if (text && byte_pc >= text_start && byte_pc < text_end)
{
filename = (const char *)0;
functionname = (const char *)0;
linenumber = 0;
- if (bfd_find_nearest_line (exec_bfd, text, (struct symbol_cache_entry **)0, byte_pc - text_start,
+ if (bfd_find_nearest_line (prog_bfd, text, (struct symbol_cache_entry **)0, byte_pc - text_start,
&filename, &functionname, &linenumber))
{
p = buf;
}
}
}
+
+ (*d10v_callback->flush_stdout) (d10v_callback);
}
static void
break;
}
}
+
+ (*d10v_callback->flush_stdout) (d10v_callback);
}
#else
OP_1200 ()
{
uint32 tmp;
- uint32 tmp1 = (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1];
- uint32 tmp2 = (State.regs[OP[1]]) << 16 | State.regs[OP[1]+1];
+ uint32 a = (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1];
+ uint32 b = (State.regs[OP[1]]) << 16 | State.regs[OP[1]+1];
trace_input ("add2w", OP_DREG, OP_DREG, OP_VOID);
- tmp = tmp1 + tmp2;
- if ( (tmp < tmp1) || (tmp < tmp2) )
- State.C = 1;
- else
- State.C = 0;
+ tmp = a + b;
+ State.C = (tmp < a);
State.regs[OP[0]] = tmp >> 16;
State.regs[OP[0]+1] = tmp & 0xFFFF;
trace_output (OP_DREG);
void
OP_1000000 ()
{
- uint16 tmp = State.regs[OP[0]];
- State.regs[OP[0]] = State.regs[OP[1]] + OP[2];
+ uint16 tmp = State.regs[OP[1]];
+ State.regs[OP[0]] = tmp + OP[2];
trace_input ("add3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16);
- if ( tmp > State.regs[OP[0]])
- State.C = 1;
- else
- State.C = 0;
+ State.C = (State.regs[OP[0]] < tmp);
trace_output (OP_REG);
}
uint tmp = State.regs[OP[0]];
if (OP[1] == 0)
OP[1] = 16;
+
trace_input ("addi", OP_REG, OP_CONSTANT16, OP_VOID);
State.regs[OP[0]] += OP[1];
- if (tmp > State.regs[OP[0]])
- State.C = 1;
- else
- State.C = 0;
+ State.C = (State.regs[OP[0]] < tmp);
trace_output (OP_REG);
}
{
trace_input ("bl.s", OP_CONSTANT8, OP_R2, OP_R3);
State.regs[13] = PC+1;
- PC += SEXT8 (OP[0]);
+ JMP( PC + SEXT8 (OP[0]));
trace_output (OP_VOID);
}
{
trace_input ("bl.l", OP_CONSTANT16, OP_R2, OP_R3);
State.regs[13] = PC+1;
- PC += OP[0];
+ JMP (PC + OP[0]);
trace_output (OP_VOID);
}
OP_4800 ()
{
trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID);
- PC += SEXT8 (OP[0]);
+ JMP (PC + SEXT8 (OP[0]));
trace_output (OP_VOID);
}
OP_24000000 ()
{
trace_input ("bra.l", OP_CONSTANT16, OP_VOID, OP_VOID);
- PC += OP[0];
+ JMP (PC + OP[0]);
trace_output (OP_VOID);
}
{
trace_input ("brf0f.s", OP_CONSTANT8, OP_VOID, OP_VOID);
if (State.F0 == 0)
- PC += SEXT8 (OP[0]);
+ JMP (PC + SEXT8 (OP[0]));
trace_output (OP_FLAG);
}
{
trace_input ("brf0f.l", OP_CONSTANT16, OP_VOID, OP_VOID);
if (State.F0 == 0)
- PC += OP[0];
+ JMP (PC + OP[0]);
trace_output (OP_FLAG);
}
{
trace_input ("brf0t.s", OP_CONSTANT8, OP_VOID, OP_VOID);
if (State.F0)
- PC += SEXT8 (OP[0]);
+ JMP (PC + SEXT8 (OP[0]));
trace_output (OP_FLAG);
}
{
trace_input ("brf0t.l", OP_CONSTANT16, OP_VOID, OP_VOID);
if (State.F0)
- PC += OP[0];
+ JMP (PC + OP[0]);
trace_output (OP_FLAG);
}
{
trace_input ("cmpeq", OP_ACCUM, OP_ACCUM, OP_VOID);
State.F1 = State.F0;
- State.F0 = (State.a[OP[0]] == State.a[OP[1]]) ? 1 : 0;
+ State.F0 = ((State.a[OP[0]] & MASK40) == (State.a[OP[1]] & MASK40)) ? 1 : 0;
trace_output (OP_FLAG);
}
int i;
trace_input ("exp", OP_REG_OUTPUT, OP_ACCUM, OP_VOID);
- if (SEXT40(State.a[OP[1]]) >= 0)
- tmp = State.a[OP[1]];
- else
- tmp = ~(State.a[OP[1]]);
+ tmp = SEXT40(State.a[OP[1]]);
+ if (tmp < 0)
+ tmp = ~tmp & MASK40;
foo = 0x4000000000LL;
for (i=1;i<25;i++)
{
trace_input ("jl", OP_REG, OP_R2, OP_R3);
State.regs[13] = PC+1;
- PC = State.regs[OP[0]];
+ JMP (State.regs[OP[0]]);
trace_output (OP_VOID);
}
(OP[0] == 13) ? OP_R2 : OP_VOID,
(OP[0] == 13) ? OP_R3 : OP_VOID);
- PC = State.regs[OP[0]];
+ JMP (State.regs[OP[0]]);
trace_output (OP_VOID);
}
void
OP_20000000 ()
{
- trace_input ("ldi.s", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID);
+ trace_input ("ldi.l", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID);
State.regs[OP[0]] = OP[1];
trace_output (OP_REG);
}
void
OP_3A00 ()
{
- int64 tmp;
+ uint64 tmp;
+ uint32 src1;
+ uint32 src2;
trace_input ("macu", OP_ACCUM, OP_REG, OP_REG);
- tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
+ src1 = (uint16) State.regs[OP[1]];
+ src2 = (uint16) State.regs[OP[2]];
+ tmp = src1 * src2;
if (State.FX)
- tmp = SEXT40( (tmp << 1) & MASK40);
- State.a[OP[0]] = (SEXT40 (State.a[OP[0]]) + tmp) & MASK40;
+ tmp = (tmp << 1);
+ State.a[OP[0]] = (State.a[OP[0]] + tmp) & MASK40;
trace_output (OP_ACCUM);
}
void
OP_3800 ()
{
- int64 tmp;
+ uint64 tmp;
+ uint32 src1;
+ uint32 src2;
trace_input ("msbu", OP_ACCUM, OP_REG, OP_REG);
- tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
+ src1 = (uint16) State.regs[OP[1]];
+ src2 = (uint16) State.regs[OP[2]];
+ tmp = src1 * src2;
if (State.FX)
- tmp = SEXT40( (tmp << 1) & MASK40);
+ tmp = (tmp << 1);
- State.a[OP[0]] = (SEXT40 (State.a[OP[0]]) - tmp) & MASK40;
+ State.a[OP[0]] = (State.a[OP[0]] - tmp) & MASK40;
trace_output (OP_ACCUM);
}
void
OP_3C00 ()
{
- int64 tmp;
+ uint64 tmp;
+ uint32 src1;
+ uint32 src2;
trace_input ("mulxu", OP_ACCUM_OUTPUT, OP_REG, OP_REG);
- tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
-
+ src1 = (uint16) State.regs[OP[1]];
+ src2 = (uint16) State.regs[OP[2]];
+ tmp = src1 * src2;
if (State.FX)
tmp <<= 1;
void
OP_3E01 ()
{
- trace_input ("mv2wtac", OP_ACCUM_OUTPUT, OP_DREG, OP_VOID);
+ trace_input ("mv2wtac", OP_DREG, OP_ACCUM_OUTPUT, OP_VOID);
State.a[OP[1]] = (SEXT16 (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1]) & MASK40;
- trace_output (OP_ACCUM);
+ trace_output (OP_ACCUM_REVERSE);
}
/* mvac */
void
OP_4201 ()
{
- int64 tmp;
+ signed64 tmp;
int shift = SEXT3 (OP[2]);
trace_input ("rachi", OP_REG_OUTPUT, OP_ACCUM, OP_CONSTANT3);
State.F1 = State.F0;
if (shift >=0)
- tmp = SEXT44 (State.a[1]) << shift;
+ tmp = SEXT40 (State.a[OP[1]]) << shift;
else
- tmp = SEXT44 (State.a[1]) >> -shift;
+ tmp = SEXT40 (State.a[OP[1]]) >> -shift;
tmp += 0x8000;
- if (tmp > MAX32)
+ if (tmp > SEXT44 (SIGNED64 (0x0007fffffff)))
{
State.regs[OP[0]] = 0x7fff;
State.F0 = 1;
}
- else if (tmp < 0xfff80000000LL)
+ else if (tmp < SEXT44 (SIGNED64 (0xfff80000000)))
{
State.regs[OP[0]] = 0x8000;
State.F0 = 1;
{
trace_input ("sra", OP_ACCUM, OP_REG, OP_VOID);
if ((State.regs[OP[1]] & 31) <= 16)
- State.a[OP[0]] >>= (State.regs[OP[1]] & 31);
+ State.a[OP[0]] = (SEXT40(State.a[OP[0]]) >> (State.regs[OP[1]] & 31)) & MASK40;
else
{
(*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", State.regs[OP[1]] & 31);
OP[1] = 16;
trace_input ("srai", OP_ACCUM, OP_CONSTANT16, OP_VOID);
- State.a[OP[0]] >>= OP[1];
+ State.a[OP[0]] = (SEXT40(State.a[OP[0]]) >> OP[1]) & MASK40;
trace_output (OP_ACCUM);
}
{
trace_input ("srl", OP_ACCUM, OP_REG, OP_VOID);
if ((State.regs[OP[1]] & 31) <= 16)
- State.a[OP[0]] >>= (State.regs[OP[1]] & 31);
+ State.a[OP[0]] = (uint64)((State.a[OP[0]] & MASK40) >> (State.regs[OP[1]] & 31));
else
{
(*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", State.regs[OP[1]] & 31);
OP[1] = 16;
trace_input ("srli", OP_ACCUM, OP_CONSTANT16, OP_VOID);
- State.a[OP[0]] >>= OP[1];
+ State.a[OP[0]] = (uint64)(State.a[OP[0]] & MASK40) >> OP[1];
trace_output (OP_ACCUM);
}
OP_6C01 ()
{
trace_input ("st", OP_REG, OP_POSTDEC, OP_VOID);
+ if ( OP[1] == 15 )
+ {
+ (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
+ State.exception = SIGILL;
+ return;
+ }
SW (State.regs[OP[1]], State.regs[OP[0]]);
INC_ADDR (State.regs[OP[1]],-2);
trace_output (OP_VOID);
void
OP_6A01 ()
{
- trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID);
+ trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID);
SW (State.regs[OP[1]], State.regs[OP[0]]);
SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
INC_ADDR (State.regs[OP[1]],4);
void
OP_6E01 ()
{
- trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID);
+ trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID);
+ if ( OP[1] == 15 )
+ {
+ (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
+ State.exception = SIGILL;
+ return;
+ }
SW (State.regs[OP[1]], State.regs[OP[0]]);
SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
INC_ADDR (State.regs[OP[1]],-4);
void
OP_0 ()
{
- int32 tmp;
+ uint16 tmp;
trace_input ("sub", OP_REG, OP_REG, OP_VOID);
- tmp = (int16)State.regs[OP[0]]- (int16)State.regs[OP[1]];
- State.C = (tmp & 0xffff0000) ? 1 : 0;
- State.regs[OP[0]] = tmp & 0xffff;
+ tmp = State.regs[OP[0]] - State.regs[OP[1]];
+ State.C = (tmp > State.regs[OP[0]]);
+ State.regs[OP[0]] = tmp;
trace_output (OP_REG);
}
void
OP_1000 ()
{
- int64 tmp;
- int32 a,b;
+ uint32 tmp,a,b;
trace_input ("sub2w", OP_DREG, OP_DREG, OP_VOID);
- a = (int32)((State.regs[OP[0]] << 16) | State.regs[OP[0]+1]);
- b = (int32)((State.regs[OP[1]] << 16) | State.regs[OP[1]+1]);
- tmp = a-b;
- State.C = (tmp & 0xffffffff00000000LL) ? 1 : 0;
+ a = (uint32)((State.regs[OP[0]] << 16) | State.regs[OP[0]+1]);
+ b = (uint32)((State.regs[OP[1]] << 16) | State.regs[OP[1]+1]);
+ /* see ../common/sim-alu.h for a more extensive discussion on how to
+ compute the carry/overflow bits */
+ tmp = a - b;
+ State.C = (a >= b);
State.regs[OP[0]] = (tmp >> 16) & 0xffff;
State.regs[OP[0]+1] = tmp & 0xffff;
trace_output (OP_DREG);
void
OP_1 ()
{
- int32 tmp;
+ unsigned tmp;
if (OP[1] == 0)
OP[1] = 16;
trace_input ("subi", OP_REG, OP_CONSTANT16, OP_VOID);
- tmp = (int16)State.regs[OP[0]] - OP[1];
- State.C = (tmp & 0xffff0000) ? 1 : 0;
- State.regs[OP[0]] = tmp & 0xffff;
+ /* see ../common/sim-alu.h for a more extensive discussion on how to
+ compute the carry/overflow bits. */
+ /* since OP[1] is never <= 0, -OP[1] == ~OP[1]+1 can never overflow */
+ tmp = ((unsigned)(unsigned16) State.regs[OP[0]]
+ + (unsigned)(unsigned16) ( - OP[1]));
+ State.C = (tmp >= (1 << 16));
+ State.regs[OP[0]] = tmp;
trace_output (OP_REG);
}
(*d10v_callback->printf_filtered) (d10v_callback, " a0 a1 f0 f1 c\n");
}
- (*d10v_callback->printf_filtered) (d10v_callback, "Trap %2d 0x%.4x:", (int)OP[0], (int)PC);
+ (*d10v_callback->printf_filtered) (d10v_callback, "Trap %2d 0x%.4x:", (int)OP[0], (int)PC);
- for (i = 0; i < 16; i++)
- (*d10v_callback->printf_filtered) (d10v_callback, " %.4x", (int) State.regs[i]);
+ for (i = 0; i < 16; i++)
+ (*d10v_callback->printf_filtered) (d10v_callback, " %.4x", (int) State.regs[i]);
- for (i = 0; i < 2; i++)
- (*d10v_callback->printf_filtered) (d10v_callback, " %.2x%.8lx",
- ((int)(State.a[i] >> 32) & 0xff),
- ((unsigned long)State.a[i]) & 0xffffffff);
+ for (i = 0; i < 2; i++)
+ (*d10v_callback->printf_filtered) (d10v_callback, " %.2x%.8lx",
+ ((int)(State.a[i] >> 32) & 0xff),
+ ((unsigned long)State.a[i]) & 0xffffffff);
- (*d10v_callback->printf_filtered) (d10v_callback, " %d %d %d\n",
- State.F0 != 0, State.F1 != 0, State.C != 0);
- break;
+ (*d10v_callback->printf_filtered) (d10v_callback, " %d %d %d\n",
+ State.F0 != 0, State.F1 != 0, State.C != 0);
+ (*d10v_callback->flush_stdout) (d10v_callback);
+ break;
+ }
#endif
- case 0:
- /* Trap 0 is used for simulating low-level I/O */
+ case 0: /* old system call trap, to be deleted */
+ case 15: /* new system call trap */
+ /* Trap 15 is used for simulating low-level I/O */
{
errno = 0;
{
trace_output (OP_VOID);
(*d10v_callback->printf_filtered) (d10v_callback, "Unknown signal %d\n", PARM2);
+ (*d10v_callback->flush_stdout) (d10v_callback);
State.exception = SIGILL;
}
else
trace_output (OP_R2);
break;
+#ifdef SYS_execv
case SYS_execv:
RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL);
trace_input ("<execv>", OP_R2, OP_R3, OP_VOID);
trace_output (OP_R2);
break;
+#endif
case SYS_pipe:
{
}
break;
+#ifdef SYS_wait
case SYS_wait:
{
int status;
trace_output (OP_R2);
}
break;
+#endif
#else
case SYS_getpid:
trace_input ("<getpid>", OP_VOID, OP_VOID, OP_VOID);
trace_output (OP_R2);
break;
+#ifdef SYS_utime
case SYS_utime:
/* Cast the second argument to void *, to avoid type mismatch
if a prototype is present. */
trace_input ("<utime>", OP_R2, OP_R3, OP_R4);
trace_output (OP_R2);
break;
+#endif
+#ifdef SYS_time
case SYS_time:
{
unsigned long ret = time (PARM1 ? MEMPTR (PARM1) : NULL);
trace_input ("<time>", OP_R2, OP_R3, OP_R4);
trace_output (OP_R2R3);
break;
+#endif
default:
abort ();
}
- RETERR = d10v_callback->get_errno(d10v_callback);
- break;
- }
-
- case 1:
- /* Trap 1 prints a string */
- {
- char *fstr = dmem_addr(State.regs[2]);
- fputs (fstr, stdout);
- break;
- }
-
- case 2:
- /* Trap 2 calls printf */
- {
- char *fstr = dmem_addr(State.regs[2]);
- (*d10v_callback->printf_filtered) (d10v_callback, fstr,
- (int16)State.regs[3],
- (int16)State.regs[4],
- (int16)State.regs[5]);
+ RETERR = (RETVAL == (uint16) -1) ? d10v_callback->get_errno(d10v_callback) : 0;
break;
}
-
- case 3:
- /* Trap 3 writes a character */
- putchar (State.regs[2]);
- break;
- }
}
}