From 6bd0f17304d78e2b7e37684a672f59c9cc2444d0 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 24 Jul 2025 03:52:32 -0400 Subject: oemu: cpu: Add decoding logic of MRO instructions Signed-off-by: Ian Moffett --- usr.bin/oemu/cpu.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'usr.bin/oemu/cpu.c') diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c index 07ddc7b..5a2c761 100644 --- a/usr.bin/oemu/cpu.c +++ b/usr.bin/oemu/cpu.c @@ -27,14 +27,34 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include +#include #include #include #include +/* + * Return true if the instruction is an + * MRO type instruction. + */ +static bool +cpu_is_mro(inst_t *inst) +{ + switch (inst->opcode) { + case INST_MROB: + case INST_MROW: + case INST_MROD: + case INST_MROQ: + return true; + } + + return false; +} + /* * Decode the INST_MOV_IMM instruction * @@ -224,6 +244,77 @@ cpu_br(struct oemu_cpu *cpu, inst_t *inst) regs->ip = br_to; } +/* + * Decode MRO type instructions + */ +static void +cpu_mro(struct oemu_cpu *cpu, inst_t *inst) +{ + inst_t *next_inst; + struct cpu_regs *regs = &cpu->regs; + char *inst_str = "bad"; + uint64_t mask = 0; + bool set_mask = false; + imm_t imm; + + switch (inst->imm) { + case 0: break; + case 1: + set_mask = true; + break; + default: + imm = inst->imm & 1; + if (inst->imm == 1) { + set_mask = true; + } + break; + } + + switch (inst->opcode) { + case INST_MROB: + inst_str = "mrob"; + if (!set_mask) { + break; + } + mask |= MASK(8); + break; + case INST_MROW: + inst_str = "mrow"; + if (!set_mask) { + break; + } + mask |= MASK(16); + break; + case INST_MROD: + inst_str = "mrod"; + if (!set_mask) { + break; + } + mask |= MASK(32); + break; + case INST_MROQ: + inst_str = "mroq"; + if (!set_mask) { + break; + } + mask |= __UINT64_MAX; + break; + } + + if (inst->rd > NELEM(regs->xreg)) { + printf("bad register operand for '%s'\n", inst_str); + return; + } + + if (set_mask) { + imm = regs->xreg[inst->rd] |= mask; + printf("set %x->x%d, new=%x\n", mask, inst->rd, imm); + } else { + imm = regs->xreg[inst->rd] &= ~mask; + printf("cleared %x->x%d, new=%x\n", mask, inst->rd, imm); + } +} + /* * Reset a CPU to a default state */ @@ -310,6 +401,11 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) case INST_BR: cpu_br(cpu, inst); break; + default: + if (cpu_is_mro(inst)) { + cpu_mro(cpu, inst); + } + break; } /* Is this a halt instruction? */ -- cgit v1.2.3