+#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 ();
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,
+ OP_R4,
+ OP_R2R3
};
#ifdef DEBUG
#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;
case INS_RIGHT: type = " R"; break;
case INS_LEFT_PARALLEL: type = "*L"; break;
case INS_RIGHT_PARALLEL: type = "*R"; break;
+ case INS_LEFT_COND_TEST: type = "?L"; break;
+ case INS_RIGHT_COND_TEST: type = "?R"; break;
+ case INS_LEFT_COND_EXE: type = "&L"; break;
+ case INS_RIGHT_COND_EXE: type = "&R"; break;
case INS_LONG: type = " B"; break;
}
if ((d10v_debug & DEBUG_LINE_NUMBER) == 0)
(*d10v_callback->printf_filtered) (d10v_callback,
- "0x%.*x %s: %-*s",
+ "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;
+ 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;
}
else if (filename)
{
- char *q = (char *) strrchr (filename, '/');
+ char *q = strrchr (filename, '/');
sprintf (p, "%s ", (q) ? q+1 : filename);
p += strlen (p);
}
}
(*d10v_callback->printf_filtered) (d10v_callback,
- "0x%.*x %s: %-*.*s %-*s",
+ "0x%.*x %s: %-*.*s %-*s ",
SIZE_PC, (unsigned)PC,
type,
SIZE_LOCATION, SIZE_LOCATION, buf,
switch (in[i])
{
case OP_VOID:
+ case OP_R2:
+ case OP_R3:
+ case OP_R4:
+ case OP_R2R3:
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;
+
+ case OP_R4:
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)State.regs[4]);
+ break;
+
+ case OP_R2R3:
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)State.regs[2]);
+ (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+ (uint16)State.regs[3]);
+ i++;
+ break;
}
}
}
+
+ (*d10v_callback->flush_stdout) (d10v_callback);
}
static void
(*d10v_callback->printf_filtered) (d10v_callback, " :: %*s F0=%d F1=%d C=%d\n", SIZE_VALUES, "",
State.F0 != 0, State.F1 != 0, State.C != 0);
break;
+
+ case OP_R2:
+ (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "",
+ (uint16)State.regs[2],
+ State.F0 != 0, State.F1 != 0, State.C != 0);
+ break;
+
+ case OP_R2R3:
+ (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "",
+ (uint16)State.regs[2], (uint16)State.regs[3],
+ State.F0 != 0, State.F1 != 0, State.C != 0);
+ 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);
}
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]);
+ JMP( 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];
+ JMP (PC + OP[0]);
trace_output (OP_VOID);
}
void
OP_4800 ()
{
- trace_input ("bra.s", OP_CONSTANT16, OP_VOID, OP_VOID);
- PC += SEXT8 (OP[0]);
+ trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID);
+ 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);
}
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]);
+ 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);
}
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]);
+ 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);
}
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);
}
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++)
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]];
+ JMP (State.regs[OP[0]]);
trace_output (OP_VOID);
}
void
OP_4C00 ()
{
- trace_input ("jmp", OP_REG, OP_VOID, OP_VOID);
- PC = State.regs[OP[0]];
+ trace_input ("jmp", OP_REG,
+ (OP[0] == 13) ? OP_R2 : OP_VOID,
+ (OP[0] == 13) ? OP_R3 : OP_VOID);
+
+ JMP (State.regs[OP[0]]);
trace_output (OP_VOID);
}
void
OP_31000000 ()
{
+ uint16 addr = State.regs[OP[2]];
trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
- State.regs[OP[0]] = RW (OP[1] + State.regs[OP[2]]);
- State.regs[OP[0]+1] = RW (OP[1] + State.regs[OP[2]] + 2);
+ State.regs[OP[0]] = RW (OP[1] + addr);
+ State.regs[OP[0]+1] = RW (OP[1] + addr + 2);
trace_output (OP_DREG);
}
void
OP_6601 ()
{
+ uint16 addr = State.regs[OP[1]];
trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
- State.regs[OP[0]] = RW (State.regs[OP[1]]);
- State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
+ State.regs[OP[0]] = RW (addr);
+ State.regs[OP[0]+1] = RW (addr+2);
INC_ADDR(State.regs[OP[1]],-4);
trace_output (OP_DREG);
}
void
OP_6201 ()
{
+ uint16 addr = State.regs[OP[1]];
trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
- State.regs[OP[0]] = RW (State.regs[OP[1]]);
- State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
+ State.regs[OP[0]] = RW (addr);
+ State.regs[OP[0]+1] = RW (addr+2);
INC_ADDR(State.regs[OP[1]],4);
- trace_output (OP_REG);
+ trace_output (OP_DREG);
}
/* ld2w */
void
OP_6200 ()
{
- trace_input ("ld", 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);
+ uint16 addr = State.regs[OP[1]];
+ trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
+ State.regs[OP[0]] = RW (addr);
+ State.regs[OP[0]+1] = RW (addr+2);
+ trace_output (OP_DREG);
}
/* ldb */
OP_38000000 ()
{
trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
- State.regs[OP[0]] = RB (OP[1] + State.regs[OP[2]]);
- SEXT8 (State.regs[OP[0]]);
+ State.regs[OP[0]] = SEXT8 (RB (OP[1] + State.regs[OP[2]]));
trace_output (OP_REG);
}
OP_7000 ()
{
trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
- State.regs[OP[0]] = RB (State.regs[OP[1]]);
- SEXT8 (State.regs[OP[0]]);
+ State.regs[OP[0]] = SEXT8 (RB (State.regs[OP[1]]));
trace_output (OP_REG);
}
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 */
if (State.SM) PSW |= 0x8000;
if (State.EA) PSW |= 0x2000;
if (State.DB) PSW |= 0x1000;
+ if (State.DM) PSW |= 0x800;
if (State.IE) PSW |= 0x400;
if (State.RP) PSW |= 0x200;
if (State.MD) PSW |= 0x100;
State.SM = (PSW & 0x8000) ? 1 : 0;
State.EA = (PSW & 0x2000) ? 1 : 0;
State.DB = (PSW & 0x1000) ? 1 : 0;
+ State.DM = (PSW & 0x800) ? 1 : 0;
State.IE = (PSW & 0x400) ? 1 : 0;
State.RP = (PSW & 0x200) ? 1 : 0;
State.MD = (PSW & 0x100) ? 1 : 0;
OP_5E00 ()
{
trace_input ("nop", OP_VOID, OP_VOID, OP_VOID);
- trace_output (OP_VOID);
- if (State.ins_type == INS_LEFT || State.ins_type == INS_LEFT_PARALLEL)
- left_nops++;
- else
- right_nops++;
+ ins_type_counters[ (int)State.ins_type ]--; /* don't count nops as normal instructions */
+ switch (State.ins_type)
+ {
+ default:
+ ins_type_counters[ (int)INS_UNKNOWN ]++;
+ break;
+
+ case INS_LEFT_PARALLEL:
+ /* Don't count a parallel op that includes a NOP as a true parallel op */
+ ins_type_counters[ (int)INS_RIGHT_PARALLEL ]--;
+ ins_type_counters[ (int)INS_RIGHT ]++;
+ ins_type_counters[ (int)INS_LEFT_NOPS ]++;
+ break;
+
+ case INS_LEFT:
+ case INS_LEFT_COND_EXE:
+ ins_type_counters[ (int)INS_LEFT_NOPS ]++;
+ break;
+
+ case INS_RIGHT_PARALLEL:
+ /* Don't count a parallel op that includes a NOP as a true parallel op */
+ ins_type_counters[ (int)INS_LEFT_PARALLEL ]--;
+ ins_type_counters[ (int)INS_LEFT ]++;
+ ins_type_counters[ (int)INS_RIGHT_NOPS ]++;
+ break;
+
+ case INS_RIGHT:
+ case INS_RIGHT_COND_EXE:
+ ins_type_counters[ (int)INS_RIGHT_NOPS ]++;
+ break;
+ }
+
+ trace_output (OP_VOID);
}
/* not */
}
State.F1 = State.F0;
+ tmp = SEXT56 ((State.a[0] << 16) | (State.a[1] & 0xffff));
if (shift >=0)
- tmp = ((State.a[0] << 16) | (State.a[1] & 0xffff)) << shift;
+ tmp <<= shift;
else
- tmp = ((State.a[0] << 16) | (State.a[1] & 0xffff)) >> -shift;
- tmp = ( SEXT60(tmp) + 0x8000 ) >> 16;
- if (tmp > MAX32)
+ tmp >>= -shift;
+ tmp += 0x8000;
+ tmp >>= 16; /* look at bits 0:43 */
+ if (tmp > SEXT44 (SIGNED64 (0x0007fffffff)))
{
State.regs[OP[0]] = 0x7fff;
State.regs[OP[0]+1] = 0xffff;
State.F0 = 1;
}
- else if (tmp < MIN32)
+ else if (tmp < SEXT44 (SIGNED64 (0xfff80000000)))
{
State.regs[OP[0]] = 0x8000;
State.regs[OP[0]+1] = 0;
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;
void
OP_460B ()
{
- uint16 tmp;
-
trace_input ("slx", OP_REG, OP_FLAG, OP_VOID);
State.regs[OP[0]] = (State.regs[OP[0]] << 1) | State.F0;
trace_output (OP_REG);
{
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_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_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_REG, 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;
+ /* see ../common/sim-alu.h for a more extensive discussion on how to
+ compute the carry/overflow bits. */
+ tmp = State.regs[OP[0]] - State.regs[OP[1]];
+ State.C = ((uint16) State.regs[OP[0]] >= (uint16) State.regs[OP[1]]);
+ 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);
}
{
trace_input ("trap", OP_CONSTANT4, OP_VOID, OP_VOID);
trace_output (OP_VOID);
-
+
switch (OP[0])
{
default:
(*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[OP[i]] >> 32) & 0xff),
- ((unsigned long)State.a[OP[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 */
{
- int save_errno = errno;
errno = 0;
/* Registers passed to trap 0 */
/* Turn a pointer in a register into a pointer into real memory. */
-#define MEMPTR(x) ((char *)((x) + State.imem))
+#define MEMPTR(x) ((char *)(dmem_addr(x)))
switch (FUNC)
{
#if !defined(__GO32__) && !defined(_WIN32)
case SYS_fork:
RETVAL = fork ();
+ trace_input ("<fork>", OP_VOID, OP_VOID, OP_VOID);
+ trace_output (OP_R2);
+ break;
+
+ case SYS_getpid:
+ trace_input ("<getpid>", OP_VOID, OP_VOID, OP_VOID);
+ RETVAL = getpid ();
+ trace_output (OP_R2);
break;
+
+ case SYS_kill:
+ trace_input ("<kill>", OP_REG, OP_REG, OP_VOID);
+ if (PARM1 == getpid ())
+ {
+ trace_output (OP_VOID);
+ State.exception = PARM2;
+ }
+ else
+ {
+ int os_sig = -1;
+ switch (PARM2)
+ {
+#ifdef SIGHUP
+ case 1: os_sig = SIGHUP; break;
+#endif
+#ifdef SIGINT
+ case 2: os_sig = SIGINT; break;
+#endif
+#ifdef SIGQUIT
+ case 3: os_sig = SIGQUIT; break;
+#endif
+#ifdef SIGILL
+ case 4: os_sig = SIGILL; break;
+#endif
+#ifdef SIGTRAP
+ case 5: os_sig = SIGTRAP; break;
+#endif
+#ifdef SIGABRT
+ case 6: os_sig = SIGABRT; break;
+#elif defined(SIGIOT)
+ case 6: os_sig = SIGIOT; break;
+#endif
+#ifdef SIGEMT
+ case 7: os_sig = SIGEMT; break;
+#endif
+#ifdef SIGFPE
+ case 8: os_sig = SIGFPE; break;
+#endif
+#ifdef SIGKILL
+ case 9: os_sig = SIGKILL; break;
+#endif
+#ifdef SIGBUS
+ case 10: os_sig = SIGBUS; break;
+#endif
+#ifdef SIGSEGV
+ case 11: os_sig = SIGSEGV; break;
+#endif
+#ifdef SIGSYS
+ case 12: os_sig = SIGSYS; break;
+#endif
+#ifdef SIGPIPE
+ case 13: os_sig = SIGPIPE; break;
+#endif
+#ifdef SIGALRM
+ case 14: os_sig = SIGALRM; break;
+#endif
+#ifdef SIGTERM
+ case 15: os_sig = SIGTERM; break;
+#endif
+#ifdef SIGURG
+ case 16: os_sig = SIGURG; break;
+#endif
+#ifdef SIGSTOP
+ case 17: os_sig = SIGSTOP; break;
+#endif
+#ifdef SIGTSTP
+ case 18: os_sig = SIGTSTP; break;
+#endif
+#ifdef SIGCONT
+ case 19: os_sig = SIGCONT; break;
+#endif
+#ifdef SIGCHLD
+ case 20: os_sig = SIGCHLD; break;
+#elif defined(SIGCLD)
+ case 20: os_sig = SIGCLD; break;
+#endif
+#ifdef SIGTTIN
+ case 21: os_sig = SIGTTIN; break;
+#endif
+#ifdef SIGTTOU
+ case 22: os_sig = SIGTTOU; break;
+#endif
+#ifdef SIGIO
+ case 23: os_sig = SIGIO; break;
+#elif defined (SIGPOLL)
+ case 23: os_sig = SIGPOLL; break;
+#endif
+#ifdef SIGXCPU
+ case 24: os_sig = SIGXCPU; break;
+#endif
+#ifdef SIGXFSZ
+ case 25: os_sig = SIGXFSZ; break;
+#endif
+#ifdef SIGVTALRM
+ case 26: os_sig = SIGVTALRM; break;
+#endif
+#ifdef SIGPROF
+ case 27: os_sig = SIGPROF; break;
+#endif
+#ifdef SIGWINCH
+ case 28: os_sig = SIGWINCH; break;
+#endif
+#ifdef SIGLOST
+ case 29: os_sig = SIGLOST; break;
+#endif
+#ifdef SIGUSR1
+ case 30: os_sig = SIGUSR1; break;
+#endif
+#ifdef SIGUSR2
+ case 31: os_sig = SIGUSR2; break;
+#endif
+ }
+
+ if (os_sig == -1)
+ {
+ 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
+ {
+ RETVAL = kill (PARM1, PARM2);
+ trace_output (OP_R2);
+ }
+ }
+ break;
+
case SYS_execve:
RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2),
(char **)MEMPTR (PARM3));
+ trace_input ("<execve>", OP_R2, OP_R3, OP_R4);
+ 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:
{
reg_t buf;
SW (buf, host_fd[0]);
buf += sizeof(uint16);
SW (buf, host_fd[1]);
+ trace_input ("<pipe>", OP_R2, OP_VOID, OP_VOID);
+ trace_output (OP_R2);
}
break;
+
+#ifdef SYS_wait
case SYS_wait:
{
int status;
RETVAL = wait (&status);
- SW (PARM1, status);
+ if (PARM1)
+ SW (PARM1, status);
+ trace_input ("<wait>", OP_R2, OP_VOID, OP_VOID);
+ trace_output (OP_R2);
}
break;
#endif
+#else
+ case SYS_getpid:
+ trace_input ("<getpid>", OP_VOID, OP_VOID, OP_VOID);
+ RETVAL = 1;
+ trace_output (OP_R2);
+ break;
+
+ case SYS_kill:
+ trace_input ("<kill>", OP_REG, OP_REG, OP_VOID);
+ trace_output (OP_VOID);
+ State.exception = PARM2;
+ break;
+#endif
+
case SYS_read:
RETVAL = d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2),
PARM3);
+ trace_input ("<read>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2);
break;
+
case SYS_write:
if (PARM1 == 1)
RETVAL = (int)d10v_callback->write_stdout (d10v_callback,
else
RETVAL = (int)d10v_callback->write (d10v_callback, PARM1,
MEMPTR (PARM2), PARM3);
+ trace_input ("<write>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2);
break;
+
case SYS_lseek:
{
unsigned long ret = d10v_callback->lseek (d10v_callback, PARM1,
RETVAL_HIGH = ret >> 16;
RETVAL_LOW = ret & 0xffff;
}
+ trace_input ("<lseek>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2R3);
break;
+
case SYS_close:
RETVAL = d10v_callback->close (d10v_callback, PARM1);
+ trace_input ("<close>", OP_R2, OP_VOID, OP_VOID);
+ trace_output (OP_R2);
break;
+
case SYS_open:
RETVAL = d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2);
+ trace_input ("<open>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2);
+ trace_input ("<open>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2);
break;
+
case SYS_exit:
State.exception = SIG_D10V_EXIT;
+ trace_input ("<exit>", OP_R2, OP_VOID, OP_VOID);
+ trace_output (OP_VOID);
break;
case SYS_stat:
SLW (buf+28, host_stat.st_mtime);
SLW (buf+36, host_stat.st_ctime);
}
+ trace_input ("<stat>", OP_R2, OP_R3, OP_VOID);
+ trace_output (OP_R2);
break;
case SYS_chown:
RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3);
+ trace_input ("<chown>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2);
break;
+
case SYS_chmod:
RETVAL = chmod (MEMPTR (PARM1), PARM2);
+ trace_input ("<chmod>", OP_R2, OP_R3, OP_R4);
+ 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. */
RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2));
+ 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);
+ RETVAL_HIGH = ret >> 16;
+ RETVAL_LOW = ret & 0xffff;
+ }
+ trace_input ("<time>", OP_R2, OP_R3, OP_R4);
+ trace_output (OP_R2R3);
break;
+#endif
+
default:
abort ();
}
- RETERR = d10v_callback->get_errno(d10v_callback);
+ RETERR = (RETVAL == (uint16) -1) ? d10v_callback->get_errno(d10v_callback) : 0;
break;
}
-
- case 1:
- /* Trap 1 prints a string */
- {
- char *fstr = State.regs[2] + State.imem;
- fputs (fstr, stdout);
- break;
- }
-
- case 2:
- /* Trap 2 calls printf */
- {
- char *fstr = State.regs[2] + State.imem;
- (*d10v_callback->printf_filtered) (d10v_callback, fstr,
- (int16)State.regs[3],
- (int16)State.regs[4],
- (int16)State.regs[5]);
- break;
- }
-
- case 3:
- /* Trap 3 writes a character */
- putchar (State.regs[2]);
- break;
- }
}
}