From f0c7fe825ea23229b8add5985f753f93daceaee1 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Sun, 11 Dec 2016 17:42:53 -0800 Subject: [PATCH] improved aica timer accuracy improved accuracy of aggregate counters updated options in readme removed some bool usage --- README.md | 12 +++-- src/core/assert.h | 10 ++-- src/core/constructor.h | 2 +- src/core/list.c | 20 ++++---- src/core/log.c | 6 +-- src/core/log.h | 4 +- src/core/option.c | 35 +++++++------ src/core/option.h | 20 +------- src/core/profiler.cc | 8 +-- src/core/profiler.h | 4 ++ src/core/ringbuf.cc | 2 +- src/core/string.c | 6 +-- src/emu/emulator.c | 32 +++++++----- src/hw/aica/aica.c | 73 +++++++++++++--------------- src/hw/aica/aica.h | 6 +-- src/hw/dreamcast.c | 2 +- src/hw/memory.c | 44 ++++++++--------- src/hw/memory.h | 6 +-- src/hw/scheduler.h | 7 +-- src/jit/frontend/sh4/sh4_disasm.c | 4 +- src/jit/frontend/sh4/sh4_translate.c | 14 +++--- src/jit/ir/ir.c | 4 -- src/jit/ir/ir.h | 11 +++-- src/jit/jit.c | 3 +- src/main.c | 2 +- src/ui/microprofile.cc | 2 +- tools/recc/README.md | 4 +- tools/recc/recc.c | 12 ++--- 28 files changed, 175 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index 724416f4..097bd41c 100644 --- a/README.md +++ b/README.md @@ -43,11 +43,13 @@ Command line flags are loaded from and saved to `$HOME/.redream/flags` each run. ### All options ``` - --bios Path to BIOS [default: dc_boot.bin] - --flash Path to flash ROM [default: dc_flash.bin] - --debug Start GDB debug server - --perf Write perf-compatible maps for generated code - --profile Path to controller profile + --bios Path to BIOS [default: dc_boot.bin] + --flash Path to flash ROM [default: dc_flash.bin] + --controller Path to controller profile + --throttle Throttle emulation speed to match the original hardware [default: 1] + --verbose Enable debug logging [default: 0] + --perf Write perf-compatible maps for generated code [default: 0] + --gdb Start GDB debug server [default: 0] ``` ### Debugging diff --git a/src/core/assert.h b/src/core/assert.h index 63680cce..7ccbb70c 100644 --- a/src/core/assert.h +++ b/src/core/assert.h @@ -4,7 +4,7 @@ #include "core/debug_break.h" #include "core/log.h" -// CHECK_* macros are usually true, hint this to the compiler if possible +/* CHECK_* macros are usually true, hint this to the compiler if possible */ #if defined(PLATFORM_LINUX) || defined(PLATFORM_DARWIN) #define CHECK_EXPECT_TRUE(expr) (__builtin_expect(!!(expr), 1)) #else @@ -17,8 +17,8 @@ const char *format_check_error_ex(const char *filename, int linenum, const char *format_check_error(const char *filename, int linenum, const char *expr, const char *unused); -// 3: VA_ARGS = format_check_error -// 4+: VA_ARGS = format_check_error_ex +/* 3: VA_ARGS = format_check_error */ +/* 4+: VA_ARGS = format_check_error_ex */ #define SELECT_FORMAT_CHECK_ERROR(_1, _2, _3, _4, _5, _6, NAME, ...) NAME #define EXPAND_FORMAT_CHECK_ERROR(x) x @@ -28,7 +28,7 @@ const char *format_check_error(const char *filename, int linenum, format_check_error_ex, format_check_error_ex, format_check_error_ex, \ format_check_error)(filename, linenum, expr, ##__VA_ARGS__)) -// checks ran for all build configurations +/* checks ran for all build configurations */ #define CHECK_BINARY_OP(v1, v2, op, ...) \ do { \ if (!CHECK_EXPECT_TRUE((v1)op(v2))) { \ @@ -60,7 +60,7 @@ const char *format_check_error(const char *filename, int linenum, } \ } while (0) -// checks ran only for debug builds +/* checks ran only for debug builds */ #ifndef NDEBUG #define DCHECK_EQ(v1, v2, ...) CHECK_EQ(v1, v2, ##__VA_ARGS__) #define DCHECK_NE(v1, v2, ...) CHECK_NE(v1, v2, ##__VA_ARGS__) diff --git a/src/core/constructor.h b/src/core/constructor.h index 6f0ec693..258f51c2 100644 --- a/src/core/constructor.h +++ b/src/core/constructor.h @@ -32,7 +32,7 @@ #else -// not supported +/* not supported */ #endif diff --git a/src/core/list.c b/src/core/list.c index 0bda5df3..0b5c4a08 100644 --- a/src/core/list.c +++ b/src/core/list.c @@ -31,7 +31,7 @@ void list_add_after(struct list *list, struct list_node *after, } } - // no need to check list->tail == NULL, in that case after would be NULL + /* no need to check list->tail == NULL, in that case after would be NULL */ if (list->tail == after) { list->tail = n; } @@ -57,8 +57,8 @@ void list_clear(struct list *list) { list->head = list->tail = NULL; } -// Implements the mergesort for linked lists as described at -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +/* implements the mergesort for linked lists as described at + http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html */ void list_sort(struct list *list, list_node_cmp cmp) { struct list_node *head = list->head; struct list_node *tail = NULL; @@ -72,10 +72,10 @@ void list_sort(struct list *list, list_node_cmp cmp) { tail = NULL; while (p) { - // track the number of lists merged this pass + /* track the number of lists merged this pass */ merges++; - // step q forward k places, tracking the size of p + /* step q forward k places, tracking the size of p */ int psize = 0; int qsize = k; struct list_node *q = p; @@ -84,8 +84,8 @@ void list_sort(struct list *list, list_node_cmp cmp) { q = q->next; } - // merge the list starting at p of length psize with the list starting - // at q of at most, length qsize + /* merge the list starting at p of length psize with the list starting + at q of at most, length qsize */ while (psize || (qsize && q)) { struct list_node *next; @@ -107,7 +107,7 @@ void list_sort(struct list *list, list_node_cmp cmp) { psize--; } - // move merged node to tail + /* move merged node to tail */ if (!tail) { head = next; } else { @@ -124,7 +124,7 @@ void list_sort(struct list *list, list_node_cmp cmp) { tail->next = NULL; } - // if only 1 pair of lists was merged, this is the end + /* if only 1 pair of lists was merged, this is the end */ if (merges <= 1) { break; } @@ -132,7 +132,7 @@ void list_sort(struct list *list, list_node_cmp cmp) { k *= 2; } - // update internal head and tail with sorted head and tail + /* update internal head and tail with sorted head and tail */ list->head = head; list->tail = tail; } diff --git a/src/core/log.c b/src/core/log.c index e7ffb1fd..736071b6 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -2,15 +2,15 @@ #include #include "core/log.h" -DEFINE_OPTION_BOOL(debug, false, "Enable debug logging"); +DEFINE_OPTION_INT(verbose, 0, "Enable debug logging"); void log_line(enum log_level level, const char *format, ...) { static char sbuffer[0x1000]; int buffer_size = sizeof(sbuffer); char *buffer = sbuffer; + /* allocate a temporary buffer if need be to fit the string */ va_list args; - // allocate a temporary buffer if need be to fit the string va_start(args, format); int len = vsnprintf(0, 0, format, args); if (len >= buffer_size) { @@ -40,7 +40,7 @@ void log_line(enum log_level level, const char *format, ...) { printf("%s\n", buffer); #endif - // cleanup the temporary buffer + /* cleanup the temporary buffer */ if (buffer != sbuffer) { free(buffer); } diff --git a/src/core/log.h b/src/core/log.h index 422637f9..e9707e38 100644 --- a/src/core/log.h +++ b/src/core/log.h @@ -5,7 +5,7 @@ #include "core/debug_break.h" #include "core/option.h" -DECLARE_OPTION_BOOL(debug); +DECLARE_OPTION_INT(verbose); enum log_level { LOG_LEVEL_DEBUG, @@ -25,7 +25,7 @@ enum log_level { void log_line(enum log_level level, const char *format, ...); #define LOG_DEBUG(...) \ - if (OPTION_debug) { \ + if (OPTION_verbose) { \ log_line(LOG_LEVEL_DEBUG, ##__VA_ARGS__); \ } diff --git a/src/core/option.c b/src/core/option.c index 2dccd60f..cf3fe4f7 100644 --- a/src/core/option.c +++ b/src/core/option.c @@ -19,13 +19,15 @@ static struct option *options_find(const char *name) { static void options_parse_value(struct option *opt, const char *value) { switch (opt->type) { - case OPT_BOOL: - *(bool *)opt->storage = strcmp(value, "false") && strcmp(value, "0"); - break; - - case OPT_INT: - *(int *)opt->storage = atoi(value); - break; + case OPT_INT: { + if (!strcmp(value, "false")) { + *(int *)opt->storage = 0; + } else if (!strcmp(value, "true")) { + *(int *)opt->storage = 1; + } else { + *(int *)opt->storage = atoi(value); + } + } break; case OPT_STRING: strncpy((char *)opt->storage, value, MAX_OPTION_LENGTH); @@ -37,9 +39,6 @@ static const char *options_format_value(struct option *opt) { static char value[MAX_OPTION_LENGTH]; switch (opt->type) { - case OPT_BOOL: - return *(bool *)opt->storage ? "true" : "false"; - case OPT_INT: snprintf(value, sizeof(value), "%d", *(int *)opt->storage); return value; @@ -65,7 +64,7 @@ void options_parse(int *argc, char ***argv) { for (int i = 1; i < end;) { char *arg = (*argv)[i]; - // move non-option to the end for parsing by the application + /* move non-option to the end for parsing by the application */ if (arg[0] != '-') { (*argv)[i] = (*argv)[end - 1]; (*argv)[end - 1] = arg; @@ -73,12 +72,12 @@ void options_parse(int *argc, char ***argv) { continue; } - // chomp leading - + /* chomp leading - */ while (arg[0] == '-') { arg++; } - // terminate arg and extract value + /* terminate arg and extract value */ char *value = arg; while (value[0] && value[0] != '=') { @@ -89,7 +88,7 @@ void options_parse(int *argc, char ***argv) { *(value++) = 0; } - // lookup the option and assign the parsed value to it + /* lookup the option and assign the parsed value to it */ struct option *opt = options_find(arg); if (opt) { @@ -114,15 +113,15 @@ static int options_ini_handler(void *user, const char *section, return 0; } -bool options_read(const char *filename) { +int options_read(const char *filename) { return ini_parse(filename, options_ini_handler, NULL) >= 0; } -bool options_write(const char *filename) { +int options_write(const char *filename) { FILE *output = fopen(filename, "wt"); if (!output) { - return false; + return 0; } list_for_each_entry(opt, &s_options, struct option, it) { @@ -131,7 +130,7 @@ bool options_write(const char *filename) { fclose(output); - return true; + return 1; } void options_print_help() { diff --git a/src/core/option.h b/src/core/option.h index 08b06e2b..7536d8bc 100644 --- a/src/core/option.h +++ b/src/core/option.h @@ -1,27 +1,12 @@ #ifndef OPTIONS_H #define OPTIONS_H -#include #include #include "core/constructor.h" #include "core/list.h" #define MAX_OPTION_LENGTH 1024 -#define DECLARE_OPTION_BOOL(name) extern bool OPTION_##name; - -#define DEFINE_OPTION_BOOL(name, value, desc) \ - bool OPTION_##name; \ - static struct option OPTION_T_##name = { \ - OPT_BOOL, #name, desc, &OPTION_##name, {0}}; \ - CONSTRUCTOR(OPTION_REGISTER_##name) { \ - *(bool *)(&OPTION_##name) = value; \ - options_register(&OPTION_T_##name); \ - } \ - DESTRUCTOR(OPTION_UNREGISTER_##name) { \ - options_unregister(&OPTION_T_##name); \ - } - #define DECLARE_OPTION_INT(name) extern int OPTION_##name; #define DEFINE_OPTION_INT(name, value, desc) \ @@ -54,7 +39,6 @@ #define OPTION_HIDDEN NULL enum option_type { - OPT_BOOL, OPT_INT, OPT_STRING, }; @@ -71,8 +55,8 @@ void options_register(struct option *option); void options_unregister(struct option *option); void options_parse(int *argc, char ***argv); -bool options_read(const char *filename); -bool options_write(const char *filename); +int options_read(const char *filename); +int options_write(const char *filename); void options_print_help(); diff --git a/src/core/profiler.cc b/src/core/profiler.cc index 994fd877..d95798fc 100644 --- a/src/core/profiler.cc +++ b/src/core/profiler.cc @@ -103,9 +103,8 @@ prof_token_t prof_get_aggregate_token(const char *name) { return tok; } -void prof_flip() { - /* flip aggregate counters every second */ - int64_t now = time_nanoseconds(); +void prof_update(int64_t now) { + /* update time-based aggregate counters every second */ int64_t next_aggregation = prof.last_aggregation + NS_PER_SEC; if (now > next_aggregation) { @@ -120,7 +119,10 @@ void prof_flip() { prof.last_aggregation = now; } +} +void prof_flip() { + /* flip frame-based profile zones at the end of every frame */ MicroProfileFlip(); } diff --git a/src/core/profiler.h b/src/core/profiler.h index 9f6cb6e4..4e8f1f1b 100644 --- a/src/core/profiler.h +++ b/src/core/profiler.h @@ -47,6 +47,10 @@ int64_t prof_counter_load(prof_token_t tok); void prof_counter_add(prof_token_t tok, int64_t count); void prof_counter_set(prof_token_t tok, int64_t count); +/* called at the end of every frame to aggregate frame-based profile zones */ void prof_flip(); +/* called periodically to aggregate time-based aggregate counters */ +void prof_update(int64_t now); + #endif diff --git a/src/core/ringbuf.cc b/src/core/ringbuf.cc index bdc279ac..ee2eac15 100644 --- a/src/core/ringbuf.cc +++ b/src/core/ringbuf.cc @@ -1,8 +1,8 @@ /* would be nice to convert this file to C once MSVC supports stdatomic.h */ #include extern "C" { -#include "core/ringbuf.h" #include "core/assert.h" +#include "core/ringbuf.h" } struct ringbuf { diff --git a/src/core/string.c b/src/core/string.c index 041dc7a1..2d0c26f3 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -40,8 +40,8 @@ int strnrep(char *dst, size_t dst_size, const char *token, size_t token_len, break; } - // move substring starting at the end of the token to the end of where the - // new value will be) + /* move substring starting at the end of the token to the end of where the + new value will be) */ size_t dst_len = strnlen(dst, dst_size); size_t move_size = (dst_len + 1) - ((ptr - dst) + token_len); @@ -51,7 +51,7 @@ int strnrep(char *dst, size_t dst_size, const char *token, size_t token_len, memmove(ptr + value_len, ptr + token_len, move_size); - // copy new value into token position + /* copy new value into token position */ memmove(ptr, value, value_len); } diff --git a/src/emu/emulator.c b/src/emu/emulator.c index b124ab15..8b40c379 100644 --- a/src/emu/emulator.c +++ b/src/emu/emulator.c @@ -1,6 +1,7 @@ #include "emu/emulator.h" #include "core/option.h" #include "core/profiler.h" +#include "hw/aica/aica.h" #include "hw/arm7/arm7.h" #include "hw/dreamcast.h" #include "hw/gdrom/gdrom.h" @@ -15,6 +16,9 @@ #include "ui/nuklear.h" #include "ui/window.h" +DEFINE_OPTION_INT(throttle, 1, + "Throttle emulation speed to match the original hardware"); + DEFINE_AGGREGATE_COUNTER(frames); struct emu { @@ -22,7 +26,6 @@ struct emu { struct window_listener listener; struct dreamcast *dc; int running; - int throttled; /* render state */ struct tr *tr; @@ -119,7 +122,7 @@ static void emu_debug_menu(void *data, struct nk_context *ctx) { if (nk_menu_begin_label(ctx, "EMULATOR", NK_TEXT_LEFT, nk_vec2(140.0f, 200.0f))) { nk_layout_row_dynamic(ctx, DEBUG_MENU_HEIGHT, 1); - nk_checkbox_label(ctx, "throttled", &emu->throttled); + nk_checkbox_label(ctx, "throttled", &OPTION_throttle); nk_menu_end(ctx); } @@ -164,16 +167,23 @@ static void *emu_core_thread(void *data) { static const int64_t MACHINE_STEP = HZ_TO_NANO(1000); int64_t current_time = time_nanoseconds(); int64_t next_time = current_time; + int64_t delta_time = 0; while (emu->running) { current_time = time_nanoseconds(); - int64_t delta_time = current_time - next_time; - - if (!emu->throttled || delta_time >= 0) { - dc_tick(emu->dc, MACHINE_STEP); - next_time = current_time + MACHINE_STEP; + if (OPTION_throttle) { + delta_time = current_time - next_time; + } else { + delta_time = 0; } + + if (delta_time >= 0) { + dc_tick(emu->dc, MACHINE_STEP); + next_time = current_time + MACHINE_STEP - delta_time; + } + + prof_update(current_time); } return 0; @@ -205,17 +215,17 @@ void emu_run(struct emu *emu, const char *path) { dc_resume(emu->dc); } - /* start core emulator thread */ - thread_t core_thread; emu->running = 1; - core_thread = thread_create(&emu_core_thread, NULL, emu); + + /* start core emulator thread */ + thread_t core_thread = thread_create(&emu_core_thread, NULL, emu); /* run the renderer / ui in the main thread */ while (emu->running) { win_pump_events(emu->window); } - /* wait for the graphics thread to exit */ + /* wait for the core thread to exit */ void *result; thread_join(core_thread, &result); } diff --git a/src/hw/aica/aica.c b/src/hw/aica/aica.c index 70ea4f12..f737723b 100644 --- a/src/hw/aica/aica.c +++ b/src/hw/aica/aica.c @@ -1,6 +1,7 @@ #include "hw/aica/aica.h" #include "core/log.h" #include "core/option.h" +#include "core/profiler.h" #include "hw/aica/aica_types.h" #include "hw/arm7/arm7.h" #include "hw/dreamcast.h" @@ -11,11 +12,13 @@ DEFINE_OPTION_INT(rtc, 0, OPTION_HIDDEN); -#define AICA_CLOCK_FREQ INT64_C(22579200) -#define AICA_SAMPLE_FREQ INT64_C(44100) +DEFINE_AGGREGATE_COUNTER(aica_samples); + #define AICA_NUM_CHANNELS 64 -#define AICA_TIMER_PERIOD 0xff +#define AICA_SAMPLE_FREQ INT64_C(44100) +#define AICA_SAMPLE_BATCH 10 #define AICA_SAMPLE_SHIFT 10 +#define AICA_TIMER_PERIOD 0xff struct aica_channel { struct channel_data *data; @@ -36,25 +39,28 @@ struct aica { struct device; uint8_t reg[0x11000]; uint8_t *wave_ram; + /* reset state */ int arm_resetting; + /* interrupts */ uint32_t arm_irq_l; uint32_t arm_irq_m; + /* timers */ struct timer *timers[3]; + /* real-time clock */ struct timer *rtc_timer; int rtc_write; uint32_t rtc; + /* channels */ struct common_data *common_data; struct aica_channel channels[AICA_NUM_CHANNELS]; + struct timer *sample_timer; }; -/* - * interrupts - */ static void aica_raise_interrupt(struct aica *aica, int intr) { aica->common_data->MCIPD |= (1 << intr); aica->common_data->SCIPD |= (1 << intr); @@ -118,9 +124,6 @@ static void aica_update_sh(struct aica *aica) { } } -/* - * timers - */ static void aica_timer_reschedule(struct aica *aica, int n, uint32_t period); static void aica_timer_expire(struct aica *aica, int n) { @@ -197,9 +200,6 @@ static void aica_timer_init(struct aica *aica) { } } -/* - * rtc - */ static uint32_t aica_rtc_reg_read(struct aica *aica, uint32_t addr, uint32_t data_mask) { switch (addr) { @@ -262,9 +262,6 @@ static void aica_rtc_init(struct aica *aica) { scheduler_start_timer(aica->scheduler, &aica_rtc_timer, aica, NS_PER_SEC); } -/* - * channels - */ static uint32_t aica_channel_step(struct aica_channel *ch) { uint32_t oct = ch->data->OCT; uint32_t step = (1 << AICA_SAMPLE_SHIFT) | ch->data->FNS; @@ -334,6 +331,7 @@ static void aica_channel_update(struct aica *aica, struct aica_channel *ch) { uint32_t ca = ch->offset >> AICA_SAMPLE_SHIFT; if (ca > ch->data->LEA) { if (ch->data->LPCTL) { + LOG_INFO("aica_channel_step %d restart", ch - aica->channels); ch->offset = ch->data->LSA << AICA_SAMPLE_SHIFT; ch->looped = 1; } else { @@ -349,6 +347,8 @@ static void aica_generate_samples(struct aica *aica, int samples) { aica_channel_update(aica, ch); } } + + prof_counter_add(COUNTER_aica_samples, samples); } static uint32_t aica_channel_reg_read(struct aica *aica, uint32_t addr, @@ -475,9 +475,6 @@ static void aica_common_reg_write(struct aica *aica, uint32_t addr, } } -/* - * memory callbacks - */ uint32_t aica_reg_read(struct aica *aica, uint32_t addr, uint32_t data_mask) { if (addr < 0x2000) { return aica_channel_reg_read(aica, addr, data_mask); @@ -505,19 +502,18 @@ void aica_reg_write(struct aica *aica, uint32_t addr, uint32_t data, WRITE_DATA(&aica->reg[addr]); } -/* - * device - */ -static void aica_run(struct device *dev, int64_t ns) { - struct aica *aica = (struct aica *)dev; - - int samples = (int)NANO_TO_CYCLES(ns, AICA_SAMPLE_FREQ); - - aica_generate_samples(aica, samples); +static void aica_next_sample(void *data) { + struct aica *aica = data; + aica_generate_samples(aica, AICA_SAMPLE_BATCH); aica_raise_interrupt(aica, AICA_INT_SAMPLE); aica_update_arm(aica); aica_update_sh(aica); + + /* reschedule */ + aica->sample_timer = + scheduler_start_timer(aica->scheduler, &aica_next_sample, aica, + HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_SAMPLE_BATCH)); } static bool aica_init(struct device *dev) { @@ -536,28 +532,27 @@ static bool aica_init(struct device *dev) { aica_timer_init(aica); aica_rtc_init(aica); - arm7_suspend(aica->arm); + aica->sample_timer = + scheduler_start_timer(aica->scheduler, &aica_next_sample, aica, + HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_SAMPLE_BATCH)); return true; } +void aica_destroy(struct aica *aica) { + scheduler_cancel_timer(aica->scheduler, aica->sample_timer); + aica_rtc_shutdown(aica); + aica_timer_shutdown(aica); + + dc_destroy_device((struct device *)aica); +} + struct aica *aica_create(struct dreamcast *dc) { struct aica *aica = dc_create_device(dc, sizeof(struct aica), "aica", &aica_init); - - aica->execute_if = dc_create_execute_interface(&aica_run, 1); - return aica; } -void aica_destroy(struct aica *aica) { - aica_rtc_shutdown(aica); - aica_timer_shutdown(aica); - - dc_destroy_execute_interface(aica->execute_if); - dc_destroy_device((struct device *)aica); -} - /* clang-format off */ AM_BEGIN(struct aica, aica_reg_map); /* over-allocate to align with the host allocation granularity */ diff --git a/src/hw/aica/aica.h b/src/hw/aica/aica.h index 907a10ee..be4995b0 100644 --- a/src/hw/aica/aica.h +++ b/src/hw/aica/aica.h @@ -7,10 +7,10 @@ struct aica; struct dreamcast; -struct aica *aica_create(struct dreamcast *dc); -void aica_destroy(struct aica *aica); - AM_DECLARE(aica_reg_map); AM_DECLARE(aica_data_map); +struct aica *aica_create(struct dreamcast *dc); +void aica_destroy(struct aica *aica); + #endif diff --git a/src/hw/dreamcast.c b/src/hw/dreamcast.c index 9f9b593c..47b992f5 100644 --- a/src/hw/dreamcast.c +++ b/src/hw/dreamcast.c @@ -15,7 +15,7 @@ #include "hw/scheduler.h" #include "hw/sh4/sh4.h" -DEFINE_OPTION_BOOL(gdb, false, "Run gdb debug server"); +DEFINE_OPTION_INT(gdb, 0, "Run gdb debug server"); void dc_joy_remove(struct dreamcast *dc, int joystick_index) { list_for_each_entry(dev, &dc->devices, struct device, it) { diff --git a/src/hw/memory.c b/src/hw/memory.c index ccef38f3..8b0b8e38 100644 --- a/src/hw/memory.c +++ b/src/hw/memory.c @@ -50,7 +50,7 @@ static int get_region_handle(page_entry_t page) { struct mirror_iterator { uint32_t base, mask, imask, step; uint32_t i, addr; - bool first; + int first; }; static void mirror_iterator_init(struct mirror_iterator *it, uint32_t addr, @@ -61,19 +61,19 @@ static void mirror_iterator_init(struct mirror_iterator *it, uint32_t addr, it->step = 1 << ctz32(it->imask); it->i = 0; it->addr = it->base; - it->first = true; + it->first = 1; } static bool mirror_iterator_next(struct mirror_iterator *it) { /* first iteration just returns base */ if (it->first) { - it->first = false; - return true; + it->first = 0; + return 1; } /* stop once mask complement is completely set */ if ((it->addr & it->imask) == it->imask) { - return false; + return 0; } /* step to the next permutation */ @@ -89,7 +89,7 @@ static bool mirror_iterator_next(struct mirror_iterator *it) { /* merge with the base */ it->addr = it->base | it->i; - return true; + return 1; } static bool reserve_address_space(uint8_t **base) { @@ -109,12 +109,12 @@ static bool reserve_address_space(uint8_t **base) { into it */ release_pages(*base, ADDRESS_SPACE_SIZE); - return true; + return 1; } LOG_WARNING("Failed to reserve address space"); - return false; + return 0; } struct memory_region *memory_get_region(struct memory *memory, @@ -187,17 +187,17 @@ uint8_t *memory_translate(struct memory *memory, const char *name, return memory->shmem_base + region->physical.shmem_offset + offset; } -static bool memory_create_shmem(struct memory *memory) { +static int memory_create_shmem(struct memory *memory) { /* create the shared memory object to back the address space */ memory->shmem = create_shared_memory("/redream", ADDRESS_SPACE_SIZE, ACC_READWRITE); if (memory->shmem == SHMEM_INVALID) { LOG_WARNING("Failed to create shared memory object"); - return false; + return 0; } - return true; + return 1; } static void memory_destroy_shmem(struct memory *memory) { @@ -206,9 +206,9 @@ static void memory_destroy_shmem(struct memory *memory) { destroy_shared_memory(memory->shmem); } -bool memory_init(struct memory *memory) { +int memory_init(struct memory *memory) { if (!memory_create_shmem(memory)) { - return false; + return 0; } /* map each memory interface's address space */ @@ -225,15 +225,15 @@ bool memory_init(struct memory *memory) { /* map raw address space */ if (!reserve_address_space(&memory->shmem_base)) { - return false; + return 0; } if (!map_shared_memory(memory->shmem, 0, memory->shmem_base, memory->shmem_size, ACC_READWRITE)) { - return false; + return 0; } - return true; + return 1; } void memory_destroy(struct memory *memory) { @@ -574,8 +574,8 @@ void as_unmap(struct address_space *space) { } } -bool as_map(struct address_space *space, const char *name, - const struct address_map *map) { +int as_map(struct address_space *space, const char *name, + const struct address_map *map) { as_unmap(space); /* flatten the supplied address map out into a virtual page table */ @@ -588,7 +588,7 @@ bool as_map(struct address_space *space, const char *name, #endif if (!reserve_address_space(&space->base)) { - return false; + return 0; } /* iterate the virtual page table, mapping it to the reserved address space */ @@ -621,21 +621,21 @@ bool as_map(struct address_space *space, const char *name, if (!map_shared_memory(space->dc->memory->shmem, shmem_offset, addr, size, ACC_READWRITE)) { - return false; + return 0; } } else { /* disable access to virtual address range for mmio regions, resulting in SIGSEGV on access */ if (!map_shared_memory(space->dc->memory->shmem, 0, addr, size, ACC_NONE)) { - return false; + return 0; } } page_index += num_pages; } - return true; + return 1; } void as_destroy(struct address_space *space) { diff --git a/src/hw/memory.h b/src/hw/memory.h index 8767fbf2..d78b040e 100644 --- a/src/hw/memory.h +++ b/src/hw/memory.h @@ -51,7 +51,7 @@ struct memory; struct memory *memory_create(struct dreamcast *dc); void memory_destroy(struct memory *memory); -bool memory_init(struct memory *memory); +int memory_init(struct memory *memory); uint8_t *memory_translate(struct memory *memory, const char *name, uint32_t offset); @@ -186,8 +186,8 @@ struct address_space { struct address_space *as_create(struct dreamcast *dc); void as_destroy(struct address_space *space); -bool as_map(struct address_space *space, const char *name, - const struct address_map *map); +int as_map(struct address_space *space, const char *name, + const struct address_map *map); void as_unmap(struct address_space *space); void as_lookup(struct address_space *space, uint32_t addr, diff --git a/src/hw/scheduler.h b/src/hw/scheduler.h index 761bb817..c18228fe 100644 --- a/src/hw/scheduler.h +++ b/src/hw/scheduler.h @@ -8,9 +8,10 @@ struct dreamcast; struct timer; struct scheduler; -#define HZ_TO_NANO(hz) (int64_t)(NS_PER_SEC / (float)hz) -#define NANO_TO_CYCLES(ns, hz) (int64_t)((ns / (float)NS_PER_SEC) * hz) -#define CYCLES_TO_NANO(cycles, hz) (int64_t)((cycles / (float)hz) * NS_PER_SEC) +#define HZ_TO_NANO(hz) (int64_t)(NS_PER_SEC / (float)(hz)) +#define NANO_TO_CYCLES(ns, hz) (int64_t)(((ns) / (float)NS_PER_SEC) * (hz)) +#define CYCLES_TO_NANO(cycles, hz) \ + (int64_t)(((cycles) / (float)(hz)) * NS_PER_SEC) typedef void (*timer_cb)(void *); diff --git a/src/jit/frontend/sh4/sh4_disasm.c b/src/jit/frontend/sh4/sh4_disasm.c index 3c9c56a9..c4c319ab 100644 --- a/src/jit/frontend/sh4/sh4_disasm.c +++ b/src/jit/frontend/sh4/sh4_disasm.c @@ -45,13 +45,13 @@ static void sh4_arg_mask(const char *instr_code, char c, uint16_t *mask, } static void sh4_init_opdefs() { - static bool initialized = false; + static int initialized = 0; if (initialized) { return; } - initialized = true; + initialized = 1; /* * finalize type information by extracting argument encoding information diff --git a/src/jit/frontend/sh4/sh4_translate.c b/src/jit/frontend/sh4/sh4_translate.c index 9b5ac534..f07bccf0 100644 --- a/src/jit/frontend/sh4/sh4_translate.c +++ b/src/jit/frontend/sh4/sh4_translate.c @@ -154,7 +154,7 @@ static void ir_store_t(struct sh4_frontend *frontend, struct ir *ir, struct ir_value *sr_t = ir_or(ir, sr, ir_alloc_i32(ir, T)); struct ir_value *sr_not = ir_and(ir, sr, ir_alloc_i32(ir, ~T)); struct ir_value *res = ir_select(ir, v, sr_t, sr_not); - store_sr(res, false); + store_sr(res, 0); } static struct ir_value *ir_load_gbr(struct ir *ir) { @@ -734,7 +734,7 @@ EMITTER(DIV0U) { ir_store_context(ir, offsetof(struct sh4_ctx, sr_qm), ir_alloc_i32(ir, 0x80000000)); - store_sr(ir_and(ir, load_sr(), ir_alloc_i32(ir, ~T)), false); + store_sr(ir_and(ir, load_sr(), ir_alloc_i32(ir, ~T)), 0); } // code cycles t-bit @@ -1314,7 +1314,7 @@ EMITTER(CLRMAC) { EMITTER(CLRS) { struct ir_value *sr = load_sr(); sr = ir_and(ir, sr, ir_alloc_i32(ir, ~S)); - store_sr(sr, true); + store_sr(sr, 1); } // code cycles t-bit @@ -1327,7 +1327,7 @@ EMITTER(CLRT) { // LDC Rm,SR EMITTER(LDCSR) { struct ir_value *rm = load_gpr(i->Rm, VALUE_I32); - store_sr(rm, true); + store_sr(rm, 1); } // LDC Rm,GBR @@ -1371,7 +1371,7 @@ EMITTER(LDCRBANK) { EMITTER(LDCMSR) { struct ir_value *addr = load_gpr(i->Rm, VALUE_I32); struct ir_value *v = load_guest(addr, VALUE_I32); - store_sr(v, true); + store_sr(v, 1); /* reload Rm, sr store could have swapped banks */ addr = load_gpr(i->Rm, VALUE_I32); addr = ir_add(ir, addr, ir_alloc_i32(ir, 4)); @@ -1518,7 +1518,7 @@ EMITTER(RTE) { ir_load_context(ir, offsetof(struct sh4_ctx, spc), VALUE_I32); struct ir_value *ssr = ir_load_context(ir, offsetof(struct sh4_ctx, ssr), VALUE_I32); - store_sr(ssr, true); + store_sr(ssr, 1); emit_delay_instr(); branch(spc); } @@ -1526,7 +1526,7 @@ EMITTER(RTE) { // SETS EMITTER(SETS) { struct ir_value *sr = ir_or(ir, load_sr(), ir_alloc_i32(ir, S)); - store_sr(sr, true); + store_sr(sr, 1); } // SETT diff --git a/src/jit/ir/ir.c b/src/jit/ir/ir.c index f2ee6ab8..cce50e2a 100644 --- a/src/jit/ir/ir.c +++ b/src/jit/ir/ir.c @@ -227,10 +227,6 @@ void ir_replace_uses(struct ir_value *v, struct ir_value *other) { } } -bool ir_is_constant(const struct ir_value *v) { - return !v->def; -} - uint64_t ir_zext_constant(const struct ir_value *v) { switch (v->type) { case VALUE_I8: diff --git a/src/jit/ir/ir.h b/src/jit/ir/ir.h index cfcc2701..9bf9aab2 100644 --- a/src/jit/ir/ir.h +++ b/src/jit/ir/ir.h @@ -161,19 +161,23 @@ static inline int ir_type_size(enum ir_type type) { } } -static inline bool ir_is_int(enum ir_type type) { +static inline int ir_is_int(enum ir_type type) { return type == VALUE_I8 || type == VALUE_I16 || type == VALUE_I32 || type == VALUE_I64; } -static inline bool ir_is_float(enum ir_type type) { +static inline int ir_is_float(enum ir_type type) { return type == VALUE_F32 || type == VALUE_F64; } -static inline bool ir_is_vector(enum ir_type type) { +static inline int ir_is_vector(enum ir_type type) { return type == VALUE_V128; } +static inline int ir_is_constant(const struct ir_value *v) { + return !v->def; +} + int ir_read(FILE *input, struct ir *ir); void ir_write(struct ir *ir, FILE *output); @@ -202,7 +206,6 @@ void ir_set_arg2(struct ir *ir, struct ir_instr *instr, struct ir_value *v); void ir_replace_use(struct ir_use *use, struct ir_value *other); void ir_replace_uses(struct ir_value *v, struct ir_value *other); -bool ir_is_constant(const struct ir_value *v); uint64_t ir_zext_constant(const struct ir_value *v); // direct access to host memory diff --git a/src/jit/jit.c b/src/jit/jit.c index 284c5464..049f67a3 100644 --- a/src/jit/jit.c +++ b/src/jit/jit.c @@ -17,8 +17,7 @@ #include #endif -DEFINE_OPTION_BOOL(perf, false, - "Generate perf-compatible maps for genrated code"); +DEFINE_OPTION_INT(perf, 0, "Generate perf-compatible maps for genrated code"); struct jit_block { /* address of source block in guest memory */ diff --git a/src/main.c b/src/main.c index f763b06a..abe0ec0e 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ #include "sys/filesystem.h" #include "ui/window.h" -DEFINE_OPTION_BOOL(help, false, "Show help"); +DEFINE_OPTION_INT(help, 0, "Show help"); int main(int argc, char **argv) { const char *appdir = fs_appdir(); diff --git a/src/ui/microprofile.cc b/src/ui/microprofile.cc index c9bb8a5f..cb97b815 100644 --- a/src/ui/microprofile.cc +++ b/src/ui/microprofile.cc @@ -21,7 +21,7 @@ static const int FONT_WIDTH = 1024; static const int FONT_HEIGHT = 9; #include "ui/microprofile_font.inc" -static const int MAX_2D_VERTICES = 16384; +static const int MAX_2D_VERTICES = 32768; static const int MAX_2D_SURFACES = 256; struct microprofile { diff --git a/tools/recc/README.md b/tools/recc/README.md index 777ad327..c66d446e 100644 --- a/tools/recc/README.md +++ b/tools/recc/README.md @@ -15,6 +15,6 @@ recc [options] ### Options ``` --pass Comma-separated list of passes to run [default: lse, dce, ra] - --stats Print pass stats [default: true] ---print_after_all Print IR after each pass [default: true] + --stats Print pass stats [default: 1] +--print_after_all Print IR after each pass [default: 1] ``` diff --git a/tools/recc/recc.c b/tools/recc/recc.c index 436743bc..e5541230 100644 --- a/tools/recc/recc.c +++ b/tools/recc/recc.c @@ -12,11 +12,11 @@ #include "jit/jit.h" #include "sys/filesystem.h" -DEFINE_OPTION_BOOL(help, false, "Show help"); +DEFINE_OPTION_INT(help, 0, "Show help"); DEFINE_OPTION_STRING(pass, "lse,cve,esimp,dce,ra", "Comma-separated list of passes to run"); -DEFINE_OPTION_BOOL(stats, true, "Print pass stats"); -DEFINE_OPTION_BOOL(print_after_all, true, "Print IR after each pass"); +DEFINE_OPTION_INT(stats, 1, "Print pass stats"); +DEFINE_OPTION_INT(print_after_all, 1, "Print IR after each pass"); DEFINE_STAT(backend_size, "Backend code size"); DEFINE_STAT(num_instrs, "Total instructions"); @@ -39,7 +39,7 @@ static int get_num_instrs(const struct ir *ir) { } static void process_file(struct jit *jit, const char *filename, - bool disable_ir_dump) { + int disable_ir_dump) { struct ir ir = {0}; ir.buffer = ir_buffer; ir.capacity = sizeof(ir_buffer); @@ -121,7 +121,7 @@ static void process_dir(struct jit *jit, const char *path) { LOG_INFO("Processing %s", filename); - process_file(jit, filename, true); + process_file(jit, filename, 1); } closedir(dir); @@ -144,7 +144,7 @@ int main(int argc, char **argv) { CHECK(jit_init(jit, &guest, NULL, backend)); if (fs_isfile(path)) { - process_file(jit, path, false); + process_file(jit, path, 0); } else { process_dir(jit, path); }