X-Git-Url: http://git.squeep.com/?p=dcpu16;a=blobdiff_plain;f=dcpu16.c;h=6f5617ccff86cdd76accf814a68d77bbb011edbe;hp=26c594e02b60e524f596afcda0490d8e697456e2;hb=a44fc6f0eb899b6f745fe8ab43d5cb3e5b743c21;hpb=28bd5d99ce17285ed06b4762a6027d3f25693265 diff --git a/dcpu16.c b/dcpu16.c index 26c594e..6f5617c 100644 --- a/dcpu16.c +++ b/dcpu16.c @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include @@ -7,6 +7,8 @@ #include #include +#include "dcpu16.h" + /* * emulates the DCPU16 system from http://0x10c.com/doc/dcpu-16.txt * @@ -18,31 +20,18 @@ * 2012 04 05 - implementation started * 2012 04 06 - first functionality achieved * 2012 04 09 - minor cleanups + * 2012 04 10 - moved cli to separate module * * TODO - * move cli driver to separate module * drop checks for assigning to literals -- it won't affect anything anyhow * debug short literal decoding */ static const char * const src_id_ = "$Id$"; -/* the target system's concept of a word */ #define WORD DCPU16_WORD -typedef unsigned short WORD; -#define RAM_SIZE 0x10000 static const char regnames_[] = "ABCXYZIJ"; -struct dcpu16 { - unsigned long long cycle; /* number of cycles it took to get to current state */ - WORD reg_work_[2]; /* holding bins for literal values when decoding instructions */ - WORD reg[8]; /* system registers, a b c x y z i j */ - WORD pc; /* program counter */ - WORD sp; /* stack pointer */ - WORD o; /* overflow */ - unsigned int skip_ : 1; /* skip execution of next instruction */ - WORD ram[RAM_SIZE]; /* memory */ -}; static unsigned int trace_mode_ = 0; /* spew overly verbose internals */ @@ -53,7 +42,7 @@ static inline void warn_(char *fmt, ...) { va_list ap; - fprintf(stderr, "!!! "); + fprintf(stderr, "[warning] "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); @@ -71,6 +60,7 @@ static inline void trace_(char *fmt, ...) { va_list ap; + fprintf(stdout, "[debug] "); va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); @@ -83,10 +73,11 @@ void dcpu16_trace_cb_set(void (*fn)(char *fmt, ...)) { } - -/* sets *v to be the destination of the value */ -/* workv is buffer to use to accumulate literal value before use */ -/* returns true if destination points to literal (id est *v should ignore writes) */ +/* value_decode_ + * sets *v to be the destination of the value + * workv is buffer to use to accumulate literal value before use + * returns true if destination points to literal (id est *v should ignore writes) + */ static unsigned int value_decode(struct dcpu16 *d, WORD value, WORD *work_v, WORD **v) { WORD nextword; unsigned int retval = 0; @@ -539,7 +530,7 @@ void dump_value(WORD value, WORD nextword) { } } -void dump_instruction(struct dcpu16 *d, WORD addr) { +void dcpu16_disassemble_print(struct dcpu16 *d, WORD addr) { WORD opcode, a, b; unsigned int instr_len = 1; const struct opcode_entry *e; @@ -587,7 +578,7 @@ void dump_instruction(struct dcpu16 *d, WORD addr) { printf("\n"); } -void dcpu16_execute_next_instruction(struct dcpu16 *d) { +void dcpu16_step(struct dcpu16 *d) { WORD opcode; WORD val_a, val_b; const struct opcode_entry *e; @@ -609,72 +600,7 @@ void dcpu16_execute_next_instruction(struct dcpu16 *d) { } } -static void usage(char *prog, unsigned int full) { - FILE *f = full ? stdout : stderr; - char *x = strrchr(prog, '/'); - - if (x && *(x + 1)) - prog = x + 1; - - if (full) - fprintf(f, "%s -- \n\n", - prog); - - fprintf(f, "Usage: %s\n", - prog); - - if (full) { - fprintf(f, "\nOptions:\n" - "\t-h -- this screen\n" - "\t-t -- test mode, load demo program\n" - "\t-v -- verbose execution tracing\n"); - - fprintf(f, "\n%78s\n", src_id_); - } -} - -static int file_load(struct dcpu16 *d, char *filename) { - FILE *f; - size_t r; - - f = fopen(filename, "rb"); - if (f == NULL) - { - fprintf(stderr, "%s(%s):%s\n", "fopen", filename, strerror(errno)); - return -1; - } - - r = fread(d->ram, sizeof(WORD), RAM_SIZE, f); - TRACE("read %zu words", r); - - if (ferror(f)) { - fprintf(stderr, "%s():%s\n", "fread", strerror(errno)); - } - - fclose(f); - return 0; -} - -static void testprog_load(struct dcpu16 *d) { - static WORD bin[] = { - 0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d, - 0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463, - 0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a, - 0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000 - }; - size_t i; - - printf("loading...\n"); - for (i = 0; i < (sizeof(bin) / sizeof(WORD)); i++) - { - printf(" %04x", bin[i]); - d->ram[i] = bin[i]; - } - printf("\nloaded 0x%04zx words\n", i - 1); -} - -static -void dump_cpu_state(struct dcpu16 *d) { +void dcpu16_state_print(struct dcpu16 *d) { unsigned int i; printf("---- cycle:0x%08llx %2s:0x%04x %2s:0x%04x %2s:0x%04x\n", @@ -688,8 +614,7 @@ void dump_cpu_state(struct dcpu16 *d) { printf("\n"); } -static -void dump_ram(struct dcpu16 *d, WORD start, WORD stop) { +void dcpu16_dump_ram(struct dcpu16 *d, WORD start, WORD stop) { unsigned int i, j; const unsigned int n = 8; /* words per line */ @@ -700,58 +625,23 @@ void dump_ram(struct dcpu16 *d, WORD start, WORD stop) { } } +/* dcpu16_new + * allocate a new dcpu16 instance + */ +struct dcpu16 *dcpu16_new(void) { + struct dcpu16 *vm; -int main(int argc, char **argv) { - struct dcpu16 *m; - int c; - char buf[512]; - - m = calloc(1, sizeof *m); - if (m == NULL) - { - fprintf(stderr, "%s:%s\n", "calloc", strerror(errno)); - exit(EX_OSERR); - } - - while ( (c = getopt(argc, argv, "htv")) != EOF ) - { - switch (c) - { - case 'v': - trace_mode_ = 1; - break; - - case 't': - dump_ram(m, 0, 0x001f); - testprog_load(m); - dump_ram(m, 0, 0x001f); - break; - - case 'h': - usage(argv[0], 1); - exit(EX_OK); - - default: - usage(argv[0], 0); - exit(EX_USAGE); - } - } - - if (argc - optind) - { - /* read file */ - file_load(m, argv[optind]); - } - - dump_cpu_state(m); - dump_instruction(m, m->pc); - while (fgets(buf, sizeof buf, stdin)) { - dcpu16_execute_next_instruction(m); - dump_cpu_state(m); - dump_instruction(m, m->pc); - } + vm = calloc(1, sizeof *vm); + if (vm == NULL) + WARN("%s: %s(%zu): %s", __func__, "calloc", strerror(errno)); - free(m); + return vm; +} - exit(EX_OK); +/* dcpu16_delete + * release a dcpu16 instance + */ +void dcpu16_delete(struct dcpu16 **vm) { + free(*vm); + *vm = NULL; }