jvm/c/native.c

321 lines
9.7 KiB
C

#include "hash_table.h"
#include "malloc.h"
#include "string.h"
#include "printf.h"
#include "native.h"
#include "native/class.h"
#include "native/libcinputstream.h"
#include "native/loader.h"
#include "native/math.h"
#include "native/memory.h"
#include "native/object.h"
#include "native/printstream.h"
#include "native/runtime.h"
#include "native/sh4intrinsic.h"
#include "native/system.h"
typedef void (* native_func_t)(struct vm * vm, uint32_t * args);
struct native_method {
const char * class_name;
const char * method_name;
const char * method_descriptor;
native_func_t func;
};
const static struct native_method native_method[] = {
// Math
{
.class_name = "java/lang/Math",
.method_name = "sin",
.method_descriptor = "(F)F",
.func = native_java_lang_math_sin_1,
},
{
.class_name = "java/lang/Math",
.method_name = "cos",
.method_descriptor = "(F)F",
.func = native_java_lang_math_cos_1,
},
{
.class_name = "java/lang/Math",
.method_name = "abs",
.method_descriptor = "(F)F",
.func = native_java_lang_math_abs_1,
},
// Memory
{
.class_name = "jvm/internal/Memory",
.method_name = "putU4",
.method_descriptor = "(II)V",
.func = native_jvm_internal_memory_putU4_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "putU2",
.method_descriptor = "(IS)V",
.func = native_jvm_internal_memory_putU2_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "putU1",
.method_descriptor = "(IB)V",
.func = native_jvm_internal_memory_putU1_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getU4",
.method_descriptor = "(I)I",
.func = native_jvm_internal_memory_getU4_1,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getU2",
.method_descriptor = "(I)S",
.func = native_jvm_internal_memory_getU2_1,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getU1",
.method_descriptor = "(I)B",
.func = native_jvm_internal_memory_getU1_1,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "putU4",
.method_descriptor = "(IIZ)V",
.func = native_jvm_internal_memory_putUnalignedU4_3,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "putU2",
.method_descriptor = "(ISZ)V",
.func = native_jvm_internal_memory_putUnalignedU2_3,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "putF4",
.method_descriptor = "(IFZ)V",
.func = native_jvm_internal_memory_putUnalignedU4_3,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getU4",
.method_descriptor = "(IZ)I",
.func = native_jvm_internal_memory_getUnalignedU4_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getU2",
.method_descriptor = "(IZ)S",
.func = native_jvm_internal_memory_getUnalignedU2_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "getF4",
.method_descriptor = "(IZ)F",
.func = native_jvm_internal_memory_getUnalignedU4_2,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "isBigEndian",
.method_descriptor = "()Z",
.func = native_jvm_internal_memory_isbigendian_0,
},
{
.class_name = "jvm/internal/Memory",
.method_name = "allocate",
.method_descriptor = "(I)I",
.func = native_jvm_internal_memory_allocate_1,
},
// PrintStream
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "([B)V",
.func = native_java_io_printstream_write_ba_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "([C)V",
.func = native_java_io_printstream_write_ca_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "(Ljava/lang/String;)V",
.func = native_java_io_printstream_write_s_1,
},
// Loader
{
.class_name = "jvm/internal/Loader",
.method_name = "load",
.method_descriptor = "([II)V",
.func = native_jvm_internal_loader_load_2,
},
{
.class_name = "jvm/internal/Loader",
.method_name = "getBuffer",
.method_descriptor = "()I",
.func = native_jvm_internal_loader_getbuffer_0,
},
// Class
{
.class_name = "java/lang/Class",
.method_name = "_getName",
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;",
.func = native_java_lang_class_getname_1,
},
{
.class_name = "java/lang/Class",
.method_name = "_getSuperclass",
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;",
.func = native_java_lang_class_getsuperclass_1,
},
// Object
{
.class_name = "java/lang/Object",
.method_name = "_getClass",
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/Class;",
.func = native_java_lang_object_getclass_1,
},
// Runtime
{
.class_name = "java/lang/Runtime",
.method_name = "_freeMemory",
.method_descriptor = "()I",
.func = native_java_lang_runtime_freememory_0,
},
{
.class_name = "java/lang/Runtime",
.method_name = "_gc",
.method_descriptor = "()V",
.func = native_java_lang_runtime_gc_0,
},
{
.class_name = "java/lang/Runtime",
.method_name = "_totalMemory",
.method_descriptor = "()I",
.func = native_java_lang_runtime_totalmemory_0,
},
// System
{
.class_name = "java/lang/System",
.method_name = "_hashCode",
.method_descriptor = "(Ljava/lang/Object;)I",
.func = native_java_lang_system_hashcode_1,
},
#if !defined(__dreamcast__)
{
.class_name = "jvm/internal/LibcInputStream",
.method_name = "_open",
.method_descriptor = "([B)I",
.func = native_jvm_internal_libcinputstream_open_1,
},
{
.class_name = "jvm/internal/LibcInputStream",
.method_name = "_available",
.method_descriptor = "(I)I",
.func = native_jvm_internal_libcinputstream_available_1,
},
{
.class_name = "jvm/internal/LibcInputStream",
.method_name = "_close",
.method_descriptor = "(I)V",
.func = native_jvm_internal_libcinputstream_close_1,
},
{
.class_name = "jvm/internal/LibcInputStream",
.method_name = "_read",
.method_descriptor = "(I)I",
.func = native_jvm_internal_libcinputstream_read_1,
},
#endif
#if defined(__dreamcast__)
{
.class_name = "jvm/internal/SH4Intrinsic",
.method_name = "pref1",
.method_descriptor = "(I)V",
.func = native_jvm_internal_sh4intrinsic_pref1_1,
},
{
.class_name = "jvm/internal/SH4Intrinsic",
.method_name = "pref2",
.method_descriptor = "(I)V",
.func = native_jvm_internal_sh4intrinsic_pref2_1,
},
#endif
};
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
{
int native_length = (sizeof (native_method)) / (sizeof (native_method[0]));
int native_hash_table_length = hash_table_next_power_of_two(native_length * 2);
uint32_t native_hash_table_size = (sizeof (struct hash_table_entry)) * native_hash_table_length;
struct hash_table_entry * native_hash_table = malloc_class_arena(native_hash_table_size);
hash_table_init(native_hash_table_length, native_hash_table);
for (int i = 0; i < native_length; i++) {
assert(native_method[i].class_name != nullptr);
assert(native_method[i].method_name != nullptr);
assert(native_method[i].method_descriptor != nullptr);
assert(native_method[i].func != nullptr);
int class_name_length = string_length(native_method[i].class_name);
int method_name_length = string_length(native_method[i].method_name);
int method_descriptor_length = string_length(native_method[i].method_descriptor);
debugf("native_init_hash_table add: %s %s %s → %p\n",
native_method[i].class_name,
native_method[i].method_name,
native_method[i].method_descriptor,
native_method[i].func
);
hash_table_add3(native_hash_table_length,
native_hash_table,
(const uint8_t *)native_method[i].class_name,
class_name_length,
(const uint8_t *)native_method[i].method_name,
method_name_length,
(const uint8_t *)native_method[i].method_descriptor,
method_descriptor_length,
native_method[i].func
);
}
*hash_table_length = native_hash_table_length;
return native_hash_table;
}
void native_method_call(struct vm * vm,
struct constant * class_name_constant,
struct constant * method_name_constant,
struct constant * method_descriptor_constant,
uint32_t * args)
{
struct hash_table_entry * e = hash_table_find3(vm->native_hash_table.length,
vm->native_hash_table.entry,
class_name_constant->utf8.bytes,
class_name_constant->utf8.length,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length
);
if (e == nullptr) {
print_bytes(class_name_constant->utf8.bytes, class_name_constant->utf8.length);
printc(' ');
print_bytes(method_name_constant->utf8.bytes, method_name_constant->utf8.length);
printc(' ');
print_bytes(method_descriptor_constant->utf8.bytes, method_descriptor_constant->utf8.length);
printc('\n');
}
assert(e != nullptr);
assert(e->value != nullptr);
native_func_t func = (native_func_t)e->value;
func(vm, args);
}