diff --git a/c/frame.c b/c/frame.c index 3b5b39a..7032cc1 100644 --- a/c/frame.c +++ b/c/frame.c @@ -271,7 +271,7 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str } } if (method_name_constant->utf8.length == 6) { - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"putSQ", 4)) { + if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"putSQ", 5)) { assert(nargs == 2); assert(return_type == 'V'); switch (method_name_constant->utf8.bytes[5]) { @@ -282,6 +282,15 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str return; } } + if (method_name_constant->utf8.length == 11) { + if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"isBigEndian", 11)) { + assert(nargs == 0); + assert(return_type == 'Z'); + uint32_t value = native_java_misc_memory_isbigendian(); + operand_stack_push_u32(vm->current_frame, value); + return; + } + } } int java_misc_resource_length = 18; diff --git a/c/native.c b/c/native.c index 763c2e0..071c4df 100644 --- a/c/native.c +++ b/c/native.c @@ -1,3 +1,5 @@ +#include + #include "native.h" #include "printf.h" @@ -123,3 +125,8 @@ uint32_t java_misc_resource_getresource_1(uint32_t * args) return 0; #endif } + +uint32_t native_java_misc_memory_isbigendian() +{ + return (__STDC_ENDIAN_BIG__ == __STDC_ENDIAN_NATIVE__); +} diff --git a/c/native.h b/c/native.h index 1ee0ce6..9eecb3c 100644 --- a/c/native.h +++ b/c/native.h @@ -15,3 +15,4 @@ void native_java_misc_memory_putSQ1_2(uint32_t * args); uint32_t native_java_lang_math_sin_1(uint32_t * args); uint32_t native_java_lang_math_cos_1(uint32_t * args); uint32_t java_misc_resource_getresource_1(uint32_t * args); +uint32_t native_java_misc_memory_isbigendian(); diff --git a/java/lang/Boolean.java b/java/lang/Boolean.java new file mode 100644 index 0000000..6985d20 --- /dev/null +++ b/java/lang/Boolean.java @@ -0,0 +1,4 @@ +package java.lang; + +class Boolean { +} diff --git a/java/lang/Byte.java b/java/lang/Byte.java new file mode 100644 index 0000000..e26ae86 --- /dev/null +++ b/java/lang/Byte.java @@ -0,0 +1,4 @@ +package java.lang; + +class Byte { +} diff --git a/java/lang/Character.java b/java/lang/Character.java new file mode 100644 index 0000000..2892c5a --- /dev/null +++ b/java/lang/Character.java @@ -0,0 +1,4 @@ +package java.lang; + +class Character { +} diff --git a/java/lang/Short.java b/java/lang/Short.java new file mode 100644 index 0000000..91d9da9 --- /dev/null +++ b/java/lang/Short.java @@ -0,0 +1,4 @@ +package java.lang; + +class Short { +} diff --git a/java/misc/Memory.java b/java/misc/Memory.java index 333fbf5..fa5d09a 100644 --- a/java/misc/Memory.java +++ b/java/misc/Memory.java @@ -10,4 +10,9 @@ public class Memory { public static native int getU1(int address); public static native void putSQ1(Object object, int address); + + public static native boolean isBigEndian(); + + // .length of the returned byte array must not be accessed + public static native byte[] wrapAddress(int address); } diff --git a/java/nio/Buffer.java b/java/nio/Buffer.java new file mode 100644 index 0000000..6bd9160 --- /dev/null +++ b/java/nio/Buffer.java @@ -0,0 +1,38 @@ +package java.nio; + +class Buffer { + protected int mark = -1; + protected int position = 0; + protected int limit; + protected final int capacity; + + Buffer(int mark, int position, int limit, int capacity) { + this.mark = mark; + this.position = position; + this.limit = limit; + this.capacity = capacity; + } + + public final int position() { + return position; + } + + public final int limit() { + return limit; + } + + public final int capacity() { + return capacity; + } + + public Buffer limit(int limit) { + this.limit = limit; + if (position > limit) position = limit; + if (mark > limit) mark = -1; + return this; + } + + public final boolean hasRemaining() { + return position < limit; + } +} diff --git a/java/nio/ByteBuffer.java b/java/nio/ByteBuffer.java new file mode 100644 index 0000000..5160472 --- /dev/null +++ b/java/nio/ByteBuffer.java @@ -0,0 +1,120 @@ +package java.nio; + +public class ByteBuffer extends Buffer { + private int offset; + private boolean bigEndian; + //private boolean sameEndian; + + private byte[] array; + + private ByteBuffer(byte[] array, int offset, int length) { + super(-1, 0, length, length); + this.array = array; + this.order(ByteOrder.BIG_ENDIAN); + } + + public static ByteBuffer wrap(byte[] array) { + return new ByteBuffer(array, 0, array.length); + } + + public static ByteBuffer wrap(byte[] array, int offset, int length) { + return new ByteBuffer(array, offset, length); + } + + public ByteOrder order() { + return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + } + + public ByteBuffer order(ByteOrder bo) { + bigEndian = (bo == ByteOrder.BIG_ENDIAN); + //sameEndian = (bo == ByteOrder.nativeOrder()); + return this; + } + + private static int intBE(int i0, int i1, int i2, int i3) { + return ((i0 << 24) + | (i1 << 16) + | (i2 << 8) + | (i3 << 0)); + } + + private static int intLE(int i0, int i1, int i2, int i3) { + return ((i0 << 0) + | (i1 << 8) + | (i2 << 16) + | (i3 << 24)); + } + + private static int shortBE(int i0, int i1) { + return ((i0 << 8) + | (i1 << 0)); + } + + private static int shortLE(int i0, int i1) { + return ((i0 << 0) + | (i1 << 8)); + } + + public byte get() { + byte i0 = array[position]; + position += 1; + return i0; + } + + public byte get(int pos) { + byte i0 = array[pos]; + return i0; + } + + public short getShort() { + int i0 = array[position + 0]; + int i1 = array[position + 1]; + + position += 2; + + if (bigEndian) { + return (short)shortBE(i0, i1); + } else { + return (short)shortLE(i0, i1); + } + } + + public short getShort(int pos) { + int i0 = array[pos + 0]; + int i1 = array[pos + 1]; + + if (bigEndian) { + return (short)shortBE(i0, i1); + } else { + return (short)shortLE(i0, i1); + } + } + + public int getInt() { + int i0 = array[position + 0]; + int i1 = array[position + 1]; + int i2 = array[position + 2]; + int i3 = array[position + 3]; + + position += 4; + + if (bigEndian) { + return intBE(i0, i1, i2, i3); + } else { + return intLE(i0, i1, i2, i3); + } + } + + public int getInt(int pos) { + int i0 = array[pos + 0]; + int i1 = array[pos + 1]; + int i2 = array[pos + 2]; + int i3 = array[pos + 3]; + + if (bigEndian) { + return intBE(i0, i1, i2, i3); + } else { + return intLE(i0, i1, i2, i3); + } + } +} diff --git a/java/nio/ByteOrder.java b/java/nio/ByteOrder.java new file mode 100644 index 0000000..272f23d --- /dev/null +++ b/java/nio/ByteOrder.java @@ -0,0 +1,15 @@ +package java.nio; + +import java.misc.Memory; + +public class ByteOrder { + public static final ByteOrder BIG_ENDIAN = new ByteOrder(); + public static final ByteOrder LITTLE_ENDIAN = new ByteOrder(); + + private static final ByteOrder NATIVE_ORDER = + Memory.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + + public static ByteOrder nativeOrder() { + return NATIVE_ORDER; + } +} diff --git a/p/TestByteBuffer.java b/p/TestByteBuffer.java new file mode 100644 index 0000000..4ffd61b --- /dev/null +++ b/p/TestByteBuffer.java @@ -0,0 +1,26 @@ +package p; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +class TestByteBuffer { + + public static int test() { + byte[] a = new byte[10]; + a[0] = 42; + a[1] = 0x12; + a[2] = 0x34; + a[3] = 0x56; + a[4] = 0x78; + + ByteBuffer buf = ByteBuffer.wrap(a).order(ByteOrder.LITTLE_ENDIAN); + buf.get(); + int b = buf.getInt(); + return b; + } + + + public static void main() { + test(); + } +} diff --git a/p/TestByteOrder.java b/p/TestByteOrder.java new file mode 100644 index 0000000..86141fd --- /dev/null +++ b/p/TestByteOrder.java @@ -0,0 +1,12 @@ +package p; + +import java.nio.ByteOrder; + +class TestByteOrder { + public static boolean test() { + return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; + } + public static void main() { + test(); + } +}