X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fd10v%2Fsimops.c;h=dc0750338d24d2be30d2302656fa6a1949d5662a;hb=19431a02809968af77b87776ecd346574f7c0f87;hp=16ac932c418e5cdc32fadee4daa0358e2160fb80;hpb=87178dbdf71a6b05a76c6835c84c38230af05879;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/d10v/simops.c b/sim/d10v/simops.c index 16ac932c41..dc0750338d 100644 --- a/sim/d10v/simops.c +++ b/sim/d10v/simops.c @@ -1,13 +1,19 @@ +#include "config.h" + #include #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif #include "d10v_sim.h" #include "simops.h" #include "sys/syscall.h" +extern char *strrchr (); + enum op_types { OP_VOID, OP_REG, @@ -21,38 +27,131 @@ enum op_types { OP_CR_OUTPUT, OP_CR_REVERSE, 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_R0, + OP_R1, + OP_R2, + OP_R0R1 }; -#if (DEBUG & DEBUG_TRACE) != 0 -static void trace_input PARAMS ((char *name, - enum op_types in1, - enum op_types in2, - enum op_types in3)); -static void trace_output PARAMS ((enum op_types result)); +void +move_to_cr (int cr, reg_t val) +{ + switch (cr) + { + case PSW_CR: + State.SM = (val & PSW_SM_BIT) != 0; + State.EA = (val & PSW_EA_BIT) != 0; + State.DB = (val & PSW_DB_BIT) != 0; + State.DM = (val & PSW_DM_BIT) != 0; + State.IE = (val & PSW_IE_BIT) != 0; + State.RP = (val & PSW_RP_BIT) != 0; + State.MD = (val & PSW_MD_BIT) != 0; + State.FX = (val & PSW_FX_BIT) != 0; + State.ST = (val & PSW_ST_BIT) != 0; + State.F0 = (val & PSW_F0_BIT) != 0; + State.F1 = (val & PSW_F1_BIT) != 0; + State.C = (val & PSW_C_BIT) != 0; + if (State.ST && !State.FX) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "ERROR at PC 0x%x: ST can only be set when FX is set.\n", + PC<<2); + State.exception = SIGILL; + } + State.cregs[cr] = (val & ~0x4032); + break; + case BPSW_CR: + case DPSW_CR: + State.cregs[cr] = (val & ~0x4032); + break; + case MOD_S_CR: + case MOD_E_CR: + State.cregs[cr] = (val & ~0x1); + break; + default: + State.cregs[cr] = val; + break; + } +} + +reg_t +move_from_cr (int cr) +{ + reg_t val = 0; + switch (cr) + { + case PSW_CR: + if (State.SM) val |= PSW_SM_BIT; + if (State.EA) val |= PSW_EA_BIT; + if (State.DB) val |= PSW_DB_BIT; + if (State.DM) val |= PSW_DM_BIT; + if (State.IE) val |= PSW_IE_BIT; + if (State.RP) val |= PSW_RP_BIT; + if (State.MD) val |= PSW_MD_BIT; + if (State.FX) val |= PSW_FX_BIT; + if (State.ST) val |= PSW_ST_BIT; + if (State.F0) val |= PSW_F0_BIT; + if (State.F1) val |= PSW_F1_BIT; + if (State.C) val |= PSW_C_BIT; + break; + default: + val = State.cregs[cr]; + break; + } + return val; +} + + +#ifdef DEBUG +static void trace_input_func PARAMS ((char *name, + enum op_types in1, + enum op_types in2, + enum op_types in3)); + +#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) #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; @@ -61,10 +160,17 @@ trace_input (name, in1, in2, in3) char *comma; enum op_types in[3]; int i; - char buf[80]; + char buf[1024]; char *p; long tmp; char *type; + const char *filename; + const char *functionname; + unsigned int linenumber; + bfd_vma byte_pc; + + if ((d10v_debug & DEBUG_TRACE) == 0) + return; switch (State.ins_type) { @@ -74,10 +180,68 @@ trace_input (name, in1, in2, in3) 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; } - printf ("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 + { + buf[0] = '\0'; + 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 (prog_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 = 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; @@ -89,6 +253,10 @@ trace_input (name, in1, in2, in3) switch (in[i]) { case OP_VOID: + case OP_R0: + case OP_R1: + case OP_R2: + case OP_R0R1: break; case OP_REG: @@ -122,6 +290,12 @@ trace_input (name, in1, in2, in3) 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); @@ -165,6 +339,7 @@ trace_input (name, in1, in2, in3) break; case OP_FLAG: + case OP_FLAG_OUTPUT: if (OP[i] == 0) sprintf (p, "%sf0", comma); @@ -172,7 +347,7 @@ trace_input (name, in1, in2, in3) sprintf (p, "%sf1", comma); else - sprintf (p, "%scarry", comma); + sprintf (p, "%sc", comma); p += strlen (p); comma = ","; @@ -180,150 +355,210 @@ trace_input (name, in1, in2, in3) } } -#if (DEBUG & DEBUG_VALUES) == 0 - *p++ = '\n'; - *p = '\0'; - fputs (buf, stdout); + if ((d10v_debug & DEBUG_VALUES) == 0) + { + *p++ = '\n'; + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%s", buf); + } + else + { + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%-*s", SIZE_OPERANDS, buf); -#else /* DEBUG_VALUES */ - *p = '\0'; - printf ("%-*s", SIZE_OPERANDS, buf); + p = buf; + for (i = 0; i < 3; i++) + { + buf[0] = '\0'; + switch (in[i]) + { + case OP_VOID: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, ""); + break; + + case OP_REG_OUTPUT: + case OP_DREG_OUTPUT: + case OP_CR_OUTPUT: + case OP_ACCUM_OUTPUT: + case OP_FLAG_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, "---"); + break; + + case OP_REG: + case OP_MEMREF: + case OP_POSTDEC: + case OP_POSTINC: + case OP_PREDEC: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[OP[i]]); + break; + + case OP_DREG: + tmp = (long)((((uint32) State.regs[OP[i]]) << 16) | ((uint32) State.regs[OP[i]+1])); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.8lx", SIZE_VALUES-10, "", tmp); + break; + + case OP_CR: + case OP_CR_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.cregs[OP[i]]); + break; + + case OP_ACCUM: + case OP_ACCUM_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.2x%.8lx", SIZE_VALUES-12, "", + ((int)(State.a[OP[i]] >> 32) & 0xff), + ((unsigned long)State.a[OP[i]]) & 0xffffffff); + break; + + case OP_CONSTANT16: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + break; + + case OP_CONSTANT4: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (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])); + break; + + case OP_FLAG: + if (OP[i] == 0) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF0 = %d", SIZE_VALUES-6, "", + State.F0 != 0); + + else if (OP[i] == 1) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF1 = %d", SIZE_VALUES-6, "", + State.F1 != 0); + + else + (*d10v_callback->printf_filtered) (d10v_callback, "%*sC = %d", SIZE_VALUES-5, "", + State.C != 0); + + break; + + case OP_MEMREF2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[OP[++i]]); + break; + + case OP_R0: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[0]); + break; + + case OP_R1: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[1]); + break; + + case OP_R2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[2]); + break; + + case OP_R0R1: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[0]); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)State.regs[1]); + i++; + break; + } + } + } - p = buf; - for (i = 0; i < 3; i++) + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +trace_output_func (result) + enum op_types result; +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { - buf[0] = '\0'; - switch (in[i]) - { - case OP_VOID: - printf ("%*s", SIZE_VALUES, ""); - break; + long tmp; - case OP_REG_OUTPUT: - case OP_DREG_OUTPUT: - case OP_CR_OUTPUT: - case OP_ACCUM_OUTPUT: - printf ("%*s", SIZE_VALUES, "---"); + switch (result) + { + default: + putchar ('\n'); break; case OP_REG: - case OP_MEMREF: - case OP_POSTDEC: - case OP_POSTINC: - case OP_PREDEC: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)State.regs[OP[i]]); + case OP_REG_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", + (uint16)State.regs[OP[0]], + State.F0 != 0, State.F1 != 0, State.C != 0); break; case OP_DREG: - tmp = (long)((((uint32) State.regs[OP[i]]) << 16) | ((uint32) State.regs[OP[i]+1])); - printf ("%*s0x%.8lx", SIZE_VALUES-10, "", tmp); + case OP_DREG_OUTPUT: + tmp = (long)((((uint32) State.regs[OP[0]]) << 16) | ((uint32) State.regs[OP[0]+1])); + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "", tmp, + State.F0 != 0, State.F1 != 0, State.C != 0); break; case OP_CR: - case OP_CR_REVERSE: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)State.cregs[OP[i]]); - break; - - case OP_ACCUM: - case OP_ACCUM_REVERSE: - printf ("%*s0x%.2x%.8lx", SIZE_VALUES-12, "", - ((int)(State.a[OP[i]] >> 32) & 0xff), - ((unsigned long)State.a[OP[i]]) & 0xffffffff); + case OP_CR_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", + (uint16)State.cregs[OP[0]], + State.F0 != 0, State.F1 != 0, State.C != 0); break; - case OP_CONSTANT16: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)OP[i]); + case OP_CR_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", + (uint16)State.cregs[OP[1]], + State.F0 != 0, State.F1 != 0, State.C != 0); break; - case OP_CONSTANT4: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)SEXT4(OP[i])); + case OP_ACCUM: + case OP_ACCUM_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.2x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-12, "", + ((int)(State.a[OP[0]] >> 32) & 0xff), + ((unsigned long)State.a[OP[0]]) & 0xffffffff, + State.F0 != 0, State.F1 != 0, State.C != 0); break; - case OP_CONSTANT3: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)SEXT3(OP[i])); + case OP_ACCUM_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.2x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-12, "", + ((int)(State.a[OP[1]] >> 32) & 0xff), + ((unsigned long)State.a[OP[1]]) & 0xffffffff, + State.F0 != 0, State.F1 != 0, State.C != 0); break; case OP_FLAG: - if (OP[i] == 0) - printf ("%*sF0 = %d", SIZE_VALUES-6, "", State.F0 != 0); - - else if (OP[i] == 1) - printf ("%*sF1 = %d", SIZE_VALUES-6, "", State.F1 != 0); - - else - printf ("%*sC = %d", SIZE_VALUES-5, "", State.C != 0); + case OP_FLAG_OUTPUT: + (*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_R0: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", + (uint16)State.regs[0], + State.F0 != 0, State.F1 != 0, State.C != 0); break; - case OP_MEMREF2: - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)OP[i]); - printf ("%*s0x%.4x", SIZE_VALUES-6, "", (uint16)State.regs[OP[++i]]); + case OP_R0R1: + (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "", + (uint16)State.regs[0], (uint16)State.regs[1], + State.F0 != 0, State.F1 != 0, State.C != 0); break; } } -#endif -} - -static void -trace_output (result) - enum op_types result; -{ -#if (DEBUG & DEBUG_VALUES) != 0 - long tmp; - - switch (result) - { - default: - putchar ('\n'); - break; - case OP_REG: - case OP_REG_OUTPUT: - printf (" :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", (uint16)State.regs[OP[0]], - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_DREG: - case OP_DREG_OUTPUT: - tmp = (long)((((uint32) State.regs[OP[0]]) << 16) | ((uint32) State.regs[OP[0]+1])); - printf (" :: %*s0x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "", tmp, - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_CR: - case OP_CR_OUTPUT: - printf (" :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", (uint16)State.cregs[OP[0]], - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_CR_REVERSE: - printf (" :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "", (uint16)State.cregs[OP[1]], - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_ACCUM: - case OP_ACCUM_OUTPUT: - printf (" :: %*s0x%.2x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "", - ((int)(State.a[OP[0]] >> 32) & 0xff), - ((unsigned long)State.a[OP[0]]) & 0xffffffff, - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_ACCUM_REVERSE: - printf (" :: %*s0x%.2x%.8lx F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "", - ((int)(State.a[OP[1]] >> 32) & 0xff), - ((unsigned long)State.a[OP[1]]) & 0xffffffff, - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - - case OP_FLAG: - printf (" :: %*s F0=%d F1=%d C=%d\n", SIZE_VALUES, "", - State.F0 != 0, State.F1 != 0, State.C != 0); - break; - } - - fflush (stdout); -#endif + (*d10v_callback->flush_stdout) (d10v_callback); } #else @@ -441,15 +676,12 @@ void 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); @@ -459,14 +691,11 @@ OP_1200 () 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); } @@ -560,10 +789,13 @@ OP_17001202 () 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]; + State.C = (State.regs[OP[0]] < tmp); trace_output (OP_REG); } @@ -598,9 +830,9 @@ OP_C01 () void OP_4900 () { - trace_input ("bl.s", OP_CONSTANT16, OP_VOID, OP_VOID); + trace_input ("bl.s", OP_CONSTANT8, OP_R0, OP_R1); State.regs[13] = PC+1; - PC += SEXT8 (OP[0]); + JMP( PC + SEXT8 (OP[0])); trace_output (OP_VOID); } @@ -608,9 +840,9 @@ OP_4900 () void OP_24800000 () { - trace_input ("bl.l", OP_CONSTANT16, OP_VOID, OP_VOID); + trace_input ("bl.l", OP_CONSTANT16, OP_R0, OP_R1); State.regs[13] = PC+1; - PC += OP[0]; + JMP (PC + OP[0]); trace_output (OP_VOID); } @@ -627,8 +859,8 @@ OP_A01 () 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); } @@ -637,7 +869,7 @@ void OP_24000000 () { trace_input ("bra.l", OP_CONSTANT16, OP_VOID, OP_VOID); - PC += OP[0]; + JMP (PC + OP[0]); trace_output (OP_VOID); } @@ -645,9 +877,9 @@ OP_24000000 () 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); } @@ -657,7 +889,7 @@ OP_25000000 () { 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); } @@ -665,9 +897,9 @@ OP_25000000 () 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); } @@ -677,7 +909,7 @@ OP_25800000 () { trace_input ("brf0t.l", OP_CONSTANT16, OP_VOID, OP_VOID); if (State.F0) - PC += OP[0]; + JMP (PC + OP[0]); trace_output (OP_FLAG); } @@ -745,7 +977,7 @@ OP_1403 () { 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); } @@ -753,9 +985,9 @@ OP_1403 () 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); } @@ -765,7 +997,7 @@ OP_2000000 () { 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); } @@ -775,7 +1007,7 @@ OP_601 () { 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); } @@ -805,7 +1037,7 @@ OP_23000000 () { 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); } @@ -815,7 +1047,7 @@ OP_4E09 () { uint8 *src, *dst; - trace_input ("cpfg", OP_FLAG, OP_VOID, OP_VOID); + trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID); if (OP[0] == 0) dst = &State.F0; else @@ -836,7 +1068,7 @@ OP_4E09 () void OP_5F20 () { - printf("***** DBT ***** PC=%x\n",PC); + /* d10v_callback->printf_filtered(d10v_callback, "***** DBT ***** PC=%x\n",PC); */ State.exception = SIGTRAP; } @@ -860,7 +1092,7 @@ void OP_4E04 () { trace_input ("exef0f", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F0) ? 0 : 1; + State.exe = (State.F0 == 0); trace_output (OP_FLAG); } @@ -869,7 +1101,7 @@ void OP_4E24 () { trace_input ("exef0t", OP_VOID, OP_VOID, OP_VOID); - State.exe = State.F0; + State.exe = (State.F0 != 0); trace_output (OP_FLAG); } @@ -878,7 +1110,7 @@ void OP_4E40 () { trace_input ("exef1f", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F1) ? 0 : 1; + State.exe = (State.F1 == 0); trace_output (OP_FLAG); } @@ -887,7 +1119,7 @@ void OP_4E42 () { trace_input ("exef1t", OP_VOID, OP_VOID, OP_VOID); - State.exe = State.F1; + State.exe = (State.F1 != 0); trace_output (OP_FLAG); } @@ -896,7 +1128,7 @@ void OP_4E00 () { trace_input ("exefaf", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F0 | State.F1) ? 0 : 1; + State.exe = (State.F0 == 0) & (State.F1 == 0); trace_output (OP_FLAG); } @@ -905,7 +1137,7 @@ void OP_4E02 () { trace_input ("exefat", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F0) ? 0 : (State.F1); + State.exe = (State.F0 == 0) & (State.F1 != 0); trace_output (OP_FLAG); } @@ -914,7 +1146,7 @@ void OP_4E20 () { trace_input ("exetaf", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F1) ? 0 : (State.F0); + State.exe = (State.F0 != 0) & (State.F1 == 0); trace_output (OP_FLAG); } @@ -923,7 +1155,7 @@ void OP_4E22 () { trace_input ("exetat", OP_VOID, OP_VOID, OP_VOID); - State.exe = (State.F0) ? (State.F1) : 0; + State.exe = (State.F0 != 0) & (State.F1 != 0); trace_output (OP_FLAG); } @@ -963,10 +1195,9 @@ OP_15002A02 () 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++) @@ -987,9 +1218,9 @@ OP_15002A02 () void OP_4D00 () { - trace_input ("jl", OP_REG, OP_VOID, OP_VOID); + trace_input ("jl", OP_REG, OP_R0, OP_R1); State.regs[13] = PC+1; - PC = State.regs[OP[0]]; + JMP (State.regs[OP[0]]); trace_output (OP_VOID); } @@ -997,8 +1228,11 @@ OP_4D00 () 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_R0 : OP_VOID, + (OP[0] == 13) ? OP_R1 : OP_VOID); + + JMP (State.regs[OP[0]]); trace_output (OP_VOID); } @@ -1044,9 +1278,10 @@ OP_6000 () void OP_31000000 () { - trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, 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); + uint16 addr = State.regs[OP[2]]; + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + State.regs[OP[0]] = RW (OP[1] + addr); + State.regs[OP[0]+1] = RW (OP[1] + addr + 2); trace_output (OP_DREG); } @@ -1054,9 +1289,10 @@ OP_31000000 () 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); } @@ -1065,21 +1301,23 @@ OP_6601 () 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 */ @@ -1087,8 +1325,7 @@ void 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); } @@ -1097,8 +1334,7 @@ void 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); } @@ -1115,7 +1351,7 @@ OP_4001 () 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); } @@ -1187,13 +1423,17 @@ OP_1A00 () 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); } @@ -1203,7 +1443,7 @@ OP_2600 () { trace_input ("max", OP_REG, OP_REG, OP_VOID); State.F1 = State.F0; - if (State.regs[OP[1]] > State.regs[OP[0]]) + if ((int16)State.regs[OP[1]] > (int16)State.regs[OP[0]]) { State.regs[OP[0]] = State.regs[OP[1]]; State.F0 = 1; @@ -1255,7 +1495,7 @@ OP_2601 () { trace_input ("min", OP_REG, OP_REG, OP_VOID); State.F1 = State.F0; - if (State.regs[OP[1]] < State.regs[OP[0]]) + if ((int16)State.regs[OP[1]] < (int16)State.regs[OP[0]]) { State.regs[OP[0]] = State.regs[OP[1]]; State.F0 = 1; @@ -1349,14 +1589,18 @@ OP_1800 () 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); } @@ -1408,11 +1652,14 @@ OP_1C00 () 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; @@ -1453,9 +1700,9 @@ OP_3E00 () 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 */ @@ -1528,23 +1775,7 @@ void OP_5200 () { trace_input ("mvfc", OP_REG_OUTPUT, OP_CR, OP_VOID); - if (OP[1] == 0) - { - /* PSW is treated specially */ - PSW = 0; - if (State.SM) PSW |= 0x8000; - if (State.EA) PSW |= 0x2000; - if (State.DB) PSW |= 0x1000; - if (State.IE) PSW |= 0x400; - if (State.RP) PSW |= 0x200; - if (State.MD) PSW |= 0x100; - if (State.FX) PSW |= 0x80; - if (State.ST) PSW |= 0x40; - if (State.F0) PSW |= 8; - if (State.F1) PSW |= 4; - if (State.C) PSW |= 1; - } - State.regs[OP[0]] = State.cregs[OP[1]]; + State.regs[OP[0]] = move_from_cr (OP[1]); trace_output (OP_REG); } @@ -1584,27 +1815,7 @@ void OP_5600 () { trace_input ("mvtc", OP_REG, OP_CR_OUTPUT, OP_VOID); - State.cregs[OP[1]] = State.regs[OP[0]]; - if (OP[1] == 0) - { - /* PSW is treated specially */ - State.SM = (PSW & 0x8000) ? 1 : 0; - State.EA = (PSW & 0x2000) ? 1 : 0; - State.DB = (PSW & 0x1000) ? 1 : 0; - State.IE = (PSW & 0x400) ? 1 : 0; - State.RP = (PSW & 0x200) ? 1 : 0; - State.MD = (PSW & 0x100) ? 1 : 0; - State.FX = (PSW & 0x80) ? 1 : 0; - State.ST = (PSW & 0x40) ? 1 : 0; - State.F0 = (PSW & 8) ? 1 : 0; - State.F1 = (PSW & 4) ? 1 : 0; - State.C = PSW & 1; - if (State.ST && !State.FX) - { - fprintf (stderr,"ERROR at PC 0x%x: ST can only be set when FX is set.\n",PC<<2); - State.exception = SIGILL; - } - } + move_to_cr (OP[1], State.regs[OP[0]]); trace_output (OP_CR_REVERSE); } @@ -1654,6 +1865,39 @@ void OP_5E00 () { trace_input ("nop", OP_VOID, OP_VOID, OP_VOID); + + 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); } @@ -1694,23 +1938,27 @@ OP_5201 () trace_input ("rac", OP_DREG_OUTPUT, OP_ACCUM, OP_CONSTANT3); if (OP[1] != 0) { - fprintf (stderr,"ERROR at PC 0x%x: instruction only valid for A0\n",PC<<2); + (*d10v_callback->printf_filtered) (d10v_callback, + "ERROR at PC 0x%x: instruction only valid for A0\n", + PC<<2); State.exception = SIGILL; } 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; @@ -1729,23 +1977,23 @@ OP_5201 () 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; @@ -1769,12 +2017,12 @@ OP_27000000 () State.RP = 1; if (RPT_C == 0) { - fprintf (stderr, "ERROR: rep with count=0 is illegal.\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep with count=0 is illegal.\n"); State.exception = SIGILL; } if (OP[1] < 4) { - fprintf (stderr, "ERROR: rep must include at least 4 instructions.\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep must include at least 4 instructions.\n"); State.exception = SIGILL; } trace_output (OP_VOID); @@ -1791,12 +2039,12 @@ OP_2F000000 () State.RP = 1; if (RPT_C == 0) { - fprintf (stderr, "ERROR: repi with count=0 is illegal.\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi with count=0 is illegal.\n"); State.exception = SIGILL; } if (OP[1] < 4) { - fprintf (stderr, "ERROR: repi must include at least 4 instructions.\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi must include at least 4 instructions.\n"); State.exception = SIGILL; } trace_output (OP_VOID); @@ -1806,7 +2054,7 @@ OP_2F000000 () void OP_5F60 () { - fprintf(stderr, "ERROR: rtd - NOT IMPLEMENTED\n"); + d10v_callback->printf_filtered(d10v_callback, "ERROR: rtd - NOT IMPLEMENTED\n"); State.exception = SIGILL; } @@ -1815,8 +2063,8 @@ void OP_5F40 () { trace_input ("rte", OP_VOID, OP_VOID, OP_VOID); - PC = BPC; - PSW = BPSW; + move_to_cr (PSW_CR, BPSW); + JMP(BPC); trace_output (OP_VOID); } @@ -1884,8 +2132,14 @@ OP_3200 () { int64 tmp; trace_input ("sll", OP_ACCUM, OP_REG, OP_VOID); - if (State.regs[OP[1]] & 31 <= 16) + if ((State.regs[OP[1]] & 31) <= 16) tmp = SEXT40 (State.a[OP[0]]) << (State.regs[OP[1]] & 31); + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", State.regs[OP[1]] & 31); + State.exception = SIGILL; + return; + } if (State.ST) { @@ -1940,8 +2194,6 @@ OP_3201 () 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); @@ -1961,8 +2213,15 @@ void OP_3400 () { 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); + if ((State.regs[OP[1]] & 31) <= 16) + 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); + State.exception = SIGILL; + return; + } + trace_output (OP_ACCUM); } @@ -1983,7 +2242,7 @@ OP_3401 () 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); } @@ -2001,8 +2260,15 @@ void OP_3000 () { 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); + if ((State.regs[OP[1]] & 31) <= 16) + 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); + State.exception = SIGILL; + return; + } + trace_output (OP_ACCUM); } @@ -2023,7 +2289,7 @@ OP_3001 () 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); } @@ -2064,7 +2330,7 @@ OP_6C1F () trace_input ("st", OP_REG, OP_PREDEC, OP_VOID); if ( OP[1] != 15 ) { - fprintf (stderr,"ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); State.exception = SIGILL; return; } @@ -2088,6 +2354,12 @@ void 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); @@ -2107,7 +2379,7 @@ OP_35000000 () 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); @@ -2117,10 +2389,10 @@ OP_6A00 () 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 ) { - fprintf (stderr,"ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); State.exception = SIGILL; return; } @@ -2134,7 +2406,7 @@ OP_6E1F () 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); @@ -2145,7 +2417,13 @@ OP_6A01 () 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); @@ -2175,7 +2453,7 @@ void OP_5FE0 () { trace_input ("stop", OP_VOID, OP_VOID, OP_VOID); - State.exception = SIGQUIT; + State.exception = SIG_D10V_STOP; trace_output (OP_VOID); } @@ -2183,12 +2461,14 @@ OP_5FE0 () 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); } @@ -2243,14 +2523,15 @@ OP_1003 () 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); @@ -2346,14 +2627,18 @@ OP_17001002 () 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); } @@ -2361,57 +2646,233 @@ OP_1 () 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: - fprintf (stderr, "Unknown trap code %d\n", OP[0]); - State.exception = SIGILL; +#if (DEBUG & DEBUG_TRAP) == 0 + { + uint16 vec = OP[0] + TRAP_VECTOR_START; + BPC = PC + 1; + move_to_cr (BPSW_CR, PSW); + move_to_cr (PSW_CR, PSW & PSW_SM_BIT); + JMP (vec); + break; + } +#else /* if debugging use trap to print registers */ + { + int i; + static int first_time = 1; - case 0: - /* Trap 0 is used for simulating low-level I/O */ + 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[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); + (*d10v_callback->flush_stdout) (d10v_callback); + break; + } +#endif + 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 */ -#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[4] /* function number */ +#define PARM1 State.regs[0] /* optional parm 1 */ +#define PARM2 State.regs[1] /* optional parm 2 */ +#define PARM3 State.regs[2] /* optional parm 3 */ +#define PARM4 State.regs[3] /* 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[0] /* return value */ +#define RETVAL_HIGH State.regs[0] /* return value */ +#define RETVAL_LOW State.regs[1] /* return value */ +#define RETERR State.regs[4] /* return error code */ /* 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) -#ifdef SYS_fork case SYS_fork: RETVAL = fork (); + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + trace_output (OP_R0); break; + + case SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL = getpid (); + trace_output (OP_R0); + break; + + case SYS_kill: + trace_input ("", 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 SYS_execve +#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_R0); + } + } + break; + case SYS_execve: RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), (char **)MEMPTR (PARM3)); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); break; -#endif + #ifdef SYS_execv case SYS_execv: RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL); + trace_input ("", OP_R0, OP_R1, OP_VOID); + trace_output (OP_R0); break; #endif -#ifdef SYS_pipe + case SYS_pipe: { reg_t buf; @@ -2422,28 +2883,45 @@ OP_5F00 () SW (buf, host_fd[0]); buf += sizeof(uint16); SW (buf, host_fd[1]); + trace_input ("", OP_R0, OP_VOID, OP_VOID); + trace_output (OP_R0); } break; -#endif + #ifdef SYS_wait case SYS_wait: { int status; RETVAL = wait (&status); - SW (PARM1, status); + if (PARM1) + SW (PARM1, status); + trace_input ("", OP_R0, OP_VOID, OP_VOID); + trace_output (OP_R0); } break; #endif +#else + case SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL = 1; + trace_output (OP_R0); + break; + + case SYS_kill: + trace_input ("", OP_REG, OP_REG, OP_VOID); + trace_output (OP_VOID); + State.exception = PARM2; + break; #endif -#ifdef SYS_read case SYS_read: RETVAL = d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2), PARM3); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); break; -#endif -#ifdef SYS_write + case SYS_write: if (PARM1 == 1) RETVAL = (int)d10v_callback->write_stdout (d10v_callback, @@ -2451,32 +2929,42 @@ OP_5F00 () else RETVAL = (int)d10v_callback->write (d10v_callback, PARM1, MEMPTR (PARM2), PARM3); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); 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; + } + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0R1); break; -#endif -#ifdef SYS_close + case SYS_close: RETVAL = d10v_callback->close (d10v_callback, PARM1); + trace_input ("", OP_R0, OP_VOID, OP_VOID); + trace_output (OP_R0); break; -#endif -#ifdef SYS_open + case SYS_open: RETVAL = d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); 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; + trace_input ("", OP_R0, OP_VOID, OP_VOID); + trace_output (OP_VOID); break; -#endif -#ifdef SYS_stat case SYS_stat: /* stat system call */ { @@ -2502,54 +2990,50 @@ OP_5F00 () SLW (buf+28, host_stat.st_mtime); SLW (buf+36, host_stat.st_ctime); } + trace_input ("", OP_R0, OP_R1, OP_VOID); + trace_output (OP_R0); break; -#endif -#ifdef SYS_chown case SYS_chown: RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); break; -#endif -#ifdef SYS_chmod + case SYS_chmod: RETVAL = chmod (MEMPTR (PARM1), PARM2); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); 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)); + trace_input ("", OP_R0, OP_R1, OP_R2); + trace_output (OP_R0); + 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 ("