diff --git a/Makefile b/Makefile index f320727..0515af8 100644 --- a/Makefile +++ b/Makefile @@ -1,34 +1,7 @@ %.csv: %.ods libreoffice --headless --convert-to csv:"Text - txt - csv (StarCalc)":44,34,76,,,,true --outdir $(dir $@) $< -%.class: %.java - javac $< - -java/lang/%.class: java/lang/%.java - javac --source 8 --target 8 --boot-class-path . $< - -OBJ = \ - c/decode.o \ - c/class_file.o \ - c/debug_class_file.o \ - c/malloc.o \ - c/file.o \ - c/execute.o \ - c/memory_allocator.o \ - c/class_resolver.o \ - c/hash_table.o \ - c/frame.o \ - c/printf.o \ - c/parse.o \ - c/unparse.o - -MAIN_OBJ = \ - $(OBJ) \ - c/main.o - -PRINT_CLASS_OBJ = \ - $(OBJ) \ - c/print_class.o \ +include java.mk CC ?= gcc ARCH = -m32 @@ -39,10 +12,10 @@ DEPFLAGS = -MMD -MP %.o: %.c $(CC) $(ARCH) $(CFLAGS) $(OPT) $(DEPFLAGS) -MF ${<}.d -c $< -o $@ -print_class: $(PRINT_CLASS_OBJ) +print_class: $(OBJ) $(PRINT_CLASS_OBJ) $(CC) $(ARCH) $^ -o $@ -main: $(MAIN_OBJ) +main: $(OBJ) $(MAIN_HOSTED_OBJ) $(CC) $(ARCH) $^ -o $@ clean: diff --git a/Makefile.dreamcast.mk b/Makefile.dreamcast.mk new file mode 100644 index 0000000..624c35f --- /dev/null +++ b/Makefile.dreamcast.mk @@ -0,0 +1,51 @@ +all: $(patsubst %.cpp,%.elf,$(wildcard example/*.cpp)) + +OPT = -O0 + +MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST))))) +LIB ?= $(MAKEFILE_PATH)/dreamcast +CFLAGS += -D__dreamcast__ -DDEBUG +CFLAGS += -I$(MAKEFILE_PATH) +CFLAGS += -I$(MAKEFILE_PATH)/dreamcast/ +CARCH = -m4-single -ml + +include dreamcast/base.mk +include dreamcast/common.mk +include dreamcast/headers.mk + +include java.mk + +%.class.o: %.class + $(BUILD_BINARY_O) + +%.class.h: %.class + $(BUILD_BINARY_H) + +libgcc/%.o: $(LIBGCC) + @mkdir -p $(dir $@) + ar x --output $(dir $@) $(LIBGCC) $(notdir $@) + sh4-none-elf-objdump -t $@ \ + | grep -E '[.]hidden' \ + | grep -vE 'UND' \ + | cut -d' ' -f10 \ + | xargs rebind --visibility=default $@ + +LIBGCC_OBJ = \ + libgcc/_divdi3.o \ + libgcc/_udiv_qrnnd_16.o \ + libgcc/_clz.o \ + libgcc/_moddi3.o \ + libgcc/_fixdfdi.o \ + libgcc/_fixunsdfdi.o \ + libgcc/_fixunssfdi.o \ + libgcc/_floatdisf.o \ + libgcc/_floatdidf.o \ + libgcc/_sdivsi3.o \ + libgcc/_fixsfdi.o \ + libgcc/_div_table.o + +CLASS_FILES = \ + p/Multiply.class.o + +main.elf: LDSCRIPT = $(LIB)/main.lds +main.elf: $(START_OBJ) $(OBJ) $(MAIN_OBJ) $(MAIN_DREAMCAST_OBJ) $(LIBGCC_OBJ) $(CLASS_FILES) diff --git a/c/assert.h b/c/assert.h index d708512..48beede 100644 --- a/c/assert.h +++ b/c/assert.h @@ -1,11 +1,7 @@ #pragma once -#if defined(__linux__) -#include "assert_hosted.h" -#elif defined(_WIN32) -#include "assert_hosted.h" -#elif defined(__APPLE__) -#include "assert_hosted.h" -#else +#if defined(__dreamcast__) #include "assert_dreamcast.h" +#else +#include "assert_hosted.h" #endif diff --git a/c/assert_dreamcast.h b/c/assert_dreamcast.h index cdf3044..089e4ff 100644 --- a/c/assert_dreamcast.h +++ b/c/assert_dreamcast.h @@ -1,3 +1,11 @@ #pragma once -#define assert(b) +#include "printf.h" + +#define assert(b) \ + do { \ + if (!(b)) { \ + printf("%s:%d %s: assertion `%s` failed\n", __FILE__, __LINE__, __func__, #b); \ + while (1); \ + } \ + } while (0); diff --git a/c/class_resolver.c b/c/class_resolver.c index 0885e10..6cd290d 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -147,9 +147,9 @@ static void class_resolver_allocate_attribute_entry(struct class_entry * class_e class_entry->attribute_entry = attribute_entry; } -struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t * class_names[], - const int class_names_length[], - uint8_t * buffers[], +struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** class_names, + const int * class_names_length, + const uint8_t ** buffers, int length, int * hash_table_length) { diff --git a/c/class_resolver.h b/c/class_resolver.h index 26238ba..793a3fa 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -48,9 +48,9 @@ struct class_entry { } methods; }; -struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t * class_names[], - const int class_names_length[], - uint8_t * buffers[], +struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** class_names, + const int * class_names_length, + const uint8_t ** buffers, int length, int * hash_table_length); struct class_entry * class_resolver_lookup_class(int class_hash_table_length, diff --git a/c/debug_class_file.c b/c/debug_class_file.c index aab185c..470f329 100644 --- a/c/debug_class_file.c +++ b/c/debug_class_file.c @@ -1,5 +1,4 @@ #include -#include #include "assert.h" #include "class_file.h" @@ -51,7 +50,7 @@ void print_constant(struct constant * constant) *(float *)(&constant->_float.bytes)); break; case CONSTANT_Long: - debugf("CONSTANT_Long bytes=%" PRId64 "\n", + debugf("CONSTANT_Long bytes=%l\n", constant->_long.bytes); break; case CONSTANT_Double: diff --git a/c/frame.c b/c/frame.c index 2b57c62..94683c5 100644 --- a/c/frame.c +++ b/c/frame.c @@ -2,7 +2,6 @@ #include "assert.h" #include "class_file.h" -#include "memory.h" #include "debug_class_file.h" #include "bytes.h" #include "decode.h" @@ -75,9 +74,17 @@ static int descriptor_nargs(struct constant * descriptor_constant, uint8_t * ret nargs += 1; while (descriptor_constant->utf8.bytes[i] != ';') i += 1; break; - default: + case 'B': [[fallthrough]]; + case 'C': [[fallthrough]]; + case 'F': [[fallthrough]]; + case 'I': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': nargs += 1; break; + default: + assert(false); + break; } i += 1; } @@ -399,6 +406,7 @@ void vm_start(int class_hash_table_length, class_hash_table, main_class, main_class_length); + assert(class_entry != nullptr); const char * method_name = "main"; diff --git a/c/main_dreamcast.c b/c/main_dreamcast.c new file mode 100644 index 0000000..13bbc37 --- /dev/null +++ b/c/main_dreamcast.c @@ -0,0 +1,41 @@ +#include + +#include "string.h" +#include "class_resolver.h" +#include "frame.h" +#include "printf.h" + +#include "sh7091_scif.h" + +#include "p/Multiply.class.h" + +void main() +{ + scif_init(0); + + const uint8_t * class_names[1]; + int class_names_length[1]; + + class_names[0] = (const uint8_t *)"p/Multiply"; + class_names_length[0] = string_length((const char *)class_names[0]); + + const uint8_t * buffers[1]; + buffers[0] = (const uint8_t *)&_binary_p_Multiply_class_start; + + const uint8_t * main_class = class_names[0]; + int main_class_length = class_names_length[0]; + + int length = (sizeof (class_names)) / (sizeof (class_names[0])); + + int class_hash_table_length; + struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(class_names, + class_names_length, + buffers, + length, + &class_hash_table_length); + + vm_start(class_hash_table_length, + class_hash_table, + main_class, + main_class_length); +} diff --git a/c/main.c b/c/main_hosted.c similarity index 98% rename from c/main.c rename to c/main_hosted.c index 1372d72..5220462 100644 --- a/c/main.c +++ b/c/main_hosted.c @@ -31,7 +31,7 @@ static struct hash_table_entry * load_from_filenames(const char * filenames[], i struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(class_names, class_names_length, - buffers, + (const uint8_t **)buffers, length, hash_table_length); diff --git a/c/sh7091_scif.cpp b/c/sh7091_scif.cpp index c5cf598..7dde06a 100644 --- a/c/sh7091_scif.cpp +++ b/c/sh7091_scif.cpp @@ -3,6 +3,62 @@ #include "sh7091_scif.h" +void scif_init_wait() +{ + sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1 + sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture; + sh7091.TMU.TCR1 = tmu::tcr1::tpsc::p_phi_1024; // 1024 / 50MHz = 20.48 μs + sh7091.TMU.TCOR1 = 0xffff'ffff; + sh7091.TMU.TCNT1 = 0xffff'ffff; + sh7091.TMU.TSTR |= tmu::tstr::str1::counter_start; + + uint32_t start = sh7091.TMU.TCNT1; + while ((start - sh7091.TMU.TCNT1) < 20); + + sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1 +} + +void scif_init(int bit_rate) +{ + using namespace scif; + + sh7091.SCIF.SCSCR2 = 0; // disable transmission / reception + + sh7091.SCIF.SCSPTR2 = 0; // clear output data pins + + sh7091.SCIF.SCFCR2 = scfcr2::tfrst::reset_operation_enabled + | scfcr2::rfrst::reset_operation_enabled; + + sh7091.SCIF.SCSMR2 = scsmr2::chr::_8_bit_data + | scsmr2::pe::parity_disabled + | scsmr2::stop::_1_stop_bit + | scsmr2::cks::p_phi_clock; + + sh7091.SCIF.SCBRR2 = bit_rate; // bps = 1562500 / (SCBRR2 + 1) + + sh7091.SCIF.SCFSR2 = (~scfsr2::er::bit_mask) + & (~scfsr2::tend::bit_mask) + & (~scfsr2::tdfe::bit_mask) + & (~scfsr2::brk::bit_mask) + & (~scfsr2::rdf::bit_mask) + & (~scfsr2::dr::bit_mask) + & 0xffff; + + + // wait 1 bit interval + scif_init_wait(); + + sh7091.SCIF.SCFCR2 = scfcr2::rtrg::trigger_on_1_byte + | scfcr2::ttrg::trigger_on_8_bytes + //| scfcr2::mce::modem_signals_enabled + ; + + sh7091.SCIF.SCSCR2 = scscr2::te::transmission_enabled + | scscr2::re::reception_enabled; + + sh7091.SCIF.SCLSR2 = 0; // clear ORER +} + void scif_character(const char c) { using namespace scif; diff --git a/c/sh7091_scif.h b/c/sh7091_scif.h index 419a1f5..55cbaee 100644 --- a/c/sh7091_scif.h +++ b/c/sh7091_scif.h @@ -4,6 +4,8 @@ extern "C" { #endif +void scif_init_wait(); +void scif_init(int bit_rate); void scif_character(const char c); #ifdef __cplusplus diff --git a/dreamcast b/dreamcast new file mode 120000 index 0000000..c64555a --- /dev/null +++ b/dreamcast @@ -0,0 +1 @@ +../dreamcast \ No newline at end of file diff --git a/java.mk b/java.mk new file mode 100644 index 0000000..15cf965 --- /dev/null +++ b/java.mk @@ -0,0 +1,31 @@ +%.class: %.java + javac $< + +java/lang/%.class: java/lang/%.java + javac --source 8 --target 8 --boot-class-path . $< + +OBJ = \ + c/decode.o \ + c/class_file.o \ + c/debug_class_file.o \ + c/malloc.o \ + c/execute.o \ + c/memory_allocator.o \ + c/class_resolver.o \ + c/hash_table.o \ + c/frame.o \ + c/printf.o \ + c/parse.o \ + c/unparse.o + +MAIN_DREAMCAST_OBJ = \ + c/sh7091_scif.o \ + c/main_dreamcast.o + +MAIN_HOSTED_OBJ = \ + c/file.o \ + c/main_hosted.o + +PRINT_CLASS_OBJ = \ + c/file.o \ + c/print_class.o diff --git a/p/Multiply.class.h b/p/Multiply.class.h new file mode 100644 index 0000000..f502b96 --- /dev/null +++ b/p/Multiply.class.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_p_Multiply_class_start __asm("_binary_p_Multiply_class_start"); +extern uint32_t _binary_p_Multiply_class_end __asm("_binary_p_Multiply_class_end"); +extern uint32_t _binary_p_Multiply_class_size __asm("_binary_p_Multiply_class_size"); + +#ifdef __cplusplus +} +#endif diff --git a/p/Multiply.java b/p/Multiply.java new file mode 100644 index 0000000..0fff10b --- /dev/null +++ b/p/Multiply.java @@ -0,0 +1,10 @@ +package p; + +class Multiply { + static int test(int a, int b) { + return a * b; + } + public static void main() { + test(6, 8); + } +}