From a30c3f54c1469f410e873d161d5ca3cf6e822c97 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 22 Jan 2025 02:09:03 -0600 Subject: [PATCH] gcc 4.9 compatibility --- Makefile.dreamcast.mk | 7 ++- c/backtrace.c | 4 ++ c/backtrace.h | 1 + c/class_file.c | 12 ++--- c/class_file.h | 1 + c/class_resolver.h | 1 + c/compat.h | 25 ++++++++++ c/debug_class_file.c | 10 ++-- c/execute.c | 64 ++++++++++++------------ c/execute.h | 2 +- c/field_size.h | 28 +++++------ c/file.h | 1 + c/find_attribute.h | 1 + c/gc.h | 1 + c/hash_table.h | 1 + c/main_dreamcast.c | 2 +- c/malloc.h | 1 + c/memory_allocator.h | 1 + c/native/class.h | 2 +- c/native/libcinputstream.h | 2 +- c/native/math.c | 18 +++++-- c/native/object.h | 2 +- c/native/printstream.h | 2 +- c/native_method.h | 1 + c/native_types.h | 16 +++--- c/native_types_allocate.h | 1 + c/parse.h | 1 + c/printf.c | 2 +- c/sh7091_scif.c | 65 ++++++++++++++++++++++++ c/sh7091_scif.cpp | 71 -------------------------- c/sh7091_scif.h | 100 +++++++++++++++++++++++++++++++++++++ c/string.h | 2 + c/unparse.h | 3 ++ c/vm.c | 28 +++++------ c/vm.h | 1 + c/vm_instance.h | 1 + generate_classpath.sh | 4 +- jvm-build.sh | 2 +- 38 files changed, 321 insertions(+), 166 deletions(-) create mode 100644 c/compat.h create mode 100644 c/sh7091_scif.c delete mode 100644 c/sh7091_scif.cpp diff --git a/Makefile.dreamcast.mk b/Makefile.dreamcast.mk index e9e3a9d..5d4e0ea 100644 --- a/Makefile.dreamcast.mk +++ b/Makefile.dreamcast.mk @@ -1,6 +1,8 @@ all: $(patsubst %.cpp,%.elf,$(wildcard example/*.cpp)) -OPT = -Og +OPT = -O2 + +CSTD = -std=gnu11 MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST))))) LIB ?= $(MAKEFILE_PATH)/dreamcast @@ -48,7 +50,8 @@ LIBGCC_OBJ = \ libgcc/_sdivsi3.o \ libgcc/_fixsfdi.o \ libgcc/_div_table.o \ - libgcc/_movmem_i4.o + libgcc/_movmem_i4.o \ + libgcc/_set_fpscr.o include classpath.mk diff --git a/c/backtrace.c b/c/backtrace.c index c28e884..238784c 100644 --- a/c/backtrace.c +++ b/c/backtrace.c @@ -6,6 +6,10 @@ #include "native_types_allocate.h" #include "vm_instance.h" +int abort() { + while (1); +} + struct objectref * backtrace_allocate(struct vm * vm) { struct objectref * objectref = vm_instance_create(vm, "java/lang/Backtrace"); diff --git a/c/backtrace.h b/c/backtrace.h index 0fef3e6..667720b 100644 --- a/c/backtrace.h +++ b/c/backtrace.h @@ -2,6 +2,7 @@ #include "native_types.h" #include "vm.h" +#include "compat.h" struct backtrace_entry { struct class_file * class_file; diff --git a/c/class_file.c b/c/class_file.c index 8a72855..47435dd 100644 --- a/c/class_file.c +++ b/c/class_file.c @@ -144,8 +144,8 @@ struct class_file * class_file_parse(const uint8_t * buf) case CONSTANT_Class: constant->class.name_index = parse_u2(&buf); break; - case CONSTANT_Fieldref: [[fallthrough]]; - case CONSTANT_Methodref: [[fallthrough]]; + case CONSTANT_Fieldref: /* fall through */; + case CONSTANT_Methodref: /* fall through */; case CONSTANT_InterfaceMethodref: constant->fieldref.class_index = parse_u2(&buf); constant->fieldref.name_and_type_index = parse_u2(&buf); @@ -153,11 +153,11 @@ struct class_file * class_file_parse(const uint8_t * buf) case CONSTANT_String: constant->string.string_index = parse_u2(&buf); break; - case CONSTANT_Integer: [[fallthrough]]; + case CONSTANT_Integer: /* fall through */; case CONSTANT_Float: constant->integer.bytes = parse_u4(&buf); break; - case CONSTANT_Long: [[fallthrough]]; + case CONSTANT_Long: /* fall through */; case CONSTANT_Double: { uint64_t high_bytes = parse_u4(&buf); @@ -183,12 +183,12 @@ struct class_file * class_file_parse(const uint8_t * buf) case CONSTANT_MethodType: constant->methodtype.descriptor_index = parse_u2(&buf); break; - case CONSTANT_Dynamic: [[fallthrough]]; + case CONSTANT_Dynamic: /* fall through */; case CONSTANT_InvokeDynamic: constant->dynamic.bootstrap_method_attr_index = parse_u2(&buf); constant->dynamic.name_and_type_index = parse_u2(&buf); break; - case CONSTANT_Module: [[fallthrough]]; + case CONSTANT_Module: /* fall through */; case CONSTANT_Package: constant->module.name_index = parse_u2(&buf); break; diff --git a/c/class_file.h b/c/class_file.h index 6c7bf48..171c5a7 100644 --- a/c/class_file.h +++ b/c/class_file.h @@ -1,6 +1,7 @@ #pragma once #include +#include "compat.h" typedef uint64_t u8; typedef uint32_t u4; diff --git a/c/class_resolver.h b/c/class_resolver.h index 25f0312..502c132 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -6,6 +6,7 @@ #include "hash_table.h" #include "native_types.h" #include "vm.h" +#include "compat.h" struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buffers, int length, diff --git a/c/compat.h b/c/compat.h new file mode 100644 index 0000000..93e0a2f --- /dev/null +++ b/c/compat.h @@ -0,0 +1,25 @@ +#pragma once + +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof (type, member) +#endif + +#ifndef bool +#define bool int +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef static_assert +#define static_assert(s) _Static_assert(s, ""); +#endif + +#ifndef nullptr +#define nullptr ((void *)0) +#endif diff --git a/c/debug_class_file.c b/c/debug_class_file.c index 9b5b75a..384d1ed 100644 --- a/c/debug_class_file.c +++ b/c/debug_class_file.c @@ -157,9 +157,9 @@ static void print_methodhandle_constant(const char * indent, struct constant * m for (int i = 0; i < (sizeof (indent2)) - 1; i++) indent2[i] = ' '; switch (methodhandle_constant->methodhandle.reference_kind) { - case REF_getField: [[fallthrough]]; - case REF_getStatic: [[fallthrough]]; - case REF_putField: [[fallthrough]]; + case REF_getField: /* fall through */; + case REF_getStatic: /* fall through */; + case REF_putField: /* fall through */; case REF_putStatic: // If the value of the reference_kind item is 1 (REF_getField), 2 // (REF_getStatic), 3 (REF_putField), or 4 (REF_putStatic), then the @@ -169,7 +169,7 @@ static void print_methodhandle_constant(const char * indent, struct constant * m assert(constant->tag == CONSTANT_Fieldref); print_methodref(indent2, constant, constant_pool); break; - case REF_invokeVirtual: [[fallthrough]]; + case REF_invokeVirtual: /* fall through */; case REF_newInvokeSpecial: // If the value of the reference_kind item is 5 (REF_invokeVirtual) or 8 // (REF_newInvokeSpecial), then the constant_pool entry at that index must be @@ -178,7 +178,7 @@ static void print_methodhandle_constant(const char * indent, struct constant * m assert(constant->tag == CONSTANT_Methodref); print_methodref(indent2, constant, constant_pool); break; - case REF_invokeStatic: [[fallthrough]]; + case REF_invokeStatic: /* fall through */; case REF_invokeSpecial: // If the value of the reference_kind item is 6 (REF_invokeStatic) or 7 // (REF_invokeSpecial), [...] the constant_pool entry at that index must be diff --git a/c/execute.c b/c/execute.c index 8c4fbb6..793d0a0 100644 --- a/c/execute.c +++ b/c/execute.c @@ -772,20 +772,20 @@ void op_getfield(struct vm * vm, uint32_t index) debugf("getfield instance_index %d\n", field_entry->instance_index); switch (field_descriptor_constant->utf8.bytes[0]) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': { void * value = objectref->oref[field_entry->instance_index]; operand_stack_push_ref(vm->current_frame, value); } break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': { void * low = objectref->oref[field_entry->instance_index]; @@ -818,20 +818,20 @@ void op_getstatic(struct vm * vm, uint32_t index) return; switch (field_descriptor_constant->utf8.bytes[0]) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': { uint32_t value = class_entry->static_fields[field_entry->static_index]; operand_stack_push_u32(vm->current_frame, value); } break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': { uint32_t low = class_entry->static_fields[field_entry->static_index]; @@ -1942,13 +1942,13 @@ void op_putfield(struct vm * vm, uint32_t index) debugf("putfield instance_index %d\n", field_entry->instance_index); switch (field_descriptor_constant->utf8.bytes[0]) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); @@ -1958,7 +1958,7 @@ void op_putfield(struct vm * vm, uint32_t index) objectref->u32[field_entry->instance_index] = value; } break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': { uint32_t high = operand_stack_pop_u32(vm->current_frame); @@ -2002,20 +2002,20 @@ void op_putstatic(struct vm * vm, uint32_t index) return; switch (field_descriptor_constant->utf8.bytes[0]) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); class_entry->static_fields[field_entry->static_index] = value; } break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': { uint32_t high = operand_stack_pop_u32(vm->current_frame); diff --git a/c/execute.h b/c/execute.h index dc2fd3e..7ff06ac 100644 --- a/c/execute.h +++ b/c/execute.h @@ -1,7 +1,7 @@ #pragma once #include - +#include "compat.h" #include "vm.h" void op_aaload(struct vm * vm); diff --git a/c/field_size.h b/c/field_size.h index 0017ffb..219dfa2 100644 --- a/c/field_size.h +++ b/c/field_size.h @@ -3,16 +3,16 @@ static inline int field_size(uint8_t c) { switch (c) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': return 1; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': return 2; default: @@ -23,18 +23,18 @@ static inline int field_size(uint8_t c) static inline int field_size_array(uint8_t c) { switch (c) { - case 'Z': [[fallthrough]]; // boolean + case 'Z': /* fall through */; // boolean case 'B': // byte return 1; - case 'C': [[fallthrough]]; // char + case 'C': /* fall through */; // char case 'S': // short return 2; - case 'F': [[fallthrough]]; // float - case 'I': [[fallthrough]]; // int - case 'L': [[fallthrough]]; // classref + case 'F': /* fall through */; // float + case 'I': /* fall through */; // int + case 'L': /* fall through */; // classref case '[': // arrayref return 4; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': return 8; default: diff --git a/c/file.h b/c/file.h index 9cbc9c4..b0605c3 100644 --- a/c/file.h +++ b/c/file.h @@ -2,5 +2,6 @@ #include #include +#include "compat.h" uint8_t * file_read(const char * path, size_t * file_size); diff --git a/c/find_attribute.h b/c/find_attribute.h index bffbca6..c2b2b84 100644 --- a/c/find_attribute.h +++ b/c/find_attribute.h @@ -1,6 +1,7 @@ #pragma once #include "class_file.h" +#include "compat.h" int find_code_name_index(struct class_file * class_file); int find_constantvalue_name_index(struct class_file * class_file); diff --git a/c/gc.h b/c/gc.h index bd41b47..242ba5a 100644 --- a/c/gc.h +++ b/c/gc.h @@ -1,6 +1,7 @@ #pragma once #include "vm.h" +#include "compat.h" void gc_mark(struct vm * vm); void gc_sweep(); diff --git a/c/hash_table.h b/c/hash_table.h index 3331324..5776a34 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -1,6 +1,7 @@ #pragma once #include +#include "compat.h" struct hash_table_entry { const uint8_t * key; diff --git a/c/main_dreamcast.c b/c/main_dreamcast.c index 7d62230..20a84a3 100644 --- a/c/main_dreamcast.c +++ b/c/main_dreamcast.c @@ -11,7 +11,7 @@ void main() { - scif_init(0); + //scif_init(0); const uint8_t * class_file_buffers[] = { #include "classpath.inc.c" diff --git a/c/malloc.h b/c/malloc.h index 94af943..f7adc20 100644 --- a/c/malloc.h +++ b/c/malloc.h @@ -1,6 +1,7 @@ #pragma once #include +#include "compat.h" void malloc_class_arena_reset(); void * malloc_class_arena(uint32_t size); diff --git a/c/memory_allocator.h b/c/memory_allocator.h index 9fac3e3..c595e99 100644 --- a/c/memory_allocator.h +++ b/c/memory_allocator.h @@ -1,6 +1,7 @@ #pragma once #include +#include "compat.h" void memory_reset_free_list(); void * memory_allocate(uint32_t size); diff --git a/c/native/class.h b/c/native/class.h index cbe7855..3a26564 100644 --- a/c/native/class.h +++ b/c/native/class.h @@ -1,7 +1,7 @@ #pragma once #include - +#include "compat.h" #include "vm.h" void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args); diff --git a/c/native/libcinputstream.h b/c/native/libcinputstream.h index 8b06ad3..9333287 100644 --- a/c/native/libcinputstream.h +++ b/c/native/libcinputstream.h @@ -1,7 +1,7 @@ #pragma once #include - +#include "compat.h" #include "vm.h" void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args); diff --git a/c/native/math.c b/c/native/math.c index b1a98b0..145a692 100644 --- a/c/native/math.c +++ b/c/native/math.c @@ -1,18 +1,28 @@ #include "math.h" -void __attribute__ ((noinline)) __attribute__ ((optimize(0))) +float __attribute__ ((noinline)) cosf(float f) +{ + return __builtin_cosf(f); +} + +float __attribute__ ((noinline)) sinf(float f) +{ + return __builtin_sinf(f); +} + +void native_java_lang_math_sin_1(struct vm * vm, uint32_t * args) { float arg = ((float *)args)[0]; - float value = __builtin_sinf(arg); + float value = sinf(arg); operand_stack_push_f32(vm->current_frame, value); } -void __attribute__ ((noinline)) __attribute__ ((optimize(0))) +void native_java_lang_math_cos_1(struct vm * vm, uint32_t * args) { float arg = ((float *)args)[0]; - float value = __builtin_cosf(arg); + float value = cosf(arg); operand_stack_push_f32(vm->current_frame, value); } diff --git a/c/native/object.h b/c/native/object.h index 54a5cdc..a9986ce 100644 --- a/c/native/object.h +++ b/c/native/object.h @@ -1,7 +1,7 @@ #pragma once #include - +#include "compat.h" #include "vm.h" void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args); diff --git a/c/native/printstream.h b/c/native/printstream.h index 0996a1a..0827ab0 100644 --- a/c/native/printstream.h +++ b/c/native/printstream.h @@ -1,7 +1,7 @@ #pragma once #include - +#include "compat.h" #include "vm.h" void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args); diff --git a/c/native_method.h b/c/native_method.h index d678375..b7e5cc7 100644 --- a/c/native_method.h +++ b/c/native_method.h @@ -1,6 +1,7 @@ #pragma once #include "vm.h" +#include "compat.h" struct hash_table_entry * native_init_hash_table(int * hash_table_length); diff --git a/c/native_types.h b/c/native_types.h index c5a36af..31b69f4 100644 --- a/c/native_types.h +++ b/c/native_types.h @@ -64,20 +64,20 @@ enum ARRAY_TYPE { static inline int array_element_size(int atype) { switch (atype) { - case T_BOOLEAN: [[fallthrough]]; // 1 byte - case T_BYTE: // 1 byte + case T_BOOLEAN: /* fall through */; // 1 byte + case T_BYTE: // 1 byte return 1; break; - case T_CHAR: [[fallthrough]]; // 2 bytes - case T_SHORT: // 2 bytes + case T_CHAR: /* fall through */; // 2 bytes + case T_SHORT: // 2 bytes return 2; break; - case T_FLOAT: [[fallthrough]]; // 4 bytes - case T_INT: // 4 bytes + case T_FLOAT: /* fall through */; // 4 bytes + case T_INT: // 4 bytes return 4; break; - case T_DOUBLE: [[fallthrough]]; // 8 bytes - case T_LONG: // 8 bytes + case T_DOUBLE: /* fall through */; // 8 bytes + case T_LONG: // 8 bytes return 8; break; default: diff --git a/c/native_types_allocate.h b/c/native_types_allocate.h index fbf93cc..a77e5bc 100644 --- a/c/native_types_allocate.h +++ b/c/native_types_allocate.h @@ -4,6 +4,7 @@ #include "gc.h" #include "vm.h" #include "memory_allocator.h" +#include "compat.h" static inline void * gc_memory_allocate(struct vm * vm, int size) { diff --git a/c/parse.h b/c/parse.h index 3e7f4e4..022b84c 100644 --- a/c/parse.h +++ b/c/parse.h @@ -1,6 +1,7 @@ #pragma once #include +#include "compat.h" #ifdef __cplusplus extern "C" { diff --git a/c/printf.c b/c/printf.c index 5639f2d..d733991 100644 --- a/c/printf.c +++ b/c/printf.c @@ -143,7 +143,7 @@ void _printf(const char * format, ...) print_char('0'); print_char('x'); } - [[fallthrough]]; + /* fall through */; case FORMAT_BASE16: { uint32_t num = va_arg(args, uint32_t); diff --git a/c/sh7091_scif.c b/c/sh7091_scif.c new file mode 100644 index 0000000..fe00629 --- /dev/null +++ b/c/sh7091_scif.c @@ -0,0 +1,65 @@ +#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 = 0xffffffff; + sh7091_TMU.TCNT1 = 0xffffffff; + 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) +{ + 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) +{ + // wait for transmit fifo to become partially empty + while ((sh7091_SCIF.SCFSR2 & scfsr2__tdfe__bit_mask) == 0); + + sh7091_SCIF.SCFSR2 &= ~scfsr2__tdfe__bit_mask; + + sh7091_SCIF.SCFTDR2 = (uint8_t)(c); +} diff --git a/c/sh7091_scif.cpp b/c/sh7091_scif.cpp deleted file mode 100644 index 7dde06a..0000000 --- a/c/sh7091_scif.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "sh7091/sh7091.hpp" -#include "sh7091/sh7091_bits.hpp" - -#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; - // wait for transmit fifo to become partially empty - while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0); - - sh7091.SCIF.SCFSR2 &= ~scfsr2::tdfe::bit_mask; - - sh7091.SCIF.SCFTDR2 = static_cast(c); -} diff --git a/c/sh7091_scif.h b/c/sh7091_scif.h index 55cbaee..493ac11 100644 --- a/c/sh7091_scif.h +++ b/c/sh7091_scif.h @@ -1,13 +1,113 @@ #pragma once +#include +#include "compat.h" + #ifdef __cplusplus extern "C" { #endif +typedef volatile uint8_t reg8; +typedef volatile uint16_t reg16; +typedef volatile uint32_t reg32; + +static_assert((sizeof (reg8)) == 1); +static_assert((sizeof (reg16)) == 2); +static_assert((sizeof (reg32)) == 4); + +struct scif_reg { + reg16 SCSMR2; /* Serial mode register 2 */ + reg8 _pad0[2]; + reg8 SCBRR2; /* Bit rate register 2 */ + reg8 _pad1[3]; + reg16 SCSCR2; /* Serial control register 2 */ + reg8 _pad2[2]; + reg8 SCFTDR2; /* Transmit FIFO data register 2 */ + reg8 _pad3[3]; + reg16 SCFSR2; /* Serial status register 2 */ + reg8 _pad4[2]; + reg8 SCFRDR2; /* Receive FIFO data register 2 */ + reg8 _pad5[3]; + reg16 SCFCR2; /* FIFO control register */ + reg8 _pad6[2]; + reg16 SCFDR2; /* FIFO data count register */ + reg8 _pad7[2]; + reg16 SCSPTR2; /* Serial port register 2 */ + reg8 _pad8[2]; + reg16 SCLSR2; /* Line status register 2 */ +}; + +static_assert((offsetof (struct scif_reg, SCSMR2)) == 0x0); +static_assert((offsetof (struct scif_reg, SCBRR2)) == 0x4); +static_assert((offsetof (struct scif_reg, SCSCR2)) == 0x8); +static_assert((offsetof (struct scif_reg, SCFTDR2)) == 0xc); +static_assert((offsetof (struct scif_reg, SCFSR2)) == 0x10); +static_assert((offsetof (struct scif_reg, SCFRDR2)) == 0x14); +static_assert((offsetof (struct scif_reg, SCFCR2)) == 0x18); +static_assert((offsetof (struct scif_reg, SCFDR2)) == 0x1c); +static_assert((offsetof (struct scif_reg, SCSPTR2)) == 0x20); +static_assert((offsetof (struct scif_reg, SCLSR2)) == 0x24); + +struct tmu_reg { + reg8 TOCR; /* Timer output control register */ + reg8 _pad0[3]; + reg8 TSTR; /* Timer start register */ + reg8 _pad1[3]; + reg32 TCOR0; /* Timer constant register 0 */ + reg32 TCNT0; /* Timer counter 0 */ + reg16 TCR0; /* Timer control register 0 */ + reg8 _pad2[2]; + reg32 TCOR1; /* Timer constant register 1 */ + reg32 TCNT1; /* Timer counter 1 */ + reg16 TCR1; /* Timer control register 1 */ + reg8 _pad3[2]; + reg32 TCOR2; /* Timer constant register 2 */ + reg32 TCNT2; /* Timer counter 2 */ + reg16 TCR2; /* Timer control register 2 */ + reg8 _pad4[2]; + reg32 TCPR2; /* Timer input capture register 2 */ +}; + +static_assert((offsetof (struct tmu_reg, TOCR)) == 0x0); +static_assert((offsetof (struct tmu_reg, TSTR)) == 0x4); +static_assert((offsetof (struct tmu_reg, TCOR0)) == 0x8); +static_assert((offsetof (struct tmu_reg, TCNT0)) == 0xc); +static_assert((offsetof (struct tmu_reg, TCR0)) == 0x10); +static_assert((offsetof (struct tmu_reg, TCOR1)) == 0x14); +static_assert((offsetof (struct tmu_reg, TCNT1)) == 0x18); +static_assert((offsetof (struct tmu_reg, TCR1)) == 0x1c); +static_assert((offsetof (struct tmu_reg, TCOR2)) == 0x20); +static_assert((offsetof (struct tmu_reg, TCNT2)) == 0x24); +static_assert((offsetof (struct tmu_reg, TCR2)) == 0x28); +static_assert((offsetof (struct tmu_reg, TCPR2)) == 0x2c); + +#define tmu__tstr__str1__counter_start (1 << 2) +#define tmu__tocr__tcoe__tclk_is_external_clock_or_input_capture (0 << 0) +#define tmu__tcr1__tpsc__p_phi_1024 (0b100 << 0) +#define scfcr2__tfrst__reset_operation_enabled (1 << 2) +#define scfcr2__rfrst__reset_operation_enabled (1 << 1) +#define scsmr2__chr__8_bit_data (0 << 6) +#define scsmr2__pe__parity_disabled (0 << 5) +#define scsmr2__stop__1_stop_bit (0 << 3) +#define scsmr2__cks__p_phi_clock (0b00 << 0) +#define scfsr2__er__bit_mask (0x1 << 7) +#define scfsr2__tend__bit_mask (0x1 << 6) +#define scfsr2__tdfe__bit_mask (0x1 << 5) +#define scfsr2__brk__bit_mask (0x1 << 4) +#define scfsr2__rdf__bit_mask (0x1 << 1) +#define scfsr2__dr__bit_mask (0x1 << 0) +#define scfcr2__rtrg__trigger_on_1_byte (0b00 << 6) +#define scfcr2__ttrg__trigger_on_8_bytes (0b00 << 4) +#define scscr2__te__transmission_enabled (1 << 5) +#define scscr2__re__reception_enabled (1 << 4) + void scif_init_wait(); void scif_init(int bit_rate); void scif_character(const char c); +extern struct tmu_reg sh7091_TMU __asm("sh7091_TMU"); +extern struct scif_reg sh7091_SCIF __asm("sh7091_SCIF"); + #ifdef __cplusplus } #endif diff --git a/c/string.h b/c/string.h index 5fab4c5..f0a5ecd 100644 --- a/c/string.h +++ b/c/string.h @@ -1,5 +1,7 @@ #pragma once +#include "compat.h" + static inline int string_length(const char * s) { const char * si = s; diff --git a/c/unparse.h b/c/unparse.h index 3f80008..7232354 100644 --- a/c/unparse.h +++ b/c/unparse.h @@ -1,5 +1,8 @@ #pragma once +#include +#include "compat.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/c/vm.c b/c/vm.c index fb0beaf..c007cb8 100644 --- a/c/vm.c +++ b/c/vm.c @@ -33,7 +33,7 @@ int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_typ switch (byte) { case '[': break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': nargs += 2; break; @@ -41,11 +41,11 @@ int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_typ nargs += 1; while (descriptor_constant->utf8.bytes[i] != ';') i += 1; break; - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'S': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'S': /* fall through */; case 'Z': nargs += 1; break; @@ -304,20 +304,20 @@ void vm_method_return(struct vm * vm) */ switch (old_frame->return_type) { - case 'B': [[fallthrough]]; - case 'C': [[fallthrough]]; - case 'F': [[fallthrough]]; - case 'I': [[fallthrough]]; - case 'L': [[fallthrough]]; - case 'S': [[fallthrough]]; - case 'Z': [[fallthrough]]; + case 'B': /* fall through */; + case 'C': /* fall through */; + case 'F': /* fall through */; + case 'I': /* fall through */; + case 'L': /* fall through */; + case 'S': /* fall through */; + case 'Z': /* fall through */; case '[': { uint32_t value = operand_stack_pop_u32(old_frame); operand_stack_push_u32(vm->current_frame, value); } break; - case 'D': [[fallthrough]]; + case 'D': /* fall through */; case 'J': { uint64_t value = operand_stack_pop_u64(old_frame); diff --git a/c/vm.h b/c/vm.h index ee80dbc..2e192e1 100644 --- a/c/vm.h +++ b/c/vm.h @@ -2,6 +2,7 @@ #include "frame_stack.h" #include "class_file.h" +#include "compat.h" bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry); void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry); diff --git a/c/vm_instance.h b/c/vm_instance.h index b6ef9a5..c9a6529 100644 --- a/c/vm_instance.h +++ b/c/vm_instance.h @@ -1,6 +1,7 @@ #pragma once #include "vm.h" +#include "compat.h" struct objectref * vm_instance_create(struct vm * vm, const char * class_name); struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant); diff --git a/generate_classpath.sh b/generate_classpath.sh index 29b927d..c0ba867 100644 --- a/generate_classpath.sh +++ b/generate_classpath.sh @@ -221,14 +221,14 @@ set -eux find . -name '*.class' -not -path "./classes/java/*" -exec rm -f {} \; -make -f Makefile.dreamcast.mk $(boot_sources | java_to_class) +make -f Makefile.dreamcast.mk TARGET=sh-elf- $(boot_sources | java_to_class) find . -name '*.class' | rename_class_files boot_classes | classpath_mk boot_classes | classpath_inc_c boot_classes | make_header boot_classes | classpath_h -make -f Makefile.dreamcast.mk $(application_sources | java_to_class) +make -f Makefile.dreamcast.mk TARGET=sh-elf- $(application_sources | java_to_class) find . -name '*.class' | rename_class_files boot_classes | sort > classes.txt diff --git a/jvm-build.sh b/jvm-build.sh index 9357b4d..0d224cf 100644 --- a/jvm-build.sh +++ b/jvm-build.sh @@ -2,5 +2,5 @@ set -eux sh generate_classpath.sh rm -f main.bin main.elf jvm.iso -make -f Makefile.dreamcast.mk jvm.iso +make -f Makefile.dreamcast.mk TARGET=sh-elf- jvm.iso ../cdi4dc jvm.iso jvm.cdi > /dev/null