📄 exec.c
字号:
} if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } mexc = memory_read(asi, address, &data, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } else { sregs->fsr = (sregs->fsr & 0x7FF000) | (data & ~0x7FF000); set_fsr(sregs->fsr); } break; case STFSR: if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; break; } if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } if (ebase.simtime < sregs->ftime) { sregs->fhold += (sregs->ftime - ebase.simtime); } mexc = memory_write(asi, address, &sregs->fsr, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } break; case STA: if (!chk_asi(sregs, &asi, op3)) break; case ST: if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } mexc = memory_write(asi, address, rdd, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } break; case STBA: if (!chk_asi(sregs, &asi, op3)) break; case STB: mexc = memory_write(asi, address, rdd, 0, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } break; case STDA: if (!chk_asi(sregs, &asi, op3)) break; case STD: if (address & 0x7) { sregs->trap = TRAP_UNALI; break; } if (rd & 1) { rd &= 0x1e; if (rd > 7) rdd = &(sregs->r[(cwp + rd) & 0x7f]); else rdd = &(sregs->g[rd]); } mexc = memory_write(asi, address, rdd, 3, &ws); sregs->hold += ws; sregs->icnt = T_STD;#ifdef STAT sregs->nstore++; /* Double store counts twice */#endif if (mexc) { sregs->trap = TRAP_DEXC; break; } break; case STDFQ: if ((sregs->psr & 0x1f) > 7) { sregs->trap = TRAP_UNIMP; break; } if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; break; } if (address & 0x7) { sregs->trap = TRAP_UNALI; break; } if (!(sregs->fsr & FSR_QNE)) { sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR; break; } rdd = &(sregs->fpq[0]); mexc = memory_write(asi, address, rdd, 3, &ws); sregs->hold += ws; sregs->icnt = T_STD;#ifdef STAT sregs->nstore++; /* Double store counts twice */#endif if (mexc) { sregs->trap = TRAP_DEXC; break; } else { sregs->fsr &= ~FSR_QNE; sregs->fpstate = FP_EXE_MODE; } break; case STHA: if (!chk_asi(sregs, &asi, op3)) break; case STH: if (address & 0x1) { sregs->trap = TRAP_UNALI; break; } mexc = memory_write(asi, address, rdd, 1, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } break; case STF: if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; break; } if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } if (ebase.simtime < sregs->ftime) { if (sregs->frd == rd) sregs->fhold += (sregs->ftime - ebase.simtime); } mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; } break; case STDF: if (!((sregs->psr & PSR_EF) && FP_PRES)) { sregs->trap = TRAP_FPDIS; break; } if (address & 0x7) { sregs->trap = TRAP_UNALI; break; } rd &= 0x1E; if (ebase.simtime < sregs->ftime) { if ((sregs->frd == rd) || (sregs->frd + 1 == rd)) sregs->fhold += (sregs->ftime - ebase.simtime); } mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws); sregs->hold += ws; sregs->icnt = T_STD;#ifdef STAT sregs->nstore++; /* Double store counts twice */#endif if (mexc) { sregs->trap = TRAP_DEXC; } break; case SWAPA: if (!chk_asi(sregs, &asi, op3)) break; case SWAP: if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } mexc = memory_read(asi, address, &data, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; break; } mexc = memory_write(asi, address, rdd, 2, &ws); sregs->hold += ws; sregs->icnt = T_LDST; if (mexc) { sregs->trap = TRAP_DEXC; break; } else *rdd = data;#ifdef STAT sregs->nload++;#endif break; default: sregs->trap = TRAP_UNIMP; break; }#ifdef LOAD_DEL if (!(op3 & 4)) { sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt; sregs->ildreg = rd; if ((op3 | 0x10) == 0x13) sregs->ildreg |= 1; /* Double load, odd register loaded * last */ }#endif break; default: sregs->trap = TRAP_UNIMP; break; } sregs->g[0] = 0; if (!sregs->trap) { sregs->pc = pc; sregs->npc = npc; } return (0);}#define T_FABSs 2#define T_FADDs 4#define T_FADDd 4#define T_FCMPs 4#define T_FCMPd 4#define T_FDIVs 20#define T_FDIVd 35#define T_FMOVs 2#define T_FMULs 5#define T_FMULd 9#define T_FNEGs 2#define T_FSQRTs 37#define T_FSQRTd 65#define T_FSUBs 4#define T_FSUBd 4#define T_FdTOi 7#define T_FdTOs 3#define T_FiTOs 6#define T_FiTOd 6#define T_FsTOi 6#define T_FsTOd 2#define FABSs 0x09#define FADDs 0x41#define FADDd 0x42#define FCMPs 0x51#define FCMPd 0x52#define FCMPEs 0x55#define FCMPEd 0x56#define FDIVs 0x4D#define FDIVd 0x4E#define FMOVs 0x01#define FMULs 0x49#define FMULd 0x4A#define FNEGs 0x05#define FSQRTs 0x29#define FSQRTd 0x2A#define FSUBs 0x45#define FSUBd 0x46#define FdTOi 0xD2#define FdTOs 0xC6#define FiTOs 0xC4#define FiTOd 0xC8#define FsTOi 0xD1#define FsTOd 0xC9static intfpexec(op3, rd, rs1, rs2, sregs) uint32 op3, rd, rs1, rs2; struct pstate *sregs;{ uint32 opf, tem, accex; int32 fcc; uint32 ldadj; if (sregs->fpstate == FP_EXC_MODE) { sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR; sregs->fpstate = FP_EXC_PE; return (0); } if (sregs->fpstate == FP_EXC_PE) { sregs->fpstate = FP_EXC_MODE; return (TRAP_FPEXC); } opf = (sregs->inst >> 5) & 0x1ff; /* * Check if we already have an FPop in the pipe. If so, halt until it is * finished by incrementing fhold with the remaining execution time */ if (ebase.simtime < sregs->ftime) { sregs->fhold = (sregs->ftime - ebase.simtime); } else { sregs->fhold = 0; /* Check load dependencies. */ if (ebase.simtime < sregs->ltime) { /* Don't check rs1 if single operand instructions */ if (((opf >> 6) == 0) || ((opf >> 6) == 3)) rs1 = 32; /* Adjust for double floats */ ldadj = opf & 1; if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj))) sregs->fhold++; } } sregs->finst++; sregs->frs1 = rs1; /* Store src and dst for dependecy check */ sregs->frs2 = rs2; sregs->frd = rd; sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold; /* SPARC is big-endian - swap double floats if host is little-endian */ /* This is ugly - I know ... */ /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER) but what about machines where float values are different endianness from integer values? */#ifdef HOST_LITTLE_ENDIAN_FLOAT rs1 &= 0x1f; switch (opf) { case FADDd: case FDIVd: case FMULd: case FSQRTd: case FSUBd: case FCMPd: case FCMPEd: case FdTOi: case FdTOs: sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1]; sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1]; sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1]; sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1]; default: ; }#endif clear_accex(); switch (opf) { case FABSs: sregs->fs[rd] = fabs(sregs->fs[rs2]); sregs->ftime += T_FABSs; sregs->frs1 = 32; /* rs1 ignored */ break; case FADDs: sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2]; sregs->ftime += T_FADDs; break; case FADDd: sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1]; sregs->ftime += T_FADDd; break; case FCMPs: case FCMPEs: if (sregs->fs[rs1] == sregs->fs[rs2]) fcc = 3; else if (sregs->fs[rs1] < sregs->fs[rs2]) fcc = 2; else if (sregs->fs[rs1] > sregs->fs[rs2]) fcc = 1; else fcc = 0; sregs->fsr |= 0x0C00; sregs->fsr &= ~(fcc << 10); sregs->ftime += T_FCMPs; sregs->frd = 32; /* rd ignored */ if ((fcc == 0) && (opf == FCMPEs)) { sregs->fpstate = FP_EXC_PE; sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14); } break; case FCMPd: case FCMPEd: if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1]) fcc = 3; else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1]) fcc = 2; else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1]) fcc = 1; else fcc = 0; sregs->fsr |= 0x0C00; sregs->fsr &= ~(fcc << 10); sregs->ftime += T_FCMPd; sregs->frd = 32; /* rd ignored */ if ((fcc == 0) && (opf == FCMPEd)) { sregs->fpstate = FP_EXC_PE; sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE; } break; case FDIVs: sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2]; sregs->ftime += T_FDIVs; break; case FDIVd: sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1]; sregs->ftime += T_FDIVd; break; case FMOVs: sregs->fs[rd] = sregs->fs[rs2]; sregs->ftime += T_FMOVs; sregs->frs1 = 32; /* rs1 ignored */ break; case FMULs: sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2]; sregs->ftime += T_FMULs; break; case FMULd: sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1]; sregs->ftime += T_FMULd; break; case FNEGs: sregs->fs[rd] = -sregs->fs[rs2]; sregs->ftime += T_FNEGs; sregs->frs1 = 32; /* rs1 ignored */ break; case FSQRTs: if (sregs->fs[rs2] < 0.0) { sregs->fpstate = FP_EXC_PE; sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE; sregs->fsr = (sregs->fsr & 0x1f) | 0x10; break; } sregs->fs[rd] = sqrt(sregs->fs[rs2]); sregs->ftime += T_FSQRTs; sregs->frs1 = 32; /* rs1 ignored */ break; case FSQRTd: if (sregs->fd[rs2 >> 1] < 0.0) { sregs->fpstate = FP_EXC_PE; sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE; sregs->fsr = (sregs->fsr & 0x1f) | 0x10; break; } sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]); sregs->ftime += T_FSQRTd; sregs->frs1 = 32; /* rs1 ignored */ break; case FSUBs: sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2]; sregs->ftime += T_FSUBs; break; case FSUBd: sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1]; sregs->ftime += T_FSUBd; break; case FdTOi: sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1]; sregs->ftime += T_FdTOi; sregs->frs1 = 32; /* rs1 ignored */ break; case FdTOs: sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1]; sregs->ftime += T_FdTOs; sregs->frs1 = 32; /* rs1 ignored */ break; case FiTOs: sregs->fs[rd] = (float32) sregs->fsi[rs2]; sregs->ftime += T_FiTOs; sregs->frs1 = 32; /* rs1 ignored */ break; case FiTOd: sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2]; sregs->ftime += T_FiTOd; sregs->frs1 = 32; /* rs1 ignored */ break; case FsTOi: sregs->fsi[rd] = (int) sregs->fs[rs2]; sregs->ftime += T_FsTOi; sregs->frs1 = 32; /* rs1 ignored */ break; case FsTOd: sregs->fd[rd >> 1] = sregs->fs[rs2]; sregs->ftime += T_FsTOd; sregs->frs1 = 32; /* rs1 ignored */ break; default: sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP; sregs->fpstate = FP_EXC_PE; }#ifdef ERRINJ if (errftt) { sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14); sregs->fpstate = FP_EXC_PE; if (sis_verbose) printf("Inserted fpu error %X\n",errftt); errftt = 0; }#endif accex = get_accex();#ifdef HOST_LITTLE_ENDIAN_FLOAT switch (opf) { case FADDd: case FDIVd: case FMULd: case FSQRTd: case FSUBd: case FiTOd: case FsTOd: sregs->fs[rd & ~1] = sregs->fdp[rd | 1]; sregs->fs[rd | 1] = sregs->fdp[rd & ~1]; default: ; }#endif if (sregs->fpstate == FP_EXC_PE) { sregs->fpq[0] = sregs->pc; sregs->fpq[1] = sregs->inst; sregs->fsr |= FSR_QNE; } else { tem = (sregs->fsr >> 23) & 0x1f; if (tem & accex) { sregs->fpstate = FP_EXC_PE; sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE; sregs->fsr = ((sregs->fsr & ~0x1f) | accex); } else { sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex); } if (sregs->fpstate == FP_EXC_PE) { sregs->fpq[0] = sregs->pc; sregs->fpq[1] = sregs->inst; sregs->fsr |= FSR_QNE; } } clear_accex(); return (0);}static intchk_asi(sregs, asi, op3) struct pstate *sregs; uint32 *asi, op3;{ if (!(sregs->psr & PSR_S)) { sregs->trap = TRAP_PRIVI; return (0); } else if (sregs->inst & INST_I) { sregs->trap = TRAP_UNIMP; return (0); } else *asi = (sregs->inst >> 5) & 0x0ff; return(1);}intexecute_trap(sregs) struct pstate *sregs;{ int32 cwp; if (sregs->trap == 256) { sregs->pc = 0; sregs->npc = 4; sregs->trap = 0; } else if (sregs->trap == 257) { return (ERROR); } else { if ((sregs->psr & PSR_ET) == 0) return (ERROR); sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4); sregs->trap = 0; sregs->psr &= ~PSR_ET; sregs->psr |= ((sregs->psr & PSR_S) >> 1); sregs->annul = 0; sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP); cwp = ((sregs->psr & PSR_CWP) << 4); sregs->r[(cwp + 17) & 0x7f] = sregs->pc; sregs->r[(cwp + 18) & 0x7f] = sregs->npc; sregs->psr |= PSR_S; sregs->pc = sregs->tbr; sregs->npc = sregs->tbr + 4; if ( 0 != (1 & sregs->asr17) ) { /* single vector trapping! */ sregs->pc = sregs->tbr & 0xfffff000; sregs->npc = sregs->pc + 4; } /* Increase simulator time */ sregs->icnt = TRAP_C; } return (0);}extern struct irqcell irqarr[16];intcheck_interrupts(sregs) struct pstate *sregs;{#ifdef ERRINJ if (errtt) { sregs->trap = errtt; if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt); errtt = 0; }#endif if ((ext_irl) && (sregs->psr & PSR_ET) && ((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) { if (sregs->trap == 0) { sregs->trap = 16 + ext_irl; irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg); return(1); } } return(0);}voidinit_regs(sregs) struct pstate *sregs;{ sregs->pc = 0; sregs->npc = 4; sregs->trap = 0; sregs->psr &= 0x00f03fdf; sregs->psr |= 0x080; /* Set supervisor bit */ sregs->breakpoint = 0; sregs->annul = 0; sregs->fpstate = FP_EXE_MODE; sregs->fpqn = 0; sregs->ftime = 0; sregs->ltime = 0; sregs->err_mode = 0; ext_irl = 0; sregs->g[0] = 0;#ifdef HOST_LITTLE_ENDIAN_FLOAT sregs->fdp = (float32 *) sregs->fd; sregs->fsi = (int32 *) sregs->fs;#else sregs->fs = (float32 *) sregs->fd; sregs->fsi = (int32 *) sregs->fd;#endif sregs->fsr = 0; sregs->fpu_pres = !nfp; set_fsr(sregs->fsr); sregs->bphit = 0; sregs->ildreg = 0; sregs->ildtime = 0; sregs->y = 0; sregs->asr17 = 0; sregs->rett_err = 0; sregs->jmpltime = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -