void vm_op_mdi(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_a; uint16_t val_b; int16_t val_b_signed; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(3); VM_SKIP_RESET; // compute 2s complement if (val_b > (2 ^ 8)) val_b_signed = 0 - (0x10000 - val_b); else val_b_signed = val_b; if (val_a != 0) *store_b = val_b_signed % val_a; else *store_b = 0; VM_HOOK_FIRE(store_b); }
void vm_op_hcf(vm_t* vm, uint16_t a) { uint16_t val_a = vm_resolve_value(vm, a, POS_A); (void)val_a; OP_NUM_CYCLES(9); vm->halted = true; }
void vm_op_hwq(vm_t* vm, uint16_t a) { hw_t queried_device; uint16_t* store_a = vm_internal_get_store(vm, REG_A, POS__); uint16_t* store_b = vm_internal_get_store(vm, REG_B, POS__); uint16_t* store_c = vm_internal_get_store(vm, REG_C, POS__); uint16_t* store_x = vm_internal_get_store(vm, REG_X, POS__); uint16_t* store_y = vm_internal_get_store(vm, REG_Y, POS__); uint16_t val_a = vm_resolve_value(vm, a, POS_A); OP_NUM_CYCLES(4); VM_SKIP_RESET; if (val_a < vm_hw_count(vm)) { queried_device = vm_hw_get_device(vm, val_a); printd(LEVEL_DEBUG, "hwq: index %d %08X\n", val_a, queried_device.id); *store_a = (queried_device.id & 0x0000FFFF) >> 0; *store_b = (queried_device.id & 0xFFFF0000) >> 16; *store_c = queried_device.version; *store_x = (queried_device.manufacturer & 0x0000FFFF) >> 0; *store_y = (queried_device.manufacturer & 0xFFFF0000) >> 16; VM_HOOK_FIRE(store_a); VM_HOOK_FIRE(store_b); VM_HOOK_FIRE(store_c); VM_HOOK_FIRE(store_x); VM_HOOK_FIRE(store_y); }
void vm_op_dvi(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_a; int16_t val_b; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = (int16_t)vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(3); VM_SKIP_RESET; if (val_a != 0) { *store_b = val_b / val_a; vm->ex = ((val_b << 16) / val_a) & 0xffff; } else { *store_b = 0; vm->ex = 0; } VM_HOOK_FIRE(store_b); }
void vm_op_int(vm_t* vm, uint16_t a) { uint16_t val_a = vm_resolve_value(vm, a, POS_A); OP_NUM_CYCLES(4); printd(LEVEL_DEBUG, "sending interrupt %u\n", val_a); vm_interrupt(vm, val_a); }
void vm_op_jsr(vm_t* vm, uint16_t a) { uint16_t val_a = vm_resolve_value(vm, a, POS_A); uint16_t t; OP_NUM_CYCLES(3); VM_SKIP_RESET; t = --vm->sp; vm->ram[t] = vm->pc; vm->pc = val_a; }
void vm_op_hwn(vm_t* vm, uint16_t a) { uint16_t* store_a = vm_internal_get_store(vm, a, POS_A); OP_NUM_CYCLES(2); VM_SKIP_RESET; *store_a = vm_hw_count(vm); VM_HOOK_FIRE(store_a); vm->skip = false; }
void vm_op_rfi(vm_t* vm, uint16_t a) { uint16_t val_a = vm_resolve_value(vm, a, POS_A); OP_NUM_CYCLES(3); VM_SKIP_RESET; vm->registers[REG_A] = vm->ram[vm->sp++]; vm->pc = vm->ram[vm->sp++]; printd(LEVEL_DEBUG, "turning off interrupt queue\n"); vm->queue_interrupts = false; printd(LEVEL_DEBUG, "returning from interrupt.\n"); VM_HOOK_FIRE(&vm->registers[REG_A]); }
void vm_op_xor(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_b, val_a; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(1); VM_SKIP_RESET; *store_b = val_b ^ val_a; VM_HOOK_FIRE(store_b); }
void vm_op_set(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_a; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(1); VM_SKIP_RESET; *store_b = val_a; VM_HOOK_FIRE(store_b); vm->skip = false; }
void vm_op_shl(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_b, val_a; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(1); VM_SKIP_RESET; *store_b = val_b << val_a; vm->ex = ((val_b << val_a) >> 16) & 0xffff; VM_HOOK_FIRE(store_b); }
void vm_op_sub(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_b, val_a; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(2); VM_SKIP_RESET; *store_b = val_b - val_a; VM_CHECK_ARITHMETIC_FLOW(-, val_b, val_a); VM_HOOK_FIRE(store_b); }
void vm_op_adx(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_b, val_a, val_ex; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(3); val_ex = vm->ex; VM_SKIP_RESET; *store_b = val_b + val_a + val_ex; VM_CHECK_ARITHMETIC_FLOW_EX(+, val_b, val_a, val_ex); VM_HOOK_FIRE(store_b); }
void vm_op_mli(vm_t* vm, uint16_t b, uint16_t a) { int16_t val_a; int16_t val_b; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); store_b = vm_internal_get_store(vm, b, POS_B); val_b = *store_b; OP_NUM_CYCLES(2); VM_SKIP_RESET; *store_b = val_b * val_a; vm->ex = ((val_b * val_a) >> 16) & 0xffff; VM_HOOK_FIRE(store_b); }
void vm_op_mod(vm_t* vm, uint16_t b, uint16_t a) { uint16_t val_b, val_a; uint16_t* store_b; val_a = vm_resolve_value(vm, a, POS_A); val_b = vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(3); VM_SKIP_RESET; if (val_a != 0) *store_b = val_b % val_a; else *store_b = 0; VM_HOOK_FIRE(store_b); }
void vm_op_asr(vm_t* vm, uint16_t b, uint16_t a) { // TODO: This may not infact be correct. C uses // arithmetic shifts if the left-hand value is // signed, however, we still need to make sure that the // excess register is completely compliant. int16_t val_b, val_a; uint16_t* store_b; val_a = (int16_t)vm_resolve_value(vm, a, POS_A); val_b = (int16_t)vm_resolve_value_once(vm, b, POS_B); store_b = vm_internal_get_store(vm, b, POS_B); OP_NUM_CYCLES(1); VM_SKIP_RESET; *store_b = val_b >> val_a; vm->ex = ((val_b << 16) >> val_a) & 0xffff; VM_HOOK_FIRE(store_b); }
void vm_op_iaq(vm_t* vm, uint16_t a) { uint16_t val_a = vm_resolve_value(vm, a, POS_A); OP_NUM_CYCLES(2); VM_SKIP_RESET; printd(LEVEL_DEBUG, "IAQ CALLED WITH %u\n", val_a); if (val_a == 0) { printd(LEVEL_DEBUG, "turning off interrupt queue\n"); vm->queue_interrupts = false; } else { printd(LEVEL_DEBUG, "turning on interrupt queue\n"); vm->queue_interrupts = true; } }