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 classpath = classpath
test = test test = test
input = $(cls)/GC.class input = $(cls)/Floats.class
cxx = g++ cxx = g++
cc = gcc cc = gcc

View File

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

View File

@ -196,6 +196,34 @@ hash(const uint16_t* s, unsigned length)
return h; 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 Machine;
class Thread; 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 int64_t
divideLong(MyThread*, int64_t a, int64_t b) divideLong(int64_t b, int64_t a)
{ {
return a / b; return a / b;
} }
int64_t int64_t
moduloLong(MyThread*, int64_t a, int64_t b) moduloLong(int64_t b, int64_t a)
{ {
return a % b; return a % b;
} }
@ -2550,11 +2678,241 @@ class JavaCompiler: public Compiler {
next.mark(); next.mark();
} break; } 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: case dup:
push(rsp, 0); push(rsp, 0);
stackMapper.dupped(); stackMapper.dupped();
break; 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: { case getfield: {
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
@ -3222,22 +3580,27 @@ class JavaCompiler: public Compiler {
break; break;
case lload: case lload:
case dload:
loadLong(codeBody(t, code, ip++)); loadLong(codeBody(t, code, ip++));
break; break;
case lload_0: case lload_0:
case dload_0:
loadLong(0); loadLong(0);
break; break;
case lload_1: case lload_1:
case dload_1:
loadLong(1); loadLong(1);
break; break;
case lload_2: case lload_2:
case dload_2:
loadLong(2); loadLong(2);
break; break;
case lload_3: case lload_3:
case dload_3:
loadLong(3); loadLong(3);
break; break;
@ -3293,23 +3656,41 @@ class JavaCompiler: public Compiler {
} }
break; 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 lstore:
case dstore:
storeLong(codeBody(t, code, ip++)); storeLong(codeBody(t, code, ip++));
break; break;
case lstore_0: case lstore_0:
case dstore_0:
storeLong(0); storeLong(0);
break; break;
case lstore_1: case lstore_1:
case dstore_1:
storeLong(1); storeLong(1);
break; break;
case lstore_2: case lstore_2:
case dstore_2:
storeLong(2); storeLong(2);
break; break;
case lstore_3: case lstore_3:
case dstore_3:
storeLong(3); storeLong(3);
break; break;

View File

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

View File

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

View File

@ -3,18 +3,34 @@ public class Floats {
if (! v) throw new RuntimeException(); 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) { public static void main(String[] args) {
expect(0.5d * 0.5d == 0.25d); expect(multiply(0.5d, 0.5d) == 0.25d);
expect(0.5f * 0.5f == 0.25f); expect(multiply(0.5f, 0.5f) == 0.25f);
expect(0.5d * 0.5d < 0.5d); expect(multiply(0.5d, 0.5d) < 0.5d);
expect(0.5f * 0.5f < 0.5f); expect(multiply(0.5f, 0.5f) < 0.5f);
expect(0.5d * 0.5d > 0.1d); expect(multiply(0.5d, 0.5d) > 0.1d);
expect(0.5f * 0.5f > 0.1f); 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);
} }
} }