implement various floating point instructions; fix Floats.java to actually test something

This commit is contained in:
Joel Dice 2007-10-15 13:12:38 -06:00
parent 659555b6ce
commit 5f6258045e
7 changed files with 468 additions and 47 deletions

View File

@ -34,7 +34,7 @@ src = src
classpath = classpath
test = test
input = $(cls)/GC.class
input = $(cls)/Floats.class
cxx = g++
cc = gcc

View File

@ -374,29 +374,25 @@ Java_java_lang_reflect_Array_makeObjectArray
extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Float_floatToRawIntBits(Thread*, jclass, jfloat v)
{
int32_t r; memcpy(&r, &v, 4);
return r;
return floatToBits(v);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_java_lang_Float_intBitsToFloat(Thread*, jclass, jint v)
{
jfloat r; memcpy(&r, &v, 4);
return r;
return bitsToFloat(v);
}
extern "C" JNIEXPORT jlong JNICALL
Java_java_lang_Double_doubleToRawLongBits(Thread*, jclass, jdouble v)
{
int64_t r; memcpy(&r, &v, 8);
return r;
return doubleToBits(v);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Double_longBitsToDouble(Thread*, jclass, jlong v)
{
jdouble r; memcpy(&r, &v, 8);
return r;
return bitsToDouble(v);
}
extern "C" JNIEXPORT jobject JNICALL

View File

@ -196,6 +196,34 @@ hash(const uint16_t* s, unsigned length)
return h;
}
inline uint32_t
floatToBits(float f)
{
int32_t bits; memcpy(&bits, &f, 4);
return bits;
}
inline uint64_t
doubleToBits(double d)
{
int64_t bits; memcpy(&bits, &d, 8);
return bits;
}
inline double
bitsToDouble(uint64_t bits)
{
double d; memcpy(&d, &bits, 8);
return d;
}
inline float
bitsToFloat(uint32_t bits)
{
float f; memcpy(&f, &bits, 4);
return f;
}
class Machine;
class Thread;

View File

@ -980,14 +980,142 @@ visitStack(MyThread* t, Heap::Visitor* v)
}
}
intptr_t
compareDoublesG(uint64_t bi, uint64_t ai)
{
double a = bitsToDouble(ai);
double b = bitsToDouble(bi);
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else {
return 1;
}
}
intptr_t
compareDoublesL(uint64_t bi, uint64_t ai)
{
double a = bitsToDouble(ai);
double b = bitsToDouble(bi);
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else {
return -1;
}
}
intptr_t
compareFloatsG(uint32_t bi, uint32_t ai)
{
float a = bitsToFloat(ai);
float b = bitsToFloat(bi);
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else {
return 1;
}
}
intptr_t
compareFloatsL(uint32_t bi, uint32_t ai)
{
float a = bitsToFloat(ai);
float b = bitsToFloat(bi);
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else {
return -1;
}
}
uint64_t
addDouble(uint64_t b, uint64_t a)
{
return doubleToBits(bitsToDouble(a) + bitsToDouble(b));
}
uint64_t
subtractDouble(uint64_t b, uint64_t a)
{
return doubleToBits(bitsToDouble(a) - bitsToDouble(b));
}
uint64_t
multiplyDouble(uint64_t b, uint64_t a)
{
return doubleToBits(bitsToDouble(a) * bitsToDouble(b));
}
uint64_t
divideDouble(uint64_t b, uint64_t a)
{
return doubleToBits(bitsToDouble(a) / bitsToDouble(b));
}
uint64_t
moduloDouble(uint64_t b, uint64_t a)
{
return doubleToBits(fmod(bitsToDouble(a), bitsToDouble(b)));
}
uint32_t
addFloat(uint32_t b, uint32_t a)
{
return floatToBits(bitsToFloat(a) + bitsToFloat(b));
}
uint32_t
subtractFloat(uint32_t b, uint32_t a)
{
return floatToBits(bitsToFloat(a) - bitsToFloat(b));
}
uint32_t
multiplyFloat(uint32_t b, uint32_t a)
{
return floatToBits(bitsToFloat(a) * bitsToFloat(b));
}
uint32_t
divideFloat(uint32_t b, uint32_t a)
{
return floatToBits(bitsToFloat(a) / bitsToFloat(b));
}
uint32_t
moduloFloat(uint32_t b, uint32_t a)
{
return floatToBits(fmod(bitsToFloat(a), bitsToFloat(b)));
}
int64_t
divideLong(MyThread*, int64_t a, int64_t b)
divideLong(int64_t b, int64_t a)
{
return a / b;
}
int64_t
moduloLong(MyThread*, int64_t a, int64_t b)
moduloLong(int64_t b, int64_t a)
{
return a % b;
}
@ -2550,11 +2678,241 @@ class JavaCompiler: public Compiler {
next.mark();
} break;
case dadd: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(addDouble));
pushLong(rax);
} else {
directCall(reinterpret_cast<void*>(addDouble));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushLong(rax, rdx);
}
} break;
case dcmpg: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(compareDoublesG));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(compareDoublesG));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushInt(rax);
}
} break;
case dcmpl: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(compareDoublesL));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(compareDoublesL));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushInt(rax);
}
} break;
case dconst_0: {
pushLong(doubleToBits(0.0));
} break;
case dconst_1: {
pushLong(doubleToBits(1.0));
} break;
case ddiv: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(divideDouble));
pushLong(rax);
} else {
directCall(reinterpret_cast<void*>(divideDouble));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushLong(rax, rdx);
}
} break;
case dmul: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(multiplyDouble));
pushLong(rax);
} else {
directCall(reinterpret_cast<void*>(multiplyDouble));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushLong(rax, rdx);
}
} break;
case vm::drem: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(moduloDouble));
pushLong(rax);
} else {
directCall(reinterpret_cast<void*>(moduloDouble));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushLong(rax, rdx);
}
} break;
case dsub: {
if (BytesPerWord == 8) {
popLong(rdi);
popLong(rsi);
directCall(reinterpret_cast<void*>(subtractDouble));
pushLong(rax);
} else {
directCall(reinterpret_cast<void*>(subtractDouble));
add(BytesPerWord * 4, rsp);
stackMapper.poppedLong();
stackMapper.poppedLong();
pushLong(rax, rdx);
}
} break;
case dup:
push(rsp, 0);
stackMapper.dupped();
break;
case fadd: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(addFloat));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(addFloat));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case fcmpg: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(compareFloatsG));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(compareFloatsG));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case fcmpl: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(compareFloatsL));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(compareFloatsL));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case fconst_0: {
pushInt(floatToBits(0.0));
} break;
case fconst_1: {
pushInt(floatToBits(1.0));
} break;
case fconst_2: {
pushInt(floatToBits(2.0));
} break;
case fdiv: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(divideFloat));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(divideFloat));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case fmul: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(multiplyFloat));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(multiplyFloat));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case frem: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(moduloFloat));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(moduloFloat));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case fsub: {
if (BytesPerWord == 8) {
popInt(rdi);
popInt(rsi);
directCall(reinterpret_cast<void*>(subtractFloat));
pushInt(rax);
} else {
directCall(reinterpret_cast<void*>(subtractFloat));
add(BytesPerWord * 2, rsp);
stackMapper.poppedInt();
stackMapper.poppedInt();
pushInt(rax);
}
} break;
case getfield: {
uint16_t index = codeReadInt16(t, code, ip);
@ -3222,22 +3580,27 @@ class JavaCompiler: public Compiler {
break;
case lload:
case dload:
loadLong(codeBody(t, code, ip++));
break;
case lload_0:
case dload_0:
loadLong(0);
break;
case lload_1:
case dload_1:
loadLong(1);
break;
case lload_2:
case dload_2:
loadLong(2);
break;
case lload_3:
case dload_3:
loadLong(3);
break;
@ -3293,23 +3656,41 @@ class JavaCompiler: public Compiler {
}
break;
case lreturn:
case dreturn:
if (BytesPerWord == 8) {
popLong(rax);
} else {
popLong(rax, rdx);
}
mov(rbp, rsp);
pop(rbp);
ret();
stackMapper.exited();
break;
case lstore:
case dstore:
storeLong(codeBody(t, code, ip++));
break;
case lstore_0:
case dstore_0:
storeLong(0);
break;
case lstore_1:
case dstore_1:
storeLong(1);
break;
case lstore_2:
case dstore_2:
storeLong(2);
break;
case lstore_3:
case dstore_3:
storeLong(3);
break;

View File

@ -64,8 +64,7 @@ pushInt(Thread* t, uint32_t v)
inline void
pushFloat(Thread* t, float v)
{
uint32_t a; memcpy(&a, &v, sizeof(uint32_t));
pushInt(t, a);
pushInt(t, floatToBits(v));
}
inline void
@ -82,8 +81,7 @@ pushLong(Thread* t, uint64_t v)
inline void
pushDouble(Thread* t, double v)
{
uint64_t a; memcpy(&a, &v, sizeof(uint64_t));
pushLong(t, a);
pushLong(t, doubleToBits(v));
}
inline object
@ -115,9 +113,7 @@ popInt(Thread* t)
inline float
popFloat(Thread* t)
{
uint32_t a = popInt(t);
float f; memcpy(&f, &a, sizeof(float));
return f;
return bitsToFloat(popInt(t));
}
inline uint64_t
@ -138,9 +134,7 @@ popLong(Thread* t)
inline float
popDouble(Thread* t)
{
uint64_t a = popLong(t);
double d; memcpy(&d, &a, sizeof(double));
return d;
return bitsToDouble(popLong(t));
}
inline object
@ -1072,9 +1066,7 @@ interpret(Thread* t)
if (LIKELY(index >= 0 and
static_cast<uintptr_t>(index) < doubleArrayLength(t, array)))
{
double d;
memcpy(&d, &doubleArrayBody(t, array, index), sizeof(double));
pushDouble(t, d);
pushLong(t, doubleArrayBody(t, array, index));
} else {
object message = makeString(t, "%d not in [0,%d)", index,
doubleArrayLength(t, array));
@ -1113,14 +1105,30 @@ interpret(Thread* t)
double b = popDouble(t);
double a = popDouble(t);
pushInt(t, (a > b ? 1 : 0));
if (a < b) {
pushInt(t, static_cast<unsigned>(-1));
} else if (a > b) {
pushInt(t, 1);
} else if (a == b) {
pushInt(t, 0);
} else {
pushInt(t, 1);
}
} goto loop;
case dcmpl: {
double b = popDouble(t);
double a = popDouble(t);
pushInt(t, (a < b ? 1 : 0));
if (a < b) {
pushInt(t, static_cast<unsigned>(-1));
} else if (a > b) {
pushInt(t, 1);
} else if (a == b) {
pushInt(t, 0);
} else {
pushInt(t, static_cast<unsigned>(-1));
}
} goto loop;
case dconst_0: {
@ -1258,8 +1266,7 @@ interpret(Thread* t)
if (LIKELY(index >= 0 and
static_cast<uintptr_t>(index) < floatArrayLength(t, array)))
{
float f; memcpy(&f, &floatArrayBody(t, array, index), sizeof(float));
pushFloat(t, f);
pushInt(t, floatArrayBody(t, array, index));
} else {
object message = makeString(t, "%d not in [0,%d)", index,
floatArrayLength(t, array));
@ -1467,15 +1474,11 @@ interpret(Thread* t)
} goto loop;
case i2d: {
double f = static_cast<double>(popInt(t));
int64_t i; memcpy(&i, &f, 8);
pushLong(t, i);
pushDouble(t, static_cast<double>(popInt(t)));
} goto loop;
case i2f: {
float f = static_cast<float>(popInt(t));
int32_t i; memcpy(&i, &f, 4);
pushInt(t, i);
pushFloat(t, static_cast<float>(popInt(t)));
} goto loop;
case i2l: {
@ -2689,10 +2692,7 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
case 'F': {
++ s;
float f = va_arg(a, double);
uint32_t i;
memcpy(&i, &f, 4);
pushInt(t, i);
pushFloat(t, va_arg(a, double));
} break;
default:

View File

@ -531,7 +531,7 @@ parsePool(Thread* t, Stream& s)
} break;
case CONSTANT_Double: {
object value = makeLong(t, s.readDouble());
object value = makeDouble(t, s.readDouble());
set(t, arrayBody(t, pool, i), value);
++i;
} break;

View File

@ -3,18 +3,34 @@ public class Floats {
if (! v) throw new RuntimeException();
}
private static double multiply(double a, double b) {
return a * b;
}
private static float multiply(float a, float b) {
return a * b;
}
private static double divide(double a, double b) {
return a / b;
}
private static double subtract(double a, double b) {
return a - b;
}
public static void main(String[] args) {
expect(0.5d * 0.5d == 0.25d);
expect(0.5f * 0.5f == 0.25f);
expect(multiply(0.5d, 0.5d) == 0.25d);
expect(multiply(0.5f, 0.5f) == 0.25f);
expect(0.5d * 0.5d < 0.5d);
expect(0.5f * 0.5f < 0.5f);
expect(multiply(0.5d, 0.5d) < 0.5d);
expect(multiply(0.5f, 0.5f) < 0.5f);
expect(0.5d * 0.5d > 0.1d);
expect(0.5f * 0.5f > 0.1f);
expect(multiply(0.5d, 0.5d) > 0.1d);
expect(multiply(0.5f, 0.5f) > 0.1f);
expect(0.5d / 0.5d == 1.0d);
expect(divide(0.5d, 0.5d) == 1.0d);
expect(0.5d - 0.5d == 0.0d);
expect(subtract(0.5d, 0.5d) == 0.0d);
}
}