diff options
Diffstat (limited to 'usr.bin/oemu')
-rw-r--r-- | usr.bin/oemu/cpu.c | 143 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/cpu.h | 1 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/osmx64.h | 1 |
3 files changed, 145 insertions, 0 deletions
diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c index 61568f2..58dd134 100644 --- a/usr.bin/oemu/cpu.c +++ b/usr.bin/oemu/cpu.c @@ -100,6 +100,104 @@ cpu_dec(struct oemu_cpu *cpu, inst_t *inst) } /* + * Decode the INST_ADD instruction + * + * @cpu: CPU that is executing + * @inst: Instruction dword + */ +static void +cpu_add(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 'add'\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_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 @@ -112,6 +210,31 @@ cpu_reset(struct oemu_cpu *cpu) memset(regs->xreg, 0x0, sizeof(regs->xreg)); } +void +cpu_regdump(struct oemu_cpu *cpu) +{ + struct cpu_regs *regs; + + regs = &cpu->regs; + printf( + "X0=%p, X1=%p, X2=%p\n" + "X3=%p, X4=%p, X5=%p\n" + "X6=%p, X7=%p, X8=%p\n" + "X9=%p, X10=%p, X11=%p\n" + "X12=%p, X13=%p, X14=%p\n" + "X15=%p, IP=%p\n", + regs->xreg[0], regs->xreg[1], + regs->xreg[2], regs->xreg[3], + regs->xreg[4], regs->xreg[5], + regs->xreg[6], regs->xreg[7], + regs->xreg[8], regs->xreg[9], + regs->xreg[10], regs->xreg[11], + regs->xreg[12], regs->xreg[13], + regs->xreg[14], regs->xreg[15], + regs->ip + ); +} + /* * Main instruction execution loop. */ @@ -135,6 +258,24 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) case INST_DEC: cpu_dec(cpu, inst); break; + 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) { @@ -143,4 +284,6 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) regs->ip += sizeof(*inst); } + + cpu_regdump(cpu); } diff --git a/usr.bin/oemu/include/oemu/cpu.h b/usr.bin/oemu/include/oemu/cpu.h index df4cc80..78b92da 100644 --- a/usr.bin/oemu/include/oemu/cpu.h +++ b/usr.bin/oemu/include/oemu/cpu.h @@ -63,6 +63,7 @@ struct oemu_cpu { struct cpu_regs regs; }; +void cpu_regdump(struct oemu_cpu *cpu); void cpu_reset(struct oemu_cpu *cpu); void cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem); diff --git a/usr.bin/oemu/include/oemu/osmx64.h b/usr.bin/oemu/include/oemu/osmx64.h index d7ea8b1..e9baae0 100644 --- a/usr.bin/oemu/include/oemu/osmx64.h +++ b/usr.bin/oemu/include/oemu/osmx64.h @@ -47,6 +47,7 @@ #define INST_SLL 0x11 /* Shift left logical operation */ #define INST_SRL 0x12 /* Shift right logical operation */ #define INST_MOV_IMM 0x13 /* Data move operation from IMM */ +#define INST_HLT 0x14 /* Halt */ /* Registers */ #define REG_X0 0x00 |