📄 interp.c
字号:
break; case SYS_stat: /* added at hmsi */ /* stat system call */ { struct stat host_stat; int buf; int len = strswaplen (regs[5]); strnswap (regs[5], len); regs[0] = stat (ptr (regs[5]), &host_stat); strnswap (regs[5], len); buf = regs[6]; WWAT (buf, host_stat.st_dev); buf += 2; WWAT (buf, host_stat.st_ino); buf += 2; WLAT (buf, host_stat.st_mode); buf += 4; WWAT (buf, host_stat.st_nlink); buf += 2; WWAT (buf, host_stat.st_uid); buf += 2; WWAT (buf, host_stat.st_gid); buf += 2; WWAT (buf, host_stat.st_rdev); buf += 2; WLAT (buf, host_stat.st_size); buf += 4; WLAT (buf, host_stat.st_atime); buf += 4; WLAT (buf, 0); buf += 4; WLAT (buf, host_stat.st_mtime); buf += 4; WLAT (buf, 0); buf += 4; WLAT (buf, host_stat.st_ctime); buf += 4; WLAT (buf, 0); buf += 4; WLAT (buf, 0); buf += 4; WLAT (buf, 0); buf += 4; } break;#ifndef _WIN32 case SYS_chown: { int len = strswaplen (regs[5]); strnswap (regs[5], len); regs[0] = chown (ptr (regs[5]), regs[6], regs[7]); strnswap (regs[5], len); break; }#endif /* _WIN32 */ case SYS_chmod: { int len = strswaplen (regs[5]); strnswap (regs[5], len); regs[0] = chmod (ptr (regs[5]), regs[6]); strnswap (regs[5], len); break; } case SYS_utime: { /* Cast the second argument to void *, to avoid type mismatch if a prototype is present. */ int len = strswaplen (regs[5]); strnswap (regs[5], len); regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6])); strnswap (regs[5], len); break; } case SYS_argc: regs[0] = count_argc (prog_argv); break; case SYS_argnlen: if (regs[5] < count_argc (prog_argv)) regs[0] = strlen (prog_argv[regs[5]]); else regs[0] = -1; break; case SYS_argn: if (regs[5] < count_argc (prog_argv)) { /* Include the termination byte. */ int i = strlen (prog_argv[regs[5]]) + 1; regs[0] = sim_write (0, regs[6], prog_argv[regs[5]], i); } else regs[0] = -1; break; case SYS_time: regs[0] = get_now (); break; case SYS_ftruncate: regs[0] = callback->ftruncate (callback, regs[5], regs[6]); break; case SYS_truncate: { int len = strswaplen (regs[5]); strnswap (regs[5], len); regs[0] = callback->truncate (callback, ptr (regs[5]), regs[6]); strnswap (regs[5], len); break; } default: regs[0] = -1; break; } regs[1] = callback->get_errno (callback); errno = perrno; } break; case 13: /* Set IBNR */ IBNR = regs[0] & 0xffff; break; case 14: /* Set IBCR */ IBCR = regs[0] & 0xffff; break; case 0xc3: case 255: raise_exception (SIGTRAP); if (i == 0xc3) return -2; break; } return 0;}voidcontrol_c (sig, code, scp, addr) int sig; int code; char *scp; char *addr;{ raise_exception (SIGINT);}static intdiv1 (R, iRn2, iRn1/*, T*/) int *R; int iRn1; int iRn2; /* int T;*/{ unsigned long tmp0; unsigned char old_q, tmp1; old_q = Q; SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0)); R[iRn1] <<= 1; R[iRn1] |= (unsigned long) T; switch (old_q) { case 0: switch (M) { case 0: tmp0 = R[iRn1]; R[iRn1] -= R[iRn2]; tmp1 = (R[iRn1] > tmp0); switch (Q) { case 0: SET_SR_Q (tmp1); break; case 1: SET_SR_Q ((unsigned char) (tmp1 == 0)); break; } break; case 1: tmp0 = R[iRn1]; R[iRn1] += R[iRn2]; tmp1 = (R[iRn1] < tmp0); switch (Q) { case 0: SET_SR_Q ((unsigned char) (tmp1 == 0)); break; case 1: SET_SR_Q (tmp1); break; } break; } break; case 1: switch (M) { case 0: tmp0 = R[iRn1]; R[iRn1] += R[iRn2]; tmp1 = (R[iRn1] < tmp0); switch (Q) { case 0: SET_SR_Q (tmp1); break; case 1: SET_SR_Q ((unsigned char) (tmp1 == 0)); break; } break; case 1: tmp0 = R[iRn1]; R[iRn1] -= R[iRn2]; tmp1 = (R[iRn1] > tmp0); switch (Q) { case 0: SET_SR_Q ((unsigned char) (tmp1 == 0)); break; case 1: SET_SR_Q (tmp1); break; } break; } break; } /*T = (Q == M);*/ SET_SR_T (Q == M); /*return T;*/}static voiddmul (sign, rm, rn) int sign; unsigned int rm; unsigned int rn;{ unsigned long RnL, RnH; unsigned long RmL, RmH; unsigned long temp0, temp1, temp2, temp3; unsigned long Res2, Res1, Res0; RnL = rn & 0xffff; RnH = (rn >> 16) & 0xffff; RmL = rm & 0xffff; RmH = (rm >> 16) & 0xffff; temp0 = RmL * RnL; temp1 = RmH * RnL; temp2 = RmL * RnH; temp3 = RmH * RnH; Res2 = 0; Res1 = temp1 + temp2; if (Res1 < temp1) Res2 += 0x00010000; temp1 = (Res1 << 16) & 0xffff0000; Res0 = temp0 + temp1; if (Res0 < temp0) Res2 += 1; Res2 += ((Res1 >> 16) & 0xffff) + temp3; if (sign) { if (rn & 0x80000000) Res2 -= rm; if (rm & 0x80000000) Res2 -= rn; } MACH = Res2; MACL = Res0;}static voidmacw (regs, memory, n, m, endianw) int *regs; unsigned char *memory; int m, n; int endianw;{ long tempm, tempn; long prod, macl, sum; tempm=RSWAT (regs[m]); regs[m]+=2; tempn=RSWAT (regs[n]); regs[n]+=2; macl = MACL; prod = (long) (short) tempm * (long) (short) tempn; sum = prod + macl; if (S) { if ((~(prod ^ macl) & (sum ^ prod)) < 0) { /* MACH's lsb is a sticky overflow bit. */ MACH |= 1; /* Store the smallest negative number in MACL if prod is negative, and the largest positive number otherwise. */ sum = 0x7fffffff + (prod < 0); } } else { long mach; /* Add to MACH the sign extended product, and carry from low sum. */ mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod); /* Sign extend at 10:th bit in MACH. */ MACH = (mach & 0x1ff) | -(mach & 0x200); } MACL = sum;}static voidmacl (regs, memory, n, m) int *regs; unsigned char *memory; int m, n;{ long tempm, tempn; long prod, macl, mach, sum; long long ans,ansl,ansh,t; unsigned long long high,low,combine; union mac64 { long m[2]; /* mach and macl*/ long long m64; /* 64 bit MAC */ }mac64; tempm = RSLAT (regs[m]); regs[m] += 4; tempn = RSLAT (regs[n]); regs[n] += 4; mach = MACH; macl = MACL; mac64.m[0] = macl; mac64.m[1] = mach; ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */ mac64.m64 += ans; /* Accumulate 64bit + 64 bit */ macl = mac64.m[0]; mach = mac64.m[1]; if (S) /* Store only 48 bits of the result */ { if (mach < 0) /* Result is negative */ { mach = mach & 0x0000ffff; /* Mask higher 16 bits */ mach |= 0xffff8000; /* Sign extend higher 16 bits */ } else mach = mach & 0x00007fff; /* Postive Result */ } MACL = macl; MACH = mach;}enum { B_BCLR = 0, B_BSET = 1, B_BST = 2, B_BLD = 3, B_BAND = 4, B_BOR = 5, B_BXOR = 6, B_BLDNOT = 11, B_BANDNOT = 12, B_BORNOT = 13, MOVB_RM = 0x0000, MOVW_RM = 0x1000, MOVL_RM = 0x2000, FMOV_RM = 0x3000, MOVB_MR = 0x4000, MOVW_MR = 0x5000, MOVL_MR = 0x6000, FMOV_MR = 0x7000, MOVU_BMR = 0x8000, MOVU_WMR = 0x9000,};/* Do extended displacement move instructions. */voiddo_long_move_insn (int op, int disp12, int m, int n, int *thatlock){ int memstalls = 0; int thislock = *thatlock; int endianw = global_endianw; int *R = &(saved_state.asregs.regs[0]); unsigned char *memory = saved_state.asregs.memory; int maskb = ~((saved_state.asregs.msize - 1) & ~0); unsigned char *insn_ptr = PT2H (saved_state.asregs.pc); switch (op) { case MOVB_RM: /* signed */ WBAT (disp12 * 1 + R[n], R[m]); break; case MOVW_RM: WWAT (disp12 * 2 + R[n], R[m]); break; case MOVL_RM: WLAT (disp12 * 4 + R[n], R[m]); break; case FMOV_RM: /* floating point */ if (FPSCR_SZ) { MA (1); WDAT (R[n] + 8 * disp12, m); } else WLAT (R[n] + 4 * disp12, FI (m)); break; case MOVB_MR: R[n] = RSBAT (disp12 * 1 + R[m]); L (n); break; case MOVW_MR: R[n] = RSWAT (disp12 * 2 + R[m]); L (n); break; case MOVL_MR: R[n] = RLAT (disp12 * 4 + R[m]); L (n); break; case FMOV_MR: if (FPSCR_SZ) { MA (1); RDAT (R[m] + 8 * disp12, n); } else SET_FI (n, RLAT (R[m] + 4 * disp12)); break; case MOVU_BMR: /* unsigned */ R[n] = RBAT (disp12 * 1 + R[m]); L (n); break; case MOVU_WMR: R[n] = RWAT (disp12 * 2 + R[m]); L (n); break; default: RAISE_EXCEPTION (SIGINT); exit (1); } saved_state.asregs.memstalls += memstalls; *thatlock = thislock;}/* Do binary logical bit-manipulation insns. */voiddo_blog_insn (int imm, int addr, int binop, unsigned char *memory, int maskb){ int oldval = RBAT (addr); switch (binop) { case B_BCLR: /* bclr.b */ WBAT (addr, oldval & ~imm); break; case B_BSET: /* bset.b */ WBAT (addr, oldval | imm); break; case B_BST: /* bst.b */ if (T) WBAT (addr, oldval | imm); else WBAT (addr, oldval & ~imm); break; case B_BLD: /* bld.b */ SET_SR_T ((oldval & imm) != 0); break; case B_BAND: /* band.b */ SET_SR_T (T && ((oldval & imm) != 0)); break; case B_BOR: /* bor.b */ SET_SR_T (T || ((oldval & imm) != 0)); break; case B_BXOR: /* bxor.b */ SET_SR_T (T ^ ((oldval & imm) != 0)); break; case B_BLDNOT: /* bldnot.b */ SET_SR_T ((oldval & imm) == 0); break; case B_BANDNOT: /* bandnot.b */ SET_SR_T (T && ((oldval & imm) == 0)); break; case B_BORNOT: /* bornot.b */ SET_SR_T (T || ((oldval & imm) == 0)); break; }}floatfsca_s (int in, double (*f) (double)){ double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383; double result = (*f) (rad); double error, upper, lower, frac; int exp; /* Search the value with the maximum error that is still within the architectural spec. */ error = ldexp (1., -21); /* compensate for calculation inaccuracy by reducing error. */ error = error - ldexp (1., -50); upper = result + error; frac = frexp (upper, &exp); upper = ldexp (floor (ldexp (frac, 24)), exp - 24); lower = result - error; frac = frexp (lower, &exp); lower = ldexp (ceil (ldexp (frac, 24)), exp - 24); return abs (upper - result) >= abs (lower - result) ? upper : lower;}floatfsrra_s (float in){ double result = 1. / sqrt (in); int exp; double frac, upper, lower, error, eps; /* refine result */ result = result - (result * result * in - 1) * 0.5 * result; /* Search the value with the maximum error that is still within the architectural spec. */ frac = frexp (result, &exp); frac = ldexp (frac, 24); error = 4.0; /* 1 << 24-1-21 */ /* use eps to compensate for possible 1 ulp error in our 'exact' result. */ eps = ldexp (1., -29); upper = floor (frac + error - eps); if (upper > 16777216.) upper = floor ((frac + error - eps) * 0.5) * 2.; lower = ceil ((frac - error + eps) * 2) * .5; if (lower > 8388608.) lower = ceil (frac - error + eps); upper = ldexp (upper, exp - 24); lower = ldexp (lower, exp - 24);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -