Ejemplo n.º 1
0
unsigned int EmulateCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   unsigned int Fd, nType, nDest, nRc = 1;

   //printk("EmulateCPDO(0x%08x)\n",opcode);

   /* Get the destination size.  If not valid let Linux perform
      an invalid instruction trap. */
   nDest = getDestinationSize(opcode);
   if (typeNone == nDest) return 0;

   SetRoundingMode(opcode);

   /* Compare the size of the operands in Fn and Fm.
      Choose the largest size and perform operations in that size,
      in order to make use of all the precision of the operands.
      If Fm is a constant, we just grab a constant of a size
      matching the size of the operand in Fn. */
   if (MONADIC_INSTRUCTION(opcode))
     nType = nDest;
   else
     nType = fpa11->fType[getFn(opcode)];

   if (!CONSTANT_FM(opcode))
   {
     register unsigned int Fm = getFm(opcode);
     if (nType < fpa11->fType[Fm])
     {
        nType = fpa11->fType[Fm];
     }
   }

   switch (nType)
   {
      case typeSingle   : nRc = SingleCPDO(opcode);   break;
      case typeDouble   : nRc = DoubleCPDO(opcode);   break;
      case typeExtended : nRc = ExtendedCPDO(opcode); break;
      default           : nRc = 0;
   }

   /* If the operation succeeded, check to see if the result in the
      destination register is the correct size.  If not force it
      to be. */
   Fd = getFd(opcode);
   nType = fpa11->fType[Fd];
   if ((0 != nRc) && (nDest != nType))
   {
     switch (nDest)
     {
       case typeSingle:
       {
         if (typeDouble == nType)
           fpa11->fpreg[Fd].fSingle =
              float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
         else
           fpa11->fpreg[Fd].fSingle =
              floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
       }
       break;

       case typeDouble:
       {
         if (typeSingle == nType)
           fpa11->fpreg[Fd].fDouble =
              float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
         else
           fpa11->fpreg[Fd].fDouble =
              floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
       }
       break;

       case typeExtended:
       {
         if (typeSingle == nType)
           fpa11->fpreg[Fd].fExtended =
              float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
         else
           fpa11->fpreg[Fd].fExtended =
              float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
       }
       break;
     }

     fpa11->fType[Fd] = nDest;
   }

   return nRc;
}
Ejemplo n.º 2
0
unsigned int ExtendedCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   floatx80 rFm, rFn;
   unsigned int Fd, Fm, Fn, nRc = 1;

   //printk("ExtendedCPDO(0x%08x)\n",opcode);

   Fm = getFm(opcode);
   if (CONSTANT_FM(opcode))
   {
     rFm = getExtendedConstant(Fm);
   }
   else
   {
     switch (fpa11->fType[Fm])
     {
        case typeSingle:
          rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
        break;

        case typeDouble:
          rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
        break;

        case typeExtended:
          rFm = fpa11->fpreg[Fm].fExtended;
        break;

        default: return 0;
     }
   }

   if (!MONADIC_INSTRUCTION(opcode))
   {
      Fn = getFn(opcode);
      switch (fpa11->fType[Fn])
      {
        case typeSingle:
          rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
        break;

        case typeDouble:
          rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
        break;

        case typeExtended:
          rFn = fpa11->fpreg[Fn].fExtended;
        break;

        default: return 0;
      }
   }

   Fd = getFd(opcode);
   switch (opcode & MASK_ARITHMETIC_OPCODE)
   {
      /* dyadic opcodes */
      case ADF_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm, &fpa11->fp_status);
      break;

      case MUF_CODE:
      case FML_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm, &fpa11->fp_status);
      break;

      case SUF_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm, &fpa11->fp_status);
      break;

      case RSF_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn, &fpa11->fp_status);
      break;

      case DVF_CODE:
      case FDV_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm, &fpa11->fp_status);
      break;

      case RDF_CODE:
      case FRD_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn, &fpa11->fp_status);
      break;

#if 0
      case POW_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm);
      break;

      case RPW_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn);
      break;
#endif

      case RMF_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm, &fpa11->fp_status);
      break;

#if 0
      case POL_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm);
      break;
#endif

      /* monadic opcodes */
      case MVF_CODE:
         fpa11->fpreg[Fd].fExtended = rFm;
      break;

      case MNF_CODE:
         rFm.high ^= 0x8000;
         fpa11->fpreg[Fd].fExtended = rFm;
      break;

      case ABS_CODE:
         rFm.high &= 0x7fff;
         fpa11->fpreg[Fd].fExtended = rFm;
      break;

      case RND_CODE:
      case URD_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm, &fpa11->fp_status);
      break;

      case SQT_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm, &fpa11->fp_status);
      break;

#if 0
      case LOG_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_log(rFm);
      break;

      case LGN_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm);
      break;

      case EXP_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm);
      break;

      case SIN_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm);
      break;

      case COS_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm);
      break;

      case TAN_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm);
      break;

      case ASN_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm);
      break;

      case ACS_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm);
      break;

      case ATN_CODE:
         fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm);
      break;
#endif

      case NRM_CODE:
      break;

      default:
      {
        nRc = 0;
      }
   }

   if (0 != nRc) fpa11->fType[Fd] = typeExtended;
   return nRc;
}
Ejemplo n.º 3
0
int CMakeFrame::MakeSingleFrame()
{
	/*转化用到中间变量*/
	char BIN[2];
	char A05Result[2],A07Result[2],A22Result[1],A23Result[3],A25Result[3];

	unsigned int i = 0, j = 0, k = 0, NumTmp = 0;
	unsigned int fieldLength = 0;
	string ip_dns;
	time_t timevar = time(0); 
	char tmp[64], *pTime; 
	tp[0]=0x00;tp[5]=0x00;
	strftime( tmp, sizeof(tmp), "%X%d",localtime(&timevar) );
	pTime = tmp;
	for(i = 0; i < 3; i ++)
	{
		tp[3-i] = ascii2charto1bcd(pTime ++);
		pTime ++;pTime++;
	}
	tp[4] = ascii2charto1bcd(--pTime);
	
	//数据时标
	char td_d[3];
	memset(tmp,0,sizeof(tmp));
	strftime( tmp, sizeof(tmp), "%d%m%y",localtime(&timevar));
	pTime = tmp;
	td_d[0] = ascii2charto1bcd(pTime ++);pTime ++;
	td_d[1]=ascii2charto1bcd(pTime ++);pTime ++;
	td_d[2]=ascii2charto1bcd(pTime ++);pTime ++;
	
	for(i=0;i<16;i++)
	{
		pw[i]=0x00;
	}
	
	//地址域
	char CollectAddrTemp[5];
	string str = CollectAddr.c_str();
	while(strlen(str.c_str()) < 10)
		str = "0" + str;
	
	AnalyzeCollectAddr1(CollectAddrTemp,str.c_str());
	
	for(i=0;i<5;i++)
	{
		MICollectAddr[i] = CollectAddrTemp[i];
	}
	
	switch(afn)
	{
	case 0x01:
		MIInfoPos = 0;
		cstruct.dir=0;
		cstruct.prm=1;
		cstruct.d5=0;
		cstruct.d4=0;
		cstruct.d03=0;
		memcpy(&MIControlField,(unsigned char *)&cstruct,1);		
		
		ip_dns="01";
		afn = atoi(ip_dns.c_str())%256;
		
		seqstruct.tpv=1;
		seqstruct.fir=1;
		seqstruct.fin=1;
		seqstruct.con=0;		
		seqstruct.prseq=0;
		memcpy(&seq,(unsigned char *)&seqstruct,1);
		{
			char chfn[2] = {0};
			memset(chfn,0,sizeof(chfn));
			getFn(chfn,fnValue[0].c_str());
			MIInformation[MIInfoPos++] = 0x00;
			MIInformation[MIInfoPos++] = 0x00;
			MIInformation[MIInfoPos++] = chfn[0];
			MIInformation[MIInfoPos++] = chfn[1];
		}
		for(i=0;i<16;i++)
		{
			pw[i]=0x00;
		}
		i = 0;
		while(i < sizeof(pw))
			MIInformation[MIInfoPos ++] = pw[i++];
		i = 0;
		while(i < sizeof(tp))
			MIInformation[MIInfoPos ++] = tp[i++];
		modifyLength=6;
		break;
	case 0x04:
		if(1 == index)
		{
			MIInfoPos = 0;
			
			cstruct.dir=0;
			cstruct.prm=1;
			cstruct.d5=0;
			cstruct.d4=0;
			cstruct.d03=0;
			memcpy(&MIControlField,(unsigned char *)&cstruct,1);
			
			ip_dns="04";
			afn = atoi(ip_dns.c_str())%256;	
			
			seqstruct.tpv=1;
			seqstruct.fir=1;
			seqstruct.fin=1;
			seqstruct.con=0;		
			seqstruct.prseq=0;
			memcpy(&seq,(unsigned char *)&seqstruct,1);
			
			for(i=0;i<FnTotalNum;i++)
			{	
				if(!strcmp(fnValue[i].c_str(),"1"))
				{
					
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					int t3,t4;
					string d0;
					
					t3 = 1;
					t4 = 1;


					char char2 = (t4&0x0f00)>>8;
					char2 |= t3 <<4;
					
					MIInformation[MIInfoPos++] = t4&0x00ff;
					MIInformation[MIInfoPos++] = char2;
					
					
					
					
					/*需要主站确认的通信服务标志*/
					struct CONSTRUCT
					{
						unsigned char d0:1;
						unsigned char d1:1;
						unsigned char d2:1;
						unsigned char d3:1;
						unsigned char d47:4;
					};
					CONSTRUCT conStruct;
					while(strlen(d0.c_str()) < 8)
					{
						d0 = d0+"0";
					}
					conStruct.d0 = atoi(d0.substr(0,1).c_str());
					conStruct.d1 = atoi(d0.substr(1,1).c_str());
					conStruct.d2 = atoi(d0.substr(2,1).c_str());
					conStruct.d3 = 0;
					conStruct.d47= 0;
					char ch;
					memcpy(&ch,(char *)&conStruct,1);
					MIInformation[MIInfoPos++] = ch;
					
				}
				if(!strcmp(fnValue[i].c_str(),"3"))
				{
					string Server_IP1="127.0.0.1";
					int Server_port1=8000;
					string Server_IP2="127.0.0.1";
					int Server_port2=8001;

					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					
					
					char pass[10],*p;
					int i=0;
					memset(pass,0,sizeof(pass));
					
					p=strtok((char *)Server_IP1.c_str(),".");
					strcpy(pass,p);
					MIInformation[MIInfoPos++] = strToInt(pass) % 256;
					while (1)
					{
						p=strtok(NULL,".");
						if (!p) {
							break;
						}
						strcpy(pass,p);
						i++;
						MIInformation[MIInfoPos++] = strToInt(pass) % 256;
						
					}
					
					MIInformation[MIInfoPos++] = Server_port1 & 0x00ff;
					MIInformation[MIInfoPos++] = (Server_port1 / 256) & 0x00ff;
					
					memset(pass,0,sizeof(pass));
					i=0;
					
					
					p=strtok((char *)Server_IP2.c_str(),".");
					strcpy(pass,p);
					MIInformation[MIInfoPos++] = strToInt(pass) % 256;
					while (1)
					{
						p=strtok(NULL,".");
						if (!p) {
							break;
						}
						strcpy(pass,p);
						i++;
						MIInformation[MIInfoPos++] = strToInt(pass) % 256;
						
					}
					MIInformation[MIInfoPos++] = Server_port2 & 0x00ff;
					MIInformation[MIInfoPos++] = (Server_port2 / 256) & 0x00ff;
				}	
				
				if(!strcmp(fnValue[i].c_str(),"5"))
				{
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					int t1,t2;
					
					t1 = 1;
					t2 = 1;
					MIInformation[MIInfoPos++] = t1%256;
					
					MIInformation[MIInfoPos++] = t2 & 0x00ff;
					MIInformation[MIInfoPos++] = (t2 / 256) & 0x00ff;
				}
				if(!strcmp(fnValue[i].c_str(),"7"))
				{
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					
					string gateway="127.0.0.1";
					int gateway_port=8000;
					string proxy="127.0.0.1";
					int proxy_port=8001;
					

					char pass[10],*p;
					int i=0;
					memset(pass,0,sizeof(pass));
					
					p=strtok((char *)gateway.c_str(),".");
					strcpy(pass,p);
					MIInformation[MIInfoPos++] = strToInt(pass) % 256;
					while (1)
					{
						p=strtok(NULL,".");
						if (!p) {
							break;
						}
						strcpy(pass,p);
						i++;
						MIInformation[MIInfoPos++] = strToInt(pass) % 256;
						
					}
					
					MIInformation[MIInfoPos++] = gateway_port & 0x00ff;
					MIInformation[MIInfoPos++] = (gateway_port / 256) & 0x00ff;
					
					memset(pass,0,sizeof(pass));
					i=0;

					p=strtok((char *)proxy.c_str(),".");
					strcpy(pass,p);
					MIInformation[MIInfoPos++] = strToInt(pass) % 256;
					while (1)
					{
						p=strtok(NULL,".");
						if (!p) {
							break;
						}
						strcpy(pass,p);
						i++;
						MIInformation[MIInfoPos++] = strToInt(pass) % 256;
					}
					MIInformation[MIInfoPos++] = proxy_port & 0x00ff;
					MIInformation[MIInfoPos++] = (proxy_port / 256) & 0x00ff;
				}
				if(!strcmp(fnValue[i].c_str(),"9"))
				{
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					

					string ErcString1,ErcString2;
					ErcString1="111111111111111111111111111111111111111111111111111111111111";
					ErcString2="111111111111111111111111111111111111111111111111111111111111";
					
					struct ERCSTRUCT 
					{
						unsigned char erc1:1;
						unsigned char erc2:1;
						unsigned char erc3:1;
						unsigned char erc4:1;
						unsigned char erc5:1;
						unsigned char erc6:1;
						unsigned char erc7:1;
						unsigned char erc8:1;
					};
					ERCSTRUCT ERC;
					int value,i,j;
					char *pErc = (char *)ErcString1.c_str();
					unsigned char EVENT_VALID;
					for( i=0;i<8;i++)
					{
						for( j=1;j<=8;j++)
						{
							value=(*pErc ++) - '0';
							if(1 == j)
							{ERC.erc1=value;}
							if(2 == j)
							{ERC.erc2=value % 256;}
							if(3 == j)
							{ERC.erc3=value % 256;}
							if(4 == j)
							{ERC.erc4=value % 256;}
							if(5 == j)
							{ERC.erc5=value % 256;}
							if(6 == j)
							{ERC.erc6=value % 256;}
							if(7 == j)
							{ERC.erc7=value % 256;}
							if(8 == j)
							{ERC.erc8=value % 256;}
						}
						memcpy(&EVENT_VALID,(unsigned char *)&ERC,1);
						MIInformation[MIInfoPos++] = EVENT_VALID;
					}
					pErc = (char *)ErcString2.c_str();
					for( i=0;i<8;i++)
					{
						for( j=1;j<=8;j++)
						{
							value=(*pErc ++) - '0';
							if(1 == j)
							{ERC.erc1=value;}
							if(2 == j)
							{ERC.erc2=value % 256;}
							if(3 == j)
							{ERC.erc3=value % 256;}
							if(4 == j)
							{ERC.erc4=value % 256;}
							if(5 == j)
							{ERC.erc5=value % 256;}
							if(6 == j)
							{ERC.erc6=value % 256;}
							if(7 == j)
							{ERC.erc7=value % 256;}
							if(8 == j)
							{ERC.erc8=value % 256;}
						}
						memcpy(&EVENT_VALID,(unsigned char *)&ERC,1);
						MIInformation[MIInfoPos++] = EVENT_VALID;
					}
				}
				if(!strcmp(fnValue[i].c_str(),"37"))
				{
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					int t1;
					t1 = 1;
					MIInformation[MIInfoPos++] = t1%256;
				}
				if(!strcmp(fnValue[i].c_str(),"59"))
				{
					char chfn[2] = {0};
					memset(chfn,0,sizeof(chfn));
					getFn(chfn,fnValue[i].c_str());
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = 0x00;
					MIInformation[MIInfoPos++] = chfn[0];
					MIInformation[MIInfoPos++] = chfn[1];
					
					double t1;
					int t2,t3;
					char A22Result[1];
					
					t1 = 1.1;
					t2 = 1;
					t3 = 1;
					
					
					AnalyzeA22(A22Result,t1);
					MIInformation[MIInfoPos++] = A22Result[0];
					MIInformation[MIInfoPos++] = t2%256;
					MIInformation[MIInfoPos++] = t3%256;		
				}
						}					
					}
unsigned int EmulateCPDO(const unsigned int opcode)
{
	FPA11 *fpa11 = GET_FPA11();
	FPREG *rFd;
	unsigned int nType, nDest, nRc;
	struct roundingData roundData;

	/* Get the destination size.  If not valid let Linux perform
	   an invalid instruction trap. */
	nDest = getDestinationSize(opcode);
	if (typeNone == nDest)
		return 0;

	roundData.mode = SetRoundingMode(opcode);
	roundData.precision = SetRoundingPrecision(opcode);
	roundData.exception = 0;

	/* Compare the size of the operands in Fn and Fm.
	   Choose the largest size and perform operations in that size,
	   in order to make use of all the precision of the operands.
	   If Fm is a constant, we just grab a constant of a size
	   matching the size of the operand in Fn. */
	if (MONADIC_INSTRUCTION(opcode))
		nType = nDest;
	else
		nType = fpa11->fType[getFn(opcode)];

	if (!CONSTANT_FM(opcode)) {
		register unsigned int Fm = getFm(opcode);
		if (nType < fpa11->fType[Fm]) {
			nType = fpa11->fType[Fm];
		}
	}

	rFd = &fpa11->fpreg[getFd(opcode)];

	switch (nType) {
	case typeSingle:
		nRc = SingleCPDO(&roundData, opcode, rFd);
		break;
	case typeDouble:
		nRc = DoubleCPDO(&roundData, opcode, rFd);
		break;
#ifdef CONFIG_FPE_NWFPE_XP
	case typeExtended:
		nRc = ExtendedCPDO(&roundData, opcode, rFd);
		break;
#endif
	default:
		nRc = 0;
	}

	/* The CPDO functions used to always set the destination type
	   to be the same as their working size. */

	if (nRc != 0) {
		/* If the operation succeeded, check to see if the result in the
		   destination register is the correct size.  If not force it
		   to be. */

		fpa11->fType[getFd(opcode)] = nDest;

#ifdef CONFIG_FPE_NWFPE_XP
		if (nDest != nType) {
			switch (nDest) {
			case typeSingle:
				{
					if (typeDouble == nType)
						rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
					else
						rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
				}
				break;

			case typeDouble:
				{
					if (typeSingle == nType)
						rFd->fDouble = float32_to_float64(rFd->fSingle);
					else
						rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
				}
				break;

			case typeExtended:
				{
					if (typeSingle == nType)
						rFd->fExtended = float32_to_floatx80(rFd->fSingle);
					else
						rFd->fExtended = float64_to_floatx80(rFd->fDouble);
				}
				break;
			}
		}
#else
		if (nDest != nType) {
			if (nDest == typeSingle)
				rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
			else
				rFd->fDouble = float32_to_float64(rFd->fSingle);
		}
#endif
	}

	if (roundData.exception)
		float_raise(roundData.exception);

	return nRc;
}
Ejemplo n.º 5
0
/* This instruction sets the flags N, Z, C, V in the FPSR. */
static unsigned int PerformComparison(const unsigned int opcode)
{
    FPA11 *fpa11 = GET_FPA11();
    unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
    int e_flag = opcode & 0x400000;	/* 1 if CxFE */
    int n_flag = opcode & 0x200000;	/* 1 if CNxx */
    unsigned int flags = 0;

#ifdef CONFIG_FPE_NWFPE_XP
    floatx80 rFn, rFm;

    /* Check for unordered condition and convert all operands to 80-bit
       format.
       ?? Might be some mileage in avoiding this conversion if possible.
       Eg, if both operands are 32-bit, detect this and do a 32-bit
       comparison (cheaper than an 80-bit one).  */
    switch (fpa11->fType[Fn]) {
    case typeSingle:
        //printk("single.\n");
        if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
            goto unordered;
        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
        break;

    case typeDouble:
        //printk("double.\n");
        if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
            goto unordered;
        rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
        break;

    case typeExtended:
        //printk("extended.\n");
        if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
            goto unordered;
        rFn = fpa11->fpreg[Fn].fExtended;
        break;

    default:
        return 0;
    }

    if (CONSTANT_FM(opcode)) {
        //printk("Fm is a constant: #%d.\n",Fm);
        rFm = getExtendedConstant(Fm);
        if (floatx80_is_nan(rFm))
            goto unordered;
    } else {
        //printk("Fm = r%d which contains a ",Fm);
        switch (fpa11->fType[Fm]) {
        case typeSingle:
            //printk("single.\n");
            if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
                goto unordered;
            rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
            break;

        case typeDouble:
            //printk("double.\n");
            if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
                goto unordered;
            rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
            break;

        case typeExtended:
            //printk("extended.\n");
            if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
                goto unordered;
            rFm = fpa11->fpreg[Fm].fExtended;
            break;

        default:
            return 0;
        }
    }

    if (n_flag)
        rFm.high ^= 0x8000;

    /* test for less than condition */
    if (floatx80_lt(rFn, rFm))
        flags |= CC_NEGATIVE;

    /* test for equal condition */
    if (floatx80_eq(rFn, rFm))
        flags |= CC_ZERO;

    /* test for greater than or equal condition */
    if (floatx80_lt(rFm, rFn))
        flags |= CC_CARRY;

#else
    if (CONSTANT_FM(opcode)) {
        /* Fm is a constant.  Do the comparison in whatever precision
           Fn happens to be stored in.  */
        if (fpa11->fType[Fn] == typeSingle) {
            float32 rFm = getSingleConstant(Fm);
            float32 rFn = fpa11->fpreg[Fn].fSingle;

            if (float32_is_nan(rFn))
                goto unordered;

            if (n_flag)
                rFm ^= 0x80000000;

            /* test for less than condition */
            if (float32_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float32_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float32_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        } else {
            float64 rFm = getDoubleConstant(Fm);
            float64 rFn = fpa11->fpreg[Fn].fDouble;

            if (float64_is_nan(rFn))
                goto unordered;

            if (n_flag)
                rFm ^= 0x8000000000000000ULL;

            /* test for less than condition */
            if (float64_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float64_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float64_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        }
    } else {
        /* Both operands are in registers.  */
        if (fpa11->fType[Fn] == typeSingle
                && fpa11->fType[Fm] == typeSingle) {
            float32 rFm = fpa11->fpreg[Fm].fSingle;
            float32 rFn = fpa11->fpreg[Fn].fSingle;

            if (float32_is_nan(rFn)
                    || float32_is_nan(rFm))
                goto unordered;

            if (n_flag)
                rFm ^= 0x80000000;

            /* test for less than condition */
            if (float32_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float32_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float32_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        } else {
            /* Promote 32-bit operand to 64 bits.  */
            float64 rFm, rFn;

            rFm = (fpa11->fType[Fm] == typeSingle) ?
                  float32_to_float64(fpa11->fpreg[Fm].fSingle)
                  : fpa11->fpreg[Fm].fDouble;

            rFn = (fpa11->fType[Fn] == typeSingle) ?
                  float32_to_float64(fpa11->fpreg[Fn].fSingle)
                  : fpa11->fpreg[Fn].fDouble;

            if (float64_is_nan(rFn)
                    || float64_is_nan(rFm))
                goto unordered;

            if (n_flag)
                rFm ^= 0x8000000000000000ULL;

            /* test for less than condition */
            if (float64_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float64_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float64_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        }
    }

#endif

    writeConditionCodes(flags);

    return 1;

unordered:
    /* ?? The FPA data sheet is pretty vague about this, in particular
       about whether the non-E comparisons can ever raise exceptions.
       This implementation is based on a combination of what it says in
       the data sheet, observation of how the Acorn emulator actually
       behaves (and how programs expect it to) and guesswork.  */
    flags |= CC_OVERFLOW;
    flags &= ~(CC_ZERO | CC_NEGATIVE);

    if (BIT_AC & readFPSR())
        flags |= CC_CARRY;

    if (e_flag)
        float_raise(float_flag_invalid);

    writeConditionCodes(flags);
    return 1;
}
Ejemplo n.º 6
0
unsigned int DoubleCPDO(const unsigned int opcode)
{
   float64 rFm, rFn;
   unsigned int Fd, Fm, Fn, nRc = 1;

   //printk("DoubleCPDO(0x%08x)\n",opcode);
   
   Fm = getFm(opcode);
   if (CONSTANT_FM(opcode))
   {
     rFm = getDoubleConstant(Fm);
   }
   else
   {  
     switch (fpa11->fType[Fm])
     {
        case typeSingle:
          rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
        break;

        case typeDouble:
          rFm = fpa11->fpreg[Fm].fDouble;
          break;

        case typeExtended:
            // !! patb
	    //printk("not implemented! why not?\n");
            //!! ScottB
            // should never get here, if extended involved
            // then other operand should be promoted then
            // ExtendedCPDO called.
            break;

        default: return 0;
     }
   }

   if (!MONADIC_INSTRUCTION(opcode))
   {
      Fn = getFn(opcode);
      switch (fpa11->fType[Fn])
      {
        case typeSingle:
          rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
        break;

        case typeDouble:
          rFn = fpa11->fpreg[Fn].fDouble;
        break;
        
        default: return 0;
      }
   }

   Fd = getFd(opcode);
   /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
   switch (opcode & MASK_ARITHMETIC_OPCODE)
   {
      /* dyadic opcodes */
      case ADF_CODE:
         fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm);
      break;

      case MUF_CODE:
      case FML_CODE:
         fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm);
      break;

      case SUF_CODE:
         fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm);
      break;

      case RSF_CODE:
         fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn);
      break;

      case DVF_CODE:
      case FDV_CODE:
         fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm);
      break;

      case RDF_CODE:
      case FRD_CODE:
         fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn);
      break;

#if 0
      case POW_CODE:
         fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
      break;

      case RPW_CODE:
         fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
      break;
#endif

      case RMF_CODE:
         fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm);
      break;

#if 0
      case POL_CODE:
         fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
      break;
#endif

      /* monadic opcodes */
      case MVF_CODE:
         fpa11->fpreg[Fd].fDouble = rFm;
      break;

      case MNF_CODE:
      {
         unsigned int *p = (unsigned int*)&rFm;
         p[1] ^= 0x80000000;
         fpa11->fpreg[Fd].fDouble = rFm;
      }
      break;

      case ABS_CODE:
      {
         unsigned int *p = (unsigned int*)&rFm;
         p[1] &= 0x7fffffff;
         fpa11->fpreg[Fd].fDouble = rFm;
      }
      break;

      case RND_CODE:
      case URD_CODE:
         fpa11->fpreg[Fd].fDouble = 
             int32_to_float64(float64_to_int32(rFm));
      break;

      case SQT_CODE:
         fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm);
      break;

#if 0
      case LOG_CODE:
         fpa11->fpreg[Fd].fDouble = float64_log(rFm);
      break;

      case LGN_CODE:
         fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
      break;

      case EXP_CODE:
         fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
      break;

      case SIN_CODE:
         fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
      break;

      case COS_CODE:
         fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
      break;

      case TAN_CODE:
         fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
      break;

      case ASN_CODE:
         fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
      break;

      case ACS_CODE:
         fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
      break;

      case ATN_CODE:
         fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
      break;
#endif

      case NRM_CODE:
      break;
      
      default:
      {
        nRc = 0;
      }
   }

   if (0 != nRc) fpa11->fType[Fd] = typeDouble;
   return nRc;
}
Ejemplo n.º 7
0
unsigned int SingleCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   float32 rFm, rFn = float32_zero;
   unsigned int Fd, Fm, Fn, nRc = 1;

   Fm = getFm(opcode);
   if (CONSTANT_FM(opcode))
   {
     rFm = getSingleConstant(Fm);
   }
   else
   {
     switch (fpa11->fType[Fm])
     {
        case typeSingle:
          rFm = fpa11->fpreg[Fm].fSingle;
        break;

        default: return 0;
     }
   }

   if (!MONADIC_INSTRUCTION(opcode))
   {
      Fn = getFn(opcode);
      switch (fpa11->fType[Fn])
      {
        case typeSingle:
          rFn = fpa11->fpreg[Fn].fSingle;
        break;

        default: return 0;
      }
   }

   Fd = getFd(opcode);
   switch (opcode & MASK_ARITHMETIC_OPCODE)
   {
      /* dyadic opcodes */
      case ADF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm, &fpa11->fp_status);
      break;

      case MUF_CODE:
      case FML_CODE:
        fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm, &fpa11->fp_status);
      break;

      case SUF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm, &fpa11->fp_status);
      break;

      case RSF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn, &fpa11->fp_status);
      break;

      case DVF_CODE:
      case FDV_CODE:
         fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm, &fpa11->fp_status);
      break;

      case RDF_CODE:
      case FRD_CODE:
         fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn, &fpa11->fp_status);
      break;

#if 0
      case POW_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);
      break;

      case RPW_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);
      break;
#endif

      case RMF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm, &fpa11->fp_status);
      break;

#if 0
      case POL_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);
      break;
#endif

      /* monadic opcodes */
      case MVF_CODE:
         fpa11->fpreg[Fd].fSingle = rFm;
      break;

      case MNF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_chs(rFm);
      break;

      case ABS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_abs(rFm);
      break;

      case RND_CODE:
      case URD_CODE:
         fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm, &fpa11->fp_status);
      break;

      case SQT_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm, &fpa11->fp_status);
      break;

#if 0
      case LOG_CODE:
         fpa11->fpreg[Fd].fSingle = float32_log(rFm);
      break;

      case LGN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_ln(rFm);
      break;

      case EXP_CODE:
         fpa11->fpreg[Fd].fSingle = float32_exp(rFm);
      break;

      case SIN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sin(rFm);
      break;

      case COS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_cos(rFm);
      break;

      case TAN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_tan(rFm);
      break;

      case ASN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);
      break;

      case ACS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);
      break;

      case ATN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);
      break;
#endif

      case NRM_CODE:
      break;

      default:
      {
        nRc = 0;
      }
   }

   if (0 != nRc) fpa11->fType[Fd] = typeSingle;
   return nRc;
}
Ejemplo n.º 8
0
static void print_frame(unw_cursor_t* cursor, const unw_proc_info_t* pip) {
    // FIXME: code duplication with PythonFrameIter::incr
    static unw_word_t interpreter_instr_end = getFunctionEnd((unw_word_t)interpreter_instr_addr);
    static unw_word_t generator_entry_end = getFunctionEnd((unw_word_t)generatorEntry);

    unw_word_t ip, bp;
    check(unw_get_reg(cursor, UNW_REG_IP, &ip));
    check(unw_get_reg(cursor, UNW_TDEP_BP, &bp));

    // NB. unw_get_proc_name is MUCH slower than dl_addr for getting the names of functions, but it gets the names of
    // more functions. However, it also has a bug that pops up when used on JITted functions, so we use dladdr for now.
    // (I've put an assert in libunwind that'll catch, but not fix, the bug.) - rntz

    // {
    //     char name[500];
    //     unw_word_t off;
    //     int err = unw_get_proc_name(cursor, name, 500, &off);
    //     // ENOMEM means name didn't fit in buffer, so it was truncated. We're okay with that.
    //     RELEASE_ASSERT(!err || err == -UNW_ENOMEM || err == -UNW_ENOINFO, "unw_get_proc_name errored");
    //     if (err != -UNW_ENOINFO) {
    //         printf(strnlen(name, 500) < 50 ? "  %-50s" : "  %s\n", name);
    //     } else {
    //         printf("  %-50s", "? (no info)");
    //     }
    // }

    {
        Dl_info dl_info;
        if (dladdr((void*)ip, &dl_info)) { // returns non-zero on success, zero on failure
            if (!dl_info.dli_sname || strlen(dl_info.dli_sname) < 50)
                printf("  %-50s", dl_info.dli_sname ? dl_info.dli_sname : "(unnamed)");
            else
                printf("  %s\n", dl_info.dli_sname);
        } else {
            printf("  %-50s", "? (no dl info)");
        }
    }

    CompiledFunction* cf = getCFForAddress(ip);
    AST_stmt* cur_stmt = nullptr;
    enum { COMPILED, INTERPRETED, GENERATOR, OTHER } frame_type;
    if (cf) {
        // compiled frame
        frame_type = COMPILED;
        printf("      ip %12lx  bp %lx    JITTED\n", ip, bp);
        // TODO: get current statement
    } else if ((unw_word_t)interpreter_instr_addr <= ip && ip < interpreter_instr_end) {
        // interpreted frame
        frame_type = INTERPRETED;
        printf("      ip %12lx  bp %lx    interpreted\n", ip, bp);
        // sometimes this assert()s!
        // cf = getCFForInterpretedFrame((void*)bp);
        // cur_stmt = getCurrentStatementForInterpretedFrame((void*) bp);
    } else if ((unw_word_t)generatorEntry <= ip && ip < generator_entry_end) {
        // generator return frame
        frame_type = GENERATOR;
        printf("      ip %12lx  bp %lx    generator\n", ip, bp);
    } else {
        // generic frame, probably C/C++
        frame_type = OTHER;
        printf("      ip %12lx  bp %lx\n", ip, bp);
    }

    if (frame_type == INTERPRETED && cf && cur_stmt) {
        auto source = cf->md->source.get();
        // FIXME: dup'ed from lineInfoForFrame
        LineInfo line(cur_stmt->lineno, cur_stmt->col_offset, source->getFn(), source->getName());
        printf("      File \"%s\", line %d, in %s\n", line.file->c_str(), line.line, line.func->c_str());
    }
}