📄 ms_inst.m4
字号:
}void opCNGTS (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Freg(ip->r2) <= Freg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFADDD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() Dreg(ip->r1) = Dreg(ip->r2) + Dreg(ip->r3);#if FPADD_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPADD; Add_to_worklist (st, FPADD_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFSUBD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() Dreg(ip->r1) = Dreg(ip->r2) - Dreg(ip->r3);#if FPADD_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPADD; Add_to_worklist (st, FPADD_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFMULD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() Dreg(ip->r1) = Dreg(ip->r2) * Dreg(ip->r3);#if FPMULD_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPMUL; Add_to_worklist (st, FPMULD_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFDIVD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r3) == 0.0) { int inum = ip - st->iwin;#ifdef MIPSY_MXS CPUState *P = (CPUState *)st->mipsyPtr; CPUWarning("MXS:ms_inst:: EXC_FPE (division by zero) at PC=0x%x\n", P->PC); RECORD_EXCEPTION (P, EXC_FPE, E_VEC, 0, P->CP0[C0_TLBHI],P->CP0[C0_CTXT],P->CP0[C0_XCTXT]); st->iwin_except [inum] = GetLastException(st);#else st->reg_rstat[ip->r1 >> 1].reg_status |= REG_ERROR;#endif st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st, ip); th->stall_except = 1; UpdateStallFetch (th); return; } Dreg(ip->r1) = Dreg(ip->r2) / Dreg(ip->r3);#if FPDIVD_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPDIV; Add_to_worklist (st, FPDIVD_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFSQRTD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP()#ifdef MIPSY_MXS fprintf(stderr, "Hit a FSQRTS inst\n");#else Dreg(ip->r1) = sqrt (Dreg(ip->r2));#endif#if FPSQRTD_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPSQRT; Add_to_worklist (st, FPSQRTD_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFABSD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() Dreg(ip->r1) = (Dreg(ip->r2) >= 0 ? Dreg(ip->r2) : -Dreg(ip->r2) );#if FPABS_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPABS; Add_to_worklist (st, FPABS_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFMOVD (struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP() Dreg(ip->r1) = Dreg(ip->r2); }void opFNEGD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() Dreg(ip->r1) = -Dreg(ip->r2);#if FPNEG_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPNEG; Add_to_worklist (st, FPNEG_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opFROUNDD (struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP() Ireg(ip->r1) = (Dreg(ip->r2) > 0.0 ? Dreg(ip->r2) + 0.5 : Dreg(ip->r2) - 0.5 ); }void opFTRUNCD (struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP() Ireg(ip->r1) = Dreg(ip->r2); }void opFCEILD (struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP() Ireg(ip->r1) = (Dreg(ip->r2) >= 0.0 ? Dreg(ip->r2) + DP_NEAR_ONE : Dreg(ip->r2) ); }void opFFLOORD (struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP(); Ireg(ip->r1) = (Dreg(ip->r2) >= 0.0 ? Dreg(ip->r2) : Dreg(ip->r2) - DP_NEAR_ONE ); }void opCVTSD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if ((ip->r1 & (~0x01)) != ip->r3) Dreg(ip->r1) = Dreg(ip->r3); Freg(ip->r1) = Dreg(ip->r2);#if FPCVT_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCVT; Add_to_worklist (st, FPCVT_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCVTWD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if ((ip->r1 & (~0x01)) != ip->r3) Dreg(ip->r1) = Dreg(ip->r3); switch (st->round_mode) { case 0: /* RN: Round to nearest */ Ireg(ip->r1) = (Dreg(ip->r2) > 0.0 ? Dreg(ip->r2) + 0.5 : Dreg(ip->r2) - 0.5 ); break; case 1: /* RZ: Round toward 0 */ Ireg(ip->r1) = Dreg(ip->r2); break; case 2: /* RP: Round to +infinity */ Ireg(ip->r1) = (Dreg(ip->r2) >= 0.0 ? Dreg(ip->r2) + DP_NEAR_ONE : Dreg(ip->r2) ); break; case 3: /* RM: Round to -infinity */ Ireg(ip->r1) = (Dreg(ip->r2) >= 0.0 ? Dreg(ip->r2) : Dreg(ip->r2) - DP_NEAR_ONE ); break; }#if FPCVT_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCVT; Add_to_worklist (st, FPCVT_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCUEQD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) == Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCULTD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) < Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCULED (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) <= Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }/* Trap if unordered, but otherwise the same as above */void opCNGLD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) == Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCNGED (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) < Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif }void opCNGTD (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; CHECKFP() if (Dreg(ip->r2) <= Dreg(ip->r3)) Ireg(ip->r1) |= CONDBIT; else Ireg(ip->r1) &= ~CONDBIT;#if FPCMP_LATENCY > 1 st->reg_excuse[ip->r1>>1] = ST_FPCMP; Add_to_worklist (st, FPCMP_LATENCY, reg_writeback, (void *)(ip->r1));#endif } /* Set floating point unit control word */void opCTL_FPC (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; CHECKFP() if (!alls_quiet (st, ip, ST_FPC)) return; inum = ip - st->iwin; Ireg(ip->r1) = Ireg(ip->r2); st->regs[th->regnames[CNDREG]] = CONDBIT & Ireg(ip->r2); st->round_mode = Ireg(ip->r2) & 0x03; set_rm (st->round_mode); clear_fpc_stall(st,th,inum); }static void clear_fpc_stall(struct s_cpu_state *st,THREAD *th, int inum) { BrTREE *br; /* Now can start fetching new instructions */ th->stall_fpc = 0; UpdateStallFetch (th); /* Unstall children, too */ br = &st->branch_tree [st->iwin_br_node[inum]]; if (br->rchild >= 0) { br = &st->branch_tree [br->rchild]; th = &st->threads [br->thread]; th->stall_fpc = 0; UpdateStallFetch (th); } } /* Read floating point unit control word */void opCTL_CFC(struct s_cpu_state *st, INST *ip, THREAD *th) { CHECKFP() Ireg(ip->r1) = Ireg(ip->r2) | (CONDBIT & Ireg(ip->r3)); } /* Control instruction: branch delay cycle */void opCTL_DLY (struct s_cpu_state *st, INST *ip, THREAD *th) { IncStat(ST_BR_NOP); }void opCP0 (struct s_cpu_state *st, INST *ip, THREAD *th) { uint srcreg, dstreg; bool hack, err; int inum = ip - st->iwin; if (ip->op == OPCP0) { if (!alls_quiet (st, ip, ST_SYSCALL)) return;#ifdef PRECISE if (st->iwin_headgrad != (ip - st->iwin)) { st->stall_type = ST_SYSCALL; st->stall_issue = 1; return; }#endif } srcreg = (ip->r2 > 0) ? Ureg(ip->r2) : 0; err = DoPrivInst(st, ip->imm, srcreg, &dstreg, &hack); if (err) { st->iwin_except [inum] = GetLastException(st); st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st, ip); th->stall_except = 1; UpdateStallFetch (th); return; }#ifndef R3K if (hack) { CPUState *P = (CPUState *)st->mipsyPtr; st->iwin_branch_pc[inum] = P->PC; th->pc = P->PC; } #endif if (ip->r1 > 0) { Ureg(ip->r1) = dstreg; } if (ip->op == OPCP0) { th->stall_cp0 = 0; clear_fpc_stall(st,th, inum); }}void opBDOOR (struct s_cpu_state *st, INST *ip, THREAD *th) { if (!alls_quiet (st, ip, ST_SYSCALL)) return;#ifdef MIPSY_MXS { /* Assume this is a call. Execute it on the real CPU. This */ /* assumes that all backdoor calls take less than 4 */ /* arguments. The prom stuff is a way for the simulated cpu to */ /* actually run the code in simbootprom.c */ CPUState *P = (CPUState *)st->mipsyPtr; int64 bdoorRetval; PA pAddr; Result ret; ret = TranslateVirtualNoSideeffect(P, (VA) th->pc-4, &pAddr); ASSERT(ret==SUCCESS);/* BASEM watch this! */ bdoorRetval = ((int64 (*)(int,int,int,int))(pAddr)) (st->regs[th->regnames[4]], st->regs[th->regnames[5]], st->regs[th->regnames[6]], st->regs[th->regnames[7]]); st->regs[th->regnames[2]] = bdoorRetval >> 32; st->regs[th->regnames[3]] = bdoorRetval & 0xffffffff; th->pc = st->regs[th->regnames[31]]; }#endif th->stall_sys = 0; clear_fpc_stall(st,th, ip - st->iwin); }void opLL (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if ((st->iwin_addr[inum] & 0x3) || (st->iwin_flags[inum] & IWIN_UNCACHED)) { LS_EXC(EXC_RADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_INTEGER_LL, inum); LoadStats() }void opSC (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if ((st->iwin_addr[inum] & 0x3) || (st->iwin_flags[inum] & IWIN_UNCACHED)) { LS_EXC(EXC_WADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; th->stall_fpc = 0; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r3, ip->r1, ST_INTEGER_SC, inum); LoadStats() }/* * Hacked LD and SD instruction execution. */void opLDHACK (struct s_cpu_state *st, INST *ip, THREAD *th) { uint tlbFlavor; uint vAddr, pAddr = 0; int inst, rt, rt2, rs, imm, ret; CPUState *P = (CPUState *)st->mipsyPtr; uint64 val; int err; void *bdoor = 0; /* * Need to single thread the processor for these hacked * isntructions. */ if (!alls_quiet (st, ip, ST_SYSCALL)) return; inst = ip->imm; tlbFlavor = TLB_READING; rs = th->regnames[(inst>>21)&0x1f]; rt = th->regnames[(inst>>16)&0x1f]; rt2 = th->regnames[((inst>>16)&0x1f)+1]; imm = ((inst&0x8000)?(inst&0x0000ffff)-0x10000:(inst&0x0000ffff)); vAddr = Ireg(rs) + imm; ret = TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor, &bdoor); if (ret != SUCCESS) {#ifdef HWBCOPY if (tlbFlavor & TLB_MSG_SPACE) err = SUCCESS; else {#else {#endif ms_break (st, &st->iwin[st->iwin_curi], "LDHACK"); err = FAILURE; } } else { /* 64bit load into registers rt and rt+1 */ err = DoUncachedRead(st, vAddr, pAddr, 8, &val); if (err == 0) { Ureg(rt) = val>>32; Ureg(rt2) = (uint)val; } } if (err == 0) { /* Worked - clear stall and continue */ th->stall_sys = 0; clear_fpc_stall(st,th, ip - st->iwin); } else { /* Retry instruction until the memory system can take it. */ st->stall_type = ST_SYSCALL; st->stall_issue = 1; return; } }void opSDHACK (struct s_cpu_state *st, INST *ip, THREAD *th) { uint tlbFlavor; uint vAddr, pAddr = 0; int inst, rt, rt2, rs, imm, ret; CPUState *P = (CPUState *)st->mipsyPtr; uint64 val; int err; void *bdoor = 0; /* * Need to single thread the processor for these hacked * isntructions. */ if (!alls_quiet (st, ip, ST_SYSCALL)) return; inst = ip->imm; tlbFlavor = TLB_WRITING; rs = th->regnames[(inst>>21)&0x1f]; rt = th->regnames[(inst>>16)&0x1f]; rt2 = th->regnames[((inst>>16)&0x1f)+1]; imm = ((inst&0x8000)?(inst&0x0000ffff)-0x10000:(inst&0x0000ffff)); vAddr = Ireg(rs) + imm; ret = TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor, &bdoor); if (ret != SUCCESS) {#ifdef HWBCOPY if (tlbFlavor & TLB_MSG_SPACE) err = SUCCESS; else {#else {#endif ms_break (st, &st->iwin[st->iwin_curi], "SDHACK"); err = FAILURE; } } else { /* 64bit store from registers rt and rt+1 */ val = Ureg(rt); val <<= 32; val |= Ureg(rt2); err = DoUncachedWrite(st,vAddr, pAddr, 8, tlbFlavor & TLB_ACCELERATED, &val); } if (err == 0) { /* Worked - clear stall and continue */ th->stall_sys = 0; clear_fpc_stall(st,th, ip - st->iwin); } else { /* Retry instruction until the memory system can take it. */ st->stall_type = ST_SYSCALL; st->stall_issue = 1; return; } } /* * alls_quiet - A utility routine for instructions that * need to wait until all outstanding * instructions are completed. * * Returns TRUE if everything is quiet, * otherwise returns FALSE. */static int alls_quiet(struct s_cpu_state *st, INST *ip, int excuse) { int i; /* Force in order issue around this instruction */ /* by stalling until all work has been done */ /* and all registers have been written. */ if (st->work_head) goto return_false; if ((st->ldst_head) || (st->ldst_nextReserved)) goto return_false;#ifndef MIPSY_MXS if (ms_bus_busy ()) goto return_false;#endif for (i=0; i<MAX_PREG/2; i++) { if (st->reg_rstat[i].reg_status & REG_IN_WIN) { if ((ip->r1 < 0) || (i != (ip->r1>>1))) goto return_false; } } return (1);return_false: st->stall_type = excuse; st->stall_issue = 1; return (0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -