aboutsummaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-05-23 16:06:46 +0100
committerJuan J. Martinez <jjm@usebox.net>2023-05-23 16:08:48 +0100
commitc5dd4897e4d7f45108b6955bebf2d4b5f22a3652 (patch)
treea85d5b933fe2dccf57dd476194a27b0f5d99becd /vm.c
parent5584f79fff0fdfc8e4430eea3867c729b82f4152 (diff)
downloadtr8vm-c5dd4897e4d7f45108b6955bebf2d4b5f22a3652.tar.gz
tr8vm-c5dd4897e4d7f45108b6955bebf2d4b5f22a3652.zip
Add cmpi, cmpd, ldi and ldd
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/vm.c b/vm.c
index 72dec72..43a6ab5 100644
--- a/vm.c
+++ b/vm.c
@@ -453,13 +453,90 @@ uint8_t tr8_eval(Tr8 *vm)
}
break;
+ case 14:
+ if (FHL(instr))
+ {
+ if (FHH(instr))
+ {
+ uint8_t f = 0;
+
+ /* CMPI */
+ flags(&vm->f, vm->read_m(ADDR(vm->regs[0], vm->regs[2])) - vm->read_m(ADDR(vm->regs[1], vm->regs[3])), ZF | CF | OF | SF);
+
+ vm->regs[2] = flags(&f, vm->regs[2] + 1, OF);
+ if (f & OF)
+ vm->regs[0]++;
+
+ vm->regs[3] = flags(&f, vm->regs[3] + 1, OF);
+ if (f & OF)
+ vm->regs[1]++;
+
+ vm->icnt += 3;
+ }
+ else
+ {
+ uint8_t f = 0;
+
+ /* CMPD */
+ flags(&vm->f, vm->read_m(ADDR(vm->regs[0], vm->regs[2])) - vm->read_m(ADDR(vm->regs[1], vm->regs[3])), ZF | CF | OF | SF);
+
+ vm->regs[2] = flags(&f, vm->regs[2] - 1, OF);
+ if (f & OF)
+ vm->regs[0]--;
+
+ vm->regs[3] = flags(&f, vm->regs[3] - 1, OF);
+ if (f & OF)
+ vm->regs[1]--;
+
+ vm->icnt += 3;
+ }
+ }
+ else
+ {
+ if (FHH(instr))
+ {
+ uint8_t f = 0;
+
+ /* LDI */
+ vm->write_m(ADDR(vm->regs[1], vm->regs[3]), vm->read_m(ADDR(vm->regs[0], vm->regs[2])));
+
+ vm->regs[2] = flags(&f, vm->regs[2] + 1, OF);
+ if (f & OF)
+ vm->regs[0]++;
+
+ vm->regs[3] = flags(&f, vm->regs[3] + 1, OF);
+ if (f & OF)
+ vm->regs[1]++;
+
+ vm->icnt += 3;
+ }
+ else
+ {
+ uint8_t f = 0;
+
+ /* LDD */
+ vm->write_m(ADDR(vm->regs[1], vm->regs[3]), vm->read_m(ADDR(vm->regs[0], vm->regs[2])));
+
+ vm->regs[2] = flags(&f, vm->regs[2] - 1, OF);
+ if (f & OF)
+ vm->regs[0]--;
+
+ vm->regs[3] = flags(&f, vm->regs[3] - 1, OF);
+ if (f & OF)
+ vm->regs[1]--;
+
+ vm->icnt += 3;
+ }
+ }
+ break;
+
default:
fprintf(stderr, "*invalid opcode 0x%01x at PC=0x%04x*\n", (instr >> 12), 2 * (vm->pc - 1));
tr8_dump(vm, stderr);
return 1;
}
- if (vm->icnt == INSTR_PER_FRAME)
+ if (vm->icnt >= INSTR_PER_FRAME)
return 1;
}
}