/* signal attached hardware */
for (i = 0; i < vm->hw_table_entries_; i++) {
- TRACE("%s>> notifying %s", __func__, vm->hw_table_[i].name_);
- vm->hw_table_[i].cycle(vm, &vm->hw_table_[i]);
+ TRACE("%s>> notifying %s", __func__, vm->hw_table_[i].mod->name_);
+ if (vm->hw_table_[i].mod->cycle)
+ vm->hw_table_[i].mod->cycle(vm, &vm->hw_table_[i]);
}
}
}
return;
}
- vm->reg[DCPU16_REG_A] = vm->hw_table_[*a].id_l;
- vm->reg[DCPU16_REG_B] = vm->hw_table_[*a].id_h;
- vm->reg[DCPU16_REG_C] = vm->hw_table_[*a].ver;
- vm->reg[DCPU16_REG_X] = vm->hw_table_[*a].mfg_l;
- vm->reg[DCPU16_REG_Y] = vm->hw_table_[*a].mfg_h;
+ vm->reg[DCPU16_REG_A] = vm->hw_table_[*a].mod->id_l;
+ vm->reg[DCPU16_REG_B] = vm->hw_table_[*a].mod->id_h;
+ vm->reg[DCPU16_REG_C] = vm->hw_table_[*a].mod->ver;
+ vm->reg[DCPU16_REG_X] = vm->hw_table_[*a].mod->mfg_l;
+ vm->reg[DCPU16_REG_Y] = vm->hw_table_[*a].mod->mfg_h;
dcpu16_cycle_inc(vm, 4);
}
}
dcpu16_cycle_inc(vm, 4);
- if (vm->hw_table_[*a].hwi)
- vm->hw_table_[*a].hwi(vm, &vm->hw_table_[*a]);
+ if (vm->hw_table_[*a].mod->hwi)
+ vm->hw_table_[*a].mod->hwi(vm, &vm->hw_table_[*a]);
else
WARN("hardware 0x%04x has no interrupt handler", *a);
}
}
}
-/*
- print the current state of the machine
- shows current cycle count, registers, and next instruction
-*/
-void dcpu16_state_print(struct dcpu16 *vm) {
- unsigned int i;
-
- if (!vm) return;
-
- printf(" ");
- for (i = 0; i < 8; i++)
- printf(" %s:0x%04x", dcpu16_reg_names[i], vm->reg[i]);
- printf("\n");
-
- printf("(0x%08llx) %2s:0x%04x %2s:0x%04x %2s:0x%04x %2s:0x%04x [%2s]:",
- vm->cycle_,
- dcpu16_reg_names[DCPU16_REG_EX], vm->reg[DCPU16_REG_EX],
- dcpu16_reg_names[DCPU16_REG_SP], vm->reg[DCPU16_REG_SP],
- dcpu16_reg_names[DCPU16_REG_PC], vm->reg[DCPU16_REG_PC],
- dcpu16_reg_names[DCPU16_REG_IA], vm->reg[DCPU16_REG_IA],
- "PC");
-
- dcpu16_disassemble_print(vm, vm->reg[DCPU16_REG_PC]);
- printf("\n");
-}
-
-/* dcpu16_dump_ram
- * print raw ram contents from start to stop
- */
-void dcpu16_dump_ram(struct dcpu16 *vm, DCPU16_WORD start, DCPU16_WORD end) {
- unsigned int i, j;
- const unsigned int n = 8; /* words per line */
-
- if (!vm) return;
-
- for (i = start, j = 0; i <= end; i++, j++) {
- if (j % n == 0)
- printf("0x%04x:\t", i);
- printf(" %04x%s", vm->ram[i], (j % n) == (n - 1) ? "\n" : "");
- }
- if ((j % n) != (n - 1))
- printf("\n");
-}
/* instantiate a new 'hardware' device */
struct dcpu16_hw *dcpu16_hw_new(struct dcpu16 *vm, struct dcpu16_hw_module *mod, void *data) {
struct dcpu16_hw *hw;
- hw = calloc(1, sizeof *hw);
+ hw = malloc(sizeof *hw);
if (hw == NULL) {
- vm->warn_cb_("%s():%s", "calloc", strerror(errno));
+ vm->warn_cb_("%s():%s", "malloc", strerror(errno));
return NULL;
}
- memcpy(hw, mod->template, sizeof *hw);
hw->vm = vm;
hw->mod = mod;
- if (mod->data_init(hw, data)) {
- vm->warn_cb_("failed to init hw module data");
- free(hw);
- return NULL;
+ if (mod->data_init) {
+ if (mod->data_init(hw, data)) {
+ vm->warn_cb_("failed to init hw module data");
+ free(hw);
+ return NULL;
+ }
+ } else {
+ hw->data = NULL;
}
return hw;
TRACE("%s>> name:%s ID:0x%04x%04x MFG:0x%04x%04x VER:0x%04x",
__func__,
- hw->name_,
- hw->id_h, hw->id_l,
- hw->mfg_l, hw->mfg_h,
- hw->ver);
+ hw->mod->name_,
+ hw->mod->id_h, hw->mod->id_l,
+ hw->mod->mfg_l, hw->mod->mfg_h,
+ hw->mod->ver);
if (vm->hw_table_entries_ == 0xffff) {
WARN("maximum hardware entries reached");
/* signal attached hardware */
for (i = 0; i < vm->hw_table_entries_; i++) {
- if (vm->hw_table_[i].reset)
- vm->hw_table_[i].reset(vm, &vm->hw_table_[i]);
+ if (vm->hw_table_[i].mod->reset)
+ vm->hw_table_[i].mod->reset(vm, &vm->hw_table_[i]);
}
memset(vm->reg, 0, sizeof vm->reg);
};
typedef void (dcpu16_hw_signal_t)(struct dcpu16 *, struct dcpu16_hw *);
-/* these are used to define hardware attached to the system */
+/* this structure defines a specific instance of this type of 'hardware' */
struct dcpu16_hw {
- struct dcpu16 *vm; /* which system do I belong to */
+ struct dcpu16 *vm; /* which system do I belong to */
struct dcpu16_hw_module *mod; /* whence I came */
- char *name_;
-
- DCPU16_WORD id_l;
- DCPU16_WORD id_h;
- DCPU16_WORD ver;
- DCPU16_WORD mfg_l;
- DCPU16_WORD mfg_h;
-
- dcpu16_hw_signal_t *hwi;
- dcpu16_hw_signal_t *cycle;
- dcpu16_hw_signal_t *reset;
-
- void *data;
+ void *data; /* per-instance data */
};
/* human-readable text describing hw module control operations, for convenience's sake */
char *data_out_type;
char *description;
};
+
typedef int (dcpu16_hw_data_init_t)(struct dcpu16_hw *, void *);
typedef void (dcpu16_hw_data_free_t)(struct dcpu16_hw *);
typedef int (dcpu16_hw_ctl_t)(struct dcpu16_hw *, const char *, void *, void *);
struct dcpu16_hw_module {
- struct dcpu16_hw *template;
- dcpu16_hw_data_init_t *data_init;
+ char *name_; /* dymo label on front panel */
+
+ DCPU16_WORD id_l;
+ DCPU16_WORD id_h;
+ DCPU16_WORD ver;
+ DCPU16_WORD mfg_l;
+ DCPU16_WORD mfg_h;
+
+ dcpu16_hw_signal_t *hwi; /* hardware interrupt handler */
+ dcpu16_hw_signal_t *cycle; /* cycle tick handler */
+ dcpu16_hw_signal_t *reset; /* reset handler */
+
+ dcpu16_hw_data_init_t *data_init; /* how to allocate a dcpu16_hw instance's data */
dcpu16_hw_data_free_t *data_free;
dcpu16_hw_ctl_t *ctl;
struct dcpu16_hw_ctl_cmd *ctl_cmd;
/* reset a core to initial state */
void dcpu16_reset(struct dcpu16 *);
-/* print the current state of a core */
-void dcpu16_state_print(struct dcpu16 *);
-
-/* print the contents of ram from second to third argument */
-void dcpu16_dump_ram(struct dcpu16 *, DCPU16_WORD, DCPU16_WORD);
-
/* print words in buf as asm */
DCPU16_WORD dcpu16_mnemonify_buf(DCPU16_WORD *);
/* release a core */
void dcpu16_delete(struct dcpu16 **);
+/* signal hardware interrupt */
int dcpu16_interrupt(struct dcpu16 *, DCPU16_WORD);
+
+/* consume a cycle */
void dcpu16_cycle_inc(struct dcpu16 *, unsigned int);
/* register callbacks to handle warning and debug messages, default is writing to stderr, may be set to null */
if (clock->interrupt_message) {
if (dcpu16_interrupt(vm, clock->interrupt_message))
- vm->warn_cb_("%s: could not send interrupt", hw->name_);
+ vm->warn_cb_("%s: could not send interrupt", hw->mod->name_);
}
}
}
}
}
-static struct dcpu16_hw hw_ = {
+
+struct dcpu16_hw_module dcpu16_hw_module_clock = {
.name_ = "Generic Clock (compatible)",
+
.id_l = 0xb402,
.id_h = 0x12d0,
.ver = 0x0001,
.hwi = clock_hwi_,
.cycle = clock_cycle_,
.reset = clock_reset_,
- .data = (struct clock_ *)NULL
-};
-struct dcpu16_hw_module dcpu16_hw_module_clock = {
- .template = &hw_,
.data_init = clock_data_init_,
.data_free = clock_data_free_,
.ctl = NULL,
return -EINVAL;
}
-static struct dcpu16_hw hw_ = {
- .vm = NULL,
+
+struct dcpu16_hw_module dcpu16_hw_module_keyboard = {
.name_ = "Generic Keyboard (compatible)",
+
.id_l = 0x7406,
.id_h = 0x30cf,
.ver = 0x0001,
.hwi = keyboard_hwi_,
.cycle = keyboard_cycle_,
.reset = keyboard_reset_,
- .data = (struct keyboard_ *)NULL
-};
-struct dcpu16_hw_module dcpu16_hw_module_keyboard = {
- .template = &hw_,
.data_init = keyboard_data_init_,
.data_free = keyboard_data_free_,
.ctl = keyboard_data_ctl_,
}
-static struct dcpu16_hw hw_ = {
+struct dcpu16_hw_module dcpu16_hw_module_lem1802 = {
.name_ = "LEM1802 - Low Energy Monitor",
+
.id_l = 0xf615,
.id_h = 0x7349,
.ver = 0x1802,
.hwi = lem1802_hwi_,
.cycle = lem1802_cycle_,
.reset = lem1802_reset_,
- .data = (struct lem1802_ *)NULL
-};
-struct dcpu16_hw_module dcpu16_hw_module_lem1802 = {
- .template = &hw_,
.data_init = lem1802_data_init_,
.data_free = lem1802_data_free_,
.ctl = lem1802_data_ctl_,
}
}
-static struct dcpu16_hw hw_ = {
- .vm = NULL,
+struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
.name_ = "SPC2000 - Suspension Chamber 2000",
+
.id_l = 0x1d9d,
.id_h = 0x40e4,
.ver = 0x005e,
.hwi = spc2000_hwi_,
.cycle = spc2000_cycle_,
.reset = spc2000_reset_,
- .data = (struct spc2000_ *)NULL
-};
-struct dcpu16_hw_module dcpu16_hw_module_spc2000 = {
- .template = &hw_,
.data_init = spc2000_data_init_,
.data_free = spc2000_data_free_,
.ctl = NULL,
return 0;
}
+/* dump_ram_
+ * print raw ram contents from start to stop
+ */
+static
+void dump_ram_(struct dcpu16 *vm, DCPU16_WORD start, DCPU16_WORD end) {
+ unsigned int i, j;
+ const unsigned int n = 8; /* words per line */
+
+ if (!vm) return;
+
+ for (i = start, j = 0; i <= end; i++, j++) {
+ if (j % n == 0)
+ printf("0x%04x:\t", i);
+ printf(" %04x%s", vm->ram[i], (j % n) == (n - 1) ? "\n" : "");
+ }
+ if ((j % n) != (n - 1))
+ printf("\n");
+}
+
+
+/*
+ print the current state of the machine
+ shows current cycle count, registers, and next instruction
+*/
+static
+void state_print_(struct dcpu16 *vm) {
+ unsigned int i;
+
+ if (!vm) return;
+
+ printf(" ");
+ for (i = 0; i < 8; i++)
+ printf(" %s:0x%04x", dcpu16_reg_names[i], vm->reg[i]);
+ printf("\n");
+
+ printf("(0x%08llx) %2s:0x%04x %2s:0x%04x %2s:0x%04x %2s:0x%04x [%2s]:",
+ vm->cycle_,
+ dcpu16_reg_names[DCPU16_REG_EX], vm->reg[DCPU16_REG_EX],
+ dcpu16_reg_names[DCPU16_REG_SP], vm->reg[DCPU16_REG_SP],
+ dcpu16_reg_names[DCPU16_REG_PC], vm->reg[DCPU16_REG_PC],
+ dcpu16_reg_names[DCPU16_REG_IA], vm->reg[DCPU16_REG_IA],
+ "PC");
+
+ dcpu16_disassemble_print(vm, vm->reg[DCPU16_REG_PC]);
+ printf("\n");
+}
+
#ifdef HAVE_LIBVNCSERVER
static struct dynamic_array rfbScreens_;
return 0;
}
- dcpu16_dump_ram(vm, addr[0], addr[1]);
+ dump_ram_(vm, addr[0], addr[1]);
return 0;
}
dcpu16_step(vm);
if (count > 1 && opt_.verbose)
- dcpu16_state_print(vm);
+ state_print_(vm);
}
return 0;
dcpu16_step(vm);
if (opt_.verbose > 1)
- dcpu16_state_print(vm);
+ state_print_(vm);
else if (opt_.verbose) {
dcpu16_disassemble_print(vm, vm->reg[DCPU16_REG_PC]);
printf("\n");
tok_v = tok_v_prev = NULL,
tok_c = tok_c_prev= 0,
snprintf(prompt, sizeof prompt, prompt_fmt, vm->reg[DCPU16_REG_PC]),
- dcpu16_state_print(vm);
+ state_print_(vm);
(line = readline(prompt));
printf("\n"),
snprintf(prompt, sizeof prompt, prompt_fmt, vm->reg[DCPU16_REG_PC]),
- dcpu16_state_print(vm)) {
+ state_print_(vm)) {
const char whitespace[] = " \t";
char *line_start;
struct command_ *c;