From 89609e11c92554f49b11a1b04505c8ac0ee35d33 Mon Sep 17 00:00:00 2001 From: Joel Dice <git@seibutsu.mailsnare.net> Date: Mon, 13 Aug 2007 08:06:31 -0600 Subject: [PATCH] implement floating point instructions --- makefile | 2 +- src/common.h | 1 + src/machine.h | 30 +++++ src/run.cpp | 309 +++++++++++++++++++++++++++++++++++++++++++---- src/stream.h | 8 +- test/Floats.java | 20 +++ 6 files changed, 341 insertions(+), 29 deletions(-) create mode 100644 test/Floats.java diff --git a/makefile b/makefile index 3a00ff670f..00f638df37 100644 --- a/makefile +++ b/makefile @@ -46,7 +46,7 @@ ifeq ($(mode),fast) cflags += -Os -DNDEBUG -DMONOLITHIC endif -lflags = $(thread-lflags) -ldl +lflags = $(thread-lflags) -ldl -lm cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x))) diff --git a/src/common.h b/src/common.h index 5d4c04df45..b2f5e177a6 100644 --- a/src/common.h +++ b/src/common.h @@ -7,6 +7,7 @@ #include "string.h" #include "stdio.h" #include "types.h" +#include "math.h" #ifdef __i386__ # define LD "%d" diff --git a/src/machine.h b/src/machine.h index 7573a96487..84cf0a351a 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1589,6 +1589,13 @@ pushInt(Thread* t, uint32_t v) ++ t->sp; } +inline void +pushFloat(Thread* t, float v) +{ + uint32_t a; memcpy(&a, &v, sizeof(uint32_t)); + pushInt(t, a); +} + inline void pushLong(Thread* t, uint64_t v) { @@ -1600,6 +1607,13 @@ pushLong(Thread* t, uint64_t v) pushInt(t, v & 0xFFFFFFFF); } +inline void +pushDouble(Thread* t, double v) +{ + uint64_t a; memcpy(&a, &v, sizeof(uint64_t)); + pushLong(t, a); +} + inline object popObject(Thread* t) { @@ -1626,6 +1640,14 @@ popInt(Thread* t) return t->stack[((-- t->sp) * 2) + 1]; } +inline float +popFloat(Thread* t) +{ + uint32_t a = popInt(t); + float f; memcpy(&f, &a, sizeof(float)); + return f; +} + inline uint64_t popLong(Thread* t) { @@ -1641,6 +1663,14 @@ popLong(Thread* t) return (b << 32) | a; } +inline float +popDouble(Thread* t) +{ + uint64_t a = popLong(t); + double d; memcpy(&d, &a, sizeof(double)); + return d; +} + inline object peekObject(Thread* t, unsigned index) { diff --git a/src/run.cpp b/src/run.cpp index 2fd7d2d062..399f6a818b 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -837,6 +837,126 @@ run(Thread* t) } } goto loop; + case d2f: { + pushFloat(t, static_cast<float>(popDouble(t))); + } goto loop; + + case d2i: { + pushInt(t, static_cast<int32_t>(popDouble(t))); + } goto loop; + + case d2l: { + pushLong(t, static_cast<int64_t>(popDouble(t))); + } goto loop; + + case dadd: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a + b); + } goto loop; + + case daload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + 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); + } else { + object message = makeString(t, "%d not in [0,%d]", index, + doubleArrayLength(t, array)); + exception = makeArrayIndexOutOfBoundsException(t, message); + goto throw_; + } + } else { + exception = makeNullPointerException(t); + goto throw_; + } + } goto loop; + + case dastore: { + double value = popDouble(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (LIKELY(index >= 0 and + static_cast<uintptr_t>(index) < doubleArrayLength(t, array))) + { + memcpy(&doubleArrayBody(t, array, index), &value, sizeof(uint64_t)); + } else { + object message = makeString(t, "%d not in [0,%d]", index, + doubleArrayLength(t, array)); + exception = makeArrayIndexOutOfBoundsException(t, message); + goto throw_; + } + } else { + exception = makeNullPointerException(t); + goto throw_; + } + } goto loop; + + case dcmpg: { + double b = popDouble(t); + double a = popDouble(t); + + pushInt(t, (a > b ? 1 : 0)); + } goto loop; + + case dcmpl: { + double b = popDouble(t); + double a = popDouble(t); + + pushInt(t, (a < b ? 1 : 0)); + } goto loop; + + case dconst_0: { + pushDouble(t, 0); + } goto loop; + + case dconst_1: { + pushDouble(t, 1); + } goto loop; + + case ddiv: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a / b); + } goto loop; + + case dmul: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a * b); + } goto loop; + + case dneg: { + double a = popDouble(t); + + pushDouble(t, - a); + } goto loop; + + case vm::drem: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, fmod(a, b)); + } goto loop; + + case dsub: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a - b); + } goto loop; + case dup: { if (DebugStack) { fprintf(stderr, "dup\n"); @@ -903,6 +1023,129 @@ run(Thread* t) sp += 2; } goto loop; + case f2d: { + pushDouble(t, popFloat(t)); + } goto loop; + + case f2i: { + pushInt(t, static_cast<int32_t>(popFloat(t))); + } goto loop; + + case f2l: { + pushLong(t, static_cast<int64_t>(popFloat(t))); + } goto loop; + + case fadd: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a + b); + } goto loop; + + case faload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + 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); + } else { + object message = makeString(t, "%d not in [0,%d]", index, + floatArrayLength(t, array)); + exception = makeArrayIndexOutOfBoundsException(t, message); + goto throw_; + } + } else { + exception = makeNullPointerException(t); + goto throw_; + } + } goto loop; + + case fastore: { + float value = popFloat(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (LIKELY(index >= 0 and + static_cast<uintptr_t>(index) < floatArrayLength(t, array))) + { + memcpy(&floatArrayBody(t, array, index), &value, sizeof(uint32_t)); + } else { + object message = makeString(t, "%d not in [0,%d]", index, + floatArrayLength(t, array)); + exception = makeArrayIndexOutOfBoundsException(t, message); + goto throw_; + } + } else { + exception = makeNullPointerException(t); + goto throw_; + } + } goto loop; + + case fcmpg: { + float b = popFloat(t); + float a = popFloat(t); + + pushInt(t, (a > b ? 1 : 0)); + } goto loop; + + case fcmpl: { + float b = popFloat(t); + float a = popFloat(t); + + pushInt(t, (a < b ? 1 : 0)); + } goto loop; + + case fconst_0: { + pushFloat(t, 0); + } goto loop; + + case fconst_1: { + pushFloat(t, 1); + } goto loop; + + case fconst_2: { + pushFloat(t, 2); + } goto loop; + + case fdiv: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a / b); + } goto loop; + + case fmul: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a * b); + } goto loop; + + case fneg: { + float a = popFloat(t); + + pushFloat(t, - a); + } goto loop; + + case frem: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, fmodf(a, b)); + } goto loop; + + case fsub: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a - b); + } goto loop; + case getfield: { if (LIKELY(peekObject(t, sp - 1))) { uint16_t index = codeReadInt16(t, ip); @@ -1269,23 +1512,28 @@ run(Thread* t) setLocalInt(t, index, localInt(t, index) + c); } goto loop; - case iload: { + case iload: + case fload: { pushInt(t, localInt(t, codeBody(t, code, ip++))); } goto loop; - case iload_0: { + case iload_0: + case fload_0: { pushInt(t, localInt(t, 0)); } goto loop; - case iload_1: { + case iload_1: + case fload_1: { pushInt(t, localInt(t, 1)); } goto loop; - case iload_2: { + case iload_2: + case fload_2: { pushInt(t, localInt(t, 2)); } goto loop; - case iload_3: { + case iload_3: + case fload_3: { pushInt(t, localInt(t, 3)); } goto loop; @@ -1426,7 +1674,8 @@ run(Thread* t) pushInt(t, a % b); } goto loop; - case ireturn: { + case ireturn: + case freturn: { int32_t result = popInt(t); if (frame > base) { popFrame(t); @@ -1451,23 +1700,28 @@ run(Thread* t) pushInt(t, a >> b); } goto loop; - case istore: { + case istore: + case fstore: { setLocalInt(t, codeBody(t, code, ip++), popInt(t)); } goto loop; - case istore_0: { + case istore_0: + case fstore_0: { setLocalInt(t, 0, popInt(t)); } goto loop; - case istore_1: { + case istore_1: + case fstore_1: { setLocalInt(t, 1, popInt(t)); } goto loop; - case istore_2: { + case istore_2: + case fstore_2: { setLocalInt(t, 2, popInt(t)); } goto loop; - case istore_3: { + case istore_3: + case fstore_3: { setLocalInt(t, 3, popInt(t)); } goto loop; @@ -1640,23 +1894,28 @@ run(Thread* t) pushLong(t, a / b); } goto loop; - case lload: { + case lload: + case dload: { pushLong(t, localLong(t, codeBody(t, code, ip++))); } goto loop; - case lload_0: { + case lload_0: + case dload_0: { pushLong(t, localLong(t, 0)); } goto loop; - case lload_1: { + case lload_1: + case dload_1: { pushLong(t, localLong(t, 1)); } goto loop; - case lload_2: { + case lload_2: + case dload_2: { pushLong(t, localLong(t, 2)); } goto loop; - case lload_3: { + case lload_3: + case dload_3: { pushLong(t, localLong(t, 3)); } goto loop; @@ -1717,7 +1976,8 @@ run(Thread* t) pushLong(t, a % b); } goto loop; - case lreturn: { + case lreturn: + case dreturn: { int64_t result = popLong(t); if (frame > base) { popFrame(t); @@ -1742,23 +2002,28 @@ run(Thread* t) pushLong(t, a >> b); } goto loop; - case lstore: { + case lstore: + case dstore: { setLocalLong(t, codeBody(t, code, ip++), popLong(t)); } goto loop; - case lstore_0: { + case lstore_0: + case dstore_0:{ setLocalLong(t, 0, popLong(t)); } goto loop; - case lstore_1: { + case lstore_1: + case dstore_1: { setLocalLong(t, 1, popLong(t)); } goto loop; - case lstore_2: { + case lstore_2: + case dstore_2: { setLocalLong(t, 2, popLong(t)); } goto loop; - case lstore_3: { + case lstore_3: + case dstore_3: { setLocalLong(t, 3, popLong(t)); } goto loop; diff --git a/src/stream.h b/src/stream.h index adbf5cac50..29e1beedb7 100644 --- a/src/stream.h +++ b/src/stream.h @@ -59,15 +59,11 @@ class Stream { } uint32_t readFloat() { - // todo - read4(); - return 0; + return read4(); } uint64_t readDouble() { - // todo - read8(); - return 0; + return read8(); } private: diff --git a/test/Floats.java b/test/Floats.java new file mode 100644 index 0000000000..2d55895073 --- /dev/null +++ b/test/Floats.java @@ -0,0 +1,20 @@ +public class Floats { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + expect(0.5d * 0.5d == 0.25d); + expect(0.5f * 0.5f == 0.25f); + + expect(0.5d * 0.5d < 0.5d); + expect(0.5f * 0.5f < 0.5f); + + expect(0.5d * 0.5d > 0.1d); + expect(0.5f * 0.5f > 0.1f); + + expect(0.5d / 0.5d == 1.0d); + + expect(0.5d - 0.5d == 0.0d); + } +}