📄 simops.c
字号:
#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#ifdef HAVE_STRING_H#include <string.h>#endif#include "d10v_sim.h"#include "simops.h"#include "targ-vals.h"extern char *strrchr ();enum op_types { OP_VOID, OP_REG, OP_REG_OUTPUT, OP_DREG, OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM_OUTPUT, OP_ACCUM_REVERSE, OP_CR, OP_CR_OUTPUT, OP_CR_REVERSE, OP_FLAG, OP_FLAG_OUTPUT, OP_CONSTANT16, OP_CONSTANT8, OP_CONSTANT3, OP_CONSTANT4, OP_MEMREF, OP_MEMREF2, OP_MEMREF3, OP_POSTDEC, OP_POSTINC, OP_PREDEC, OP_R0, OP_R1, OP_R2,};enum { PSW_MASK = (PSW_SM_BIT | PSW_EA_BIT | PSW_DB_BIT | PSW_IE_BIT | PSW_RP_BIT | PSW_MD_BIT | PSW_FX_BIT | PSW_ST_BIT | PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT), /* The following bits in the PSW _can't_ be set by instructions such as mvtc. */ PSW_HW_MASK = (PSW_MASK | PSW_DM_BIT)};reg_tmove_to_cr (int cr, reg_t mask, reg_t val, int psw_hw_p){ /* A MASK bit is set when the corresponding bit in the CR should be left alone */ /* This assumes that (VAL & MASK) == 0 */ switch (cr) { case PSW_CR: if (psw_hw_p) val &= PSW_HW_MASK; else val &= PSW_MASK; if ((mask & PSW_SM_BIT) == 0) { int new_psw_sm = (val & PSW_SM_BIT) != 0; /* save old SP */ SET_HELD_SP (PSW_SM, GPR (SP_IDX)); if (PSW_SM != new_psw_sm) /* restore new SP */ SET_GPR (SP_IDX, HELD_SP (new_psw_sm)); } if ((mask & (PSW_ST_BIT | PSW_FX_BIT)) == 0) { if (val & PSW_ST_BIT && !(val & PSW_FX_BIT)) { (*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; } } /* keep an up-to-date psw around for tracing */ State.trace.psw = (State.trace.psw & mask) | val; break; case BPSW_CR: case DPSW_CR: /* Just like PSW, mask things like DM out. */ if (psw_hw_p) val &= PSW_HW_MASK; else val &= PSW_MASK; break; case MOD_S_CR: case MOD_E_CR: val &= ~1; break; default: break; } /* only issue an update if the register is being changed */ if ((State.cregs[cr] & ~mask) != val) SLOT_PEND_MASK (State.cregs[cr], mask, val); return val;}#ifdef DEBUGstatic 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)#ifndef SIZE_INSTRUCTION#define SIZE_INSTRUCTION 8#endif#ifndef SIZE_OPERANDS#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#endifstatic voidtrace_input_func (name, in1, in2, in3) char *name; enum op_types in1; enum op_types in2; enum op_types in3;{ char *comma; enum op_types in[3]; int i; 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) { default: case INS_UNKNOWN: type = " ?"; break; case INS_LEFT: type = " L"; break; 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 ", 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 bfd_symbol **)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; in[2] = in3; comma = ""; p = buf; for (i = 0; i < 3; i++) { switch (in[i]) { case OP_VOID: case OP_R0: case OP_R1: case OP_R2: break; case OP_REG: case OP_REG_OUTPUT: case OP_DREG: case OP_DREG_OUTPUT: sprintf (p, "%sr%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_CR: case OP_CR_OUTPUT: case OP_CR_REVERSE: sprintf (p, "%scr%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_ACCUM: case OP_ACCUM_OUTPUT: case OP_ACCUM_REVERSE: sprintf (p, "%sa%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_CONSTANT16: sprintf (p, "%s%d", comma, OP[i]); p += strlen (p); 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); comma = ","; break; case OP_CONSTANT3: sprintf (p, "%s%d", comma, SEXT3(OP[i])); p += strlen (p); comma = ","; break; case OP_MEMREF: sprintf (p, "%s@r%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_MEMREF2: sprintf (p, "%s@(%d,r%d)", comma, (int16)OP[i], OP[i+1]); p += strlen (p); comma = ","; break; case OP_MEMREF3: sprintf (p, "%s@%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_POSTINC: sprintf (p, "%s@r%d+", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_POSTDEC: sprintf (p, "%s@r%d-", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_PREDEC: sprintf (p, "%s@-r%d", comma, OP[i]); p += strlen (p); comma = ","; break; case OP_FLAG: case OP_FLAG_OUTPUT: if (OP[i] == 0) sprintf (p, "%sf0", comma); else if (OP[i] == 1) sprintf (p, "%sf1", comma); else sprintf (p, "%sc", comma); p += strlen (p); comma = ","; break; } } 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); 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) GPR (OP[i])); break; case OP_MEMREF3: (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) OP[i]); break; case OP_DREG: tmp = (long)((((uint32) GPR (OP[i])) << 16) | ((uint32) GPR (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) CREG (OP[i])); break; case OP_ACCUM: case OP_ACCUM_REVERSE: (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.2x%.8lx", SIZE_VALUES-12, "", ((int)(ACC (OP[i]) >> 32) & 0xff), ((unsigned long) ACC (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, "", PSW_F0 != 0); else if (OP[i] == 1) (*d10v_callback->printf_filtered) (d10v_callback, "%*sF1 = %d", SIZE_VALUES-6, "", PSW_F1 != 0); else (*d10v_callback->printf_filtered) (d10v_callback, "%*sC = %d", SIZE_VALUES-5, "", PSW_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)GPR (OP[i + 1])); i++; break; case OP_R0: (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) GPR (0)); break; case OP_R1: (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) GPR (1)); break; case OP_R2: (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) GPR (2)); break; } } } (*d10v_callback->flush_stdout) (d10v_callback);}static voiddo_trace_output_flush (void){ (*d10v_callback->flush_stdout) (d10v_callback);}static voiddo_trace_output_finish (void){ (*d10v_callback->printf_filtered) (d10v_callback, " F0=%d F1=%d C=%d\n", (State.trace.psw & PSW_F0_BIT) != 0, (State.trace.psw & PSW_F1_BIT) != 0, (State.trace.psw & PSW_C_BIT) != 0); (*d10v_callback->flush_stdout) (d10v_callback);}static voidtrace_output_40 (uint64 val){ if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.2x%.8lx", SIZE_VALUES - 12, "", ((int)(val >> 32) & 0xff), ((unsigned long) val) & 0xffffffff); do_trace_output_finish (); }}static voidtrace_output_32 (uint32 val){ if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.8x", SIZE_VALUES - 10, "", (int) val); do_trace_output_finish (); }}static voidtrace_output_16 (uint16 val){ if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x", SIZE_VALUES - 6, "", (int) val); do_trace_output_finish (); }}static voidtrace_output_void (){ if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { (*d10v_callback->printf_filtered) (d10v_callback, "\n"); do_trace_output_flush (); }}static voidtrace_output_flag (){ if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) { (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s", SIZE_VALUES, ""); do_trace_output_finish (); }}#else#define trace_input(NAME, IN1, IN2, IN3)#define trace_output(RESULT)#endif/* abs */voidOP_4607 (){ int16 tmp; trace_input ("abs", OP_REG, OP_VOID, OP_VOID); SET_PSW_F1 (PSW_F0); tmp = GPR(OP[0]); if (tmp < 0) { tmp = - tmp; SET_PSW_F0 (1); } else SET_PSW_F0 (0); SET_GPR (OP[0], tmp); trace_output_16 (tmp);}/* abs */voidOP_5607 (){ int64 tmp; trace_input ("abs", OP_ACCUM, OP_VOID, OP_VOID); SET_PSW_F1 (PSW_F0); tmp = SEXT40 (ACC (OP[0])); if (tmp < 0 ) { tmp = - tmp; if (PSW_ST) { if (tmp > SEXT40(MAX32)) tmp = (MAX32); else if (tmp < SEXT40(MIN32)) tmp = (MIN32); else tmp = (tmp & MASK40); } else tmp = (tmp & MASK40); SET_PSW_F0 (1); } else { tmp = (tmp & MASK40); SET_PSW_F0 (0); } SET_ACC (OP[0], tmp); trace_output_40 (tmp);}/* add */voidOP_200 (){ uint16 a = GPR (OP[0]); uint16 b = GPR (OP[1]); uint16 tmp = (a + b); trace_input ("add", OP_REG, OP_REG, OP_VOID); SET_PSW_C (a > tmp); SET_GPR (OP[0], tmp); trace_output_16 (tmp);}/* add */voidOP_1201 (){ int64 tmp; tmp = SEXT40(ACC (OP[0])) + (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1)); trace_input ("add", OP_ACCUM, OP_REG, OP_VOID); if (PSW_ST) { if (tmp > SEXT40(MAX32)) tmp = (MAX32); else if (tmp < SEXT40(MIN32)) tmp = (MIN32); else tmp = (tmp & MASK40); } else tmp = (tmp & MASK40); SET_ACC (OP[0], tmp); trace_output_40 (tmp);}/* add */voidOP_1203 (){ int64 tmp; tmp = SEXT40(ACC (OP[0])) + SEXT40(ACC (OP[1]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -