X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fd10v%2Fsimops.c;h=3c4a0af7dc9a62aae5fa31fce5e52625b3f7d847;hb=08db4a658e9a7b23cd2cb6953f33a7a7dbc486f8;hp=e547f9bcd32db9bfa5863cd6eac9fbbd9b5096f1;hpb=57bc1a721a6b00bf4f01897cdba81ca42fa94f6d;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/d10v/simops.c b/sim/d10v/simops.c index e547f9bcd3..3c4a0af7dc 100644 --- a/sim/d10v/simops.c +++ b/sim/d10v/simops.c @@ -1,13 +1,18 @@ +#include "config.h" + #include #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif #include "d10v_sim.h" #include "simops.h" #include "sys/syscall.h" -#include "bfd.h" + +extern char *strrchr (); enum op_types { OP_VOID, @@ -50,12 +55,6 @@ 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 8 #endif @@ -94,7 +93,6 @@ trace_input_func (name, in1, in2, in3) char *p; long tmp; char *type; - asection *s; const char *filename; const char *functionname; unsigned int linenumber; @@ -111,6 +109,10 @@ trace_input_func (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; } @@ -123,21 +125,8 @@ trace_input_func (name, in1, in2, in3) 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; @@ -165,7 +154,7 @@ trace_input_func (name, in1, in2, in3) } else if (filename) { - char *q = (char *) strrchr (filename, '/'); + char *q = strrchr (filename, '/'); sprintf (p, "%s ", (q) ? q+1 : filename); p += strlen (p); } @@ -196,6 +185,7 @@ trace_input_func (name, in1, in2, in3) case OP_R2: case OP_R3: case OP_R4: + case OP_R2R3: break; case OP_REG: @@ -406,9 +396,19 @@ trace_input_func (name, in1, in2, in3) (*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 @@ -486,6 +486,8 @@ trace_output_func (result) break; } } + + (*d10v_callback->flush_stdout) (d10v_callback); } #else @@ -603,15 +605,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); @@ -621,14 +620,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); } @@ -725,12 +721,10 @@ 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; + State.C = (State.regs[OP[0]] < tmp); trace_output (OP_REG); } @@ -767,7 +761,7 @@ OP_4900 () { 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); } @@ -777,7 +771,7 @@ OP_24800000 () { 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); } @@ -795,7 +789,7 @@ 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); } @@ -804,7 +798,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); } @@ -814,7 +808,7 @@ OP_4A00 () { 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); } @@ -824,7 +818,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); } @@ -834,7 +828,7 @@ OP_4B00 () { 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); } @@ -844,7 +838,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); } @@ -912,7 +906,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); } @@ -1130,10 +1124,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++) @@ -1156,7 +1149,7 @@ OP_4D00 () { 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); } @@ -1168,7 +1161,7 @@ OP_4C00 () (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); } @@ -1186,6 +1179,12 @@ void OP_6401 () { trace_input ("ld", OP_REG_OUTPUT, 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; + } State.regs[OP[0]] = RW (State.regs[OP[1]]); INC_ADDR(State.regs[OP[1]],-2); trace_output (OP_REG); @@ -1227,6 +1226,12 @@ OP_6601 () { uint16 addr = State.regs[OP[1]]; trace_input ("ld2w", OP_REG_OUTPUT, 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; + } State.regs[OP[0]] = RW (addr); State.regs[OP[0]+1] = RW (addr+2); INC_ADDR(State.regs[OP[1]],-4); @@ -1261,8 +1266,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); } @@ -1271,8 +1275,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); } @@ -1289,7 +1292,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); } @@ -1627,9 +1630,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 */ @@ -1830,12 +1833,40 @@ void 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 */ @@ -2129,8 +2160,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); @@ -2151,7 +2180,7 @@ 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); + 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); @@ -2179,7 +2208,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); } @@ -2198,7 +2227,7 @@ 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); + 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); @@ -2226,7 +2255,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); } @@ -2291,6 +2320,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); @@ -2338,6 +2373,12 @@ void OP_6A01 () { 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); @@ -2386,12 +2427,12 @@ 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; + 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); } @@ -2446,14 +2487,13 @@ 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]); + a = (uint32)((State.regs[OP[0]] << 16) | State.regs[OP[0]+1]); + b = (uint32)((State.regs[OP[1]] << 16) | State.regs[OP[1]+1]); tmp = a-b; - State.C = (tmp & 0xffffffff00000000LL) ? 1 : 0; + State.C = (tmp > a); State.regs[OP[0]] = (tmp >> 16) & 0xffff; State.regs[OP[0]+1] = tmp & 0xffff; trace_output (OP_DREG); @@ -2549,14 +2589,14 @@ OP_17001002 () void OP_1 () { - int32 tmp; + uint16 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; + tmp = State.regs[OP[0]] - OP[1]; + State.C = (tmp > State.regs[OP[0]]); + State.regs[OP[0]] = tmp; trace_output (OP_REG); } @@ -2595,18 +2635,18 @@ OP_5F00 () 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); + ((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 0: /* Trap 0 is used for simulating low-level I/O */ { - int save_errno = errno; errno = 0; /* Registers passed to trap 0 */ @@ -2626,7 +2666,7 @@ OP_5F00 () /* 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) { @@ -2760,6 +2800,7 @@ OP_5F00 () { 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 @@ -2942,7 +2983,7 @@ OP_5F00 () case 1: /* Trap 1 prints a string */ { - char *fstr = State.regs[2] + State.imem; + char *fstr = dmem_addr(State.regs[2]); fputs (fstr, stdout); break; } @@ -2950,11 +2991,12 @@ OP_5F00 () case 2: /* Trap 2 calls printf */ { - char *fstr = State.regs[2] + State.imem; + 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]); + (*d10v_callback->flush_stdout) (d10v_callback); break; }