improved aica timer accuracy

improved accuracy of aggregate counters
updated options in readme
removed some bool usage
This commit is contained in:
Anthony Pesch 2016-12-11 17:42:53 -08:00
parent ae3d459960
commit f0c7fe825e
28 changed files with 175 additions and 180 deletions

View File

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

View File

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

View File

@ -32,7 +32,7 @@
#else
// not supported
/* not supported */
#endif

View File

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

View File

@ -2,15 +2,15 @@
#include <stdio.h>
#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);
}

View File

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

View File

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

View File

@ -1,27 +1,12 @@
#ifndef OPTIONS_H
#define OPTIONS_H
#include <stdbool.h>
#include <string.h>
#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();

View File

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

View File

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

View File

@ -1,8 +1,8 @@
/* would be nice to convert this file to C once MSVC supports stdatomic.h */
#include <atomic>
extern "C" {
#include "core/ringbuf.h"
#include "core/assert.h"
#include "core/ringbuf.h"
}
struct ringbuf {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,8 +17,7 @@
#include <unistd.h>
#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 */

View File

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

View File

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

View File

@ -15,6 +15,6 @@ recc [options] <path to file or directory>
### 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]
```

View File

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