/*
    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, see <http://www.gnu.org/licenses/>.
*/

#include "fpa11.h"
#include "softfloat.h"
#include "fpopcode.h"
#include "fpa11.inl"
//#include "fpmodule.h"
//#include "fpmodule.inl"

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)), &fpa11->fp_status);
      }
      break;

      case ROUND_DOUBLE:
      {
        fpa11->fType[getFn(opcode)] = typeDouble;
        fpa11->fpreg[getFn(opcode)].fDouble =
            int32_to_float64(readRegister(getRd(opcode)), &fpa11->fp_status);
      }
      break;

      case ROUND_EXTENDED:
      {
        fpa11->fType[getFn(opcode)] = typeExtended;
        fpa11->fpreg[getFn(opcode)].fExtended =
	   int32_to_floatx80(readRegister(getRd(opcode)), &fpa11->fp_status);
      }
      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, &fpa11->fp_status));
      }
      break;

      case typeDouble:
      {
         //printf("F%d is 0x%" PRIx64 "\n",Fn,fpa11->fpreg[Fn].fDouble);
         writeRegister(getRd(opcode),
	               float64_to_int32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status));
      }
      break;

      case typeExtended:
      {
         writeRegister(getRd(opcode),
	               floatx80_to_int32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status));
      }
      break;

      default: nRc = 0;
  }

  return nRc;
}


static __inline unsigned int
PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
{
   FPA11 *fpa11 = GET_FPA11();
   unsigned int flags = 0;

   /* test for less than condition */
   if (floatx80_lt(Fn,Fm, &fpa11->fp_status))
   {
      flags |= CC_NEGATIVE;
   }

   /* test for equal condition */
   if (floatx80_eq_quiet(Fn,Fm, &fpa11->fp_status))
   {
      flags |= CC_ZERO;
   }

   /* test for greater than or equal condition */
   if (floatx80_lt(Fm,Fn, &fpa11->fp_status))
   {
      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_any_nan(fpa11->fpreg[Fn].fSingle))
	   goto unordered;
        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
      break;

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

      case typeExtended:
        //printk("extended.\n");
	if (floatx80_is_any_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_any_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_any_nan(fpa11->fpreg[Fm].fSingle))
	      goto unordered;
           rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
         break;

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

         case typeExtended:
           //printk("extended.\n");
	   if (floatx80_is_any_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, &fpa11->fp_status);

   writeConditionCodes(flags);
   return 1;
}
