for (i = 0; i < vm->cb_table_entries_; i++) {
if ( (cb[i].mask & ev) )
- cb[i].fn(vm, ev, addr, cb[i].data);
+ if (addr >= cb[i].addr_l && addr <= cb[i].addr_h)
+ cb[i].fn(vm, ev, addr, cb[i].data);
}
}
* decoding next operand..
*
*/
+#define EWHAT_NONE (0)
+#define EWHAT_REG (1<<1)
+#define EWHAT_RAM (1<<2)
static inline
void value_decode_(struct dcpu16 *vm, DCPU16_WORD value, unsigned int value_is_a, DCPU16_WORD value_data,
- DCPU16_WORD *work_v, DCPU16_WORD **v, DCPU16_WORD *e_addr,
+ DCPU16_WORD *work_v, DCPU16_WORD **v, DCPU16_WORD *e_addr, enum dcpu16_register_indexes *e_reg, unsigned int *e_what,
short *pc_adjust, short *sp_adjust, unsigned int *cycle_adjust) {
assert(value <= 0x3f);
DCPU16_WORD pc = (DCPU16_WORD)(vm->reg[DCPU16_REG_PC] + *pc_adjust),
sp = (DCPU16_WORD)(vm->reg[DCPU16_REG_SP] + *sp_adjust);
+ (void)pc;
TRACE("%s>> is_a:%u pc:0x%04x sp:0x%04x value_data:0x%04x\n",
__func__,
value_is_a,
value_data);
if (value <= 0x07) { /* register */
- *v = vm->reg + value;
+ *e_what = EWHAT_REG;
+ *e_reg = value & 0x07;
+ *v = vm->reg + *e_reg;
TRACE("%s>> %s (0x%04x)",
__func__,
dcpu16_reg_names[value],
}
if (value <= 0x0f) { /* [register] */
- *v = &(vm->ram[ vm->reg[value & 0x07] ]);
+ *e_what = EWHAT_RAM;
*e_addr = vm->reg[value & 0x07];
+ *v = &(vm->ram[ *e_addr ]);
+ acct_event_(vm, DCPU16_ACCT_EV_REG_READ, value & 0x07);
TRACE("%s>> [%s] [0x%04x] (0x%04x)",
__func__,
dcpu16_reg_names[value & 0x07],
}
if (value <= 0x17) { /* [next word + register] */
+ acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
*pc_adjust += 1; /* consume next word */
*cycle_adjust += 1;
+ *e_what = EWHAT_RAM;
*e_addr = value_data + vm->reg[value & 0x07];
+ acct_event_(vm, DCPU16_ACCT_EV_REG_READ, value & 0x07);
*v = vm->ram + *e_addr;
TRACE("%s>> [nextword + %s] [0x%04x + 0x%04x] (0x%04x)",
__func__,
switch (value) {
case 0x18: /* PUSH/[--SP] or POP/[SP++] */
+ *e_what = EWHAT_RAM;
+ acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
+ acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_SP);
if (value_is_a == 0) { /* b */
*v = &(vm->ram[sp - 1]);
*sp_adjust -= 1;
break;
case 0x19: /* PEEK/[SP] */
+ acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
+ *e_what = EWHAT_RAM;
*v = &(vm->ram[sp]);
*e_addr = sp;
TRACE("%s>> PEEK [0x%04x] (0x%04x)",
break;
case 0x1a: /* PICK n */
+ acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
+ *e_what = EWHAT_RAM;
*pc_adjust += 1;
*cycle_adjust += 1;
*e_addr = sp + value_data;
break;
case 0x1b: /* SP */
+ *e_reg = DCPU16_REG_SP;
+ *e_what = EWHAT_REG;
*v = &(vm->reg[DCPU16_REG_SP]);
TRACE("%s>> %s (0x%04x)",
__func__,
break;
case 0x1c: /* PC */
+ *e_reg = DCPU16_REG_PC;
+ *e_what = EWHAT_REG;
*v = &(vm->reg[DCPU16_REG_PC]);
TRACE("%s>> %s (0x%04x)",
__func__,
break;
case 0x1d: /* EX */
+ *e_reg = DCPU16_REG_EX;
+ *e_what = EWHAT_REG;
*v = &(vm->reg[DCPU16_REG_EX]);
TRACE("%s>> %s (0x%04x)",
__func__,
break;
case 0x1e: /* [next word] / [[pc++]] */
+ *e_what = EWHAT_RAM;
+ acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
*pc_adjust += 1;
*cycle_adjust += 1;
*e_addr = value_data;
break;
case 0x1f: /* next word (literal) / [pc++] */
+ *e_what = EWHAT_NONE;
+ acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
*pc_adjust += 1;
*cycle_adjust += 1;
*work_v = value_data;
break;
default: /* 0x20-0x3f: literal values 0xffff-0x1e */
+ *e_what = EWHAT_NONE;
*work_v = (value & 0x1f) - 1;
*v = work_v;
TRACE("%s>> literal (0x%04x)",
#define OP_TYPE(op_type) DCPU16_WORD *a, *b;\
DCPU16_WORD ev_a_addr = 0, ev_b_addr = 0;\
+ enum dcpu16_register_indexes ev_a_reg = DCPU16_REG__NUM, ev_b_reg = DCPU16_REG__NUM;\
+ unsigned int ev_a_what = 0, ev_b_what = 0;\
short pc_adjust = 0, sp_adjust = 0;\
unsigned int cycle_adjust = 0;\
do {\
op_type;\
value_decode_(vm, val_a, 1, val_a_data,\
- &vm->reg_work_[1], &a, &ev_a_addr,\
+ &vm->reg_work_[1], &a, &ev_a_addr, &ev_a_reg, &ev_a_what,\
&pc_adjust, &sp_adjust, &cycle_adjust);\
vm->reg[DCPU16_REG_SP] += sp_adjust;\
dcpu16_cycle_inc(vm, cycle_adjust);\
} while (0)
-#define OP_NBI_ (void)val_b, (void)b, (void)ev_b_addr, (void)val_b_data
+#define OP_NBI_ (void)val_b, (void)b, (void)ev_b_addr, (void)val_b_data, (void)ev_b_reg, (void)ev_b_what
#define OP_BASIC_ value_decode_(vm, val_b, 0, val_b_data,\
- &vm->reg_work_[0], &b, &ev_b_addr,\
+ &vm->reg_work_[0], &b, &ev_b_addr, &ev_b_reg, &ev_b_what,\
&pc_adjust, &sp_adjust, &cycle_adjust)
#define OP_BASIC(x) OP_TYPE(OP_BASIC_)
#define OP_NBI(x) OP_TYPE(OP_NBI_)
accounting helpers, these fire off the related callbacks for memory reads,
memory writes, and execution of reserved instructions
*/
-#define ACCT_R(addr) do { acct_event_(vm, DCPU16_ACCT_EV_READ, addr); } while (0)
-#define ACCT_W(addr) do { acct_event_(vm, DCPU16_ACCT_EV_WRITE, addr); } while (0)
#define ACCT_ILL(addr) do { acct_event_(vm, DCPU16_ACCT_EV_NOP, addr); } while (0)
+#define ACCT_RAM_R(addr) do { acct_event_(vm, DCPU16_ACCT_EV_READ, addr); } while (0)
+#define ACCT_RAM_W(addr) do { acct_event_(vm, DCPU16_ACCT_EV_WRITE, addr); } while (0)
+#define ACCT_REG_R(reg) do { acct_event_(vm, DCPU16_ACCT_EV_REG_READ, reg); } while (0)
+#define ACCT_REG_W(reg) do { acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, reg); } while (0)
+
+#define ACCT_R(__x__) do {\
+ if (ev_##__x__##_what & EWHAT_REG) ACCT_REG_R(ev_##__x__##_reg);\
+ if (ev_##__x__##_what & EWHAT_RAM) ACCT_RAM_R(ev_##__x__##_addr);\
+} while (0)
+#define ACCT_W(__x__) do {\
+ if (ev_##__x__##_what & EWHAT_REG) ACCT_REG_W(ev_##__x__##_reg);\
+ if (ev_##__x__##_what & EWHAT_RAM) ACCT_RAM_W(ev_##__x__##_addr);\
+} while (0)
/* extended opcodes */
/* fire an illegal instruction event for current instruction */
DCPU16_WORD future_opcode = (vm->ram[vm->reg[DCPU16_REG_PC] - pc_adjust] >> (OPCODE_BASIC_BITS + OPCODE_OPERAND_B_BITS));
+
WARN("reserved future opcode 0x%04x invoked", future_opcode);
ACCT_ILL(vm->reg[DCPU16_REG_PC] - pc_adjust);
+
+ dcpu16_cycle_inc(vm, 1);
}
OP_IMPL(nbi_jsr) {
OP_NBI(nbi_jsr);
/* pushes the address of the next instruction to the stack, then sets PC to a */
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
+ ACCT_REG_R(DCPU16_REG_PC);
+ ACCT_REG_R(DCPU16_REG_SP);
vm->ram[ --vm->reg[DCPU16_REG_SP] ] = vm->reg[DCPU16_REG_PC];
+ ACCT_REG_W(DCPU16_REG_SP);
+ ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
+
vm->reg[DCPU16_REG_PC] = *a;
+ ACCT_REG_W(DCPU16_REG_PC);
- dcpu16_cycle_inc(vm, 2);
- ACCT_W(vm->reg[DCPU16_REG_SP] + 1);
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(nbi__reserved2_) {
WARN("reserved nbi opcode invoked");
ACCT_ILL(vm->reg[DCPU16_REG_PC] - pc_adjust);
+
+ dcpu16_cycle_inc(vm, 1);
}
OP_IMPL(nbi_int) {
OP_NBI(nbi_int);
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
+ ACCT_REG_R(DCPU16_REG_IA);
if (vm->reg[DCPU16_REG_IA]) {
if ( interrupt_enqueue_(vm, *a) ) {
WARN("failed to queue interrupt");
return;
vm->interrupts_deferred_ = 1;
+
+ ACCT_REG_R(DCPU16_REG_PC);
+ ACCT_REG_R(DCPU16_REG_SP);
vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_PC];
+ ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
+ ACCT_REG_W(DCPU16_REG_SP);
+
+ ACCT_REG_R(DCPU16_REG_A);
+ ACCT_REG_R(DCPU16_REG_SP);
vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_A];
+ ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
+ ACCT_REG_W(DCPU16_REG_SP);
+
+ ACCT_REG_R(DCPU16_REG_IA);
vm->reg[DCPU16_REG_PC] = vm->reg[DCPU16_REG_IA];
- vm->reg[0] = *a;
+ ACCT_REG_W(DCPU16_REG_PC);
+
+ vm->reg[DCPU16_REG_A] = *a;
+ ACCT_REG_W(DCPU16_REG_A);
}
dcpu16_cycle_inc(vm, 4);
OP_IMPL(nbi_iag) {
OP_NBI(nbi_iag);
+ ACCT_REG_R(DCPU16_REG_IA);
*a = vm->reg[DCPU16_REG_IA];
- dcpu16_cycle_inc(vm, 1);
+ ACCT_W(a);
- ACCT_W(ev_a_addr);
+ dcpu16_cycle_inc(vm, 1);
}
OP_IMPL(nbi_ias) {
OP_NBI(nbi_ias);
+ ACCT_R(a);
+
vm->reg[DCPU16_REG_IA] = *a;
+ ACCT_REG_W(DCPU16_REG_IA);
dcpu16_cycle_inc(vm, 1);
-
- ACCT_R(ev_a_addr);
}
/* does this just ignore its operand? */
OP_IMPL(nbi_rfi) {
OP_NBI(nbi_rfi);
+ /* well, it consumes the argument, currently, so I guess pretend like we care */
+ ACCT_R(a);
+
vm->interrupts_deferred_ = 0;
+
+ ACCT_REG_R(DCPU16_REG_SP);
+ ACCT_RAM_R(vm->reg[DCPU16_REG_SP]);
vm->reg[DCPU16_REG_A] = vm->ram[vm->reg[DCPU16_REG_SP]++];
+ ACCT_REG_W(DCPU16_REG_A);
+ ACCT_REG_W(DCPU16_REG_SP);
+
+ ACCT_REG_R(DCPU16_REG_SP);
+ ACCT_RAM_R(vm->reg[DCPU16_REG_SP]);
vm->reg[DCPU16_REG_PC] = vm->ram[vm->reg[DCPU16_REG_SP]++];
+ ACCT_REG_W(DCPU16_REG_PC);
+ ACCT_REG_W(DCPU16_REG_SP);
dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(nbi_iaq) {
OP_NBI(nbi_iaq);
+ ACCT_R(a);
+
if (*a) {
vm->interrupts_deferred_ = 1;
} else {
}
dcpu16_cycle_inc(vm, 2);
-
- ACCT_R(ev_a_addr);
}
OP_IMPL(nbi_hwn) {
OP_NBI(nbi_hwn);
- ACCT_W(ev_a_addr);
-
*a = vm->hw_table_entries_;
+ ACCT_W(a);
dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(nbi_hwq) {
OP_NBI(nbi_hwq);
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
if (*a >= vm->hw_table_entries_) {
WARN("hardware query for non-extant device 0x%04x", *a);
vm->reg[DCPU16_REG_C] = 0;
vm->reg[DCPU16_REG_X] = 0;
vm->reg[DCPU16_REG_Y] = 0;
- return;
+ } else {
+ 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;
}
- 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;
+ ACCT_REG_W(DCPU16_REG_A);
+ ACCT_REG_W(DCPU16_REG_B);
+ ACCT_REG_W(DCPU16_REG_C);
+ ACCT_REG_W(DCPU16_REG_X);
+ ACCT_REG_W(DCPU16_REG_Y);
dcpu16_cycle_inc(vm, 4);
}
OP_IMPL(nbi_hwi) {
OP_NBI(nbi_hwi);
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
if (*a > vm->hw_table_entries_) {
WARN("interrupt for non-extant device 0x%04x", *a);
return;
}
- dcpu16_cycle_inc(vm, 4);
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);
+
+ dcpu16_cycle_inc(vm, 4);
}
OP_IMPL(nbi_hcf) {
OP_NBI(nbi_hcf);
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
vm->on_fire_ = 1;
WARN("system on fire");
OP_BASIC(set);
/* sets b to a */
- ACCT_R(ev_a_addr);
+ ACCT_R(a);
/*
if b is a literal, it's aimed at a scratch register,
*/
*b = *a;
+ ACCT_W(b);
+
dcpu16_cycle_inc(vm, 1);
-
- ACCT_W(ev_b_addr);
}
OP_IMPL(add) {
/* sets b to b+a, sets EX to 0x0001 if there's an overflow, 0x0 otherwise */
unsigned int acc = *b + *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc;
vm->reg[DCPU16_REG_EX] = (acc > 0xffff);
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_EX);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(sub) {
/* sets b to b-a, sets EX to 0xffff if there's an underflow, 0x0 otherwise */
unsigned int acc = *b - *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc;
vm->reg[DCPU16_REG_EX] = (acc > 0xffff);
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_EX);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(mul) {
/* sets b to b*a, unsigned, sets EX to ((b*a)>>16)&0xffff */
unsigned int acc = *b * *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc;
vm->reg[DCPU16_REG_EX] = acc >> 16;
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_EX);
+
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(mli) {
/* sets b to b*a, signed */
int acc = (short)*b * (short)*a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc;
vm->reg[DCPU16_REG_EX] = acc >> 16;
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_EX);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(div) {
OP_BASIC(div);
/* sets b to b/a, sets EX to ((b<<16)/a)&0xffff. if a==0, sets a and EX to 0 instead. */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*a == 0) {
*b = 0;
vm->reg[DCPU16_REG_EX] = (*b << 16) / *a;
}
- dcpu16_cycle_inc(vm, 3);
+ ACCT_REG_W(DCPU16_REG_EX);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(dvi) {
OP_BASIC(dvi);
/* sets b to b/a, signed, round towards 0 */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*a == 0) {
*b = 0;
vm->reg[DCPU16_REG_EX] = (short)(*b << 16) / (short)*a;
}
- dcpu16_cycle_inc(vm, 3);
+ ACCT_REG_W(DCPU16_REG_EX);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(mod) {
OP_BASIC(mod);
/* sets b to b%a. if a==0, sets b to 0 instead. */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*a == 0) {
*b = 0;
*b = *b % *a;
}
- dcpu16_cycle_inc(vm, 3);
+ ACCT_W(a);
- ACCT_W(ev_a_addr);
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(mdi) {
OP_BASIC(mdi);
/* sets b to b%a, signed */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*a == 0) {
*b = 0;
*b = (short)*b % (short)*a;
}
- dcpu16_cycle_inc(vm, 3);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(and) {
OP_BASIC(and);
/* sets b to b&a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = *b & *a;
- dcpu16_cycle_inc(vm, 1);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 1);
}
OP_IMPL(bor) {
OP_BASIC(bor);
/* sets b to b|a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = *b | *a;
- dcpu16_cycle_inc(vm, 1);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 1);
}
OP_IMPL(xor) {
OP_BASIC(xor);
/* sets b to b^a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = *b ^ *a;
dcpu16_cycle_inc(vm, 1);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
}
OP_IMPL(shr) {
/* sets b to b>>>a, sets EX to ((b<<16)>>a)&0xffff */
unsigned int acc = *b >> *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc & 0xffff;
vm->reg[DCPU16_REG_EX] = (*b << 16) >> *a;
- dcpu16_cycle_inc(vm, 2);
-
WARN("IMPLEMENT");
- ACCT_W(ev_b_addr);
+ ACCT_REG_W(DCPU16_REG_EX);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(asr) {
/* sets b to b>>a, sets EX to ((b<<16)>>>a)&0xffff (arithmetic shift) (treats b as signed) */
unsigned int acc = *b << *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc & 0xffff;
vm->reg[DCPU16_REG_EX] = (*b << 16) >> *a;
- dcpu16_cycle_inc(vm, 2);
-
WARN("IMPLEMENT");
- ACCT_W(ev_b_addr);
+ ACCT_REG_W(DCPU16_REG_EX);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(shl) {
/* sets b to b<<a, sets EX to ((b<<a)>>16)&0xffff */
unsigned int acc = *b << *a;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = acc;
vm->reg[DCPU16_REG_EX] = acc >> 16;
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_EX);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(ifb) {
OP_BASIC(ifb);
/* performs next instruction only if (b&a)!=0 */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if ((*b & *a) != 0) {
/* */
OP_BASIC(ifc);
/* performs next instruction only if (b&a)==0 */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if ((*b & *a) == 0) {
/* */
OP_BASIC(ife);
/* performs next instruction only if b==a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b == *a) {
/* */
OP_BASIC(ifn);
/* performs next instruction only if b!=a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b != *a) {
/* */
OP_BASIC(ifg);
/* performs next instruction only if b>a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b > *a) {
/* */
OP_BASIC(ifa);
/* performs next instruction only if b>a (signed) */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b > *a) {
/* */
OP_BASIC(ifl);
/* performs next instruction only if b<a */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b < *a) {
/* */
OP_BASIC(ifu);
/* performs next instruction only if b<a (signed) */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
if (*b < *a) {
/* */
/* sets b to b+a+EX, sets EX to 0x0001 if overflow, 0x0 otherwise */
unsigned int acc;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
+
+ ACCT_REG_R(DCPU16_REG_EX);
acc = *b + *a + vm->reg[DCPU16_REG_EX];
*b = acc & 0xffff;
else
vm->reg[DCPU16_REG_EX] = 0x0000;
- dcpu16_cycle_inc(vm, 3);
+ ACCT_REG_W(DCPU16_REG_EX);
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(sbx) {
/* sets b to b-a+EX, sets EX to 0xffff if underflow, 0x0 otherwise */
unsigned int acc;
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
+
+ ACCT_REG_R(DCPU16_REG_EX);
acc = *b - *a + vm->reg[DCPU16_REG_EX];
*b = acc & 0xffff;
else
vm->reg[DCPU16_REG_EX] = 0;
- dcpu16_cycle_inc(vm, 3);
+ ACCT_REG_W(DCPU16_REG_EX);
+
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 3);
}
OP_IMPL(sti) {
OP_BASIC(sti);
/* sets b to a, then increases I and J by 1 */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = *a;
vm->reg[DCPU16_REG_I] += 1;
vm->reg[DCPU16_REG_J] += 1;
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_I);
+ ACCT_REG_W(DCPU16_REG_J);
+
+ ACCT_W(b);
- ACCT_W(ev_b_addr);
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(std) {
OP_BASIC(std);
/* sets b to a, then decreases I and J by 1 */
- ACCT_R(ev_b_addr);
- ACCT_R(ev_a_addr);
+ ACCT_R(b);
+ ACCT_R(a);
*b = *a;
vm->reg[DCPU16_REG_I] -= 1;
vm->reg[DCPU16_REG_J] -= 1;
- dcpu16_cycle_inc(vm, 2);
+ ACCT_REG_W(DCPU16_REG_I);
+ ACCT_REG_W(DCPU16_REG_J);
- ACCT_W(ev_b_addr);
+ ACCT_W(b);
+
+ dcpu16_cycle_inc(vm, 2);
}
OP_IMPL(_reserved_) {
* 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, dcpu16_ev_cb_t *fn, void *data) {
- struct dcpu16_acct_cb cb;
+int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event mask, dcpu16_ev_cb_t *fn, DCPU16_WORD addr_l, DCPU16_WORD addr_h, void *data) {
+ struct dcpu16_acct_cb cb = {
+ .mask = mask,
+ .addr_l = addr_l,
+ .addr_h = addr_h,
+ .fn = fn,
+ .data = data,
+ };
if (!vm)
return -1;
cb.mask = mask;
+ cb.addr_l = addr_l;
+ cb.addr_h = addr_h;
cb.fn = fn;
cb.data = data;
return NULL;
}
+ new_instance.screen->port += rfbScreens->entries;
+ new_instance.screen->ipv6port += rfbScreens->entries;
+
new_instance.attached_display = NULL;
new_instance.attached_keyboard = NULL;
s = dynarray_add(rfbScreens, &new_instance);
fprintf(f, "Sets addr to value.");
}
-#define MICROSECONDS_PER_CYCLE 10
+#define NANOSECONDS_PER_CYCLE 10000
+#define MIN_NANOSLEEP 31000
COMMAND_IMPL(run) {
struct sigaction act;
- struct timeval run_start_tv, run_stop_tv;
- long long run_cycle_start;
- struct timeval start_tv, now_tv, diff_tv;
+ long long run_cycle_start, run_cycle_end;
long long cycle_start, cycles_to_wait;
- struct timespec sleep_time, rem_time;
- long long run_usec;
+
+ struct timespec ts_run_start, ts_run_end, ts_run_diff;
+ struct timespec ts_cycle_start, ts_cycle_end_target, ts_cycle_end, ts_cycle_waste, ts_cycle_rem;
+ const struct timespec ts_cycle_time = { .tv_sec = 0, .tv_nsec = NANOSECONDS_PER_CYCLE };
(void)arg_count, (void)arg_vector;
running_ = 1;
- gettimeofday(&run_start_tv, NULL);
+ gettimespecofday(&ts_run_start);
run_cycle_start = vm->cycle_;
memset(&act, 0, sizeof act);
}
while (running_) {
- gettimeofday(&start_tv, NULL);
+ gettimespecofday(&ts_cycle_start);
+ ts_cycle_end_target = ts_cycle_start;
+
cycle_start = vm->cycle_;
dcpu16_step(vm);
/* how many cycles did this instr use? */
cycles_to_wait = vm->cycle_ - cycle_start;
- if (cycles_to_wait == 0)
- continue;
-
- /* each cycle wants 10 microseconds */
+ /* each cycle wants to take 10 microseconds */
+ while (cycles_to_wait--)
+ timespec_add(&ts_cycle_end_target, &ts_cycle_time);
/* how much of that did we spend already */
- gettimeofday(&now_tv, NULL);
- timeval_subtract(&diff_tv, &now_tv, &start_tv);
- /* do we have time to kill? */
- if (cycles_to_wait * MICROSECONDS_PER_CYCLE > diff_tv.tv_usec) {
- sleep_time.tv_sec = diff_tv.tv_sec;
- /* this is not accurate.. */
- sleep_time.tv_nsec = 250 * ( (cycles_to_wait * MICROSECONDS_PER_CYCLE) - diff_tv.tv_usec);
+ gettimespecofday(&ts_cycle_end);
+ /* do we have time to kill? */
+ if (timespec_subtract(&ts_cycle_waste, &ts_cycle_end_target, &ts_cycle_end) == 0) {
/* nanosleep doesn't interfere with libvncserver, unlike usleep */
- while ( nanosleep(&sleep_time, &rem_time) ) {
- sleep_time = rem_time;
- fprintf(stderr, "rem:%ld %ld\n", rem_time.tv_sec, rem_time.tv_nsec);
- }
+ if (ts_cycle_waste.tv_sec == 0 && ts_cycle_waste.tv_nsec >= MIN_NANOSLEEP)
+ while ( nanosleep(&ts_cycle_waste, &ts_cycle_rem) )
+ ts_cycle_waste = ts_cycle_rem;
+ } else {
+ /* negative, we've already blown our time */
+#if 0
+ fprintf(stderr, "cycle time overrun %ld.%09lds\n", ts_cycle_waste.tv_sec, ts_cycle_waste.tv_nsec);
+#endif
}
+
+#if 0
+ /* how did we do */
+ gettimespecofday(&ts_cycle_end);
+ timespec_subtract(&ts_cycle_rem, &ts_cycle_end_target, &ts_cycle_end);
+ fprintf(stderr, "projected end: %ld.%09ld actual end: %ld.%09ld diff: %ld.%09ld\n",
+ ts_cycle_end_target.tv_sec, ts_cycle_end_target.tv_nsec,
+ ts_cycle_end.tv_sec, ts_cycle_end.tv_nsec,
+ ts_cycle_rem.tv_sec, ts_cycle_rem.tv_nsec);
+#endif
+
}
- gettimeofday(&run_stop_tv, NULL);
- timeval_subtract(&diff_tv, &run_stop_tv, &run_start_tv);
- run_usec = diff_tv.tv_sec * 1000000;
- run_usec += diff_tv.tv_usec;
- fprintf(stderr, "ran %llu cycles in %lds %dus (%lldus)\n",
- vm->cycle_ - run_cycle_start,
- diff_tv.tv_sec,
- diff_tv.tv_usec,
- run_usec);
+ run_cycle_end = vm->cycle_;
+ gettimespecofday(&ts_run_end);
+ timespec_subtract(&ts_run_diff, &ts_run_end, &ts_run_start);
+ fprintf(stderr, "ran %lld cycles in %ld.%09lds\n",
+ run_cycle_end - run_cycle_start,
+ ts_run_diff.tv_sec, ts_run_diff.tv_nsec);
printf("interrupted...\n");