xref: /openbmc/linux/arch/arm/nwfpe/fpa11_cpdt.c (revision 74ba9207)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds     NetWinder Floating Point Emulator
41da177e4SLinus Torvalds     (c) Rebel.com, 1998-1999
51da177e4SLinus Torvalds     (c) Philip Blundell, 1998, 2001
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include "fpa11.h"
121da177e4SLinus Torvalds #include "softfloat.h"
131da177e4SLinus Torvalds #include "fpopcode.h"
141da177e4SLinus Torvalds #include "fpmodule.h"
151da177e4SLinus Torvalds #include "fpmodule.inl"
161da177e4SLinus Torvalds 
1733fa9b13SRussell King #include <linux/uaccess.h>
181da177e4SLinus Torvalds 
loadSingle(const unsigned int Fn,const unsigned int __user * pMem)191da177e4SLinus Torvalds static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
201da177e4SLinus Torvalds {
211da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
221da177e4SLinus Torvalds 	fpa11->fType[Fn] = typeSingle;
231da177e4SLinus Torvalds 	get_user(fpa11->fpreg[Fn].fSingle, pMem);
241da177e4SLinus Torvalds }
251da177e4SLinus Torvalds 
loadDouble(const unsigned int Fn,const unsigned int __user * pMem)261da177e4SLinus Torvalds static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
271da177e4SLinus Torvalds {
281da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
291da177e4SLinus Torvalds 	unsigned int *p;
301da177e4SLinus Torvalds 	p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
311da177e4SLinus Torvalds 	fpa11->fType[Fn] = typeDouble;
321da177e4SLinus Torvalds #ifdef __ARMEB__
331da177e4SLinus Torvalds 	get_user(p[0], &pMem[0]);	/* sign & exponent */
341da177e4SLinus Torvalds 	get_user(p[1], &pMem[1]);
351da177e4SLinus Torvalds #else
361da177e4SLinus Torvalds 	get_user(p[0], &pMem[1]);
371da177e4SLinus Torvalds 	get_user(p[1], &pMem[0]);	/* sign & exponent */
381da177e4SLinus Torvalds #endif
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
loadExtended(const unsigned int Fn,const unsigned int __user * pMem)421da177e4SLinus Torvalds static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
431da177e4SLinus Torvalds {
441da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
451da177e4SLinus Torvalds 	unsigned int *p;
461da177e4SLinus Torvalds 	p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
471da177e4SLinus Torvalds 	fpa11->fType[Fn] = typeExtended;
481da177e4SLinus Torvalds 	get_user(p[0], &pMem[0]);	/* sign & exponent */
49bedf142bSLennert Buytenhek #ifdef __ARMEB__
50bedf142bSLennert Buytenhek 	get_user(p[1], &pMem[1]);	/* ms bits */
51bedf142bSLennert Buytenhek 	get_user(p[2], &pMem[2]);	/* ls bits */
52bedf142bSLennert Buytenhek #else
531da177e4SLinus Torvalds 	get_user(p[1], &pMem[2]);	/* ls bits */
541da177e4SLinus Torvalds 	get_user(p[2], &pMem[1]);	/* ms bits */
55bedf142bSLennert Buytenhek #endif
561da177e4SLinus Torvalds }
571da177e4SLinus Torvalds #endif
581da177e4SLinus Torvalds 
loadMultiple(const unsigned int Fn,const unsigned int __user * pMem)591da177e4SLinus Torvalds static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
601da177e4SLinus Torvalds {
611da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
621da177e4SLinus Torvalds 	register unsigned int *p;
631da177e4SLinus Torvalds 	unsigned long x;
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds 	p = (unsigned int *) &(fpa11->fpreg[Fn]);
661da177e4SLinus Torvalds 	get_user(x, &pMem[0]);
671da177e4SLinus Torvalds 	fpa11->fType[Fn] = (x >> 14) & 0x00000003;
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	switch (fpa11->fType[Fn]) {
701da177e4SLinus Torvalds 	case typeSingle:
711da177e4SLinus Torvalds 	case typeDouble:
721da177e4SLinus Torvalds 		{
731da177e4SLinus Torvalds 			get_user(p[0], &pMem[2]);	/* Single */
741da177e4SLinus Torvalds 			get_user(p[1], &pMem[1]);	/* double msw */
751da177e4SLinus Torvalds 			p[2] = 0;			/* empty */
761da177e4SLinus Torvalds 		}
771da177e4SLinus Torvalds 		break;
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
801da177e4SLinus Torvalds 	case typeExtended:
811da177e4SLinus Torvalds 		{
821da177e4SLinus Torvalds 			get_user(p[1], &pMem[2]);
831da177e4SLinus Torvalds 			get_user(p[2], &pMem[1]);	/* msw */
841da177e4SLinus Torvalds 			p[0] = (x & 0x80003fff);
851da177e4SLinus Torvalds 		}
861da177e4SLinus Torvalds 		break;
871da177e4SLinus Torvalds #endif
881da177e4SLinus Torvalds 	}
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
storeSingle(struct roundingData * roundData,const unsigned int Fn,unsigned int __user * pMem)91f148af25SRichard Purdie static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
921da177e4SLinus Torvalds {
931da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
941da177e4SLinus Torvalds 	union {
951da177e4SLinus Torvalds 		float32 f;
961da177e4SLinus Torvalds 		unsigned int i[1];
971da177e4SLinus Torvalds 	} val;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	switch (fpa11->fType[Fn]) {
1001da177e4SLinus Torvalds 	case typeDouble:
101f148af25SRichard Purdie 		val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
1021da177e4SLinus Torvalds 		break;
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
1051da177e4SLinus Torvalds 	case typeExtended:
106f148af25SRichard Purdie 		val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
1071da177e4SLinus Torvalds 		break;
1081da177e4SLinus Torvalds #endif
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	default:
1111da177e4SLinus Torvalds 		val.f = fpa11->fpreg[Fn].fSingle;
1121da177e4SLinus Torvalds 	}
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	put_user(val.i[0], pMem);
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds 
storeDouble(struct roundingData * roundData,const unsigned int Fn,unsigned int __user * pMem)117f148af25SRichard Purdie static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
1181da177e4SLinus Torvalds {
1191da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
1201da177e4SLinus Torvalds 	union {
1211da177e4SLinus Torvalds 		float64 f;
1221da177e4SLinus Torvalds 		unsigned int i[2];
1231da177e4SLinus Torvalds 	} val;
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 	switch (fpa11->fType[Fn]) {
1261da177e4SLinus Torvalds 	case typeSingle:
1271da177e4SLinus Torvalds 		val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
1281da177e4SLinus Torvalds 		break;
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
1311da177e4SLinus Torvalds 	case typeExtended:
132f148af25SRichard Purdie 		val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
1331da177e4SLinus Torvalds 		break;
1341da177e4SLinus Torvalds #endif
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds 	default:
1371da177e4SLinus Torvalds 		val.f = fpa11->fpreg[Fn].fDouble;
1381da177e4SLinus Torvalds 	}
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds #ifdef __ARMEB__
1411da177e4SLinus Torvalds 	put_user(val.i[0], &pMem[0]);	/* msw */
1421da177e4SLinus Torvalds 	put_user(val.i[1], &pMem[1]);	/* lsw */
1431da177e4SLinus Torvalds #else
1441da177e4SLinus Torvalds 	put_user(val.i[1], &pMem[0]);	/* msw */
1451da177e4SLinus Torvalds 	put_user(val.i[0], &pMem[1]);	/* lsw */
1461da177e4SLinus Torvalds #endif
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
storeExtended(const unsigned int Fn,unsigned int __user * pMem)1501da177e4SLinus Torvalds static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
1511da177e4SLinus Torvalds {
1521da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
1531da177e4SLinus Torvalds 	union {
1541da177e4SLinus Torvalds 		floatx80 f;
1551da177e4SLinus Torvalds 		unsigned int i[3];
1561da177e4SLinus Torvalds 	} val;
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds 	switch (fpa11->fType[Fn]) {
1591da177e4SLinus Torvalds 	case typeSingle:
1601da177e4SLinus Torvalds 		val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
1611da177e4SLinus Torvalds 		break;
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds 	case typeDouble:
1641da177e4SLinus Torvalds 		val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
1651da177e4SLinus Torvalds 		break;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	default:
1681da177e4SLinus Torvalds 		val.f = fpa11->fpreg[Fn].fExtended;
1691da177e4SLinus Torvalds 	}
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	put_user(val.i[0], &pMem[0]);	/* sign & exp */
172bedf142bSLennert Buytenhek #ifdef __ARMEB__
173bedf142bSLennert Buytenhek 	put_user(val.i[1], &pMem[1]);	/* msw */
174bedf142bSLennert Buytenhek 	put_user(val.i[2], &pMem[2]);
175bedf142bSLennert Buytenhek #else
1761da177e4SLinus Torvalds 	put_user(val.i[1], &pMem[2]);
1771da177e4SLinus Torvalds 	put_user(val.i[2], &pMem[1]);	/* msw */
178bedf142bSLennert Buytenhek #endif
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds #endif
1811da177e4SLinus Torvalds 
storeMultiple(const unsigned int Fn,unsigned int __user * pMem)1821da177e4SLinus Torvalds static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
1831da177e4SLinus Torvalds {
1841da177e4SLinus Torvalds 	FPA11 *fpa11 = GET_FPA11();
1851da177e4SLinus Torvalds 	register unsigned int nType, *p;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	p = (unsigned int *) &(fpa11->fpreg[Fn]);
1881da177e4SLinus Torvalds 	nType = fpa11->fType[Fn];
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	switch (nType) {
1911da177e4SLinus Torvalds 	case typeSingle:
1921da177e4SLinus Torvalds 	case typeDouble:
1931da177e4SLinus Torvalds 		{
1941da177e4SLinus Torvalds 			put_user(p[0], &pMem[2]);	/* single */
1951da177e4SLinus Torvalds 			put_user(p[1], &pMem[1]);	/* double msw */
1961da177e4SLinus Torvalds 			put_user(nType << 14, &pMem[0]);
1971da177e4SLinus Torvalds 		}
1981da177e4SLinus Torvalds 		break;
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
2011da177e4SLinus Torvalds 	case typeExtended:
2021da177e4SLinus Torvalds 		{
2031da177e4SLinus Torvalds 			put_user(p[2], &pMem[1]);	/* msw */
2041da177e4SLinus Torvalds 			put_user(p[1], &pMem[2]);
2051da177e4SLinus Torvalds 			put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
2061da177e4SLinus Torvalds 		}
2071da177e4SLinus Torvalds 		break;
2081da177e4SLinus Torvalds #endif
2091da177e4SLinus Torvalds 	}
2101da177e4SLinus Torvalds }
2111da177e4SLinus Torvalds 
PerformLDF(const unsigned int opcode)2121da177e4SLinus Torvalds unsigned int PerformLDF(const unsigned int opcode)
2131da177e4SLinus Torvalds {
2141da177e4SLinus Torvalds 	unsigned int __user *pBase, *pAddress, *pFinal;
2151da177e4SLinus Torvalds 	unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 	pBase = (unsigned int __user *) readRegister(getRn(opcode));
2181da177e4SLinus Torvalds 	if (REG_PC == getRn(opcode)) {
2191da177e4SLinus Torvalds 		pBase += 2;
2201da177e4SLinus Torvalds 		write_back = 0;
2211da177e4SLinus Torvalds 	}
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 	pFinal = pBase;
2241da177e4SLinus Torvalds 	if (BIT_UP_SET(opcode))
2251da177e4SLinus Torvalds 		pFinal += getOffset(opcode);
2261da177e4SLinus Torvalds 	else
2271da177e4SLinus Torvalds 		pFinal -= getOffset(opcode);
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 	if (PREINDEXED(opcode))
2301da177e4SLinus Torvalds 		pAddress = pFinal;
2311da177e4SLinus Torvalds 	else
2321da177e4SLinus Torvalds 		pAddress = pBase;
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	switch (opcode & MASK_TRANSFER_LENGTH) {
2351da177e4SLinus Torvalds 	case TRANSFER_SINGLE:
2361da177e4SLinus Torvalds 		loadSingle(getFd(opcode), pAddress);
2371da177e4SLinus Torvalds 		break;
2381da177e4SLinus Torvalds 	case TRANSFER_DOUBLE:
2391da177e4SLinus Torvalds 		loadDouble(getFd(opcode), pAddress);
2401da177e4SLinus Torvalds 		break;
2411da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
2421da177e4SLinus Torvalds 	case TRANSFER_EXTENDED:
2431da177e4SLinus Torvalds 		loadExtended(getFd(opcode), pAddress);
2441da177e4SLinus Torvalds 		break;
2451da177e4SLinus Torvalds #endif
2461da177e4SLinus Torvalds 	default:
2471da177e4SLinus Torvalds 		nRc = 0;
2481da177e4SLinus Torvalds 	}
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds 	if (write_back)
2511da177e4SLinus Torvalds 		writeRegister(getRn(opcode), (unsigned long) pFinal);
2521da177e4SLinus Torvalds 	return nRc;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
PerformSTF(const unsigned int opcode)2551da177e4SLinus Torvalds unsigned int PerformSTF(const unsigned int opcode)
2561da177e4SLinus Torvalds {
2571da177e4SLinus Torvalds 	unsigned int __user *pBase, *pAddress, *pFinal;
2581da177e4SLinus Torvalds 	unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
259f148af25SRichard Purdie 	struct roundingData roundData;
2601da177e4SLinus Torvalds 
261f148af25SRichard Purdie 	roundData.mode = SetRoundingMode(opcode);
262f148af25SRichard Purdie 	roundData.precision = SetRoundingPrecision(opcode);
263f148af25SRichard Purdie 	roundData.exception = 0;
2641da177e4SLinus Torvalds 
2651da177e4SLinus Torvalds 	pBase = (unsigned int __user *) readRegister(getRn(opcode));
2661da177e4SLinus Torvalds 	if (REG_PC == getRn(opcode)) {
2671da177e4SLinus Torvalds 		pBase += 2;
2681da177e4SLinus Torvalds 		write_back = 0;
2691da177e4SLinus Torvalds 	}
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	pFinal = pBase;
2721da177e4SLinus Torvalds 	if (BIT_UP_SET(opcode))
2731da177e4SLinus Torvalds 		pFinal += getOffset(opcode);
2741da177e4SLinus Torvalds 	else
2751da177e4SLinus Torvalds 		pFinal -= getOffset(opcode);
2761da177e4SLinus Torvalds 
2771da177e4SLinus Torvalds 	if (PREINDEXED(opcode))
2781da177e4SLinus Torvalds 		pAddress = pFinal;
2791da177e4SLinus Torvalds 	else
2801da177e4SLinus Torvalds 		pAddress = pBase;
2811da177e4SLinus Torvalds 
2821da177e4SLinus Torvalds 	switch (opcode & MASK_TRANSFER_LENGTH) {
2831da177e4SLinus Torvalds 	case TRANSFER_SINGLE:
284f148af25SRichard Purdie 		storeSingle(&roundData, getFd(opcode), pAddress);
2851da177e4SLinus Torvalds 		break;
2861da177e4SLinus Torvalds 	case TRANSFER_DOUBLE:
287f148af25SRichard Purdie 		storeDouble(&roundData, getFd(opcode), pAddress);
2881da177e4SLinus Torvalds 		break;
2891da177e4SLinus Torvalds #ifdef CONFIG_FPE_NWFPE_XP
2901da177e4SLinus Torvalds 	case TRANSFER_EXTENDED:
2911da177e4SLinus Torvalds 		storeExtended(getFd(opcode), pAddress);
2921da177e4SLinus Torvalds 		break;
2931da177e4SLinus Torvalds #endif
2941da177e4SLinus Torvalds 	default:
2951da177e4SLinus Torvalds 		nRc = 0;
2961da177e4SLinus Torvalds 	}
2971da177e4SLinus Torvalds 
298f148af25SRichard Purdie 	if (roundData.exception)
299f148af25SRichard Purdie 		float_raise(roundData.exception);
300f148af25SRichard Purdie 
3011da177e4SLinus Torvalds 	if (write_back)
3021da177e4SLinus Torvalds 		writeRegister(getRn(opcode), (unsigned long) pFinal);
3031da177e4SLinus Torvalds 	return nRc;
3041da177e4SLinus Torvalds }
3051da177e4SLinus Torvalds 
PerformLFM(const unsigned int opcode)3061da177e4SLinus Torvalds unsigned int PerformLFM(const unsigned int opcode)
3071da177e4SLinus Torvalds {
3081da177e4SLinus Torvalds 	unsigned int __user *pBase, *pAddress, *pFinal;
3091da177e4SLinus Torvalds 	unsigned int i, Fd, write_back = WRITE_BACK(opcode);
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds 	pBase = (unsigned int __user *) readRegister(getRn(opcode));
3121da177e4SLinus Torvalds 	if (REG_PC == getRn(opcode)) {
3131da177e4SLinus Torvalds 		pBase += 2;
3141da177e4SLinus Torvalds 		write_back = 0;
3151da177e4SLinus Torvalds 	}
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds 	pFinal = pBase;
3181da177e4SLinus Torvalds 	if (BIT_UP_SET(opcode))
3191da177e4SLinus Torvalds 		pFinal += getOffset(opcode);
3201da177e4SLinus Torvalds 	else
3211da177e4SLinus Torvalds 		pFinal -= getOffset(opcode);
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds 	if (PREINDEXED(opcode))
3241da177e4SLinus Torvalds 		pAddress = pFinal;
3251da177e4SLinus Torvalds 	else
3261da177e4SLinus Torvalds 		pAddress = pBase;
3271da177e4SLinus Torvalds 
3281da177e4SLinus Torvalds 	Fd = getFd(opcode);
3291da177e4SLinus Torvalds 	for (i = getRegisterCount(opcode); i > 0; i--) {
3301da177e4SLinus Torvalds 		loadMultiple(Fd, pAddress);
3311da177e4SLinus Torvalds 		pAddress += 3;
3321da177e4SLinus Torvalds 		Fd++;
3331da177e4SLinus Torvalds 		if (Fd == 8)
3341da177e4SLinus Torvalds 			Fd = 0;
3351da177e4SLinus Torvalds 	}
3361da177e4SLinus Torvalds 
3371da177e4SLinus Torvalds 	if (write_back)
3381da177e4SLinus Torvalds 		writeRegister(getRn(opcode), (unsigned long) pFinal);
3391da177e4SLinus Torvalds 	return 1;
3401da177e4SLinus Torvalds }
3411da177e4SLinus Torvalds 
PerformSFM(const unsigned int opcode)3421da177e4SLinus Torvalds unsigned int PerformSFM(const unsigned int opcode)
3431da177e4SLinus Torvalds {
3441da177e4SLinus Torvalds 	unsigned int __user *pBase, *pAddress, *pFinal;
3451da177e4SLinus Torvalds 	unsigned int i, Fd, write_back = WRITE_BACK(opcode);
3461da177e4SLinus Torvalds 
3471da177e4SLinus Torvalds 	pBase = (unsigned int __user *) readRegister(getRn(opcode));
3481da177e4SLinus Torvalds 	if (REG_PC == getRn(opcode)) {
3491da177e4SLinus Torvalds 		pBase += 2;
3501da177e4SLinus Torvalds 		write_back = 0;
3511da177e4SLinus Torvalds 	}
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds 	pFinal = pBase;
3541da177e4SLinus Torvalds 	if (BIT_UP_SET(opcode))
3551da177e4SLinus Torvalds 		pFinal += getOffset(opcode);
3561da177e4SLinus Torvalds 	else
3571da177e4SLinus Torvalds 		pFinal -= getOffset(opcode);
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 	if (PREINDEXED(opcode))
3601da177e4SLinus Torvalds 		pAddress = pFinal;
3611da177e4SLinus Torvalds 	else
3621da177e4SLinus Torvalds 		pAddress = pBase;
3631da177e4SLinus Torvalds 
3641da177e4SLinus Torvalds 	Fd = getFd(opcode);
3651da177e4SLinus Torvalds 	for (i = getRegisterCount(opcode); i > 0; i--) {
3661da177e4SLinus Torvalds 		storeMultiple(Fd, pAddress);
3671da177e4SLinus Torvalds 		pAddress += 3;
3681da177e4SLinus Torvalds 		Fd++;
3691da177e4SLinus Torvalds 		if (Fd == 8)
3701da177e4SLinus Torvalds 			Fd = 0;
3711da177e4SLinus Torvalds 	}
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds 	if (write_back)
3741da177e4SLinus Torvalds 		writeRegister(getRn(opcode), (unsigned long) pFinal);
3751da177e4SLinus Torvalds 	return 1;
3761da177e4SLinus Torvalds }
3771da177e4SLinus Torvalds 
EmulateCPDT(const unsigned int opcode)3781da177e4SLinus Torvalds unsigned int EmulateCPDT(const unsigned int opcode)
3791da177e4SLinus Torvalds {
3801da177e4SLinus Torvalds 	unsigned int nRc = 0;
3811da177e4SLinus Torvalds 
3821da177e4SLinus Torvalds 	if (LDF_OP(opcode)) {
3831da177e4SLinus Torvalds 		nRc = PerformLDF(opcode);
3841da177e4SLinus Torvalds 	} else if (LFM_OP(opcode)) {
3851da177e4SLinus Torvalds 		nRc = PerformLFM(opcode);
3861da177e4SLinus Torvalds 	} else if (STF_OP(opcode)) {
3871da177e4SLinus Torvalds 		nRc = PerformSTF(opcode);
3881da177e4SLinus Torvalds 	} else if (SFM_OP(opcode)) {
3891da177e4SLinus Torvalds 		nRc = PerformSFM(opcode);
3901da177e4SLinus Torvalds 	} else {
3911da177e4SLinus Torvalds 		nRc = 0;
3921da177e4SLinus Torvalds 	}
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds 	return nRc;
3951da177e4SLinus Torvalds }
396