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

📄 fpa11_cpdt.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
字号:
/*    NetWinder Floating Point Emulator    (c) Rebel.com, 1998-1999    (c) Philip Blundell, 1998, 2001    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "fpa11.h"#include "softfloat.h"#include "fpopcode.h"#include "fpmodule.h"#include "fpmodule.inl"#include <asm/uaccess.h>static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	fpa11->fType[Fn] = typeSingle;	get_user(fpa11->fpreg[Fn].fSingle, pMem);}static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	unsigned int *p;	p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;	fpa11->fType[Fn] = typeDouble;	get_user(p[0], &pMem[1]);	get_user(p[1], &pMem[0]);	/* sign & exponent */}#ifdef CONFIG_FPE_NWFPE_XPstatic inline void loadExtended(const unsigned int Fn, const unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	unsigned int *p;	p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;	fpa11->fType[Fn] = typeExtended;	get_user(p[0], &pMem[0]);	/* sign & exponent */	get_user(p[1], &pMem[2]);	/* ls bits */	get_user(p[2], &pMem[1]);	/* ms bits */}#endifstatic inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	register unsigned int *p;	unsigned long x;	p = (unsigned int *) &(fpa11->fpreg[Fn]);	get_user(x, &pMem[0]);	fpa11->fType[Fn] = (x >> 14) & 0x00000003;	switch (fpa11->fType[Fn]) {	case typeSingle:	case typeDouble:		{			get_user(p[0], &pMem[2]);	/* Single */			get_user(p[1], &pMem[1]);	/* double msw */			p[2] = 0;			/* empty */		}		break;#ifdef CONFIG_FPE_NWFPE_XP	case typeExtended:		{			get_user(p[1], &pMem[2]);			get_user(p[2], &pMem[1]);	/* msw */			p[0] = (x & 0x80003fff);		}		break;#endif	}}static inline void storeSingle(const unsigned int Fn, unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	float32 val;	register unsigned int *p = (unsigned int *) &val;	switch (fpa11->fType[Fn]) {	case typeDouble:		val = float64_to_float32(fpa11->fpreg[Fn].fDouble);		break;#ifdef CONFIG_FPE_NWFPE_XP	case typeExtended:		val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);		break;#endif	default:		val = fpa11->fpreg[Fn].fSingle;	}	put_user(p[0], pMem);}static inline void storeDouble(const unsigned int Fn, unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	float64 val;	register unsigned int *p = (unsigned int *) &val;	switch (fpa11->fType[Fn]) {	case typeSingle:		val = float32_to_float64(fpa11->fpreg[Fn].fSingle);		break;#ifdef CONFIG_FPE_NWFPE_XP	case typeExtended:		val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);		break;#endif	default:		val = fpa11->fpreg[Fn].fDouble;	}	put_user(p[1], &pMem[0]);	/* msw */	put_user(p[0], &pMem[1]);	/* lsw */}#ifdef CONFIG_FPE_NWFPE_XPstatic inline void storeExtended(const unsigned int Fn, unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	floatx80 val;	register unsigned int *p = (unsigned int *) &val;	switch (fpa11->fType[Fn]) {	case typeSingle:		val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);		break;	case typeDouble:		val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);		break;	default:		val = fpa11->fpreg[Fn].fExtended;	}	put_user(p[0], &pMem[0]);	/* sign & exp */	put_user(p[1], &pMem[2]);	put_user(p[2], &pMem[1]);	/* msw */}#endifstatic inline void storeMultiple(const unsigned int Fn, unsigned int *pMem){	FPA11 *fpa11 = GET_FPA11();	register unsigned int nType, *p;	p = (unsigned int *) &(fpa11->fpreg[Fn]);	nType = fpa11->fType[Fn];	switch (nType) {	case typeSingle:	case typeDouble:		{			put_user(p[0], &pMem[2]);	/* single */			put_user(p[1], &pMem[1]);	/* double msw */			put_user(nType << 14, &pMem[0]);		}		break;#ifdef CONFIG_FPE_NWFPE_XP	case typeExtended:		{			put_user(p[2], &pMem[1]);	/* msw */			put_user(p[1], &pMem[2]);			put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);		}		break;#endif	}}unsigned int PerformLDF(const unsigned int opcode){	unsigned int *pBase, *pAddress, *pFinal, nRc = 1,	    write_back = WRITE_BACK(opcode);	pBase = (unsigned int *) readRegister(getRn(opcode));	if (REG_PC == getRn(opcode)) {		pBase += 2;		write_back = 0;	}	pFinal = pBase;	if (BIT_UP_SET(opcode))		pFinal += getOffset(opcode);	else		pFinal -= getOffset(opcode);	if (PREINDEXED(opcode))		pAddress = pFinal;	else		pAddress = pBase;	switch (opcode & MASK_TRANSFER_LENGTH) {	case TRANSFER_SINGLE:		loadSingle(getFd(opcode), pAddress);		break;	case TRANSFER_DOUBLE:		loadDouble(getFd(opcode), pAddress);		break;#ifdef CONFIG_FPE_NWFPE_XP	case TRANSFER_EXTENDED:		loadExtended(getFd(opcode), pAddress);		break;#endif	default:		nRc = 0;	}	if (write_back)		writeRegister(getRn(opcode), (unsigned int) pFinal);	return nRc;}unsigned int PerformSTF(const unsigned int opcode){	unsigned int *pBase, *pAddress, *pFinal, nRc = 1,	    write_back = WRITE_BACK(opcode);	SetRoundingMode(ROUND_TO_NEAREST);	pBase = (unsigned int *) readRegister(getRn(opcode));	if (REG_PC == getRn(opcode)) {		pBase += 2;		write_back = 0;	}	pFinal = pBase;	if (BIT_UP_SET(opcode))		pFinal += getOffset(opcode);	else		pFinal -= getOffset(opcode);	if (PREINDEXED(opcode))		pAddress = pFinal;	else		pAddress = pBase;	switch (opcode & MASK_TRANSFER_LENGTH) {	case TRANSFER_SINGLE:		storeSingle(getFd(opcode), pAddress);		break;	case TRANSFER_DOUBLE:		storeDouble(getFd(opcode), pAddress);		break;#ifdef CONFIG_FPE_NWFPE_XP	case TRANSFER_EXTENDED:		storeExtended(getFd(opcode), pAddress);		break;#endif	default:		nRc = 0;	}	if (write_back)		writeRegister(getRn(opcode), (unsigned int) pFinal);	return nRc;}unsigned int PerformLFM(const unsigned int opcode){	unsigned int i, Fd, *pBase, *pAddress, *pFinal,	    write_back = WRITE_BACK(opcode);	pBase = (unsigned int *) readRegister(getRn(opcode));	if (REG_PC == getRn(opcode)) {		pBase += 2;		write_back = 0;	}	pFinal = pBase;	if (BIT_UP_SET(opcode))		pFinal += getOffset(opcode);	else		pFinal -= getOffset(opcode);	if (PREINDEXED(opcode))		pAddress = pFinal;	else		pAddress = pBase;	Fd = getFd(opcode);	for (i = getRegisterCount(opcode); i > 0; i--) {		loadMultiple(Fd, pAddress);		pAddress += 3;		Fd++;		if (Fd == 8)			Fd = 0;	}	if (write_back)		writeRegister(getRn(opcode), (unsigned int) pFinal);	return 1;}unsigned int PerformSFM(const unsigned int opcode){	unsigned int i, Fd, *pBase, *pAddress, *pFinal,	    write_back = WRITE_BACK(opcode);	pBase = (unsigned int *) readRegister(getRn(opcode));	if (REG_PC == getRn(opcode)) {		pBase += 2;		write_back = 0;	}	pFinal = pBase;	if (BIT_UP_SET(opcode))		pFinal += getOffset(opcode);	else		pFinal -= getOffset(opcode);	if (PREINDEXED(opcode))		pAddress = pFinal;	else		pAddress = pBase;	Fd = getFd(opcode);	for (i = getRegisterCount(opcode); i > 0; i--) {		storeMultiple(Fd, pAddress);		pAddress += 3;		Fd++;		if (Fd == 8)			Fd = 0;	}	if (write_back)		writeRegister(getRn(opcode), (unsigned int) pFinal);	return 1;}unsigned int EmulateCPDT(const unsigned int opcode){	unsigned int nRc = 0;	if (LDF_OP(opcode)) {		nRc = PerformLDF(opcode);	} else if (LFM_OP(opcode)) {		nRc = PerformLFM(opcode);	} else if (STF_OP(opcode)) {		nRc = PerformSTF(opcode);	} else if (SFM_OP(opcode)) {		nRc = PerformSFM(opcode);	} else {		nRc = 0;	}	return nRc;}

⌨️ 快捷键说明

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