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; }
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; }
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; }
/* 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; }
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; }
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; }
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()); } }