summaryrefslogtreecommitdiff
path: root/usr.bin/oemu/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/oemu/cpu.c')
-rw-r--r--usr.bin/oemu/cpu.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c
index 9b8c622..5689953 100644
--- a/usr.bin/oemu/cpu.c
+++ b/usr.bin/oemu/cpu.c
@@ -123,6 +123,81 @@ cpu_add(struct oemu_cpu *cpu, inst_t *inst)
}
/*
+ * Decode the INST_SUB instruction
+ *
+ * @cpu: CPU that is executing
+ * @inst: Instruction dword
+ */
+static void
+cpu_sub(struct oemu_cpu *cpu, inst_t *inst)
+{
+ struct cpu_regs *regs = &cpu->regs;
+ imm_t imm;
+
+ if (inst->rd > NELEM(regs->xreg)) {
+ printf("bad register operand for 'sub'\n");
+ return;
+ }
+
+ imm = regs->xreg[inst->rd];
+ regs->xreg[inst->rd] -= inst->imm;
+ printf("%d - %d -> X%d, new=%d\n",
+ imm, inst->imm, inst->rd, regs->xreg[inst->rd]);
+}
+
+/*
+ * Decode the INST_MUL instruction
+ *
+ * @cpu: CPU that is executing
+ * @inst: Instruction dword
+ */
+static void
+cpu_mul(struct oemu_cpu *cpu, inst_t *inst)
+{
+ struct cpu_regs *regs = &cpu->regs;
+ imm_t imm;
+
+ if (inst->rd > NELEM(regs->xreg)) {
+ printf("bad register operand for 'mul'\n");
+ return;
+ }
+
+ imm = regs->xreg[inst->rd];
+ regs->xreg[inst->rd] *= inst->imm;
+ printf("%d * %d -> X%d, new=%d\n",
+ imm, inst->imm, inst->rd, regs->xreg[inst->rd]);
+}
+
+/*
+ * Decode the INST_DIV instruction
+ *
+ * @cpu: CPU that is executing
+ * @inst: Instruction dword
+ */
+static void
+cpu_div(struct oemu_cpu *cpu, inst_t *inst)
+{
+ struct cpu_regs *regs = &cpu->regs;
+ imm_t imm;
+
+ if (inst->rd > NELEM(regs->xreg)) {
+ printf("bad register operand for 'div'\n");
+ return;
+ }
+
+ imm = regs->xreg[inst->rd];
+ if (imm == 0) {
+ /* TODO: Some sort of interrupt */
+ printf("** DIVIDE BY ZERO **\n");
+ return;
+ }
+
+ regs->xreg[inst->rd] /= inst->imm;
+ printf("%d / %d -> X%d, new=%d\n",
+ imm, inst->imm, inst->rd, regs->xreg[inst->rd]);
+}
+
+/*
* Reset a CPU to a default state
*/
void
@@ -161,6 +236,21 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem)
case INST_ADD:
cpu_add(cpu, inst);
break;
+ case INST_SUB:
+ cpu_sub(cpu, inst);
+ break;
+ case INST_MUL:
+ cpu_mul(cpu, inst);
+ break;
+ case INST_DIV:
+ cpu_div(cpu, inst);
+ break;
+ }
+
+ /* Is this a halt instruction? */
+ if (inst->opcode == INST_HLT) {
+ printf("HALTED\n");
+ break;
}
if (regs->ip >= MEMORY_SIZE) {