nestopia/source/core/NstCore.cpp
2013-01-14 16:40:40 -05:00

176 lines
4.1 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia 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.
//
// Nestopia 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 Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#include "NstCore.hpp"
#if NST_MSVC
#if (defined(_DEBUG) && defined(NDEBUG)) || (!defined(_DEBUG) && !defined(NDEBUG))
#pragma message("warning, NDEBUG and _DEBUG macro inconsistency!")
#endif
#if !defined(_DEBUG) && defined(__MSVC_RUNTIME_CHECKS)
#pragma message("performance warning, RTCx compiler options enabled in non-debug mode!")
#endif
#ifdef _CPPRTTI
#pragma message("performance warning, RTTI compiler option needlessly enabled!")
#endif
#endif
#ifndef NST_NATIVE_QWORD
#if NST_MSVC || NST_MWERKS >= 0x3000 || NST_BCB >= 0x600
#pragma message("performance warning, no native 64bit integer support!")
#elif NST_GCC && !defined(__STRICT_ANSI__)
#warning "performance warning, no native 64bit integer support!"
#endif
#include "NstAssert.hpp"
namespace Nes
{
void qaword::Multiply(qaword multiplier)
{
qaword multiplicand(*this);
lo = 0;
hi = 0;
while (multiplicand)
{
if (multiplicand.lo & 0x1)
(*this) += multiplier;
multiplicand.lo = (multiplicand.lo >> 1) | (multiplicand.hi << 31 & LO_MASK);
multiplicand.hi >>= 1;
multiplier.hi = (multiplier.hi << 1 & LO_MASK) | (multiplier.lo >> 31);
multiplier.lo = (multiplier.lo << 1 & LO_MASK);
}
}
void qaword::Divide(qaword& dividend,const qaword divisor,const bool mod)
{
NST_ASSERT( bool(divisor) );
qaword remainder(0);
qaword quotient(0);
if (divisor < dividend)
{
uint bits = 64;
do
{
remainder.hi = (remainder.hi << 1 & LO_MASK) | (remainder.lo >> 31);
remainder.lo = (remainder.lo << 1 & LO_MASK) | (dividend.hi >> 31);
dividend.hi = (dividend.hi << 1 & LO_MASK) | (dividend.lo >> 31);
dividend.lo = (dividend.lo << 1 & LO_MASK);
--bits;
}
while (remainder < divisor);
for (;;)
{
qaword tmp(remainder);
tmp -= divisor;
quotient.hi = (quotient.hi << 1 & LO_MASK) | (quotient.lo >> 31);
quotient.lo = (quotient.lo << 1 & LO_MASK);
if (!(tmp.hi & LO_MSB))
{
quotient.lo |= 0x1;
remainder = tmp;
}
if (!bits)
break;
--bits;
remainder.hi = (remainder.hi << 1 & LO_MASK) | (remainder.lo >> 31);
remainder.lo = (remainder.lo << 1 & LO_MASK) | (dividend.hi >> 31);
dividend.hi = (dividend.hi << 1 & LO_MASK) | (dividend.lo >> 31);
dividend.lo = (dividend.lo << 1 & LO_MASK);
}
}
else if (divisor == dividend)
{
quotient = 1;
}
else
{
remainder = dividend;
}
if (!mod)
dividend = quotient;
else
dividend = remainder;
}
void qaword::Shl(const uint v)
{
NST_ASSERT( v < 64 );
if (v)
{
if (v < 32)
{
dword t = lo >> (32-v);
lo = (lo << v) & LO_MASK;
hi = (hi << v | t) & LO_MASK;
}
else
{
hi = (lo << (v-32)) & LO_MASK;
lo = 0;
}
}
}
void qaword::Shr(const uint v)
{
NST_ASSERT( v < 64 );
if (v)
{
if (v < 32)
{
dword t = (hi << (32-v)) & LO_MASK;
hi = hi >> v;
lo = lo >> v | t;
}
else
{
lo = hi >> (v-32);
hi = 0;
}
}
}
}
#endif