gcc 4.9 compatibility

This commit is contained in:
Zack Buhman 2025-01-22 02:09:03 -06:00
parent 44fbfc7f29
commit a30c3f54c1
38 changed files with 321 additions and 166 deletions

View File

@ -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

View File

@ -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");

View File

@ -2,6 +2,7 @@
#include "native_types.h"
#include "vm.h"
#include "compat.h"
struct backtrace_entry {
struct class_file * class_file;

View File

@ -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;

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
typedef uint64_t u8;
typedef uint32_t u4;

View File

@ -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,

25
c/compat.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#include "vm.h"
void op_aaload(struct vm * vm);

View File

@ -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:

View File

@ -2,5 +2,6 @@
#include <stdint.h>
#include <stddef.h>
#include "compat.h"
uint8_t * file_read(const char * path, size_t * file_size);

View File

@ -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);

1
c/gc.h
View File

@ -1,6 +1,7 @@
#pragma once
#include "vm.h"
#include "compat.h"
void gc_mark(struct vm * vm);
void gc_sweep();

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
struct hash_table_entry {
const uint8_t * key;

View File

@ -11,7 +11,7 @@
void main()
{
scif_init(0);
//scif_init(0);
const uint8_t * class_file_buffers[] = {
#include "classpath.inc.c"

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
void malloc_class_arena_reset();
void * malloc_class_arena(uint32_t size);

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
void memory_reset_free_list();
void * memory_allocate(uint32_t size);

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#include "vm.h"
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args);

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#include "vm.h"
void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args);

View File

@ -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);
}

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#include "vm.h"
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#include "vm.h"
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args);

View File

@ -1,6 +1,7 @@
#pragma once
#include "vm.h"
#include "compat.h"
struct hash_table_entry * native_init_hash_table(int * hash_table_length);

View File

@ -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:

View File

@ -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)
{

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#ifdef __cplusplus
extern "C" {

View File

@ -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);

65
c/sh7091_scif.c Normal file
View File

@ -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);
}

View File

@ -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<uint8_t>(c);
}

View File

@ -1,13 +1,113 @@
#pragma once
#include <stdint.h>
#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

View File

@ -1,5 +1,7 @@
#pragma once
#include "compat.h"
static inline int string_length(const char * s)
{
const char * si = s;

View File

@ -1,5 +1,8 @@
#pragma once
#include <stdint.h>
#include "compat.h"
#ifdef __cplusplus
extern "C" {
#endif

28
c/vm.c
View File

@ -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);

1
c/vm.h
View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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