⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpu.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
         EXCEPTION(P, EXC_II);          return C1_CONTINUE;      }      if (DoubleReg(fs) == 0.0) {         CPUWarning("MIPSY: FDIV divide by zero\n");      }       DoubleReg(fd) = 1.0 / DoubleReg(fs);      SIM_DEBUG(('f', "C1:FRECIP.D f%d %Le / f%d %Le = f%d %Le\n", fs, DoubleReg(fs), ft,                  DoubleReg(ft), fd, DoubleReg(fd)));      break;   }   case frsqrt_op+F_SSINGLE:      statusReg.ts_data = P->CP0[C0_SR];      /* Make sure we can execute mips4 instructions */      if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) {         EXCEPTION(P, EXC_II);          return C1_CONTINUE;      }      if (FloatReg(fs) == 0.0) {         CPUWarning("MIPSY: FRSQRT divide by zero\n");      }       FloatReg(fd) = 1.0 / (float)sqrt((double)FloatReg(fs));      break;         case frsqrt_op+F_SDOUBLE:      statusReg.ts_data = P->CP0[C0_SR];      /* Make sure we can execute mips4 instructions */      if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) {         EXCEPTION(P, EXC_II);          return C1_CONTINUE;      }      if (DoubleReg(fs) == 0.0) {         CPUWarning("MIPSY: FDIV divide by zero\n");      }       DoubleReg(fd) = 1.0 / sqrt(DoubleReg(fs));      break;   case fround_op+F_SSINGLE:      IntReg(fd) = (FloatReg(fs) > 0.0 ? FloatReg(fs) + 0.5 : FloatReg(fs) - 0.5 );      break;   case fround_op+F_SDOUBLE:      IntReg(fd) = (DoubleReg(fs) > 0.0 ? DoubleReg(fs) + 0.5 : DoubleReg(fs) - 0.5 );      break;   case froundl_op+F_SSINGLE:      CHECK_64BIT_ALLOWED(P);      LongLongReg(fd) = (FloatReg(fs) > 0.0 ? FloatReg(fs) + 0.5 : FloatReg(fs) - 0.5 );      break;   case froundl_op+F_SDOUBLE:      CHECK_64BIT_ALLOWED(P);      LongLongReg(fd) = (DoubleReg(fs) > 0.0 ? DoubleReg(fs) + 0.5 : DoubleReg(fs) - 0.5 );      break;   case fceil_op+F_SSINGLE:      IntReg(fd) = (FloatReg(fs) >= 0.0 ? FloatReg(fs) + SP_NEAR_ONE : FloatReg(fs) );      break;   case fceil_op+F_SDOUBLE:      IntReg(fd) = (DoubleReg(fs) >= 0.0 ? DoubleReg(fs) + DP_NEAR_ONE : DoubleReg(fs) );      break;   case fceill_op+F_SSINGLE:      CHECK_64BIT_ALLOWED(P);      LongLongReg(fd) = (FloatReg(fs) >= 0.0 ? FloatReg(fs) + SP_NEAR_ONE : FloatReg(fs) );      break;   case fceill_op+F_SDOUBLE:      CHECK_64BIT_ALLOWED(P);      LongLongReg(fd) = (DoubleReg(fs) >= 0.0 ? DoubleReg(fs) + DP_NEAR_ONE : DoubleReg(fs) );      break;      /* floating point comparison operations */   case F_C_EQ+F_SSINGLE:      if (FloatReg(fs) == FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_EQ+F_SDOUBLE:      if (DoubleReg(fs) == DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGL+F_SSINGLE:      if (FloatReg(fs) == FloatReg(ft))         IntReg(fd) |= CONDBIT;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGL+F_SDOUBLE:      if (DoubleReg(fs) == DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;         case F_C_LE+F_SSINGLE:      if (FloatReg(fs) <= FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_LE+F_SDOUBLE:      if (DoubleReg(fs) <= DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_LT+F_SSINGLE:      if (FloatReg(fs) < FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_LT+F_SDOUBLE:      if (DoubleReg(fs) < DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGE+F_SSINGLE:      if (FloatReg(fs) < FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGE+F_SDOUBLE:      if (DoubleReg(fs) < DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGLE+F_SSINGLE:      P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGLE+F_SDOUBLE:      P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGT+F_SSINGLE:      if (FloatReg(fs) <= FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_NGT+F_SDOUBLE:      if (DoubleReg(fs) <= DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_OLE+F_SSINGLE:      if (FloatReg(fs) < FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_OLE+F_SDOUBLE:      if (DoubleReg(fs) < DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_OLT+F_SSINGLE:      if (FloatReg(fs) < FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_OLT+F_SDOUBLE:     if (DoubleReg(fs) < DoubleReg(ft)) {       P->FCR[31] |= M_csr_c;     } else {       P->FCR[31] &= ~M_csr_c;     }     break;   case F_C_SEQ+F_SSINGLE:      if (FloatReg(fs) == FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_SEQ+F_SDOUBLE:      if (DoubleReg(fs) == DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_SF+F_SSINGLE:      P->FCR[31] &= ~M_csr_c;      break;   case F_C_SF+F_SDOUBLE:      P->FCR[31] &= ~M_csr_c;      break;   case F_C_UEQ+F_SSINGLE:      if (FloatReg(fs) == FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_UEQ+F_SDOUBLE:      if (DoubleReg(fs) == DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_ULE+F_SSINGLE:      if (FloatReg(fs) <= FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_ULE+F_SDOUBLE:      if (DoubleReg(fs) <= DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_ULT+F_SSINGLE:      if (FloatReg(fs) < FloatReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_ULT+F_SDOUBLE:      if (DoubleReg(fs) < DoubleReg(ft))         P->FCR[31] |= M_csr_c;      else         P->FCR[31] &= ~M_csr_c;      break;   case F_C_UN+F_SSINGLE:      P->FCR[31] &= ~M_csr_c;      break;   case F_C_UN+F_SDOUBLE:      P->FCR[31] &= ~M_csr_c;      break;   default:      CPUWarning("ERROR!!! FPU instruction 0x%x unimplemented at PC 0x%llx\n",		 instr, (Reg64)P->PC);      ASSERT(0);   } /* cp1_function */   return C1_SUCCESS;}/***************************************************************** * MipsyFPU *****************************************************************/static Result MipsyFPUx(CPUState *P, Inst instr) {   uint ft  = FT(instr); /* 2nd source register */   uint fs  = FS(instr); /* 1st source reg */   uint fr  = FORMAT(instr); /* 3rd source reg. */   uint fd  = FD(instr); /* destionation */   uint func = FUNC(instr);   switch(func) {   case madd_s_op:      FloatReg(fd) = (FloatReg(fs) * FloatReg(ft)) + FloatReg(fr);      break;   case madd_d_op:      DoubleReg(fd) = (DoubleReg(fs) * DoubleReg(ft)) + DoubleReg(fr);      break;   case msub_s_op:      FloatReg(fd) = (FloatReg(fs) * FloatReg(ft)) - FloatReg(fr);      break;   case msub_d_op:      DoubleReg(fd) = (DoubleReg(fs) * DoubleReg(ft)) - DoubleReg(fr);      break;   case nmadd_s_op:      FloatReg(fd) = -((FloatReg(fs) * FloatReg(ft)) + FloatReg(fr));      break;   case nmadd_d_op:      DoubleReg(fd) = -((DoubleReg(fs) * DoubleReg(ft)) + DoubleReg(fr));      break;   case nmsub_s_op:      FloatReg(fd) = -((FloatReg(fs) * FloatReg(ft)) - FloatReg(fr));      break;   case nmsub_d_op:      DoubleReg(fd) = -((DoubleReg(fs) * DoubleReg(ft)) - DoubleReg(fr));      break;   default:      EXCEPTION(P, EXC_II);      return C1_CONTINUE;   }   return C1_SUCCESS;}/***************************************************************** * Set the rounding mode of the host processor to match that of the * simulated machine. This is needed since we're actually executing the * instructions on the host platform.  *****************************************************************/static void SetRoundingMode(int modeNum){#if defined(sgi) || defined(sparc)   fp_rnd newMode = FP_RN;       switch (modeNum) {   case 0:      newMode = FP_RN;      break;   case 1:      newMode = FP_RZ;      break;   case 2:      newMode = FP_RP;      break;   case 3:      newMode = FP_RM;      break;   default:      CPUWarning("Bad rounding mode set in FCR31 (%d)\n", modeNum);      break;   }   fpsetround(newMode);#endif#ifdef __alpha   write_rnd(modeNum);#endif#ifdef linux   {      static int fpwarned = 0;      if (!fpwarned) {         CPUWarning("MIPSY: could not figure out how to fpsetround on x86 \n");         fpwarned = 1;      }   }#endif}/***************************************************************** * All fpu (COP1) insts come through here. *****************************************************************/int ExecuteC1Instruction(CPUState *P, Inst instr){   int immediate   = IMMED(instr);   uint fs  = FS(instr); /* 1st source reg */   uint ft  = FT(instr); /* 2nd source register */   uint sub_value = FORMAT(instr);   uint br_value  = ft;   uint major_op;   Result result = C1_SUCCESS;   uint func = FUNC(instr);   StatusReg statusReg;      /* The kernel sets the cop1 usable flag to 0 when it */   /* first starts a new context to limit the saving of */   /* FPU registers to those procs who use them. The */   /* first time a process uses a FPU instruction it */   /* needs to trap into the kernel for it to set this */   /* bit. */      statusReg.ts_data = P->CP0[C0_SR];   if (!(statusReg.s32.ts_cu1)) {      CauseReg  causeReg;            causeReg.tc_data = P->CP0[C0_CAUSE];      causeReg.s32.tc_ce = 1;      P->CP0[C0_CAUSE] = causeReg.tc_data;            EXCEPTION(P, EXC_CPU);       return C1_CONTINUE;   }   SetRoundingMode(P->FCR[31] & 0x3);   major_op = MAJOR_OP(instr);   if (major_op == cop1_op) {       switch(sub_value) {      case bc_op:         if (br_value & 0x1) { /* BC1T */            /* Check if the condition bit in the csr is set */            if (P->FCR[31] & M_csr_c) {               P->branchTarget = P->nPC + SIGN_EXTEND(18, (immediate << 2));                P->branchStatus = BranchStatus_taken;            }  else { 		if( br_value & 0x2 ) { /* branch likely */		    /* Skip instruction in delay slot */		    P->nPC = P->nPC + 4;		} else {		    P->branchStatus = BranchStatus_nottaken;                }             }         } else { /* BC1F */            /* Check if condition bit not set */            if (!(P->FCR[31] & M_csr_c)) {               P->branchTarget = P->nPC + SIGN_EXTEND(18, (immediate << 2));               P->branchStatus = BranchStatus_taken;            }  else { 		if( br_value & 0x2 ) { /* branch likely */		    /* Skip instruction in delay slot */		    P->nPC = P->nPC + 4;		} else {		    P->branchStatus = BranchStatus_nottaken;                }            }         }         break;            case cfc_op:         if (fs == 31) {            P->R[ft] = P->FCR[fs];         } else {            P->R[ft] = (3 << 8); /* R3010 FPU */         }         SIM_DEBUG(('f', "C1: CFC1 got %#x from fcr %d\n", P->R[ft], fs));         break;            case ctc_op:         P->FCR[fs] = P->R[ft];         SIM_DEBUG(('f', "C1: CTC1 put %#x into fcr %d\n", P->R[ft], fs));         break;            case mfc_op:          P->R[ft] = (Reg32_s)IntReg(fs);         SIM_DEBUG(('f', "C1: mfc1 put f%d %d into r%d \n", fs, IntReg(fs), ft));         break;            case mtc_op:         IntReg(fs) = (Reg32)P->R[ft];         SIM_DEBUG(('f', "C1: mtc1 put f%d %d into f%d -> %d\n", ft, P->R[ft],                fs, IntReg(fs)));         break;        case dmfc_op:          CHECK_64BIT_ALLOWED(P)            P->R[ft] = LongLongReg(fs);         SIM_DEBUG(('f', "C1: dmfc1 put f%d %lld into r%d \n", fs, LongLongReg(fs), ft));         break;            case dmtc_op:         CHECK_64BIT_ALLOWED(P)            LongLongReg(fs) = P->R[ft];         SIM_DEBUG(('f', "C1: dmtc1 put f%d %lldd into f%d -> %lld\n", ft, P->R[ft],                fs, LongLongReg(fs)));         break;      default:          /* S, D, W format instructions */         switch (func) {         case fmovc_op:         case fmovn_op:         case fmovz_op: {             /* Make sure we can execute mips4 instructions */            if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) {               EXCEPTION(P, EXC_II);                return C1_CONTINUE;            }            break;         }         default:            STATS_INC(P->myNum, numFPOps, 1);            break;         }          result = MipsyFPU(P, instr);         break;      } /* switch subvalue */   } else if (major_op == cop1x_op) {      if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) {         EXCEPTION(P, EXC_II);          return C1_CONTINUE;      }      STATS_INC(P->myNum, numFPOps, 1);      result = MipsyFPUx(P,instr);         } else if (major_op == spec_op) {       /* Must be on the MOVC instructions */      ASSERT(FUNC(instr) == movc_op);      /* Move conditional on FP condition */      if (TF(instr)) {          if (P->FCR[31] & M_csr_c) {            P->R[RT(instr)] = P->R[RS(instr)];         }      } else {         if (!(P->FCR[31] & M_csr_c)) {            P->R[RT(instr)] = P->R[RS(instr)];         }      }   } else {      ASSERT(0); /* unknown C1 instruction */   }         return result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -