📄 simops.c
字号:
#include "sim-main.h"#include "v850_sim.h"#include "simops.h"#include <sys/types.h>#ifdef HAVE_UTIME_H#include <utime.h>#endif#ifdef HAVE_TIME_H#include <time.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#include "targ-vals.h"#include "libiberty.h"#include <errno.h>#if !defined(__GO32__) && !defined(_WIN32)#include <sys/stat.h>#include <sys/times.h>#include <sys/time.h>#endif/* This is an array of the bit positions of registers r20 .. r31 in that order in a prepare/dispose instruction. */int type1_regs[12] = { 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 0, 21 };/* This is an array of the bit positions of registers r16 .. r31 in that order in a push/pop instruction. */int type2_regs[16] = { 3, 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21};/* This is an array of the bit positions of registers r1 .. r15 in that order in a push/pop instruction. */int type3_regs[15] = { 2, 1, 0, 27, 26, 25, 24, 31, 30, 29, 28, 23, 22, 20, 21};#ifdef DEBUG#ifndef SIZE_INSTRUCTION#define SIZE_INSTRUCTION 18#endif#ifndef SIZE_VALUES#define SIZE_VALUES 11#endifunsigned32 trace_values[3];int trace_num_values;unsigned32 trace_pc;const char *trace_name;int trace_module;voidtrace_input (name, type, size) char *name; enum op_types type; int size;{ if (!TRACE_ALU_P (STATE_CPU (simulator, 0))) return; trace_pc = PC; trace_name = name; trace_module = TRACE_ALU_IDX; switch (type) { default: case OP_UNKNOWN: case OP_NONE: case OP_TRAP: trace_num_values = 0; break; case OP_REG: case OP_REG_REG_MOVE: trace_values[0] = State.regs[OP[0]]; trace_num_values = 1; break; case OP_BIT_CHANGE: case OP_REG_REG: case OP_REG_REG_CMP: trace_values[0] = State.regs[OP[1]]; trace_values[1] = State.regs[OP[0]]; trace_num_values = 2; break; case OP_IMM_REG: case OP_IMM_REG_CMP: trace_values[0] = SEXT5 (OP[0]); trace_values[1] = OP[1]; trace_num_values = 2; break; case OP_IMM_REG_MOVE: trace_values[0] = SEXT5 (OP[0]); trace_num_values = 1; break; case OP_COND_BR: trace_values[0] = State.pc; trace_values[1] = SEXT9 (OP[0]); trace_values[2] = PSW; trace_num_values = 3; break; case OP_LOAD16: trace_values[0] = OP[1] * size; trace_values[1] = State.regs[30]; trace_num_values = 2; break; case OP_STORE16: trace_values[0] = State.regs[OP[0]]; trace_values[1] = OP[1] * size; trace_values[2] = State.regs[30]; trace_num_values = 3; break; case OP_LOAD32: trace_values[0] = EXTEND16 (OP[2]); trace_values[1] = State.regs[OP[0]]; trace_num_values = 2; break; case OP_STORE32: trace_values[0] = State.regs[OP[1]]; trace_values[1] = EXTEND16 (OP[2]); trace_values[2] = State.regs[OP[0]]; trace_num_values = 3; break; case OP_JUMP: trace_values[0] = SEXT22 (OP[0]); trace_values[1] = State.pc; trace_num_values = 2; break; case OP_IMM_REG_REG: trace_values[0] = EXTEND16 (OP[0]) << size; trace_values[1] = State.regs[OP[1]]; trace_num_values = 2; break; case OP_IMM16_REG_REG: trace_values[0] = EXTEND16 (OP[2]) << size; trace_values[1] = State.regs[OP[1]]; trace_num_values = 2; break; case OP_UIMM_REG_REG: trace_values[0] = (OP[0] & 0xffff) << size; trace_values[1] = State.regs[OP[1]]; trace_num_values = 2; break; case OP_UIMM16_REG_REG: trace_values[0] = (OP[2]) << size; trace_values[1] = State.regs[OP[1]]; trace_num_values = 2; break; case OP_BIT: trace_num_values = 0; break; case OP_EX1: trace_values[0] = PSW; trace_num_values = 1; break; case OP_EX2: trace_num_values = 0; break; case OP_LDSR: trace_values[0] = State.regs[OP[0]]; trace_num_values = 1; break; case OP_STSR: trace_values[0] = State.sregs[OP[1]]; trace_num_values = 1; } }voidtrace_result (int has_result, unsigned32 result){ char buf[1000]; char *chp; buf[0] = '\0'; chp = buf; /* write out the values saved during the trace_input call */ { int i; for (i = 0; i < trace_num_values; i++) { sprintf (chp, "%*s0x%.8lx", SIZE_VALUES - 10, "", (long) trace_values[i]); chp = strchr (chp, '\0'); } while (i++ < 3) { sprintf (chp, "%*s", SIZE_VALUES, ""); chp = strchr (chp, '\0'); } } /* append any result to the end of the buffer */ if (has_result) sprintf (chp, " :: 0x%.8lx", (unsigned long)result); trace_generic (simulator, STATE_CPU (simulator, 0), trace_module, buf);}voidtrace_output (result) enum op_types result;{ if (!TRACE_ALU_P (STATE_CPU (simulator, 0))) return; switch (result) { default: case OP_UNKNOWN: case OP_NONE: case OP_TRAP: case OP_REG: case OP_REG_REG_CMP: case OP_IMM_REG_CMP: case OP_COND_BR: case OP_STORE16: case OP_STORE32: case OP_BIT: case OP_EX2: trace_result (0, 0); break; case OP_LOAD16: case OP_STSR: trace_result (1, State.regs[OP[0]]); break; case OP_REG_REG: case OP_REG_REG_MOVE: case OP_IMM_REG: case OP_IMM_REG_MOVE: case OP_LOAD32: case OP_EX1: trace_result (1, State.regs[OP[1]]); break; case OP_IMM_REG_REG: case OP_UIMM_REG_REG: case OP_IMM16_REG_REG: case OP_UIMM16_REG_REG: trace_result (1, State.regs[OP[1]]); break; case OP_JUMP: if (OP[1] != 0) trace_result (1, State.regs[OP[1]]); else trace_result (0, 0); break; case OP_LDSR: trace_result (1, State.sregs[OP[1]]); break; }}#endif/* Returns 1 if the specific condition is met, returns 0 otherwise. */intcondition_met (unsigned code){ unsigned int psw = PSW; switch (code & 0xf) { case 0x0: return ((psw & PSW_OV) != 0); case 0x1: return ((psw & PSW_CY) != 0); case 0x2: return ((psw & PSW_Z) != 0); case 0x3: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) != 0); case 0x4: return ((psw & PSW_S) != 0); /*case 0x5: return 1;*/ case 0x6: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) != 0); case 0x7: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) != 0); case 0x8: return ((psw & PSW_OV) == 0); case 0x9: return ((psw & PSW_CY) == 0); case 0xa: return ((psw & PSW_Z) == 0); case 0xb: return ((((psw & PSW_CY) != 0) | ((psw & PSW_Z) != 0)) == 0); case 0xc: return ((psw & PSW_S) == 0); case 0xd: return ((psw & PSW_SAT) != 0); case 0xe: return ((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) == 0); case 0xf: return (((((psw & PSW_S) != 0) ^ ((psw & PSW_OV) != 0)) || ((psw & PSW_Z) != 0)) == 0); } return 1;}static unsigned longAdd32 (unsigned long a1, unsigned long a2, int * carry){ unsigned long result = (a1 + a2); * carry = (result < a1); return result;}static voidMultiply64 (int sign, unsigned long op0){ unsigned long op1; unsigned long lo; unsigned long mid1; unsigned long mid2; unsigned long hi; unsigned long RdLo; unsigned long RdHi; int carry; op1 = State.regs[ OP[1] ]; if (sign) { /* Compute sign of result and adjust operands if necessary. */ sign = (op0 ^ op1) & 0x80000000; if (((signed long) op0) < 0) op0 = - op0; if (((signed long) op1) < 0) op1 = - op1; } /* We can split the 32x32 into four 16x16 operations. This ensures that we do not lose precision on 32bit only hosts: */ lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF)); mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF)); hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); /* We now need to add all of these results together, taking care to propogate the carries from the additions: */ RdLo = Add32 (lo, (mid1 << 16), & carry); RdHi = carry; RdLo = Add32 (RdLo, (mid2 << 16), & carry); RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); if (sign) { /* Negate result if necessary. */ RdLo = ~ RdLo; RdHi = ~ RdHi; if (RdLo == 0xFFFFFFFF) { RdLo = 0; RdHi += 1; } else RdLo += 1; } /* Don't store into register 0. */ if (OP[1]) State.regs[ OP[1] ] = RdLo; if (OP[2] >> 11) State.regs[ OP[2] >> 11 ] = RdHi; return;}/* Read a null terminated string from memory, return in a buffer */static char *fetch_str (sd, addr) SIM_DESC sd; address_word addr;{ char *buf; int nr = 0; while (sim_core_read_1 (STATE_CPU (sd, 0), PC, read_map, addr + nr) != 0) nr++; buf = NZALLOC (char, nr + 1); sim_read (simulator, addr, buf, nr); return buf;}/* Read a null terminated argument vector from memory, return in a buffer */static char **fetch_argv (sd, addr) SIM_DESC sd; address_word addr;{ int max_nr = 64; int nr = 0; char **buf = xmalloc (max_nr * sizeof (char*)); while (1) { unsigned32 a = sim_core_read_4 (STATE_CPU (sd, 0), PC, read_map, addr + nr * 4); if (a == 0) break; buf[nr] = fetch_str (sd, a); nr ++; if (nr == max_nr - 1) { max_nr += 50; buf = xrealloc (buf, max_nr * sizeof (char*)); } } buf[nr] = 0; return buf;}/* sst.b */intOP_380 (){ trace_input ("sst.b", OP_STORE16, 1); store_mem (State.regs[30] + (OP[3] & 0x7f), 1, State.regs[ OP[1] ]); trace_output (OP_STORE16); return 2;}/* sst.h */intOP_480 (){ trace_input ("sst.h", OP_STORE16, 2); store_mem (State.regs[30] + ((OP[3] & 0x7f) << 1), 2, State.regs[ OP[1] ]); trace_output (OP_STORE16); return 2;}/* sst.w */intOP_501 (){ trace_input ("sst.w", OP_STORE16, 4); store_mem (State.regs[30] + ((OP[3] & 0x7e) << 1), 4, State.regs[ OP[1] ]); trace_output (OP_STORE16); return 2;}/* ld.b */intOP_700 (){ int adr; trace_input ("ld.b", OP_LOAD32, 1); adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); State.regs[ OP[1] ] = EXTEND8 (load_mem (adr, 1)); trace_output (OP_LOAD32); return 4;}/* ld.h */intOP_720 (){ int adr; trace_input ("ld.h", OP_LOAD32, 2); adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); adr &= ~0x1; State.regs[ OP[1] ] = EXTEND16 (load_mem (adr, 2)); trace_output (OP_LOAD32); return 4;}/* ld.w */intOP_10720 (){ int adr; trace_input ("ld.w", OP_LOAD32, 4); adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1); adr &= ~0x3; State.regs[ OP[1] ] = load_mem (adr, 4); trace_output (OP_LOAD32); return 4;}/* st.b */intOP_740 (){ trace_input ("st.b", OP_STORE32, 1); store_mem (State.regs[ OP[0] ] + EXTEND16 (OP[2]), 1, State.regs[ OP[1] ]); trace_output (OP_STORE32); return 4;}/* st.h */intOP_760 (){ int adr; trace_input ("st.h", OP_STORE32, 2); adr = State.regs[ OP[0] ] + EXTEND16 (OP[2]); adr &= ~1; store_mem (adr, 2, State.regs[ OP[1] ]); trace_output (OP_STORE32); return 4;}/* st.w */intOP_10760 (){ int adr; trace_input ("st.w", OP_STORE32, 4); adr = State.regs[ OP[0] ] + EXTEND16 (OP[2] & ~1); adr &= ~3; store_mem (adr, 4, State.regs[ OP[1] ]); trace_output (OP_STORE32); return 4;}/* add reg, reg */intOP_1C0 (){ unsigned int op0, op1, result, z, s, cy, ov; trace_input ("add", OP_REG_REG, 0); /* Compute the result. */ op0 = State.regs[ OP[0] ]; op1 = State.regs[ OP[1] ]; result = op0 + op1; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); cy = (result < op0 || result < op1); ov = ((op0 & 0x80000000) == (op1 & 0x80000000) && (op0 & 0x80000000) != (result & 0x80000000)); /* Store the result and condition codes. */ State.regs[OP[1]] = result; PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_REG_REG); return 2;}/* add sign_extend(imm5), reg */intOP_240 (){ unsigned int op0, op1, result, z, s, cy, ov; int temp; trace_input ("add", OP_IMM_REG, 0); /* Compute the result. */ temp = SEXT5 (OP[0]); op0 = temp; op1 = State.regs[OP[1]]; result = op0 + op1; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); cy = (result < op0 || result < op1); ov = ((op0 & 0x80000000) == (op1 & 0x80000000) && (op0 & 0x80000000) != (result & 0x80000000)); /* Store the result and condition codes. */ State.regs[OP[1]] = result; PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_IMM_REG); return 2;}/* addi sign_extend(imm16), reg, reg */intOP_600 (){ unsigned int op0, op1, result, z, s, cy, ov; trace_input ("addi", OP_IMM16_REG_REG, 0); /* Compute the result. */ op0 = EXTEND16 (OP[2]); op1 = State.regs[ OP[0] ]; result = op0 + op1; /* Compute the condition codes. */ z = (result == 0); s = (result & 0x80000000); cy = (result < op0 || result < op1); ov = ((op0 & 0x80000000) == (op1 & 0x80000000) && (op0 & 0x80000000) != (result & 0x80000000)); /* Store the result and condition codes. */ State.regs[OP[1]] = result; PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); trace_output (OP_IMM16_REG_REG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -