Commit e1f61725 authored by Stephanie Gawroriski's avatar Stephanie Gawroriski
Browse files

Cherry pick soft math from SummerCoat WIP.

parent 66861fb7
...@@ -28,14 +28,14 @@ public class SoftDouble ...@@ -28,14 +28,14 @@ public class SoftDouble
/** /**
* Adds two values. * Adds two values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double add(int __ah, int __al, int __bh, int __bl) public static double add(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -44,14 +44,14 @@ public class SoftDouble ...@@ -44,14 +44,14 @@ public class SoftDouble
/** /**
* Compares two values. * Compares two values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static int cmpl(int __ah, int __al, int __bh, int __bl) public static int cmpl(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -60,14 +60,14 @@ public class SoftDouble ...@@ -60,14 +60,14 @@ public class SoftDouble
/** /**
* Compares two values. * Compares two values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static int cmpg(int __ah, int __al, int __bh, int __bl) public static int cmpg(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -76,14 +76,14 @@ public class SoftDouble ...@@ -76,14 +76,14 @@ public class SoftDouble
/** /**
* Divides two values. * Divides two values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double div(int __ah, int __al, int __bh, int __bl) public static double div(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -92,14 +92,14 @@ public class SoftDouble ...@@ -92,14 +92,14 @@ public class SoftDouble
/** /**
* Multiplies two values. * Multiplies two values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double mul(int __ah, int __al, int __bh, int __bl) public static double mul(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -108,12 +108,12 @@ public class SoftDouble ...@@ -108,12 +108,12 @@ public class SoftDouble
/** /**
* Negates a value. * Negates a value.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __ah A high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double neg(int __ah, int __al) public static double neg(int __al, int __ah)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -122,29 +122,29 @@ public class SoftDouble ...@@ -122,29 +122,29 @@ public class SoftDouble
/** /**
* ORs value, used for constants. * ORs value, used for constants.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/27 * @since 2019/05/27
*/ */
public static double or(int __ah, int __al, int __bh, int __bl) public static double or(int __al, int __ah, int __bl, int __bh)
{ {
return Assembly.doublePack(__ah | __bh, __al | __bl); return Assembly.doublePack(__al | __bl, __ah | __bh);
} }
/** /**
* Remainders a value. * Remainders a value.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double rem(int __ah, int __al, int __bh, int __bl) public static double rem(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -153,14 +153,14 @@ public class SoftDouble ...@@ -153,14 +153,14 @@ public class SoftDouble
/** /**
* Subtracts values. * Subtracts values.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __bh B high. * @param __ah A high.
* @param __bl B low. * @param __bl B low.
* @param __bh B high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static double sub(int __ah, int __al, int __bh, int __bl) public static double sub(int __al, int __ah, int __bl, int __bh)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -169,12 +169,12 @@ public class SoftDouble ...@@ -169,12 +169,12 @@ public class SoftDouble
/** /**
* Converts to float. * Converts to float.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __ah A high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static float toFloat(int __ah, int __al) public static float toFloat(int __al, int __ah)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -183,12 +183,12 @@ public class SoftDouble ...@@ -183,12 +183,12 @@ public class SoftDouble
/** /**
* Converts to integer. * Converts to integer.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __ah A high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static int toInteger(int __ah, int __al) public static int toInteger(int __al, int __ah)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
...@@ -197,12 +197,12 @@ public class SoftDouble ...@@ -197,12 +197,12 @@ public class SoftDouble
/** /**
* Converts to long. * Converts to long.
* *
* @param __ah A high.
* @param __al A low. * @param __al A low.
* @param __ah A high.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
public static long toLong(int __ah, int __al) public static long toLong(int __al, int __ah)
{ {
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
......
...@@ -9,13 +9,55 @@ ...@@ -9,13 +9,55 @@
package cc.squirreljme.jvm; package cc.squirreljme.jvm;
import cc.squirreljme.runtime.cldc.util.UnsignedInteger;
/** /**
* Software math operations on 32-bit floats. * Software math operations on 32-bit floats.
* *
* This source file uses parts of the Berkeley SoftFloat Release 3e library,
* converted into Java. See the 3rd party licenses documentation.
*
* @since 2019/05/24 * @since 2019/05/24
*/ */
public class SoftFloat @SuppressWarnings({"CommentedOutCode", "MagicNumber"})
public final class SoftFloat
{ {
/** The sign mask. */
public static final int SIGN_MASK =
0b1000_0000_0000_0000__0000_0000_0000_0000;
/** Exponent Mask. */
public static final int EXPONENT_MASK =
0b0111_1111_1000_0000__0000_0000_0000_0000;
/** Fraction Mask. */
public static final int FRACTION_MASK =
0b0000_0000_0111_1111__1111_1111_1111_1111;
/** The mask for NaN values. */
public static final int NAN_MASK =
0b0111_1111_1000_0000__0000_0000_0000_0000;
/** Exponent shift. */
private static final byte _EXP_SHIFT =
23;
/** Default NaN value. */
public static final float FLOAT_DEFAULT_NAN =
Float.intBitsToFloat(0xFFC0_0000);
/** Integer from negative overflow. */
private static final int _INT_FROM_NEGOVER =
-0x7FFFFFFF - 1;
/** Integer from positive overflow. */
private static final int _INT_FROM_POSOVER =
-0x7FFFFFFF - 1;
/** Round near even mode. */
private static final int _ROUND_NEAR_EVEN =
0;
/** /**
* Not used. * Not used.
* *
...@@ -40,31 +82,37 @@ public class SoftFloat ...@@ -40,31 +82,37 @@ public class SoftFloat
} }
/** /**
* Compares two values. * Compares two values, NaN returns {@code -1}.
* *
* @param __a A. * @param __a A.
* @param __b B. * @param __b B.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
@SuppressWarnings("SpellCheckingInspection")
public static int cmpl(int __a, int __b) public static int cmpl(int __a, int __b)
{ {
Assembly.breakpoint(); if (SoftFloat.isNaN(__a) || SoftFloat.isNaN(__b))
throw new todo.TODO(); return -1;
return SoftFloat.__cmp(__a, __b);
} }
/** /**
* Compares two values. * Compares two values, NaN returns {@code 1}.
* *
* @param __a A. * @param __a A.
* @param __b B. * @param __b B.
* @return The result. * @return The result.
* @since 2019/05/24 * @since 2019/05/24
*/ */
@SuppressWarnings("SpellCheckingInspection")
public static int cmpg(int __a, int __b) public static int cmpg(int __a, int __b)
{ {
Assembly.breakpoint(); if (SoftFloat.isNaN(__a) || SoftFloat.isNaN(__b))
throw new todo.TODO(); return 1;
return SoftFloat.__cmp(__a, __b);
} }
/** /**
...@@ -81,6 +129,18 @@ public class SoftFloat ...@@ -81,6 +129,18 @@ public class SoftFloat
throw new todo.TODO(); throw new todo.TODO();
} }
/**
* Is this Not a Number?
*
* @param __a The value to check.
* @return If this is not a number.
* @since 2021/04/07
*/
public static boolean isNaN(int __a)
{
return SoftFloat.NAN_MASK == (__a & SoftFloat.NAN_MASK);
}
/** /**
* Multiplies two values. * Multiplies two values.
* *
...@@ -91,8 +151,97 @@ public class SoftFloat ...@@ -91,8 +151,97 @@ public class SoftFloat
*/ */
public static float mul(int __a, int __b) public static float mul(int __a, int __b)
{ {
Assembly.breakpoint(); // First value
throw new todo.TODO(); boolean signA = SoftFloat.__signF32UI(__a);
int expA = SoftFloat.__expF32UI(__a);
int sigA = SoftFloat.__fracF32UI(__a);
// Second value
boolean signB = SoftFloat.__signF32UI(__b);
int expB = SoftFloat.__expF32UI(__b);
int sigB = SoftFloat.__fracF32UI(__b);
// Will this result in a negative value?
boolean signZ = signA ^ signB;
boolean returnInfinite = false;
int magBits = 0;
if (expA == 0xFF)
{
// if ( sigA || ((expB == 0xFF) && sigB) )
if (sigA != 0 || ((expB == 0xFF) && (sigB != 0)))
return Float.intBitsToFloat(
SoftFloat.__propagateNaNF32UI(__a, __b));
magBits = expB | sigB;
returnInfinite = true;
}
if (!returnInfinite && expB == 0xFF)
{
// if ( sigB )
if (sigB != 0)
return Float.intBitsToFloat(
SoftFloat.__propagateNaNF32UI(__a, __b));
magBits = expA | sigA;
returnInfinite = true;
}
// Returning infinite value?
if (returnInfinite)
{
// if ( ! magBits )
if (magBits == 0)
return SoftFloat.FLOAT_DEFAULT_NAN;
return Float.intBitsToFloat(
SoftFloat.__packToF32UI(signZ, 0xFF, 0));
}
// if ( ! expA )
if (expA == 0)
{
// if ( ! sigA )
if (sigA == 0)
return Float.intBitsToFloat(
SoftFloat.__packToF32UI(signZ, 0, 0));
long normExpSig = SoftFloat.__normSubnormalF32Sig(sigA);
expA = (short)Assembly.longUnpackHigh(normExpSig);
sigA = Assembly.longUnpackLow(normExpSig);
}
// if ( ! expB )
if (expB == 0)
{
// if ( ! sigB )
if (sigB == 0)
return Float.intBitsToFloat(
SoftFloat.__packToF32UI(signZ, 0, 0));
long normExpSig = SoftFloat.__normSubnormalF32Sig(sigB);
expB = (short)Assembly.longUnpackHigh(normExpSig);
sigB = Assembly.longUnpackLow(normExpSig);
}
int expZ = (short)(expA + expB - 0x7F);
sigA = (sigA | 0x0080_0000) << 7;
sigB = (sigB | 0x0080_0000) << 8;
// sigZ = softfloat_shortShiftRightJam64(
// (uint_fast64_t)sigA * sigB, 32); <-- unsigned multiply
int sigZ = (int)SoftFloat.__shortShiftRightJam64(
(sigA & 0xFFFF_FFFFL) * (sigB & 0xFFFF_FFFFL), 32);
// if ( sigZ < 0x40000000 )
if (UnsignedInteger.compareUnsigned(sigZ, 0x4000_0000) < 0)
{
expZ = (short)(expZ - 1);
sigZ <<= 1;
}
return Float.intBitsToFloat(
SoftFloat.__roundPackToF32(signZ, expZ, sigZ));
} }
/** /**
...@@ -171,8 +320,21 @@ public class SoftFloat ...@@ -171,8 +320,21 @@ public class SoftFloat
*/ */
public static int toInteger(int __a) public static int toInteger(int __a)
{ {
Assembly.breakpoint(); boolean sign = SoftFloat.__signF32UI(__a);
throw new todo.TODO(); int exp = SoftFloat.__expF32UI(__a);
int sig = SoftFloat.__fracF32UI(__a);
if (exp != 0)
sig |= 0x0080_0000;
// sig64 = (uint_fast64_t) sig<<32;
long sig64 = Assembly.longPack(0, sig);
int shiftDist = 0xAA - exp;
if (UnsignedInteger.compareUnsigned(0, shiftDist) < 0)
sig64 = SoftFloat.__shiftRightJam64(sig64, shiftDist);
return SoftFloat.__roundToI32(sign, sig64);
} }
/** /**
...@@ -187,5 +349,353 @@ public class SoftFloat ...@@ -187,5 +349,353 @@ public class SoftFloat
Assembly.breakpoint(); Assembly.breakpoint();
throw new todo.TODO(); throw new todo.TODO();
} }
}
/**
* Compares two values.
*
* @param __a A.
* @param __b B.
* @return The result.