#ifndef DCPU16_H_3XXIQQG2 #define DCPU16_H_3XXIQQG2 #include /* the target system's concept of a word */ typedef unsigned short DCPU16_WORD; /* how much ram the system has */ #define DCPU16_RAM 0x10000 #define DCPU16_INTERRUPT_QUEUE_SIZE 256 extern const char * const dcpu16_reg_names[]; enum dcpu16_register_indexes { DCPU16_REG_A = 0, DCPU16_REG_B, DCPU16_REG_C, DCPU16_REG_X, DCPU16_REG_Y, DCPU16_REG_Z, DCPU16_REG_I, DCPU16_REG_J, DCPU16_REG_PC, DCPU16_REG_SP, DCPU16_REG_EX, DCPU16_REG_IA, DCPU16_REG__NUM }; /* we call this sort of function for emitting a readable message */ typedef void (dcpu16_msg_cb_t)(unsigned int, char *, ...); /* we may emit any of these types of messages */ enum dcpu16_msg_type { DCPU16_MSG_ERROR = 0, DCPU16_MSG_INFO, DCPU16_MSG_DEBUG }; /* update the default message handler */ dcpu16_msg_cb_t *dcpu16_msg_set_default(dcpu16_msg_cb_t *); /* hardware devices may want to call this directly, without a core context */ extern dcpu16_msg_cb_t *dcpu16_msg_; /* a self-contained dcpu16 core */ struct dcpu16 { dcpu16_msg_cb_t *msg_cb_; /* callback to invoke for messages */ struct dcpu16_acct_cb *cb_table_; /* list of callbacks to invoke for certain events */ size_t cb_table_entries_; /* callback list maintenance */ size_t cb_table_allocated_; /* callback list maintenance */ struct dcpu16_hw *hw_table_; /* list of hardware attached to system */ size_t hw_table_entries_; /* hardware list maintenance */ size_t hw_table_allocated_; /* hardware list maintenance */ unsigned long long cycle_; /* number of cycles this core has executed */ unsigned int skip_ : 1; /* skip execution of next instruction */ unsigned int interrupts_deferred_ : 1; /* queue software interrupts */ unsigned int on_fire_ : 1; /* cpu is on fire */ DCPU16_WORD reg_work_[2]; /* work registers for holding literal values while decoding instructions */ DCPU16_WORD interrupts_[DCPU16_INTERRUPT_QUEUE_SIZE]; /* fifo of pending interrupts */ size_t interrupts_head_; /* interrupt queue maintenance */ size_t interrupts_tail_; /* interrupt queue maintenance */ DCPU16_WORD reg[DCPU16_REG__NUM]; /* system registers, a b c x y z i j */ DCPU16_WORD ram[DCPU16_RAM]; /* memory */ }; /* these are used for accounting/watchpointing/modules/&c */ typedef unsigned int dcpu16_acct_event; typedef void (dcpu16_ev_cb_t)(struct dcpu16 *, dcpu16_acct_event, DCPU16_WORD, void *); #define DCPU16_ACCT_EV_CYCLE (1<<1) #define DCPU16_ACCT_EV_READ (1<<2) #define DCPU16_ACCT_EV_WRITE (1<<3) #define DCPU16_ACCT_EV_REG_READ (1<<4) #define DCPU16_ACCT_EV_REG_WRITE (1<<5) #define DCPU16_ACCT_EV_NOP (1<<6) #define DCPU16_ACCT_EV_RESET (1<<7) struct dcpu16_acct_cb { dcpu16_ev_cb_t *fn; /* call this */ void *data; /* also mention this */ dcpu16_acct_event mask; /* when (mask & event) is true and */ DCPU16_WORD addr_l, /* addr is this or higher and */ addr_h; /* addr is this or lower */ }; typedef void (dcpu16_hw_signal_t)(struct dcpu16 *, struct dcpu16_hw *); /* 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_hw_module *mod; /* whence I came */ void *data; /* per-instance data */ }; /* human-readable text describing hw module control operations, for convenience's sake */ struct dcpu16_hw_ctl_cmd { char *command; char *data_in_type; 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 { 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; }; /* update a message handler */ dcpu16_msg_cb_t *dcpu16_msg_set(struct dcpu16 *, dcpu16_msg_cb_t *); /* instantiate a new core */ struct dcpu16 *dcpu16_new(void); /* reset a core to initial state */ void dcpu16_reset(struct dcpu16 *); /* print words in buf as asm */ DCPU16_WORD dcpu16_mnemonify_buf(DCPU16_WORD *); /* print the instruction at the specified address, returns number of words consumed in decoding */ DCPU16_WORD dcpu16_disassemble_print(struct dcpu16 *, DCPU16_WORD); /* create and delete 'hardware' objects */ struct dcpu16_hw *dcpu16_hw_new(struct dcpu16 *, struct dcpu16_hw_module *, void *); void dcpu16_hw_del(struct dcpu16_hw **); /* set options on hardware objects */ int dcpu16_hw_ctl(struct dcpu16_hw *, const char *, void *, void *); /* register new 'hardware' device with system */ int dcpu16_hw_attach(struct dcpu16 *, struct dcpu16_hw *); /* register a callback for an accounting event */ int dcpu16_acct_add(struct dcpu16 *, dcpu16_acct_event, dcpu16_ev_cb_t *, DCPU16_WORD, DCPU16_WORD, void *); /* execute the next instruction */ void dcpu16_step(struct dcpu16 *); /* 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); #endif /* DCPU16_H_3XXIQQG2 */