*
* TODO
* change api to print into buffers rather than stdio
- * drop checks for assigning to literals -- it won't affect anything anyhow
* refactor opcode functiontables into switch statements
*/
#define OPCODE_BASIC_BITS 4
#define OPCODE_OPERAND_BITS 6
-static const char regnames_[] = "ABCXYZIJ";
+static const char * const regnames_ = "ABCXYZIJ";
/* some default warning and debug reporting functions, which can be overridden by clients */
#define WARN(...) do { if (warn_cb_) warn_cb_(__VA_ARGS__); } while (0)
for (i = 0; i < vm->cb_table_entries_; i++) {
if ( (cb[i].mask & ev) )
- cb[i].fn(ev, addr);
+ cb[i].fn(vm, ev, addr, cb[i].data);
}
}
/* basic opcodes */
/*
- N.B. the following function does not decode values, as the nbi
- instructions only have one operand.
+ N.B. the following function does not decode values, (thus does not advance pc &c)
+ Decoding is handled by the opcode functions it calls.
*/
OP_IMPL(_nbi_) {
/* non-basic instruction */
/* sets a to b */
ACCT_R(ev_b_addr);
- ACCT_W(ev_a_addr);
- /* only set non-literal target */
- if (!lit_a) {
- *a = *b;
- }
+ /*
+ if a is a literal, it's aimed at a scratch register,
+ so it's fine to update, as it won't have any effect.
+ */
+ *a = *b;
d->cycle += 1;
+
+ ACCT_W(ev_a_addr);
}
OP_IMPL(add) {
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = acc;
- }
+ *a = acc;
d->o = (acc > 0xffff);
d->cycle += 2;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = acc;
- }
+ *a = acc;
d->o = (acc > 0xffff);
+
d->cycle += 2;
ACCT_W(ev_a_addr);
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = acc;
- }
+ *a = acc;
d->o = acc >> 16;
+
d->cycle += 2;
ACCT_W(ev_a_addr);
ACCT_R(ev_a_addr);
if (*b == 0) {
- if (!lit_a) {
- *a = 0;
- }
+ *a = 0;
d->o = 0;
} else {
- unsigned int acc = *a / *b;
-
- if (!lit_a) {
- *a = acc;
- }
-
- acc = (*a << 16) / *b;
- d->o = acc;
+ *a = *a / *b;
+ d->o = (*a << 16) / *b;
}
d->cycle += 3;
ACCT_R(ev_a_addr);
if (*b == 0) {
- if (!lit_a) {
- *a = 0;
- }
+ *a = 0;
} else {
- if (!lit_a) {
- *a = *a % *b;
- }
+ *a = *a % *b;
}
d->cycle += 3;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = acc;
- }
+ *a = acc;
+
d->o = acc >> 16;
d->cycle += 2;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = acc;
- }
+ *a = acc;
d->o = (*a << 16) >> *b;
d->cycle += 2;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = *a & *b;
- }
+ *a = *a & *b;
d->cycle += 1;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = *a | *b;
- }
+ *a = *a | *b;
d->cycle += 1;
ACCT_R(ev_b_addr);
ACCT_R(ev_a_addr);
- if (!lit_a) {
- *a = *a ^ *b;
- }
-
- ACCT_W(ev_a_addr);
+ *a = *a ^ *b;
d->cycle += 1;
+
+ ACCT_W(ev_a_addr);
}
OP_IMPL(ife) {
* Register callback fn to be triggered whenever event matching any events
* in bitwise mask occur.
*/
-int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event_ mask, void (*fn)(dcpu16_acct_event_, DCPU16_WORD)) {
+int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event_ mask, void (*fn)(struct dcpu16 *, dcpu16_acct_event_, DCPU16_WORD, void *), void *data) {
struct dcpu16_acct_cb cb;
cb.mask = mask;
cb.fn = fn;
+ cb.data = data;
if (vm->cb_table_entries_ == vm->cb_table_allocated_) {
size_t new_entries = vm->cb_table_allocated_ + 32;