diff --git a/Makefile b/Makefile index 04e6d61..5704539 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,14 @@ include java.mk +MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST))))) CC ?= gcc ARCH = -m32 CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g +CFLAGS += -I$(MAKEFILE_PATH)/ +CFLAGS += -I$(MAKEFILE_PATH)/c CFLAGS += -DDEBUG -#CFLAGS += -DDEBUG_PRINT +CFLAGS += -DDEBUG_PRINT LDFLAGS = -lm OPT ?= -O0 DEPFLAGS = -MMD -MP @@ -22,7 +25,11 @@ main: $(OBJ) $(MAIN_HOSTED_OBJ) $(CC) $(ARCH) $(LDFLAGS) $^ -o $@ clean: - rm -f main print_class c/*.o c/*.d *.elf *.bin + rm -f main print_class *.elf *.bin + find -P \ + -regextype posix-egrep \ + -regex '.*\.(o|d|gch)$$' \ + -exec rm {} \; .SUFFIXES: .INTERMEDIATE: diff --git a/Makefile.dreamcast.mk b/Makefile.dreamcast.mk index 7e2964c..20fdea2 100644 --- a/Makefile.dreamcast.mk +++ b/Makefile.dreamcast.mk @@ -7,8 +7,9 @@ LIB ?= $(MAKEFILE_PATH)/dreamcast CFLAGS += -D__dreamcast__ CFLAGS += -DDEBUG #CFLAGS += -DDEBUG_PRINT -CFLAGS += -I$(MAKEFILE_PATH) -CFLAGS += -I$(MAKEFILE_PATH)/dreamcast/ +CFLAGS += -I$(MAKEFILE_PATH)/c +CFLAGS += -I$(MAKEFILE_PATH)/dreamcast +CFLAGS += -I$(MAKEFILE_PATH)/ CFLAGS += -Wno-error=strict-aliasing -fno-strict-aliasing CARCH = -m4-single -ml diff --git a/c/assert_hosted.h b/c/assert_hosted.h index 7cf48a1..eef5e7a 100644 --- a/c/assert_hosted.h +++ b/c/assert_hosted.h @@ -1,3 +1,15 @@ #pragma once -#include +extern void __assert_fail (const char *__assertion, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__noreturn__)); + +#define __ASSERT_FUNCTION __func__ + +#define assert(expr) \ + ((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \ + if (expr) \ + ; /* empty */ \ + else \ + __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ + })) diff --git a/c/backtrace.c b/c/backtrace.c index 881e5f5..c28e884 100644 --- a/c/backtrace.c +++ b/c/backtrace.c @@ -4,22 +4,16 @@ #include "find_attribute.h" #include "memory_allocator.h" #include "native_types_allocate.h" +#include "vm_instance.h" struct objectref * backtrace_allocate(struct vm * vm) { - struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length, - vm->class_hash_table.entry, - (const uint8_t *)"java/lang/Backtrace", - 19); - debugf("backtrace class entry: %p\n", class_entry); - - assert(class_entry->instance_fields_count >= 1); - struct objectref * objectref = obj_allocate(vm, class_entry->instance_fields_count); - objectref->class_entry = class_entry; + struct objectref * objectref = vm_instance_create(vm, "java/lang/Backtrace"); + assert(objectref != nullptr); + assert(objectref->class_entry->instance_fields_count >= 1); int num_entries = vm->frame_stack.ix; struct arrayref * arrayref = prim_array_allocate(vm, (sizeof (struct backtrace_entry)), num_entries); - arrayref->length = num_entries; arrayref->class_entry = nullptr; struct backtrace_entry * backtrace_entry = (struct backtrace_entry *)&arrayref->u32[0]; diff --git a/c/backtrace.h b/c/backtrace.h index 2fa4967..539f28a 100644 --- a/c/backtrace.h +++ b/c/backtrace.h @@ -1,5 +1,6 @@ #pragma once +#include "native_types.h" #include "frame.h" struct backtrace_entry { diff --git a/c/class_resolver.c b/c/class_resolver.c index d8f613d..93661b2 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -15,6 +15,7 @@ #include "find_attribute.h" #include "frame.h" #include "native_types_allocate.h" +#include "vm_instance.h" static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) { @@ -219,7 +220,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff int length, int * hash_table_length) { - int class_hash_table_length = hash_table_next_power_of_two(hash_table_next_power_of_two(length * 2)); + int class_hash_table_length = hash_table_next_power_of_two(length * 2); uint32_t class_hash_table_size = (sizeof (struct hash_table_entry)) * class_hash_table_length; struct hash_table_entry * class_hash_table = malloc_class_arena(class_hash_table_size); hash_table_init(class_hash_table_length, class_hash_table); @@ -605,12 +606,6 @@ struct objectref * class_resolver_lookup_string(struct vm * vm, struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1]; assert(utf8_constant->tag == CONSTANT_Utf8); - struct class_entry * string_class_entry = class_resolver_lookup_class(vm->class_hash_table.length, - vm->class_hash_table.entry, - (const uint8_t *)"java/lang/String", - 16); - debugf("string class entry: %p\n", string_class_entry); - int32_t count = utf8_constant->utf8.length; struct arrayref * arrayref = prim_array_allocate(vm, 1, count); assert(arrayref != nullptr); @@ -620,14 +615,9 @@ struct objectref * class_resolver_lookup_string(struct vm * vm, arrayref->u8[i] = utf8_constant->utf8.bytes[i]; } - assert(string_class_entry != nullptr); - int fields_count = string_class_entry->instance_fields_count; - struct objectref * objectref = obj_allocate(vm, fields_count); + struct objectref * objectref = vm_instance_create(vm, "java/lang/String"); assert(objectref != nullptr); - objectref->class_entry = string_class_entry; - for (int i = 0; i < fields_count; i++) { - objectref->oref[i] = nullptr; - } + assert(objectref->class_entry->instance_fields_count >= 1); objectref->aref[0] = arrayref; // cache the result diff --git a/c/classpath.h b/c/classpath.h index 80532fd..e7f56f5 100644 --- a/c/classpath.h +++ b/c/classpath.h @@ -1,25 +1,25 @@ -#include "example/GdromClassLoader.class.h" -#include "example/GdromDirectoryRecordHandler.class.h" -#include "filesystem/iso9660/ByteParser.class.h" -#include "filesystem/iso9660/DirectoryRecord.class.h" -#include "filesystem/iso9660/ExtentReader.class.h" -#include "filesystem/iso9660/PrimaryVolumeDescriptor.class.h" -#include "filesystem/iso9660/VolumeParser.class.h" -#include "java/io/PrintStream.class.h" -#include "java/lang/DecimalDigits.class.h" -#include "java/lang/Integer.class.h" -#include "java/lang/Object.class.h" -#include "java/lang/String.class.h" -#include "java/lang/System.class.h" -#include "java/misc/Memory.class.h" -#include "sega/dreamcast/gdrom/G1IF.class.h" -#include "sega/dreamcast/gdrom/GdromIF.class.h" -#include "sega/dreamcast/gdrom/GdromBits.class.h" -#include "sega/dreamcast/gdrom/Gdrom.class.h" -#include "sega/dreamcast/gdrom/GdromExtentReader.class.h" -#include "sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.h" -#include "sega/dreamcast/gdrom/GdromCommandPacketFormat.class.h" -#include "sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.h" -#include "sega/dreamcast/gdrom/GdromCommandPacketInterface.class.h" -#include "sega/dreamcast/gdrom/GdromProtocol.class.h" -#include "jvm/internal/Loader.class.h" +#include "classes/example/GdromClassLoader.class.h" +#include "classes/example/GdromDirectoryRecordHandler.class.h" +#include "classes/filesystem/iso9660/ByteParser.class.h" +#include "classes/filesystem/iso9660/DirectoryRecord.class.h" +#include "classes/filesystem/iso9660/ExtentReader.class.h" +#include "classes/filesystem/iso9660/PrimaryVolumeDescriptor.class.h" +#include "classes/filesystem/iso9660/VolumeParser.class.h" +#include "classes/java/io/PrintStream.class.h" +#include "classes/java/lang/DecimalDigits.class.h" +#include "classes/java/lang/Integer.class.h" +#include "classes/java/lang/Object.class.h" +#include "classes/java/lang/String.class.h" +#include "classes/java/lang/System.class.h" +#include "classes/java/misc/Memory.class.h" +#include "classes/sega/dreamcast/gdrom/G1IF.class.h" +#include "classes/sega/dreamcast/gdrom/GdromIF.class.h" +#include "classes/sega/dreamcast/gdrom/GdromBits.class.h" +#include "classes/sega/dreamcast/gdrom/Gdrom.class.h" +#include "classes/sega/dreamcast/gdrom/GdromExtentReader.class.h" +#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.h" +#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat.class.h" +#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.h" +#include "classes/sega/dreamcast/gdrom/GdromCommandPacketInterface.class.h" +#include "classes/sega/dreamcast/gdrom/GdromProtocol.class.h" +#include "classes/jvm/internal/Loader.class.h" diff --git a/c/classpath.inc.c b/c/classpath.inc.c index 0e7e9bc..09bff97 100644 --- a/c/classpath.inc.c +++ b/c/classpath.inc.c @@ -1,25 +1,25 @@ -(const uint8_t *)&_binary_example_GdromClassLoader_class_start, -(const uint8_t *)&_binary_example_GdromDirectoryRecordHandler_class_start, -(const uint8_t *)&_binary_filesystem_iso9660_ByteParser_class_start, -(const uint8_t *)&_binary_filesystem_iso9660_DirectoryRecord_class_start, -(const uint8_t *)&_binary_filesystem_iso9660_ExtentReader_class_start, -(const uint8_t *)&_binary_filesystem_iso9660_PrimaryVolumeDescriptor_class_start, -(const uint8_t *)&_binary_filesystem_iso9660_VolumeParser_class_start, -(const uint8_t *)&_binary_java_io_PrintStream_class_start, -(const uint8_t *)&_binary_java_lang_DecimalDigits_class_start, -(const uint8_t *)&_binary_java_lang_Integer_class_start, -(const uint8_t *)&_binary_java_lang_Object_class_start, -(const uint8_t *)&_binary_java_lang_String_class_start, -(const uint8_t *)&_binary_java_lang_System_class_start, -(const uint8_t *)&_binary_java_misc_Memory_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_G1IF_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromIF_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromBits_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_Gdrom_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromExtentReader_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_cd_read_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_get_toc_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketInterface_class_start, -(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromProtocol_class_start, -(const uint8_t *)&_binary_jvm_internal_Loader_class_start, +(const uint8_t *)&_binary_classes_example_GdromClassLoader_class_start, +(const uint8_t *)&_binary_classes_example_GdromDirectoryRecordHandler_class_start, +(const uint8_t *)&_binary_classes_filesystem_iso9660_ByteParser_class_start, +(const uint8_t *)&_binary_classes_filesystem_iso9660_DirectoryRecord_class_start, +(const uint8_t *)&_binary_classes_filesystem_iso9660_ExtentReader_class_start, +(const uint8_t *)&_binary_classes_filesystem_iso9660_PrimaryVolumeDescriptor_class_start, +(const uint8_t *)&_binary_classes_filesystem_iso9660_VolumeParser_class_start, +(const uint8_t *)&_binary_classes_java_io_PrintStream_class_start, +(const uint8_t *)&_binary_classes_java_lang_DecimalDigits_class_start, +(const uint8_t *)&_binary_classes_java_lang_Integer_class_start, +(const uint8_t *)&_binary_classes_java_lang_Object_class_start, +(const uint8_t *)&_binary_classes_java_lang_String_class_start, +(const uint8_t *)&_binary_classes_java_lang_System_class_start, +(const uint8_t *)&_binary_classes_java_misc_Memory_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_G1IF_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromIF_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromBits_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_Gdrom_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromExtentReader_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_cd_read_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_get_toc_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketInterface_class_start, +(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromProtocol_class_start, +(const uint8_t *)&_binary_classes_jvm_internal_Loader_class_start, diff --git a/c/execute.c b/c/execute.c index 915199d..1dff955 100644 --- a/c/execute.c +++ b/c/execute.c @@ -74,7 +74,6 @@ void op_anewarray(struct vm * vm, uint32_t index) int32_t count = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = ref_array_allocate(vm, count); assert(arrayref != nullptr); - arrayref->length = count; arrayref->class_entry = class_entry; /* All components of the new array are initialized to null, the default value @@ -1171,8 +1170,6 @@ void op_invokevirtual(struct vm * vm, uint32_t index) assert(interfacemethodref_constant->tag == CONSTANT_Methodref); struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1]; assert(nameandtype_constant->tag == CONSTANT_NameAndType); - struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; - assert(method_name_constant->tag == CONSTANT_Utf8); struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; assert(method_descriptor_constant->tag == CONSTANT_Utf8); @@ -1665,7 +1662,6 @@ static struct arrayref * _multiarray(struct vm * vm, int32_t * dims, int num_dim arrayref = prim_array_allocate(vm, element_size, count); } assert(arrayref != nullptr); - arrayref->length = count; arrayref->class_entry = nullptr; int32_t array_element_size = count * element_size; // bytes @@ -1749,7 +1745,6 @@ void op_newarray(struct vm * vm, uint32_t atype) int32_t element_size = array_element_size(atype); struct arrayref * arrayref = prim_array_allocate(vm, element_size, count); assert(arrayref != nullptr); - arrayref->length = count; arrayref->class_entry = nullptr; /* Each of the elements of the new array is initialized to the default initial diff --git a/c/file.c b/c/file.c index 675d819..04661aa 100644 --- a/c/file.c +++ b/c/file.c @@ -1,13 +1,15 @@ -#include #include #include #include #include "file.h" +#include "assert.h" +#include "printf.h" uint8_t * file_read(const char * path, size_t * file_size) { int ret; + debugf("file_read: ", path); FILE * f = fopen(path, "rb"); assert(f != nullptr); ret = fseek(f, 0L, SEEK_END); diff --git a/c/frame.c b/c/frame.c index 2488a9b..ca64891 100644 --- a/c/frame.c +++ b/c/frame.c @@ -171,165 +171,35 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str args[nargs - i - 1] = value; } - debugf("native:\n "); + debugf("native: "); struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1]; + assert(class_constant->tag == CONSTANT_Class); struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; + assert(class_name_constant->tag == CONSTANT_Utf8); debug_print__constant__utf8_string(class_name_constant); debugs(" "); struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1]; + assert(method_name_constant->tag == CONSTANT_Utf8); debug_print__constant__utf8_string(method_name_constant); + debugs(" "); + struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1]; + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + debug_print__constant__utf8_string(method_descriptor_constant); debugc('\n'); + int old_stack_ix = vm->current_frame->operand_stack_ix; - int java_lang_math_length = 14; - bool java_lang_math = - class_name_constant->utf8.length == java_lang_math_length && - hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/lang/Math", class_name_constant->utf8.length); - if (java_lang_math) { - if (method_name_constant->utf8.length == 3) { - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"sin", 3)) { - assert(nargs == 1); - assert(return_type == 'F'); - uint32_t value = native_java_lang_math_sin_1(args); - operand_stack_push_u32(vm->current_frame, value); - return; - } - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"cos", 3)) { - assert(nargs == 1); - assert(return_type == 'F'); - uint32_t value = native_java_lang_math_cos_1(args); - operand_stack_push_u32(vm->current_frame, value); - return; - } - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"abs", 3)) { - assert(nargs == 1); - assert(return_type == 'F'); - uint32_t value = native_java_lang_math_abs_1(args); - operand_stack_push_u32(vm->current_frame, value); - return; - } - } + native_method_call(vm, + class_name_constant, + method_name_constant, + method_descriptor_constant, + args); + + if (return_type != 'V') { + assert(old_stack_ix == vm->current_frame->operand_stack_ix - 1); + } else { + assert(old_stack_ix == vm->current_frame->operand_stack_ix); } - - int java_misc_memory_length = 16; - bool java_misc_memory = - class_name_constant->utf8.length == java_misc_memory_length && - hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/misc/Memory", class_name_constant->utf8.length); - if (java_misc_memory) { - if (method_name_constant->utf8.length == 5) { - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"putU", 4)) { - assert(nargs == 2); - assert(return_type == 'V'); - switch (method_name_constant->utf8.bytes[4]) { - case '4': native_java_misc_memory_putU4_2(args); break; - case '2': native_java_misc_memory_putU2_2(args); break; - case '1': native_java_misc_memory_putU1_2(args); break; - default: assert(false); - } - return; - } - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getU", 4)) { - assert(nargs == 1); - assert(return_type == 'I'); - uint32_t value; - switch (method_name_constant->utf8.bytes[4]) { - case '4': value = native_java_misc_memory_getU4_1(args); break; - case '2': value = native_java_misc_memory_getU2_1(args); break; - case '1': value = native_java_misc_memory_getU1_1(args); break; - default: assert(false); - } - operand_stack_push_u32(vm->current_frame, value); - return; - } - } - if (method_name_constant->utf8.length == 6) { - 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]) { - //case '2': value = native_java_misc_memory_putSQ2_2(args); break; - case '1': native_java_misc_memory_putSQ1_2(args); break; - default: assert(false); - } - 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; - bool java_misc_resource = - class_name_constant->utf8.length == java_misc_resource_length && - hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/misc/Resource", class_name_constant->utf8.length); - if (java_misc_resource) { - int getresource_length = 11; - bool getresource = - method_name_constant->utf8.length == getresource_length && - hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getResource", method_name_constant->utf8.length); - if (getresource) { - assert(nargs == 1); - assert(return_type == '['); - uint32_t value = java_misc_resource_getresource_1(args); - operand_stack_push_u32(vm->current_frame, value); - return; - } - } - - int java_io_printstream_length = 19; - bool java_io_printstream = - class_name_constant->utf8.length == java_io_printstream_length && - hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/io/PrintStream", class_name_constant->utf8.length); - if (java_io_printstream) { - int write_length = 5; - bool write = - method_name_constant->utf8.length == write_length && - hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"write", method_name_constant->utf8.length); - if (write) { - if (nargs == 1) { - assert(return_type == 'V'); - native_java_io_printstream_write_1(args); - return; - } else if (nargs == 2) { - assert(return_type == 'V'); - native_java_io_printstream_write_2(args); - return; - } - } - } - - int jvm_internal_loader_length = 19; - bool jvm_internal_loader = - class_name_constant->utf8.length == jvm_internal_loader_length && - hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"jvm/internal/Loader", class_name_constant->utf8.length); - if (jvm_internal_loader) { - if (method_name_constant->utf8.length == 4) { - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"load", 4)) { - assert(nargs == 2); - assert(return_type == 'V'); - native_jvm_internal_loader_load(args); - return; - } - } - if (method_name_constant->utf8.length == 9) { - if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getBuffer", 9)) { - assert(nargs == 0); - assert(return_type == 'I'); - uint32_t value = native_jvm_internal_loader_getbuffer(); - operand_stack_push_u32(vm->current_frame, value); - return; - } - } - } - - assert(false); } void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type) @@ -587,6 +457,8 @@ void vm_execute(struct vm * vm) struct vm * vm_start(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, const uint8_t * main_class_name, int main_class_name_length) { @@ -611,6 +483,8 @@ struct vm * vm_start(int class_hash_table_length, static struct vm vm; vm.class_hash_table.length = class_hash_table_length; vm.class_hash_table.entry = class_hash_table; + vm.native_hash_table.length = native_hash_table_length; + vm.native_hash_table.entry = native_hash_table; vm.frame_stack.ix = 0; vm.frame_stack.capacity = 1024; diff --git a/c/frame.h b/c/frame.h index 4795baf..2ddc22a 100644 --- a/c/frame.h +++ b/c/frame.h @@ -35,7 +35,12 @@ struct vm { int length; struct hash_table_entry * entry; } class_hash_table; + struct { + int length; + struct hash_table_entry * entry; + } native_hash_table; }; + static inline struct frame * stack_push_frame(struct stack * stack, int num_frames) { struct frame * frame = &stack->frame[stack->ix]; @@ -185,6 +190,8 @@ void vm_method_return(struct vm * vm); void vm_execute(struct vm * vm); struct vm * vm_start(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, const uint8_t * main_class_name, int main_class_name_length); int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); diff --git a/c/hash_table.c b/c/hash_table.c index 95cd601..9037e3f 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -186,26 +186,105 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, return nullptr; } -/* -void hash_table_add_int(int hash_table_length, - struct hash_table_entry * entry, - int key, - void * value) +struct hash_table_entry * hash_table_add3(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + const uint8_t * key3, + int key3_length, + void * value) { - hash_table_add(hash_table_length, - entry, - (const uint8_t *)&key, - 4, - value); + assert(hash_table_length != 0); + assert((hash_table_length & (hash_table_length - 1)) == 0); + uint32_t hash = fnv_offset_basis; + hash = fnv_1(hash, key1, key1_length); + hash = fnv_1(hash, key2, key2_length); + hash = fnv_1(hash, key3, key3_length); + hash &= (hash_table_length - 1); + + printf("hash: %d %u %p\n", hash_table_length, hash, value); + + struct hash_table_entry * e = &entry[hash]; + + while (e->next != nullptr) { + e = e->next; + } + + if (e->key != nullptr) { + // allocate e from overflow + e->next = malloc_class_arena((sizeof (struct hash_table_entry))); + e->next->key = nullptr; + e->next->next = nullptr; + e = e->next; + } + + uint8_t * key_copy = malloc_class_arena(key1_length + key2_length + key3_length); + for (int i = 0; i < key1_length; i++) key_copy[i] = key1[i]; + for (int i = 0; i < key2_length; i++) key_copy[key1_length + i] = key2[i]; + for (int i = 0; i < key3_length; i++) key_copy[key1_length + key2_length + i] = key3[i]; + e->key = key_copy; + e->key_length = key1_length + key2_length + key3_length; + e->value = value; + + return e; } -struct hash_table_entry * hash_table_find_int(int hash_table_length, - struct hash_table_entry * entry, - int key) +static inline bool key_equal3(const uint8_t * a1, int a1_length, + const uint8_t * a2, int a2_length, + const uint8_t * a3, int a3_length, + const uint8_t * b) { - return hash_table_find(hash_table_length, - entry, - (const uint8_t *)&key, - 4); + for (int i = 0; i < a1_length; i++) { + if (a1[i] != b[i]) + return false; + } + for (int i = 0; i < a2_length; i++) { + if (a2[i] != b[a1_length + i]) + return false; + } + for (int i = 0; i < a3_length; i++) { + if (a3[i] != b[a1_length + a2_length + i]) + return false; + } + return true; +} + +struct hash_table_entry * hash_table_find3(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + const uint8_t * key3, + int key3_length) +{ + if (hash_table_length == 0) + return nullptr; + + assert((hash_table_length & (hash_table_length - 1)) == 0); + uint32_t hash = fnv_offset_basis; + hash = fnv_1(hash, key1, key1_length); + hash = fnv_1(hash, key2, key2_length); + hash = fnv_1(hash, key3, key3_length); + hash &= (hash_table_length - 1); + + printf("hash: %d %u\n", hash_table_length, hash); + + struct hash_table_entry * e = &entry[hash]; + + while (e != nullptr && e->key != nullptr) { + bool equal = + e->key_length == (key1_length + key2_length + key3_length) && + key_equal3(key1, key1_length, + key2, key2_length, + key3, key3_length, + e->key); + if (equal) { + return e; + } + e = e->next; + } + return nullptr; } -*/ diff --git a/c/hash_table.h b/c/hash_table.h index 358bf1d..3331324 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -40,6 +40,25 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, const uint8_t * key2, int key2_length); +struct hash_table_entry * hash_table_add3(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + const uint8_t * key3, + int key3_length, + void * value); + +struct hash_table_entry * hash_table_find3(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + const uint8_t * key3, + int key3_length); + static inline bool hash_table_key_equal(const uint8_t * a, const uint8_t * b, int length) { for (int i = 0; i < length; i++) { diff --git a/c/main_dreamcast.c b/c/main_dreamcast.c index dc918d9..90465be 100644 --- a/c/main_dreamcast.c +++ b/c/main_dreamcast.c @@ -2,15 +2,13 @@ #include "string.h" #include "class_resolver.h" -#include "frame.h" -#include "printf.h" +#include "native.h" #include "malloc.h" -#include "memory_allocator.h" - -#include "sh7091_scif.h" #include "classpath.h" +#include "sh7091_scif.h" + void main() { scif_init(0); @@ -36,9 +34,15 @@ void main() class_file_buffers_length, &class_hash_table_length); + int native_hash_table_length; + struct hash_table_entry * native_hash_table = native_init_hash_table(&native_hash_table_length); + struct vm * vm = vm_start(class_hash_table_length, class_hash_table, + native_hash_table_length, + native_hash_table, main_class, main_class_length); + vm_execute(vm); } diff --git a/c/main_hosted.c b/c/main_hosted.c index 55fbe05..ca1c9a8 100644 --- a/c/main_hosted.c +++ b/c/main_hosted.c @@ -1,15 +1,14 @@ #include -#include #include "printf.h" -#include "frame.h" #include "class_resolver.h" #include "string.h" #include "file.h" #include "malloc.h" +#include "native.h" #include "memory_allocator.h" -#include "backtrace.h" -#include "gc.h" + +void * memset(void * s, int c, size_t n); static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length) { @@ -49,15 +48,17 @@ int main(int argc, const char * argv[]) int class_hash_table_length; struct hash_table_entry * class_hash_table = load_from_filenames(class_filenames, num_class_filenames, &class_hash_table_length); + int native_hash_table_length; + struct hash_table_entry * native_hash_table = native_init_hash_table(&native_hash_table_length); + debugf("vm_start\n"); struct vm * vm = vm_start(class_hash_table_length, class_hash_table, + native_hash_table_length, + native_hash_table, main_class, main_class_length); vm_execute(vm); - - gc_mark(vm); - gc_sweep(); } diff --git a/c/native.c b/c/native.c index 00bd903..81e3637 100644 --- a/c/native.c +++ b/c/native.c @@ -1,166 +1,168 @@ -#include "native.h" -#include "printf.h" -#include "string.h" +#include "hash_table.h" #include "malloc.h" -#include "memory_allocator.h" -#include "class_resolver.h" -#include "frame.h" +#include "string.h" +#include "printf.h" +#include "native.h" +#include "native/math.h" +#include "native/memory.h" +#include "native/printstream.h" +#include "native/loader.h" -void native_java_io_printstream_write_1(uint32_t * args) +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[] = { + { + .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 = "javva/lang/Math", + .method_name = "abs", + .method_descriptor = "(F)F", + .func = native_java_lang_math_abs_1, + }, + { + .class_name = "java/misc/Memory", + .method_name = "putU4", + .method_descriptor = "(II)V", + .func = native_java_misc_memory_putU4_2, + }, + { + .class_name = "java/misc/Memory", + .method_name = "putU2", + .method_descriptor = "(II)V", + .func = native_java_misc_memory_putU2_2, + }, + { + .class_name = "java/misc/Memory", + .method_name = "putU1", + .method_descriptor = "(II)V", + .func = native_java_misc_memory_putU1_2, + }, + { + .class_name = "java/misc/Memory", + .method_name = "getU4", + .method_descriptor = "(I)I", + .func = native_java_misc_memory_getU4_1, + }, + { + .class_name = "java/misc/Memory", + .method_name = "getU2", + .method_descriptor = "(I)I", + .func = native_java_misc_memory_getU2_1, + }, + { + .class_name = "java/misc/Memory", + .method_name = "getU1", + .method_descriptor = "(I)I", + .func = native_java_misc_memory_getU1_1, + }, + { + .class_name = "java/misc/Memory", + .method_name = "putSQ1", + .method_descriptor = "(Ljava/lang/Object;I)V", + .func = native_java_misc_memory_putSQ1_2, + }, + { + .class_name = "java/misc/Memory", + .method_name = "isBigEndian", + .method_descriptor = "()Z", + .func = native_java_misc_memory_isbigendian_0, + }, + { + .class_name = "java/io/PrintStream", + .method_name = "write", + .method_descriptor = "([B)V", + .func = native_java_io_printstream_write_1, + }, + { + .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, + }, +}; + +struct hash_table_entry * native_init_hash_table(int * hash_table_length) { - struct arrayref * arrayref = (struct arrayref *)args[0]; - print_string((const char *)arrayref->u8, arrayref->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_java_io_printstream_write_2(uint32_t * args) +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) { - //uint32_t this = args[0]; - struct arrayref * arrayref = (struct arrayref *)args[1]; - print_string((const char *)arrayref->u8, arrayref->length); -} - -void native_java_misc_memory_putU4_2(uint32_t * args) -{ - uint32_t * address = (uint32_t *)args[0]; - uint32_t value = args[1]; - *address = value; -} - -void native_java_misc_memory_putU2_2(uint32_t * args) -{ - uint16_t * address = (uint16_t *)args[0]; - uint16_t value = args[1]; - *address = value; -} - -void native_java_misc_memory_putU1_2(uint32_t * args) -{ - uint8_t * address = (uint8_t *)args[0]; - uint8_t value = args[1]; - *address = value; -} - -uint32_t native_java_misc_memory_getU4_1(uint32_t * args) -{ - uint32_t * address = (uint32_t *)args[0]; - uint32_t value = *address; - return value; -} - -uint32_t native_java_misc_memory_getU2_1(uint32_t * args) -{ - uint16_t * address = (uint16_t *)args[0]; - uint16_t value = *address; - return value; -} - -uint32_t native_java_misc_memory_getU1_1(uint32_t * args) -{ - uint8_t * address = (uint8_t *)args[0]; - uint8_t value = *address; - return value; -} - -extern uint32_t store_queue[0x4000000] __asm("store_queue"); - -void native_java_misc_memory_putSQ1_2(uint32_t * args) -{ - #if defined(__dreamcast__) - struct objectref * objectref = (struct objectref *)args[0]; - uint32_t address = (uint32_t)args[1]; - store_queue[0] = objectref->u32[0]; - store_queue[1] = objectref->u32[1]; - store_queue[2] = objectref->u32[2]; - store_queue[3] = objectref->u32[3]; - store_queue[4] = objectref->u32[4]; - store_queue[5] = objectref->u32[5]; - store_queue[6] = objectref->u32[6]; - store_queue[7] = objectref->u32[7]; - - *((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2; - - __asm__ volatile ("pref @%0" - : // output - : "r" (&store_queue[0]) // input - : "memory"); - #endif -} - -uint32_t __attribute__ ((noinline)) __attribute__ ((optimize(0))) -native_java_lang_math_sin_1(uint32_t * args) -{ - float arg = ((float *)args)[0]; - float value = __builtin_sinf(arg); - return *((uint32_t *)&value); -} - -uint32_t __attribute__ ((noinline)) __attribute__ ((optimize(0))) -native_java_lang_math_cos_1(uint32_t * args) -{ - float arg = ((float *)args)[0]; - float value = __builtin_cosf(arg); - return *((uint32_t *)&value); -} - -uint32_t native_java_lang_math_abs_1(uint32_t * args) -{ - float arg = ((float *)args)[0]; - float value = __builtin_fabsf(arg); - return *((uint32_t *)&value); -} - -#if defined(__dreamcast__) -#include "resources.inc.c" -#endif - -uint32_t java_misc_resource_getresource_1(uint32_t * args) -{ - struct objectref * objectref = (struct objectref *)args[0]; - struct arrayref * arrayref = objectref->aref[0]; - #if defined(__dreamcast__) - uint32_t resource = find_resource(arrayref->u8, arrayref->length); - return resource; - #else - (void)arrayref; - return 0; - #endif -} - -uint32_t native_java_misc_memory_isbigendian() -{ - return (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); -} - -static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32))); - -uint32_t native_jvm_internal_loader_getbuffer() -{ - return (uint32_t)&loader_buffer[0]; -} - -extern struct vm vm; - -void native_jvm_internal_loader_load(uint32_t * args) -{ - struct arrayref * arrayref = (struct arrayref *)args[0]; - const uint8_t ** buffers = (const uint8_t **)&arrayref->u32[0]; - int32_t num_buffers = (int32_t)args[1]; - printf("num_buffers: %d\n", num_buffers); - printf("loader_buffer[0]: %p ; buffers[0]: %p\n", &loader_buffer[0], (uint32_t)buffers[0]); - - const uint8_t * main_class = (const uint8_t *)"Main"; - int main_class_length = string_length((const char *)main_class); - - memory_reset_free_list(); - malloc_class_arena_reset(); - - int class_hash_table_length; - struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(buffers, - num_buffers, - &class_hash_table_length); - - vm_start(class_hash_table_length, - class_hash_table, - main_class, - main_class_length); + 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 + ); + assert(e != nullptr); + assert(e->value != nullptr); + + native_func_t func = (native_func_t)e->value; + func(vm, args); } diff --git a/c/native.h b/c/native.h index 78c2d20..65d7b4a 100644 --- a/c/native.h +++ b/c/native.h @@ -1,21 +1,10 @@ #pragma once -#include +#include "frame.h" -void native_java_io_printstream_write(uint32_t * arrayref); -void native_java_io_printstream_write_1(uint32_t * args); -void native_java_io_printstream_write_2(uint32_t * args); -void native_java_misc_memory_putU4_2(uint32_t * args); -void native_java_misc_memory_putU2_2(uint32_t * args); -void native_java_misc_memory_putU1_2(uint32_t * args); -uint32_t native_java_misc_memory_getU4_1(uint32_t * args); -uint32_t native_java_misc_memory_getU2_1(uint32_t * args); -uint32_t native_java_misc_memory_getU1_1(uint32_t * args); -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 native_java_lang_math_abs_1(uint32_t * args); -uint32_t java_misc_resource_getresource_1(uint32_t * args); -uint32_t native_java_misc_memory_isbigendian(); -uint32_t native_jvm_internal_loader_getbuffer(); -void native_jvm_internal_loader_load(uint32_t * args); +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 * native_init_hash_table(int * hash_table_length); diff --git a/c/native/loader.c b/c/native/loader.c new file mode 100644 index 0000000..7df0350 --- /dev/null +++ b/c/native/loader.c @@ -0,0 +1,42 @@ +#include "native_types.h" +#include "printf.h" +#include "string.h" +#include "malloc.h" +#include "loader.h" + +static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32))); + +void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args) +{ + uint32_t value = (uint32_t)&loader_buffer[0]; + operand_stack_push_u32(vm->current_frame, value); +} + +extern struct vm vm; + +void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args) +{ + struct arrayref * arrayref = (struct arrayref *)args[0]; + const uint8_t ** buffers = (const uint8_t **)&arrayref->u32[0]; + int32_t num_buffers = (int32_t)args[1]; + debugf("num_buffers: %d\n", num_buffers); + debugf("loader_buffer[0]: %p ; buffers[0]: %p\n", &loader_buffer[0], (uint32_t)buffers[0]); + + const uint8_t * main_class = (const uint8_t *)"Main"; + int main_class_length = string_length((const char *)main_class); + + memory_reset_free_list(); + malloc_class_arena_reset(); + + int class_hash_table_length; + struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(buffers, + num_buffers, + &class_hash_table_length); + + vm_start(class_hash_table_length, + class_hash_table, + vm->native_hash_table.length, + vm->native_hash_table.entry, + main_class, + main_class_length); +} diff --git a/c/native/loader.h b/c/native/loader.h new file mode 100644 index 0000000..f765fb3 --- /dev/null +++ b/c/native/loader.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include "frame.h" + +void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args); +void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args); diff --git a/c/native/math.c b/c/native/math.c new file mode 100644 index 0000000..e427a24 --- /dev/null +++ b/c/native/math.c @@ -0,0 +1,24 @@ +#include "math.h" + +void __attribute__ ((noinline)) __attribute__ ((optimize(0))) +native_java_lang_math_sin_1(struct vm * vm, uint32_t * args) +{ + float arg = ((float *)args)[0]; + float value = __builtin_sinf(arg); + operand_stack_push_u32(vm->current_frame, value); +} + +void __attribute__ ((noinline)) __attribute__ ((optimize(0))) +native_java_lang_math_cos_1(struct vm * vm, uint32_t * args) +{ + float arg = ((float *)args)[0]; + float value = __builtin_cosf(arg); + operand_stack_push_u32(vm->current_frame, value); +} + +void native_java_lang_math_abs_1(struct vm * vm, uint32_t * args) +{ + float arg = ((float *)args)[0]; + float value = __builtin_fabsf(arg); + operand_stack_push_u32(vm->current_frame, value); +} diff --git a/c/native/math.h b/c/native/math.h new file mode 100644 index 0000000..485ad85 --- /dev/null +++ b/c/native/math.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include "frame.h" + +void native_java_lang_math_sin_1(struct vm * vm, uint32_t * args); +void native_java_lang_math_cos_1(struct vm * vm, uint32_t * args); +void native_java_lang_math_abs_1(struct vm * vm, uint32_t * args); diff --git a/c/native/memory.c b/c/native/memory.c new file mode 100644 index 0000000..408521a --- /dev/null +++ b/c/native/memory.c @@ -0,0 +1,75 @@ +#include "native_types.h" +#include "memory.h" + +void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args) +{ + uint32_t * address = (uint32_t *)args[0]; + uint32_t value = args[1]; + *address = value; +} + +void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args) +{ + uint16_t * address = (uint16_t *)args[0]; + uint16_t value = args[1]; + *address = value; +} + +void native_java_misc_memory_putU1_2(struct vm * vm, uint32_t * args) +{ + uint8_t * address = (uint8_t *)args[0]; + uint8_t value = args[1]; + *address = value; +} + +void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args) +{ + uint32_t * address = (uint32_t *)args[0]; + uint32_t value = *address; + operand_stack_push_u32(vm->current_frame, value); +} + +void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args) +{ + uint16_t * address = (uint16_t *)args[0]; + uint16_t value = *address; + operand_stack_push_u32(vm->current_frame, value); +} + +void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args) +{ + uint8_t * address = (uint8_t *)args[0]; + uint8_t value = *address; + operand_stack_push_u32(vm->current_frame, value); +} + +extern uint32_t store_queue[0x4000000] __asm("store_queue"); + +void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args) +{ + #if defined(__dreamcast__) + struct objectref * objectref = (struct objectref *)args[0]; + uint32_t address = (uint32_t)args[1]; + store_queue[0] = objectref->u32[0]; + store_queue[1] = objectref->u32[1]; + store_queue[2] = objectref->u32[2]; + store_queue[3] = objectref->u32[3]; + store_queue[4] = objectref->u32[4]; + store_queue[5] = objectref->u32[5]; + store_queue[6] = objectref->u32[6]; + store_queue[7] = objectref->u32[7]; + + *((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2; + + __asm__ volatile ("pref @%0" + : // output + : "r" (&store_queue[0]) // input + : "memory"); + #endif +} + +void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args) +{ + uint32_t value = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); + operand_stack_push_u32(vm->current_frame, value); +} diff --git a/c/native/memory.h b/c/native/memory.h new file mode 100644 index 0000000..112b4b3 --- /dev/null +++ b/c/native/memory.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "frame.h" + +void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args); +void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args); +void native_java_misc_memory_putU1_2(struct vm * vm, uint32_t * args); +void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args); +void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args); +void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args); +void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args); +void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args); diff --git a/c/native/printstream.c b/c/native/printstream.c new file mode 100644 index 0000000..0594f66 --- /dev/null +++ b/c/native/printstream.c @@ -0,0 +1,9 @@ +#include "native_types.h" +#include "printstream.h" +#include "printf.h" + +void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args) +{ + struct arrayref * arrayref = (struct arrayref *)args[0]; + print_string((const char *)arrayref->u8, arrayref->length); +} diff --git a/c/native/printstream.h b/c/native/printstream.h new file mode 100644 index 0000000..aab3bac --- /dev/null +++ b/c/native/printstream.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "frame.h" + +void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args); diff --git a/c/native_types.h b/c/native_types.h index c861d42..f402c0b 100644 --- a/c/native_types.h +++ b/c/native_types.h @@ -1,8 +1,8 @@ #pragma once #include -#include +#include "assert.h" #include "class_resolver.h" #include "memory_allocator.h" diff --git a/c/native_types_allocate.h b/c/native_types_allocate.h index da9b99a..92c192f 100644 --- a/c/native_types_allocate.h +++ b/c/native_types_allocate.h @@ -21,6 +21,7 @@ static inline struct arrayref * prim_array_allocate(struct vm * vm, int element_ if (arrayref != nullptr) { arrayref->tag.type = TAG_TYPE_PRIM_ARRAY; arrayref->tag.mark = 0; + arrayref->length = count; } return arrayref; } @@ -32,6 +33,7 @@ static inline struct arrayref * ref_array_allocate(struct vm * vm, int count) if (arrayref != nullptr) { arrayref->tag.type = TAG_TYPE_REF_ARRAY; arrayref->tag.mark = 0; + arrayref->length = count; } return arrayref; } diff --git a/c/test_hash_table.c b/c/test_hash_table.c index 441e779..5997204 100644 --- a/c/test_hash_table.c +++ b/c/test_hash_table.c @@ -1,8 +1,8 @@ #include #include -#include #include "hash_table.h" +#include "assert.h" static const char * names[] = { "java/beans/Introspector.java", diff --git a/c/vm_instance.c b/c/vm_instance.c new file mode 100644 index 0000000..4776b3e --- /dev/null +++ b/c/vm_instance.c @@ -0,0 +1,23 @@ +#include "string.h" +#include "native_types_allocate.h" +#include "vm_instance.h" + +struct objectref * vm_instance_create(struct vm * vm, const char * class_name) +{ + struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length, + vm->class_hash_table.entry, + (const uint8_t *)class_name, + string_length(class_name)); + assert(class_entry != nullptr); + + struct objectref * objectref = obj_allocate(vm, class_entry->instance_fields_count); + if (objectref != nullptr) { + objectref->class_entry = class_entry; + + for (int i = 0; i < class_entry->instance_fields_count; i++) { + objectref->oref[i] = nullptr; + } + } + + return objectref; +} diff --git a/c/vm_instance.h b/c/vm_instance.h new file mode 100644 index 0000000..56d56ba --- /dev/null +++ b/c/vm_instance.h @@ -0,0 +1,5 @@ +#pragma once + +#include "frame.h" + +struct objectref * vm_instance_create(struct vm * vm, const char * class_name); diff --git a/example/DreamcastVideo.java b/classes/example/DreamcastVideo.java similarity index 100% rename from example/DreamcastVideo.java rename to classes/example/DreamcastVideo.java diff --git a/example/GdromClassLoader.java b/classes/example/GdromClassLoader.java similarity index 100% rename from example/GdromClassLoader.java rename to classes/example/GdromClassLoader.java diff --git a/example/JavaCube.java b/classes/example/JavaCube.java similarity index 100% rename from example/JavaCube.java rename to classes/example/JavaCube.java diff --git a/classes/java/lang/Class.java b/classes/java/lang/Class.java new file mode 100644 index 0000000..83c9a86 --- /dev/null +++ b/classes/java/lang/Class.java @@ -0,0 +1,18 @@ +package java.lang; + +public class Class { + private Object object; + private String name; + + private Class() { + } + + private native String getClassName(); + + public String getName() { + if (this.name == null) { + this.name = getClassName(); + } + return this.name; + } +} diff --git a/classes/java/lang/Object.java b/classes/java/lang/Object.java index 61743b5..a9e856e 100644 --- a/classes/java/lang/Object.java +++ b/classes/java/lang/Object.java @@ -3,7 +3,12 @@ package java.lang; public class Object { public Object() {} + public final native Class getClass(); + + public native int hashCode(); + public String toString() { - return "Object"; + return null; + //return getClass().getName() + "@" + Integer.toString(hashCode()); } } diff --git a/classes/java/misc/Memory.java b/classes/java/misc/Memory.java index fa5d09a..1460d32 100644 --- a/classes/java/misc/Memory.java +++ b/classes/java/misc/Memory.java @@ -12,7 +12,4 @@ public class Memory { 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/classes/test/TestGeneric.java b/classes/test/TestGeneric.java new file mode 100644 index 0000000..27d5dd6 --- /dev/null +++ b/classes/test/TestGeneric.java @@ -0,0 +1,24 @@ +package test; + +class Test { + T obj; + + Test(T obj) { + this.obj = obj; + } + + public T getObject() { + return this.obj; + } +} + +class TestGeneric { + public static void main(String[] args) + { + Test ti = new Test(15); + System.out.println(ti.getObject()); + + Test ts = new Test("GeeksForGeeks"); + System.out.println(ts.getObject()); + } +} diff --git a/classpath.mk b/classpath.mk index 2a2662c..5bfb2a4 100644 --- a/classpath.mk +++ b/classpath.mk @@ -1,26 +1,26 @@ CLASS_PATH = \ - example/GdromClassLoader.class.o \ - example/GdromDirectoryRecordHandler.class.o \ - filesystem/iso9660/ByteParser.class.o \ - filesystem/iso9660/DirectoryRecord.class.o \ - filesystem/iso9660/ExtentReader.class.o \ - filesystem/iso9660/PrimaryVolumeDescriptor.class.o \ - filesystem/iso9660/VolumeParser.class.o \ - java/io/PrintStream.class.o \ - java/lang/DecimalDigits.class.o \ - java/lang/Integer.class.o \ - java/lang/Object.class.o \ - java/lang/String.class.o \ - java/lang/System.class.o \ - java/misc/Memory.class.o \ - sega/dreamcast/gdrom/G1IF.class.o \ - sega/dreamcast/gdrom/GdromIF.class.o \ - sega/dreamcast/gdrom/GdromBits.class.o \ - sega/dreamcast/gdrom/Gdrom.class.o \ - sega/dreamcast/gdrom/GdromExtentReader.class.o \ - sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.o \ - sega/dreamcast/gdrom/GdromCommandPacketFormat.class.o \ - sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.o \ - sega/dreamcast/gdrom/GdromCommandPacketInterface.class.o \ - sega/dreamcast/gdrom/GdromProtocol.class.o \ - jvm/internal/Loader.class.o + classes/example/GdromClassLoader.class.o \ + classes/example/GdromDirectoryRecordHandler.class.o \ + classes/filesystem/iso9660/ByteParser.class.o \ + classes/filesystem/iso9660/DirectoryRecord.class.o \ + classes/filesystem/iso9660/ExtentReader.class.o \ + classes/filesystem/iso9660/PrimaryVolumeDescriptor.class.o \ + classes/filesystem/iso9660/VolumeParser.class.o \ + classes/java/io/PrintStream.class.o \ + classes/java/lang/DecimalDigits.class.o \ + classes/java/lang/Integer.class.o \ + classes/java/lang/Object.class.o \ + classes/java/lang/String.class.o \ + classes/java/lang/System.class.o \ + classes/java/misc/Memory.class.o \ + classes/sega/dreamcast/gdrom/G1IF.class.o \ + classes/sega/dreamcast/gdrom/GdromIF.class.o \ + classes/sega/dreamcast/gdrom/GdromBits.class.o \ + classes/sega/dreamcast/gdrom/Gdrom.class.o \ + classes/sega/dreamcast/gdrom/GdromExtentReader.class.o \ + classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.o \ + classes/sega/dreamcast/gdrom/GdromCommandPacketFormat.class.o \ + classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.o \ + classes/sega/dreamcast/gdrom/GdromCommandPacketInterface.class.o \ + classes/sega/dreamcast/gdrom/GdromProtocol.class.o \ + classes/jvm/internal/Loader.class.o diff --git a/generate_classpath.sh b/generate_classpath.sh index 4d87169..2c008e3 100644 --- a/generate_classpath.sh +++ b/generate_classpath.sh @@ -39,27 +39,29 @@ function classpath_inc_c () { function make_header () { while read line; do - truncate -s0 "${line}.h" + local filename="${line}.h" local name0="${line//\//_}" local name1="${name0//$/_}" local name="${name1//./_}" - echo '#pragma once' > "${line}.h" - echo '' >> "${line}.h" - echo '#include ' >> "${line}.h" - echo '' >> "${line}.h" - echo '#ifdef __cplusplus' >> "${line}.h" - echo 'extern C {' >> "${line}.h" - echo '#endif' >> "${line}.h" - echo '' >> "${line}.h" - echo "extern uint32_t _binary_${name}_start __asm(\"_binary_${name}_start\");" >> "${line}.h" - echo "extern uint32_t _binary_${name}_end __asm(\"_binary_${name}_end\");" >> "${line}.h" - echo "extern uint32_t _binary_${name}_size __asm(\"_binary_${name}_size\");" >> "${line}.h" - echo '' >> "${line}.h" - echo '#ifdef __cplusplus' >> "${line}.h" - echo '}' >> "${line}.h" - echo '#endif' >> "${line}.h" + truncate -s0 "${filename}" + + echo '#pragma once' > "${filename}" + echo '' >> "${filename}" + echo '#include ' >> "${filename}" + echo '' >> "${filename}" + echo '#ifdef __cplusplus' >> "${filename}" + echo 'extern C {' >> "${filename}" + echo '#endif' >> "${filename}" + echo '' >> "${filename}" + echo "extern uint32_t _binary_${name}_start __asm(\"_binary_${name}_start\");" >> "${filename}" + echo "extern uint32_t _binary_${name}_end __asm(\"_binary_${name}_end\");" >> "${filename}" + echo "extern uint32_t _binary_${name}_size __asm(\"_binary_${name}_size\");" >> "${filename}" + echo '' >> "${filename}" + echo '#ifdef __cplusplus' >> "${filename}" + echo '}' >> "${filename}" + echo '#endif' >> "${filename}" done } @@ -102,7 +104,7 @@ function boot_classes () { local length=${#boot_classes[@]} for ((i=0;i