aboutsummaryrefslogtreecommitdiff
path: root/arch/arm26/nwfpe/fpa11_cprt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm26/nwfpe/fpa11_cprt.c')
-rw-r--r--arch/arm26/nwfpe/fpa11_cprt.c289
1 files changed, 0 insertions, 289 deletions
diff --git a/arch/arm26/nwfpe/fpa11_cprt.c b/arch/arm26/nwfpe/fpa11_cprt.c
deleted file mode 100644
index a201076c1f1..00000000000
--- a/arch/arm26/nwfpe/fpa11_cprt.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- NetWinder Floating Point Emulator
- (c) Rebel.COM, 1998,1999
- (c) Philip Blundell, 1999
-
- 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 "milieu.h"
-#include "softfloat.h"
-#include "fpopcode.h"
-#include "fpa11.inl"
-#include "fpmodule.h"
-#include "fpmodule.inl"
-
-extern flag floatx80_is_nan(floatx80);
-extern flag float64_is_nan( float64);
-extern flag float32_is_nan( float32);
-
-void SetRoundingMode(const unsigned int opcode);
-
-unsigned int PerformFLT(const unsigned int opcode);
-unsigned int PerformFIX(const unsigned int opcode);
-
-static unsigned int
-PerformComparison(const unsigned int opcode);
-
-unsigned int EmulateCPRT(const unsigned int opcode)
-{
- unsigned int nRc = 1;
-
- //printk("EmulateCPRT(0x%08x)\n",opcode);
-
- if (opcode & 0x800000)
- {
- /* This is some variant of a comparison (PerformComparison will
- sort out which one). Since most of the other CPRT
- instructions are oddball cases of some sort or other it makes
- sense to pull this out into a fast path. */
- return PerformComparison(opcode);
- }
-
- /* Hint to GCC that we'd like a jump table rather than a load of CMPs */
- switch ((opcode & 0x700000) >> 20)
- {
- case FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
- case FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
-
- case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
- case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
-
-#if 0 /* We currently have no use for the FPCR, so there's no point
- in emulating it. */
- case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
- case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
-#endif
-
- default: nRc = 0;
- }
-
- return nRc;
-}
-
-unsigned int PerformFLT(const unsigned int opcode)
-{
- FPA11 *fpa11 = GET_FPA11();
-
- unsigned int nRc = 1;
- SetRoundingMode(opcode);
-
- switch (opcode & MASK_ROUNDING_PRECISION)
- {
- case ROUND_SINGLE:
- {
- fpa11->fType[getFn(opcode)] = typeSingle;
- fpa11->fpreg[getFn(opcode)].fSingle =
- int32_to_float32(readRegister(getRd(opcode)));
- }
- break;
-
- case ROUND_DOUBLE:
- {
- fpa11->fType[getFn(opcode)] = typeDouble;
- fpa11->fpreg[getFn(opcode)].fDouble =
- int32_to_float64(readRegister(getRd(opcode)));
- }
- break;
-
- case ROUND_EXTENDED:
- {
- fpa11->fType[getFn(opcode)] = typeExtended;
- fpa11->fpreg[getFn(opcode)].fExtended =
- int32_to_floatx80(readRegister(getRd(opcode)));
- }
- break;
-
- default: nRc = 0;
- }
-
- return nRc;
-}
-
-unsigned int PerformFIX(const unsigned int opcode)
-{
- FPA11 *fpa11 = GET_FPA11();
- unsigned int nRc = 1;
- unsigned int Fn = getFm(opcode);
-
- SetRoundingMode(opcode);
-
- switch (fpa11->fType[Fn])
- {
- case typeSingle:
- {
- writeRegister(getRd(opcode),
- float32_to_int32(fpa11->fpreg[Fn].fSingle));
- }
- break;
-
- case typeDouble:
- {
- writeRegister(getRd(opcode),
- float64_to_int32(fpa11->fpreg[Fn].fDouble));
- }
- break;
-
- case typeExtended:
- {
- writeRegister(getRd(opcode),
- floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
- }
- break;
-
- default: nRc = 0;
- }
-
- return nRc;
-}
-
-
-static unsigned int __inline__
-PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
-{
- unsigned int flags = 0;
-
- /* test for less than condition */
- if (floatx80_lt(Fn,Fm))
- {
- flags |= CC_NEGATIVE;
- }
-
- /* test for equal condition */
- if (floatx80_eq(Fn,Fm))
- {
- flags |= CC_ZERO;
- }
-
- /* test for greater than or equal condition */
- if (floatx80_lt(Fm,Fn))
- {
- flags |= CC_CARRY;
- }
-
- writeConditionCodes(flags);
- return 1;
-}
-
-/* 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, Fm;
- floatx80 rFn, rFm;
- int e_flag = opcode & 0x400000; /* 1 if CxFE */
- int n_flag = opcode & 0x200000; /* 1 if CNxx */
- unsigned int flags = 0;
-
- //printk("PerformComparison(0x%08x)\n",opcode);
-
- Fn = getFn(opcode);
- Fm = getFm(opcode);
-
- /* 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;
- }
-
- return PerformComparisonOperation(rFn,rFm);
-
- 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;
-}