mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-24 13:32:39 +00:00
Squashed commit of the following:
commit 13b5c532e1b72b7d3737c451a519af749d25c61f Author: Kelvin Sherlock <ksherlock@gmail.com> Date: Tue Jan 6 17:46:00 2015 -0500 add fclassify sane ops. commit 374aa6cc90218d8f86843cf5eecbf3095fe59a5e Author: Kelvin Sherlock <ksherlock@gmail.com> Date: Tue Jan 6 16:55:16 2015 -0500 proc entry / proc exit stubs and updated environment documentation
This commit is contained in:
parent
2bb2bd4326
commit
45c89042ee
198
toolbox/sane.cpp
198
toolbox/sane.cpp
@ -48,8 +48,55 @@ using std::to_string;
|
||||
|
||||
|
||||
namespace {
|
||||
// default environment is:
|
||||
// rounding direction: to nearest
|
||||
// rounding precision: extended
|
||||
// exception flags: clear
|
||||
// halts: clear
|
||||
|
||||
/*
|
||||
* Environment: x d d e e e e e x p p h h h h h
|
||||
* x - reserved
|
||||
* d d - rounding direction
|
||||
* e - exception flags
|
||||
* p - rounding precision
|
||||
* h - halt flags
|
||||
*/
|
||||
|
||||
enum {
|
||||
|
||||
kExceptionInexact = 1 << 12,
|
||||
kExceptionDivideByZero = 1 << 11,
|
||||
kExceptionOverflow = 1 << 10,
|
||||
kExceptionUnderflow = 1 << 9,
|
||||
kExceptionInvalid = 1 << 8,
|
||||
|
||||
kHaltInexact = 1 << 4,
|
||||
kHaltDivideByZero = 1 << 3,
|
||||
kHaltOverflow = 1 << 2,
|
||||
kHaltUnderflow = 1 << 1,
|
||||
kHaltInvalid = 1 << 0,
|
||||
|
||||
kRoundingDirectionMask = 0x6000,
|
||||
kRoundingDirectionToNearest = 0x0000,
|
||||
kRoundingDirectionUpward = 0x2000,
|
||||
kRoundingDirectionDownward = 0x4000,
|
||||
kRoundingDirectionTowardZero = 0x6000,
|
||||
|
||||
kRoundingPrecisionMask = 0x0060,
|
||||
kRoundingPrecisionExtended = 0x0000,
|
||||
kRoundingPrecisionDouble = 0x0020,
|
||||
kRoundingPrecisionSingle = 0x0040,
|
||||
kRoundingPrecisionUndefined = 0x0060,
|
||||
};
|
||||
|
||||
|
||||
const uint16_t DefaultEnvironment = 0;
|
||||
|
||||
uint16_t Environment = DefaultEnvironment;
|
||||
|
||||
|
||||
|
||||
uint16_t Environment = 0;
|
||||
}
|
||||
|
||||
// long double is an 80-bit extended with an extra 48-bits of 0 padding.
|
||||
@ -672,8 +719,113 @@ using std::to_string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int classify(float x) { return fpclassify(x); }
|
||||
inline int classify(double x) { return fpclassify(x); }
|
||||
inline int classify(extended x) { return fpclassify(x); }
|
||||
inline int classify(complex c) {
|
||||
if (c.isnan()) return FP_NAN;
|
||||
if ((uint64_t)c == (uint64_t)0) return FP_ZERO;
|
||||
return FP_NORMAL;
|
||||
}
|
||||
|
||||
inline int sign(float x) { return signbit(x); }
|
||||
inline int sign(double x) { return signbit(x); }
|
||||
inline int sign(extended x) { return signbit(x); }
|
||||
inline int sign(complex c) {
|
||||
if (c.isnan()) return 0;
|
||||
return ((int64_t)c < (int64_t)0) ? 1 : 0;
|
||||
}
|
||||
|
||||
template <class SrcType>
|
||||
uint16_t fclassify(const char *name)
|
||||
{
|
||||
/*
|
||||
* The classify operations set the sign of the destination to
|
||||
* the sign of the source and the value of the destination
|
||||
* according to the class of the source, as shown in Table E-18.
|
||||
* The destination is an integer variable. (pg 273)
|
||||
*
|
||||
*
|
||||
* Table E-18
|
||||
* Class Information
|
||||
* ----------------------
|
||||
* Class of SRC Value
|
||||
* ----------------------
|
||||
* Signaling NaN 1
|
||||
* Quiet NaN 2
|
||||
* Infinity 3
|
||||
* Zero 4
|
||||
* Normalized 5
|
||||
* Denormalized 6
|
||||
*
|
||||
* Table E-19
|
||||
* ---------------------------
|
||||
* Sign of SRC Sign of DST
|
||||
* ---------------------------
|
||||
* Positive Positive
|
||||
* Negative Negative
|
||||
*/
|
||||
|
||||
// N.B. - Sane.h uses 0-5, but how can you have integer -0?
|
||||
uint16_t op;
|
||||
uint32_t dest;
|
||||
uint32_t src;
|
||||
|
||||
StackFrame<10>(src, dest, op);
|
||||
Log(" %s(%08x, %08x, %04x)\n", name, src, dest, op);
|
||||
|
||||
SrcType s = readnum<SrcType>(src);
|
||||
|
||||
if (ToolBox::Trace)
|
||||
{
|
||||
std::string tmp1 = to_string(s);
|
||||
Log(" %s\n", tmp1.c_str());
|
||||
}
|
||||
|
||||
|
||||
int16_t klass = 0;
|
||||
|
||||
switch(classify(s))
|
||||
{
|
||||
case FP_INFINITE:
|
||||
klass = 3;
|
||||
break;
|
||||
case FP_NAN:
|
||||
// todo -- signaling NaN is indicated
|
||||
// by the MSB of the fraction field f
|
||||
// 1 is quiet, 0 is signaling.
|
||||
klass = 1;
|
||||
break;
|
||||
case FP_NORMAL:
|
||||
klass = 5;
|
||||
break;
|
||||
case FP_SUBNORMAL:
|
||||
klass = 6;
|
||||
break;
|
||||
case FP_ZERO:
|
||||
klass = 4;
|
||||
break;
|
||||
|
||||
}
|
||||
if (sign(s)) klass = -klass;
|
||||
|
||||
if (dest) {
|
||||
memoryWriteWord(klass, dest);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma mark - environment
|
||||
|
||||
/*
|
||||
* environment is a uint16_t *.
|
||||
* void setenvironment(environment e);
|
||||
* void getenvironment(environment *e);
|
||||
* void procentry(environment *e);
|
||||
* void procexit(environment e);
|
||||
*/
|
||||
|
||||
uint16_t fgetenv(void)
|
||||
{
|
||||
uint32_t address;
|
||||
@ -686,23 +838,52 @@ using std::to_string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint16_t fsetenv(void)
|
||||
{
|
||||
uint32_t address;
|
||||
uint16_t value;
|
||||
uint16_t op;
|
||||
|
||||
StackFrame<6>(address, op);
|
||||
value = address ? memoryReadWord(address) : DefaultEnvironment;
|
||||
Log(" FSETENV(%08x (%04x))\n", address, value);
|
||||
|
||||
Environment = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t fprocentry(void)
|
||||
{
|
||||
uint32_t address;
|
||||
uint16_t op;
|
||||
|
||||
StackFrame<6>(address, op);
|
||||
|
||||
Log(" FPROCENTRY(%08x)\n", address);
|
||||
|
||||
if (address) memoryWriteWord(Environment, address);
|
||||
Environment = DefaultEnvironment;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t fprocexit(void)
|
||||
{
|
||||
uint32_t address;
|
||||
uint16_t value;
|
||||
uint16_t op;
|
||||
|
||||
|
||||
StackFrame<6>(address, op);
|
||||
value = memoryReadWord(address);
|
||||
Log(" FSETENV(%08x (%04x))\n", address, value);
|
||||
value = address ? memoryReadWord(address) : DefaultEnvironment;
|
||||
Log(" FPROCEXIT(%08x (%04x))\n", address, value);
|
||||
|
||||
// todo -- also should signal exceptions/halts at this point.
|
||||
Environment = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" void cpuSetFlagsAbs(UWO f);
|
||||
uint16_t fp68k(uint16_t trap)
|
||||
{
|
||||
@ -785,12 +966,19 @@ using std::to_string;
|
||||
case 0x280e: return fconvert<int32_t, extended>("FL2X");
|
||||
|
||||
|
||||
case 0x001c: return fclassify<extended>("FCLASSX");
|
||||
case 0x081c: return fclassify<double>("FCLASSD");
|
||||
case 0x101c: return fclassify<float>("FCLASSS");
|
||||
case 0x301c: return fclassify<complex>("FCLASSC");
|
||||
|
||||
case 0x0009:
|
||||
// fdec2x
|
||||
return fdecimal<extended>("FDEC2X");
|
||||
break;
|
||||
|
||||
|
||||
case 0x0017: return fprocentry();
|
||||
case 0x0019: return fprocexit();
|
||||
case 0x0003: return fgetenv();
|
||||
case 0x0001: return fsetenv();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user