#include "d10v_sim.h"
#include "simops.h"
#include "sys/syscall.h"
+#include "bfd.h"
enum op_types {
OP_VOID,
OP_FLAG,
OP_FLAG_OUTPUT,
OP_CONSTANT16,
+ OP_CONSTANT8,
OP_CONSTANT3,
OP_CONSTANT4,
OP_MEMREF,
OP_MEMREF2,
OP_POSTDEC,
OP_POSTINC,
- OP_PREDEC
+ OP_PREDEC,
+ OP_R2,
+ OP_R3
};
#ifdef DEBUG
-static void trace_input PARAMS ((char *name,
- enum op_types in1,
- enum op_types in2,
- enum op_types in3));
+static void trace_input_func PARAMS ((char *name,
+ enum op_types in1,
+ enum op_types in2,
+ enum op_types in3));
-static void trace_output PARAMS ((enum op_types result));
+#define trace_input(name, in1, in2, in3) do { if (d10v_debug) trace_input_func (name, in1, in2, in3); } while (0)
+
+static void trace_output_func PARAMS ((enum op_types result));
+
+#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 10
+#define SIZE_INSTRUCTION 8
#endif
#ifndef SIZE_OPERANDS
-#define SIZE_OPERANDS 24
+#define SIZE_OPERANDS 18
#endif
#ifndef SIZE_VALUES
#define SIZE_VALUES 13
#endif
+#ifndef SIZE_LOCATION
+#define SIZE_LOCATION 20
+#endif
+
+#ifndef SIZE_PC
+#define SIZE_PC 6
+#endif
+
+#ifndef SIZE_LINE_NUMBER
+#define SIZE_LINE_NUMBER 4
+#endif
+
static void
-trace_input (name, in1, in2, in3)
+trace_input_func (name, in1, in2, in3)
char *name;
enum op_types in1;
enum op_types in2;
char *comma;
enum op_types in[3];
int i;
- char buf[80];
+ char buf[1024];
char *p;
long tmp;
char *type;
+ asection *s;
+ const char *filename;
+ const char *functionname;
+ unsigned int linenumber;
+ bfd_vma byte_pc;
if ((d10v_debug & DEBUG_TRACE) == 0)
return;
case INS_LONG: type = " B"; break;
}
- (*d10v_callback->printf_filtered) (d10v_callback,
- "0x%.6x %s: %-*s",
- (unsigned)PC, type,
- SIZE_INSTRUCTION, name);
+ if ((d10v_debug & DEBUG_LINE_NUMBER) == 0)
+ (*d10v_callback->printf_filtered) (d10v_callback,
+ "0x%.*x %s: %-*s ",
+ SIZE_PC, (unsigned)PC,
+ type,
+ SIZE_INSTRUCTION, name);
+
+ 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;
+ 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,
+ &filename, &functionname, &linenumber))
+ {
+ p = buf;
+ if (linenumber)
+ {
+ sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber);
+ p += strlen (p);
+ }
+ else
+ {
+ sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
+ p += SIZE_LINE_NUMBER+2;
+ }
+
+ if (functionname)
+ {
+ sprintf (p, "%s ", functionname);
+ p += strlen (p);
+ }
+ else if (filename)
+ {
+ char *q = (char *) strrchr (filename, '/');
+ sprintf (p, "%s ", (q) ? q+1 : filename);
+ p += strlen (p);
+ }
+
+ if (*p == ' ')
+ *p = '\0';
+ }
+ }
+
+ (*d10v_callback->printf_filtered) (d10v_callback,
+ "0x%.*x %s: %-*.*s %-*s ",
+ SIZE_PC, (unsigned)PC,
+ type,
+ SIZE_LOCATION, SIZE_LOCATION, buf,
+ SIZE_INSTRUCTION, name);
+ }
in[0] = in1;
in[1] = in2;
switch (in[i])
{
case OP_VOID:
+ case OP_R2:
+ case OP_R3:
break;
case OP_REG:
comma = ",";
break;
+ case OP_CONSTANT8:
+ sprintf (p, "%s%d", comma, SEXT8(OP[i]));
+ p += strlen (p);
+ comma = ",";
+ break;
+
case OP_CONSTANT4:
sprintf (p, "%s%d", comma, SEXT4(OP[i]));
p += strlen (p);
(uint16)SEXT4(OP[i]));
break;
+ case OP_CONSTANT8:
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)SEXT8(OP[i]));
+ break;
+
case OP_CONSTANT3:
(*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
(uint16)SEXT3(OP[i]));
(*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
(uint16)State.regs[OP[++i]]);
break;
+
+ case OP_R2:
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)State.regs[2]);
+ break;
+
+ case OP_R3:
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)State.regs[3]);
+ break;
}
}
}
}
static void
-trace_output (result)
+trace_output_func (result)
enum op_types result;
{
if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES))
void
OP_201 ()
{
+ 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;
trace_output (OP_REG);
}
void
OP_4900 ()
{
- trace_input ("bl.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+ trace_input ("bl.s", OP_CONSTANT8, OP_R2, OP_R3);
State.regs[13] = PC+1;
PC += SEXT8 (OP[0]);
trace_output (OP_VOID);
void
OP_24800000 ()
{
- trace_input ("bl.l", OP_CONSTANT16, OP_VOID, OP_VOID);
+ trace_input ("bl.l", OP_CONSTANT16, OP_R2, OP_R3);
State.regs[13] = PC+1;
PC += OP[0];
trace_output (OP_VOID);
void
OP_4800 ()
{
- trace_input ("bra.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+ trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID);
PC += SEXT8 (OP[0]);
trace_output (OP_VOID);
}
void
OP_4A00 ()
{
- trace_input ("brf0f.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+ trace_input ("brf0f.s", OP_CONSTANT8, OP_VOID, OP_VOID);
if (State.F0 == 0)
PC += SEXT8 (OP[0]);
trace_output (OP_FLAG);
void
OP_4B00 ()
{
- trace_input ("brf0t.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+ trace_input ("brf0t.s", OP_CONSTANT8, OP_VOID, OP_VOID);
if (State.F0)
PC += SEXT8 (OP[0]);
trace_output (OP_FLAG);
void
OP_401 ()
{
- trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT16, OP_VOID);
+ trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT4, OP_VOID);
State.F1 = State.F0;
- State.F0 = (State.regs[OP[0]] == SEXT4(OP[1])) ? 1 : 0;
+ State.F0 = (State.regs[OP[0]] == (reg_t)SEXT4(OP[1])) ? 1 : 0;
trace_output (OP_FLAG);
}
{
trace_input ("cmpeqi.l", OP_REG, OP_CONSTANT16, OP_VOID);
State.F1 = State.F0;
- State.F0 = (State.regs[OP[0]] == OP[1]) ? 1 : 0;
+ State.F0 = (State.regs[OP[0]] == (reg_t)OP[1]) ? 1 : 0;
trace_output (OP_FLAG);
}
{
trace_input ("cmpi.s", OP_REG, OP_CONSTANT4, OP_VOID);
State.F1 = State.F0;
- State.F0 = ((int16)(State.regs[OP[0]]) < SEXT4(OP[1])) ? 1 : 0;
+ State.F0 = ((int16)(State.regs[OP[0]]) < (int16)SEXT4(OP[1])) ? 1 : 0;
trace_output (OP_FLAG);
}
{
trace_input ("cmpui", OP_REG, OP_CONSTANT16, OP_VOID);
State.F1 = State.F0;
- State.F0 = (State.regs[OP[0]] < OP[1]) ? 1 : 0;
+ State.F0 = (State.regs[OP[0]] < (reg_t)OP[1]) ? 1 : 0;
trace_output (OP_FLAG);
}
void
OP_5F20 ()
{
- d10v_callback->printf_filtered(d10v_callback, "***** DBT ***** PC=%x\n",PC);
+ /* d10v_callback->printf_filtered(d10v_callback, "***** DBT ***** PC=%x\n",PC); */
State.exception = SIGTRAP;
}
void
OP_4D00 ()
{
- trace_input ("jl", OP_REG, OP_VOID, OP_VOID);
+ trace_input ("jl", OP_REG, OP_R2, OP_R3);
State.regs[13] = PC+1;
PC = State.regs[OP[0]];
trace_output (OP_VOID);
void
OP_4C00 ()
{
- trace_input ("jmp", OP_REG, OP_VOID, OP_VOID);
+ trace_input ("jmp", OP_REG,
+ (OP[0] == 13) ? OP_R2 : OP_VOID,
+ (OP[0] == 13) ? OP_R3 : OP_VOID);
+
PC = State.regs[OP[0]];
trace_output (OP_VOID);
}
void
OP_6200 ()
{
- trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
+ trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
State.regs[OP[0]] = RW (State.regs[OP[1]]);
State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
trace_output (OP_REG);
void
OP_6A00 ()
{
- trace_input ("st2w", OP_REG, OP_MEMREF, OP_VOID);
+ trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID);
SW (State.regs[OP[1]], State.regs[OP[0]]);
SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
trace_output (OP_VOID);
void
OP_6E1F ()
{
- trace_input ("st2w", OP_REG, OP_PREDEC, OP_VOID);
+ trace_input ("st2w", OP_DREG, OP_PREDEC, OP_VOID);
if ( OP[1] != 15 )
{
(*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n");
void
OP_6A01 ()
{
- trace_input ("st2w", OP_REG, OP_POSTDEC, OP_VOID);
+ trace_input ("st2w", OP_DREG, OP_POSTDEC, 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_REG, OP_POSTINC, 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);
OP_5FE0 ()
{
trace_input ("stop", OP_VOID, OP_VOID, OP_VOID);
- State.exception = SIGQUIT;
+ State.exception = SIG_D10V_STOP;
trace_output (OP_VOID);
}
void
OP_5F00 ()
{
- trace_input ("trap", OP_CONSTANT16, OP_REG, OP_VOID);
+ trace_input ("trap", OP_CONSTANT4, OP_VOID, OP_VOID);
trace_output (OP_VOID);
switch (OP[0])
{
default:
+#if 0
(*d10v_callback->printf_filtered) (d10v_callback, "Unknown trap code %d\n", OP[0]);
State.exception = SIGILL;
+#else
+ /* Use any other traps for batch debugging. */
+ {
+ int i;
+ static int first_time = 1;
+
+ if (first_time)
+ {
+ first_time = 0;
+ (*d10v_callback->printf_filtered) (d10v_callback, "Trap # PC ");
+ for (i = 0; i < 16; i++)
+ (*d10v_callback->printf_filtered) (d10v_callback, " %sr%d", (i > 9) ? "" : " ", i);
+ (*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);
+
+ 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[OP[i]] >> 32) & 0xff),
+ ((unsigned long)State.a[OP[i]]) & 0xffffffff);
+
+ (*d10v_callback->printf_filtered) (d10v_callback, " %d %d %d\n",
+ State.F0 != 0, State.F1 != 0, State.C != 0);
+ break;
+#endif
case 0:
/* Trap 0 is used for simulating low-level I/O */
/* Registers passed to trap 0 */
-#define FUNC State.regs[2] /* function number, return value */
-#define PARM1 State.regs[3] /* optional parm 1 */
-#define PARM2 State.regs[4] /* optional parm 2 */
-#define PARM3 State.regs[5] /* optional parm 3 */
+#define FUNC State.regs[6] /* function number */
+#define PARM1 State.regs[2] /* optional parm 1 */
+#define PARM2 State.regs[3] /* optional parm 2 */
+#define PARM3 State.regs[4] /* optional parm 3 */
+#define PARM4 State.regs[5] /* optional parm 3 */
/* Registers set by trap 0 */
-#define RETVAL State.regs[2] /* return value */
-#define RETERR State.regs[3] /* return error code */
+#define RETVAL State.regs[2] /* return value */
+#define RETVAL_HIGH State.regs[2] /* return value */
+#define RETVAL_LOW State.regs[3] /* return value */
+#define RETERR State.regs[4] /* return error code */
/* Turn a pointer in a register into a pointer into real memory. */
switch (FUNC)
{
#if !defined(__GO32__) && !defined(_WIN32)
-#ifdef SYS_fork
case SYS_fork:
RETVAL = fork ();
break;
-#endif
-#ifdef SYS_execve
case SYS_execve:
RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2),
(char **)MEMPTR (PARM3));
break;
-#endif
-#ifdef SYS_execv
case SYS_execv:
RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL);
break;
-#endif
-#ifdef SYS_pipe
case SYS_pipe:
{
reg_t buf;
SW (buf, host_fd[1]);
}
break;
-#endif
-#ifdef SYS_wait
case SYS_wait:
{
int status;
}
break;
#endif
-#endif
-
-#ifdef SYS_read
case SYS_read:
RETVAL = d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2),
PARM3);
break;
-#endif
-#ifdef SYS_write
case SYS_write:
if (PARM1 == 1)
RETVAL = (int)d10v_callback->write_stdout (d10v_callback,
RETVAL = (int)d10v_callback->write (d10v_callback, PARM1,
MEMPTR (PARM2), PARM3);
break;
-#endif
-#ifdef SYS_lseek
case SYS_lseek:
- RETVAL = d10v_callback->lseek (d10v_callback, PARM1, PARM2, PARM3);
+ {
+ unsigned long ret = d10v_callback->lseek (d10v_callback, PARM1,
+ (((unsigned long)PARM2) << 16) || (unsigned long)PARM3,
+ PARM4);
+ RETVAL_HIGH = ret >> 16;
+ RETVAL_LOW = ret & 0xffff;
+ }
break;
-#endif
-#ifdef SYS_close
case SYS_close:
RETVAL = d10v_callback->close (d10v_callback, PARM1);
break;
-#endif
-#ifdef SYS_open
case SYS_open:
RETVAL = d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2);
break;
-#endif
-#ifdef SYS_exit
case SYS_exit:
- /* EXIT - caller can look in PARM1 to work out the
- reason */
- State.exception = SIGQUIT;
+ State.exception = SIG_D10V_EXIT;
break;
-#endif
-#ifdef SYS_stat
case SYS_stat:
/* stat system call */
{
SLW (buf+36, host_stat.st_ctime);
}
break;
-#endif
-#ifdef SYS_chown
case SYS_chown:
RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3);
break;
-#endif
-#ifdef SYS_chmod
case SYS_chmod:
RETVAL = chmod (MEMPTR (PARM1), PARM2);
break;
-#endif
-#ifdef SYS_utime
case SYS_utime:
/* Cast the second argument to void *, to avoid type mismatch
if a prototype is present. */
RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2));
break;
-#endif
default:
abort ();
}
- RETERR = errno;
- errno = save_errno;
+ RETERR = d10v_callback->get_errno(d10v_callback);
break;
}
/* Trap 3 writes a character */
putchar (State.regs[2]);
break;
+ }
}
}